Commit 3768c95371

Jakub Konka <kubkon@jakubkonka.com>
2023-10-19 15:57:58
elf: actually check for dynamic executables
1 parent ae2cd5f
Changed files (3)
src/link/Elf/Atom.zig
@@ -600,7 +600,7 @@ fn dynAbsRelocAction(symbol: *const Symbol, elf_file: *Elf) RelocAction {
 }
 
 fn outputType(elf_file: *Elf) u2 {
-    return switch (elf_file.base.options.output_mode) {
+    return switch (elf_file.base.options.effectiveOutputMode()) {
         .Obj => unreachable,
         .Lib => 0,
         .Exe => if (elf_file.base.options.pie) 1 else 2,
src/link/Elf/synthetic_sections.zig
@@ -54,7 +54,7 @@ pub const DynamicSection = struct {
         if (elf_file.base.options.z_now) {
             flags_1 |= elf.DF_1_NOW;
         }
-        if (elf_file.base.options.pie) {
+        if (elf_file.isExe() and elf_file.base.options.pie) {
             flags_1 |= elf.DF_1_PIE;
         }
         // if (elf_file.base.options.z_nodlopen) {
@@ -226,7 +226,7 @@ pub const ZigGotSection = struct {
     flags: Flags = .{},
 
     const Flags = packed struct {
-        needs_rela: bool = false, // TODO in prep for PIC/PIE and base relocations
+        needs_rela: bool = false,
         dirty: bool = false,
     };
 
@@ -251,7 +251,7 @@ pub const ZigGotSection = struct {
         entry.* = sym_index;
         const symbol = elf_file.symbol(sym_index);
         symbol.flags.has_zig_got = true;
-        if (elf_file.base.options.pic) {
+        if (elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) {
             zig_got.flags.needs_rela = true;
         }
         if (symbol.extra(elf_file)) |extra| {
@@ -491,7 +491,7 @@ pub const GotSection = struct {
         const symbol = elf_file.symbol(sym_index);
         symbol.flags.has_got = true;
         if (symbol.flags.import or symbol.isIFunc(elf_file) or
-            (elf_file.base.options.pic and !symbol.isAbs(elf_file)))
+            ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and !symbol.isAbs(elf_file)))
         {
             got.flags.needs_rela = true;
         }
@@ -582,8 +582,11 @@ pub const GotSection = struct {
                         if (symbol.?.flags.import) break :blk 0;
                         if (symbol.?.isIFunc(elf_file))
                             break :blk if (apply_relocs) value else 0;
-                        if (elf_file.base.options.pic and !symbol.?.isAbs(elf_file))
+                        if ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and
+                            !symbol.?.isAbs(elf_file))
+                        {
                             break :blk if (apply_relocs) value else 0;
+                        }
                         break :blk value;
                     };
                     try writeInt(value, elf_file, writer);
@@ -655,7 +658,9 @@ pub const GotSection = struct {
                         });
                         continue;
                     }
-                    if (elf_file.base.options.pic and !symbol.?.isAbs(elf_file)) {
+                    if ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and
+                        !symbol.?.isAbs(elf_file))
+                    {
                         elf_file.addRelaDynAssumeCapacity(.{
                             .offset = offset,
                             .type = elf.R_X86_64_RELATIVE,
@@ -734,8 +739,9 @@ pub const GotSection = struct {
                 inline else => elf_file.symbol(entry.symbol_index),
             };
             switch (entry.tag) {
-                .got => if (symbol.?.flags.import or
-                    symbol.?.isIFunc(elf_file) or (elf_file.base.options.pic and !symbol.?.isAbs(elf_file)))
+                .got => if (symbol.?.flags.import or symbol.?.isIFunc(elf_file) or
+                    ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and
+                    !symbol.?.isAbs(elf_file)))
                 {
                     num += 1;
                 },
src/link/Elf.zig
@@ -2956,7 +2956,7 @@ fn writeHeader(self: *Elf) !void {
     assert(index == 16);
 
     const elf_type: elf.ET = switch (self.base.options.effectiveOutputMode()) {
-        .Exe => if (self.base.options.pic) .DYN else .EXEC,
+        .Exe => if (self.base.options.pie) .DYN else .EXEC,
         .Obj => .REL,
         .Lib => switch (self.base.options.link_mode) {
             .Static => @as(elf.ET, .REL),
@@ -4869,6 +4869,7 @@ fn allocateSpecialPhdrs(self: *Elf) void {
             phdr.p_align = shdr.sh_addralign;
             phdr.p_offset = shdr.sh_offset;
             phdr.p_vaddr = shdr.sh_addr;
+            phdr.p_paddr = shdr.sh_addr;
             phdr.p_filesz = shdr.sh_size;
             phdr.p_memsz = shdr.sh_size;
         }
@@ -5581,7 +5582,8 @@ const CsuObjects = struct {
 };
 
 pub fn calcImageBase(self: Elf) u64 {
-    if (self.base.options.pic) return 0; // TODO flag an error if PIC and image_base_override
+    if (self.isDynLib()) return 0;
+    if (self.isExe() and self.base.options.pie) return 0;
     return self.base.options.image_base_override orelse switch (self.ptr_width) {
         .p32 => 0x1000,
         .p64 => 0x1000000,