Commit d32af9ea2a

Jakub Konka <kubkon@jakubkonka.com>
2024-08-27 15:22:33
elf: move initOutputSection into Elf from Object
1 parent b44dd59
Changed files (2)
src
src/link/Elf/Object.zig
@@ -311,58 +311,6 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
     };
 }
 
-fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u32 {
-    const name = blk: {
-        const name = self.getString(shdr.sh_name);
-        if (elf_file.base.isRelocatable()) break :blk name;
-        if (shdr.sh_flags & elf.SHF_MERGE != 0) break :blk name;
-        const sh_name_prefixes: []const [:0]const u8 = &.{
-            ".text",       ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro",       ".bss",
-            ".init_array", ".fini_array",  ".tbss", ".tdata",  ".gcc_except_table", ".ctors",
-            ".dtors",      ".gnu.warning",
-        };
-        inline for (sh_name_prefixes) |prefix| {
-            if (std.mem.eql(u8, name, prefix) or std.mem.startsWith(u8, name, prefix ++ ".")) {
-                break :blk prefix;
-            }
-        }
-        break :blk name;
-    };
-    const @"type" = tt: {
-        if (elf_file.getTarget().cpu.arch == .x86_64 and
-            shdr.sh_type == elf.SHT_X86_64_UNWIND) break :tt elf.SHT_PROGBITS;
-
-        const @"type" = switch (shdr.sh_type) {
-            elf.SHT_NULL => unreachable,
-            elf.SHT_PROGBITS => blk: {
-                if (std.mem.eql(u8, name, ".init_array") or std.mem.startsWith(u8, name, ".init_array."))
-                    break :blk elf.SHT_INIT_ARRAY;
-                if (std.mem.eql(u8, name, ".fini_array") or std.mem.startsWith(u8, name, ".fini_array."))
-                    break :blk elf.SHT_FINI_ARRAY;
-                break :blk shdr.sh_type;
-            },
-            else => shdr.sh_type,
-        };
-        break :tt @"type";
-    };
-    const flags = blk: {
-        var flags = shdr.sh_flags;
-        if (!elf_file.base.isRelocatable()) {
-            flags &= ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP | elf.SHF_GNU_RETAIN);
-        }
-        break :blk switch (@"type") {
-            elf.SHT_INIT_ARRAY, elf.SHT_FINI_ARRAY => flags | elf.SHF_WRITE,
-            else => flags,
-        };
-    };
-    const out_shndx = elf_file.sectionByName(name) orelse try elf_file.addSection(.{
-        .type = @"type",
-        .flags = flags,
-        .name = try elf_file.insertShString(name),
-    });
-    return out_shndx;
-}
-
 fn skipShdr(self: *Object, index: u32, elf_file: *Elf) bool {
     const comp = elf_file.base.comp;
     const shdr = self.shdrs.items[index];
@@ -985,7 +933,11 @@ pub fn initOutputSections(self: *Object, elf_file: *Elf) !void {
         const atom_ptr = self.atom(atom_index) orelse continue;
         if (!atom_ptr.alive) continue;
         const shdr = atom_ptr.inputShdr(elf_file);
-        _ = try self.initOutputSection(elf_file, shdr);
+        _ = try elf_file.initOutputSection(.{
+            .name = self.getString(shdr.sh_name),
+            .flags = shdr.sh_flags,
+            .type = shdr.sh_type,
+        });
     }
 }
 
@@ -994,7 +946,11 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
         const atom_ptr = self.atom(atom_index) orelse continue;
         if (!atom_ptr.alive) continue;
         const shdr = atom_ptr.inputShdr(elf_file);
-        atom_ptr.output_section_index = self.initOutputSection(elf_file, shdr) catch unreachable;
+        atom_ptr.output_section_index = elf_file.initOutputSection(.{
+            .name = self.getString(shdr.sh_name),
+            .flags = shdr.sh_flags,
+            .type = shdr.sh_type,
+        }) catch unreachable;
 
         const comp = elf_file.base.comp;
         const gpa = comp.gpa;
@@ -1009,7 +965,11 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void {
         if (!atom_ptr.alive) continue;
         const shndx = atom_ptr.relocsShndx() orelse continue;
         const shdr = self.shdrs.items[shndx];
-        const out_shndx = try self.initOutputSection(elf_file, shdr);
+        const out_shndx = try elf_file.initOutputSection(.{
+            .name = self.getString(shdr.sh_name),
+            .flags = shdr.sh_flags,
+            .type = shdr.sh_type,
+        });
         const out_shdr = &elf_file.sections.items(.shdr)[out_shndx];
         out_shdr.sh_type = elf.SHT_RELA;
         out_shdr.sh_addralign = @alignOf(elf.Elf64_Rela);
@@ -1025,7 +985,11 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {
         const shndx = blk: {
             const shndx = atom_ptr.relocsShndx() orelse continue;
             const shdr = self.shdrs.items[shndx];
-            break :blk self.initOutputSection(elf_file, shdr) catch unreachable;
+            break :blk elf_file.initOutputSection(.{
+                .name = self.getString(shdr.sh_name),
+                .flags = shdr.sh_flags,
+                .type = shdr.sh_type,
+            }) catch unreachable;
         };
         const slice = elf_file.sections.slice();
         const shdr = &slice.items(.shdr)[shndx];
src/link/Elf.zig
@@ -1827,6 +1827,59 @@ fn scanRelocs(self: *Elf) !void {
     }
 }
 
+pub fn initOutputSection(self: *Elf, args: struct {
+    name: [:0]const u8,
+    flags: u64,
+    type: u32,
+}) error{OutOfMemory}!u32 {
+    const name = blk: {
+        if (self.base.isRelocatable()) break :blk args.name;
+        if (args.flags & elf.SHF_MERGE != 0) break :blk args.name;
+        const name_prefixes: []const [:0]const u8 = &.{
+            ".text",       ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro",       ".bss",
+            ".init_array", ".fini_array",  ".tbss", ".tdata",  ".gcc_except_table", ".ctors",
+            ".dtors",      ".gnu.warning",
+        };
+        inline for (name_prefixes) |prefix| {
+            if (std.mem.eql(u8, args.name, prefix) or std.mem.startsWith(u8, args.name, prefix ++ ".")) {
+                break :blk prefix;
+            }
+        }
+        break :blk args.name;
+    };
+    const @"type" = tt: {
+        if (self.getTarget().cpu.arch == .x86_64 and
+            args.type == elf.SHT_X86_64_UNWIND) break :tt elf.SHT_PROGBITS;
+        switch (args.type) {
+            elf.SHT_NULL => unreachable,
+            elf.SHT_PROGBITS => {
+                if (std.mem.eql(u8, args.name, ".init_array") or std.mem.startsWith(u8, args.name, ".init_array."))
+                    break :tt elf.SHT_INIT_ARRAY;
+                if (std.mem.eql(u8, args.name, ".fini_array") or std.mem.startsWith(u8, args.name, ".fini_array."))
+                    break :tt elf.SHT_FINI_ARRAY;
+                break :tt args.type;
+            },
+            else => break :tt args.type,
+        }
+    };
+    const flags = blk: {
+        var flags = args.flags;
+        if (!self.base.isRelocatable()) {
+            flags &= ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP | elf.SHF_GNU_RETAIN);
+        }
+        break :blk switch (@"type") {
+            elf.SHT_INIT_ARRAY, elf.SHT_FINI_ARRAY => flags | elf.SHF_WRITE,
+            else => flags,
+        };
+    };
+    const out_shndx = self.sectionByName(name) orelse try self.addSection(.{
+        .type = @"type",
+        .flags = flags,
+        .name = try self.insertShString(name),
+    });
+    return out_shndx;
+}
+
 fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {
     dev.check(.lld_linker);