From 8672fba5020ec72acf931a9a63b12a3c57f6c5cb Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Fri, 21 Jul 2023 23:25:01 +0200 Subject: [PATCH] elf: handle text relocations --- src/Elf.zig | 1 + src/Elf/Atom.zig | 6 +----- src/Elf/Options.zig | 4 ++-- src/Elf/synthetic.zig | 9 ++++++++ test/elf.zig | 48 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 7 deletions(-) diff --git a/src/Elf.zig b/src/Elf.zig index 8681960f..1726c87f 100644 --- a/src/Elf.zig +++ b/src/Elf.zig @@ -87,6 +87,7 @@ comdat_groups_owners: std.ArrayListUnmanaged(ComdatGroupOwner) = .{}, comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{}, needs_tlsld: bool = false, +has_text_reloc: bool = false, num_ifunc_dynrelocs: usize = 0, default_sym_version: elf.Elf64_Versym, diff --git a/src/Elf/Atom.zig b/src/Elf/Atom.zig index 5c78053e..1aecc1de 100644 --- a/src/Elf/Atom.zig +++ b/src/Elf/Atom.zig @@ -349,11 +349,7 @@ inline fn checkTextReloc(self: Atom, symbol: *const Symbol, elf_file: *Elf) void symbol.getName(elf_file), }); } else { - // TODO - elf_file.base.fatal("{s}: {s}: TODO handle relocations in read-only section", .{ - self.getObject(elf_file).fmtPath(), - self.getName(elf_file), - }); + elf_file.has_text_reloc = true; } } } diff --git a/src/Elf/Options.zig b/src/Elf/Options.zig index 2c3cb12e..cf8644b0 100644 --- a/src/Elf/Options.zig +++ b/src/Elf/Options.zig @@ -57,7 +57,7 @@ const usage = \\ nodlopen Mark DSO not available to dlopen \\ now Disable lazy function resolution \\ stack-size=[value] Override default stack size - \\ text Do not allow relocations against read-only segments (default) + \\ text Do not allow relocations against read-only segments \\ notext \\ relro Make some sections read-only after dynamic relocations \\ norelro @@ -115,7 +115,7 @@ z_nocopyreloc: bool = false, /// Mark DSO not available for dlopen. z_nodlopen: bool = false, /// Do not allow relocations against read-only segments. -z_text: bool = true, +z_text: bool = false, /// Make some sections read-only after dynamic relocations. /// TODO make this default to true. z_relro: bool = false, diff --git a/src/Elf/synthetic.zig b/src/Elf/synthetic.zig index dc9baa68..abf55855 100644 --- a/src/Elf/synthetic.zig +++ b/src/Elf/synthetic.zig @@ -42,6 +42,9 @@ pub const DynamicSection = struct { }, else => {}, }; + if (elf_file.has_text_reloc) { + flags |= elf.DF_TEXTREL; + } return if (flags > 0) flags else null; } @@ -75,6 +78,7 @@ pub const DynamicSection = struct { if (elf_file.got_plt_sect_index != null) nentries += 1; // PLTGOT nentries += 1; // HASH if (elf_file.gnu_hash_sect_index != null) nentries += 1; // GNU_HASH + if (elf_file.has_text_reloc) nentries += 1; // TEXTREL nentries += 1; // SYMTAB nentries += 1; // SYMENT nentries += 1; // STRTAB @@ -165,6 +169,11 @@ pub const DynamicSection = struct { try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr }); } + // TEXTREL + if (elf_file.has_text_reloc) { + try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_TEXTREL, .d_val = 0 }); + } + // SYMTAB + SYMENT { assert(elf_file.dynsymtab_sect_index != null); diff --git a/test/elf.zig b/test/elf.zig index 9c44bcbd..d30707f9 100644 --- a/test/elf.zig +++ b/test/elf.zig @@ -69,6 +69,7 @@ pub fn addElfTests(b: *Build, opts: Options) *Step { elf_step.dependOn(testWeakExportExe(b, opts)); elf_step.dependOn(testWeakUndefDso(b, opts)); elf_step.dependOn(testZNow(b, opts)); + elf_step.dependOn(testZText(b, opts)); } return elf_step; @@ -3007,6 +3008,53 @@ fn testZNow(b: *Build, opts: Options) *Step { return test_step; } +fn testZText(b: *Build, opts: Options) *Step { + const test_step = b.step("test-elf-z-text", ""); + + const a_o = cc(b, opts); + a_o.addAsmSource( + \\.globl fn1 + \\fn1: + \\ sub $8, %rsp + \\ movabs ptr, %rax + \\ call *%rax + \\ add $8, %rsp + \\ ret + ); + a_o.addArg("-c"); + + const b_o = cc(b, opts); + b_o.addCSource( + \\#include + \\int fn1(); + \\int fn2() { + \\ return 3; + \\} + \\void *ptr = fn2; + \\int main() { + \\ printf("%d\n", fn1()); + \\} + ); + b_o.addArgs(&.{ "-fPIC", "-c" }); + + const exe = cc(b, opts); + exe.addFileSource(a_o.out); + exe.addFileSource(b_o.out); + exe.addArg("-pie"); + + const run = exe.run(); + run.expectStdOutEqual("3\n"); + test_step.dependOn(run.step()); + + const check = exe.check(); + check.checkInDynamicSection(); + // check.checkExact("TEXTREL 0"); // TODO fix in CheckObject parser + check.checkExact("FLAGS TEXTREL"); + test_step.dependOn(&check.step); + + return test_step; +} + fn cc(b: *Build, opts: Options) SysCmd { const cmd = Run.create(b, "cc"); cmd.addArgs(&.{ "cc", "-fno-lto" });