Commit 4cd92567e7

Jakub Konka <kubkon@jakubkonka.com>
2024-04-08 10:24:48
link/elf: propagate Haiku requirement of always passing -shared for images
1 parent b98e3be
src/link/Elf/Atom.zig
@@ -1054,7 +1054,7 @@ const x86_64 = struct {
         it: *RelocsIterator,
     ) !void {
         const is_static = elf_file.base.isStatic();
-        const is_dyn_lib = elf_file.base.isDynLib();
+        const is_dyn_lib = elf_file.isEffectivelyDynLib();
 
         const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
         const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
@@ -1599,7 +1599,7 @@ const aarch64 = struct {
         _ = it;
 
         const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
-        const is_dyn_lib = elf_file.base.isDynLib();
+        const is_dyn_lib = elf_file.isEffectivelyDynLib();
 
         switch (r_type) {
             .ABS64 => {
src/link/Elf/Object.zig
@@ -568,7 +568,7 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {
         }
 
         const is_import = blk: {
-            if (!elf_file.base.isDynLib()) break :blk false;
+            if (!elf_file.isEffectivelyDynLib()) break :blk false;
             const vis = @as(elf.STV, @enumFromInt(esym.st_other));
             if (vis == .HIDDEN) break :blk false;
             break :blk true;
src/link/Elf/synthetic_sections.zig
@@ -89,7 +89,7 @@ pub const DynamicSection = struct {
         if (elf_file.verneed_section_index != null) nentries += 2; // VERNEED
         if (dt.getFlags(elf_file) != null) nentries += 1; // FLAGS
         if (dt.getFlags1(elf_file) != null) nentries += 1; // FLAGS_1
-        if (!elf_file.base.isDynLib()) nentries += 1; // DEBUG
+        if (!elf_file.isEffectivelyDynLib()) nentries += 1; // DEBUG
         nentries += 1; // NULL
         return nentries * @sizeOf(elf.Elf64_Dyn);
     }
@@ -216,7 +216,7 @@ pub const DynamicSection = struct {
         }
 
         // DEBUG
-        if (!elf_file.base.isDynLib()) try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_DEBUG, .d_val = 0 });
+        if (!elf_file.isEffectivelyDynLib()) try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_DEBUG, .d_val = 0 });
 
         // NULL
         try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NULL, .d_val = 0 });
@@ -256,7 +256,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.isDynLib() or (elf_file.base.isExe() and comp.config.pie)) {
+        if (elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) {
             zig_got.flags.needs_rela = true;
         }
         if (symbol.extra(elf_file)) |extra| {
@@ -495,7 +495,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.isDynLib() or (elf_file.base.isExe() and comp.config.pie)) and !symbol.isAbs(elf_file)))
+            ((elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) and !symbol.isAbs(elf_file)))
         {
             got.flags.needs_rela = true;
         }
@@ -528,7 +528,7 @@ pub const GotSection = struct {
         entry.symbol_index = sym_index;
         const symbol = elf_file.symbol(sym_index);
         symbol.flags.has_tlsgd = true;
-        if (symbol.flags.import or elf_file.base.isDynLib()) got.flags.needs_rela = true;
+        if (symbol.flags.import or elf_file.isEffectivelyDynLib()) got.flags.needs_rela = true;
         if (symbol.extra(elf_file)) |extra| {
             var new_extra = extra;
             new_extra.tlsgd = index;
@@ -545,7 +545,7 @@ pub const GotSection = struct {
         entry.symbol_index = sym_index;
         const symbol = elf_file.symbol(sym_index);
         symbol.flags.has_gottp = true;
-        if (symbol.flags.import or elf_file.base.isDynLib()) got.flags.needs_rela = true;
+        if (symbol.flags.import or elf_file.isEffectivelyDynLib()) got.flags.needs_rela = true;
         if (symbol.extra(elf_file)) |extra| {
             var new_extra = extra;
             new_extra.gottp = index;
@@ -580,7 +580,7 @@ pub const GotSection = struct {
 
     pub fn write(got: GotSection, elf_file: *Elf, writer: anytype) !void {
         const comp = elf_file.base.comp;
-        const is_dyn_lib = elf_file.base.isDynLib();
+        const is_dyn_lib = elf_file.isEffectivelyDynLib();
         const apply_relocs = true; // TODO add user option for this
 
         for (got.entries.items) |entry| {
@@ -595,7 +595,7 @@ 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.isDynLib() or (elf_file.base.isExe() and comp.config.pie)) and
+                        if ((elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) and
                             !symbol.?.isAbs(elf_file))
                         {
                             break :blk if (apply_relocs) value else 0;
@@ -653,7 +653,7 @@ pub const GotSection = struct {
     pub fn addRela(got: GotSection, elf_file: *Elf) !void {
         const comp = elf_file.base.comp;
         const gpa = comp.gpa;
-        const is_dyn_lib = elf_file.base.isDynLib();
+        const is_dyn_lib = elf_file.isEffectivelyDynLib();
         const cpu_arch = elf_file.getTarget().cpu.arch;
         try elf_file.rela_dyn.ensureUnusedCapacity(gpa, got.numRela(elf_file));
 
@@ -683,7 +683,7 @@ pub const GotSection = struct {
                         });
                         continue;
                     }
-                    if ((elf_file.base.isDynLib() or (elf_file.base.isExe() and comp.config.pie)) and
+                    if ((elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) and
                         !symbol.?.isAbs(elf_file))
                     {
                         elf_file.addRelaDynAssumeCapacity(.{
@@ -758,7 +758,7 @@ pub const GotSection = struct {
 
     pub fn numRela(got: GotSection, elf_file: *Elf) usize {
         const comp = elf_file.base.comp;
-        const is_dyn_lib = elf_file.base.isDynLib();
+        const is_dyn_lib = elf_file.isEffectivelyDynLib();
         var num: usize = 0;
         for (got.entries.items) |entry| {
             const symbol = switch (entry.tag) {
@@ -767,7 +767,7 @@ pub const GotSection = struct {
             };
             switch (entry.tag) {
                 .got => if (symbol.?.flags.import or symbol.?.isIFunc(elf_file) or
-                    ((elf_file.base.isDynLib() or (elf_file.base.isExe() and comp.config.pie)) and
+                    ((elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) and
                     !symbol.?.isAbs(elf_file)))
                 {
                     num += 1;
src/link/Elf/ZigObject.zig
@@ -367,7 +367,7 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void {
         }
 
         const is_import = blk: {
-            if (!elf_file.base.isDynLib()) break :blk false;
+            if (!elf_file.isEffectivelyDynLib()) break :blk false;
             const vis = @as(elf.STV, @enumFromInt(esym.st_other));
             if (vis == .HIDDEN) break :blk false;
             break :blk true;
src/link/Elf.zig
@@ -1461,7 +1461,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
             }
         }
 
-        if (self.base.isDynLib()) {
+        if (self.isEffectivelyDynLib()) {
             if (self.soname) |name| {
                 try argv.append("-soname");
                 try argv.append(name);
@@ -1517,7 +1517,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
 
         if (self.base.isStatic()) {
             try argv.append("-static");
-        } else if (self.base.isDynLib() or (target.os.tag == .haiku and self.base.isExe())) {
+        } else if (self.isEffectivelyDynLib()) {
             try argv.append("-shared");
         }
 
@@ -1997,7 +1997,7 @@ fn markImportsExports(self: *Elf) void {
                 }
                 if (file_ptr.index() == file_index) {
                     global.flags.@"export" = true;
-                    if (elf_file.base.isDynLib() and vis != .PROTECTED) {
+                    if (elf_file.isEffectivelyDynLib() and vis != .PROTECTED) {
                         global.flags.import = true;
                     }
                 }
@@ -2005,7 +2005,7 @@ fn markImportsExports(self: *Elf) void {
         }
     }.mark;
 
-    if (!self.base.isDynLib()) {
+    if (!self.isEffectivelyDynLib()) {
         for (self.shared_objects.items) |index| {
             for (self.file(index).?.globals()) |global_index| {
                 const global = self.symbol(global_index);
@@ -3117,7 +3117,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
         }
     }
 
-    if (self.getTarget().cpu.arch == .riscv64 and self.base.isDynLib()) {
+    if (self.getTarget().cpu.arch == .riscv64 and self.isEffectivelyDynLib()) {
         self.global_pointer_index = try linker_defined.addGlobal("__global_pointer$", self);
     }
 
@@ -3423,7 +3423,7 @@ fn initSyntheticSections(self: *Elf) !void {
         });
     }
 
-    if (self.base.isDynLib() or self.shared_objects.items.len > 0 or comp.config.pie) {
+    if (self.isEffectivelyDynLib() or self.shared_objects.items.len > 0 or comp.config.pie) {
         self.dynstrtab_section_index = try self.addSection(.{
             .name = ".dynstr",
             .flags = elf.SHF_ALLOC,
@@ -3660,7 +3660,7 @@ fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void {
         try self.dynamic.addNeeded(shared_object, self);
     }
 
-    if (self.base.isDynLib()) {
+    if (self.isEffectivelyDynLib()) {
         if (self.soname) |soname| {
             try self.dynamic.setSoname(soname, self);
         }
@@ -5249,6 +5249,16 @@ const CsuObjects = struct {
     }
 };
 
+/// If a target compiles other output modes as dynamic libraries,
+/// this function returns true for those too.
+pub fn isEffectivelyDynLib(self: Elf) bool {
+    if (self.base.isDynLib()) return true;
+    return switch (self.getTarget().os.tag) {
+        .haiku => self.base.isExe(),
+        else => false,
+    };
+}
+
 pub fn isZigSection(self: Elf, shndx: u32) bool {
     inline for (&[_]?u32{
         self.zig_text_section_index,