Commit 42e0850d78

Jakub Konka <kubkon@jakubkonka.com>
2023-08-27 07:31:29
macho: save indexes to all sections of interest
1 parent 84853c5
src/link/MachO/Atom.zig
@@ -244,13 +244,16 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
                             .{},
                         );
                     } else if (mem.eql(u8, sectname, "__data")) {
-                        break :blk zld.getSectionByName("__DATA", "__data") orelse try MachO.initSection(
-                            gpa,
-                            zld,
-                            "__DATA",
-                            "__data",
-                            .{},
-                        );
+                        if (zld.data_section_index == null) {
+                            zld.data_section_index = try MachO.initSection(
+                                gpa,
+                                zld,
+                                "__DATA",
+                                "__data",
+                                .{},
+                            );
+                        }
+                        break :blk zld.data_section_index.?;
                     }
                 }
                 break :blk zld.getSectionByName(segname, sectname) orelse try MachO.initSection(
@@ -264,6 +267,35 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
             else => break :blk null,
         }
     };
+
+    // TODO we can do this directly in the selection logic above.
+    // Or is it not worth it?
+    if (zld.data_const_section_index == null) {
+        if (zld.getSectionByName("__DATA_CONST", "__const")) |index| {
+            zld.data_const_section_index = index;
+        }
+    }
+    if (zld.thread_vars_section_index == null) {
+        if (zld.getSectionByName("__DATA", "__thread_vars")) |index| {
+            zld.thread_vars_section_index = index;
+        }
+    }
+    if (zld.thread_data_section_index == null) {
+        if (zld.getSectionByName("__DATA", "__thread_data")) |index| {
+            zld.thread_data_section_index = index;
+        }
+    }
+    if (zld.thread_bss_section_index == null) {
+        if (zld.getSectionByName("__DATA", "__thread_bss")) |index| {
+            zld.thread_bss_section_index = index;
+        }
+    }
+    if (zld.bss_section_index == null) {
+        if (zld.getSectionByName("__DATA", "__bss")) |index| {
+            zld.bss_section_index = index;
+        }
+    }
+
     return res;
 }
 
@@ -662,9 +694,9 @@ pub fn getRelocTargetAddress(zld: *Zld, target: SymbolWithLoc, is_tlv: bool) !u6
         // * wrt to __thread_data if defined, then
         // * wrt to __thread_bss
         const sect_id: u16 = sect_id: {
-            if (zld.getSectionByName("__DATA", "__thread_data")) |i| {
+            if (zld.thread_data_section_index) |i| {
                 break :sect_id i;
-            } else if (zld.getSectionByName("__DATA", "__thread_bss")) |i| {
+            } else if (zld.thread_bss_section_index) |i| {
                 break :sect_id i;
             } else {
                 log.err("threadlocal variables present but no initializer sections found", .{});
src/link/MachO/eh_frame.zig
@@ -46,7 +46,7 @@ pub fn scanRelocs(zld: *Zld) !void {
 }
 
 pub fn calcSectionSize(zld: *Zld, unwind_info: *const UnwindInfo) !void {
-    const sect_id = zld.getSectionByName("__TEXT", "__eh_frame") orelse return;
+    const sect_id = zld.eh_frame_section_index orelse return;
     const sect = &zld.sections.items(.header)[sect_id];
     sect.@"align" = 3;
     sect.size = 0;
@@ -97,7 +97,7 @@ pub fn calcSectionSize(zld: *Zld, unwind_info: *const UnwindInfo) !void {
 }
 
 pub fn write(zld: *Zld, unwind_info: *UnwindInfo) !void {
-    const sect_id = zld.getSectionByName("__TEXT", "__eh_frame") orelse return;
+    const sect_id = zld.eh_frame_section_index orelse return;
     const sect = zld.sections.items(.header)[sect_id];
     const seg_id = zld.sections.items(.segment_index)[sect_id];
     const seg = zld.segments.items[seg_id];
src/link/MachO/Object.zig
@@ -687,8 +687,8 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {
 
     const gpa = zld.gpa;
 
-    if (zld.getSectionByName("__TEXT", "__eh_frame") == null) {
-        _ = try MachO.initSection(gpa, zld, "__TEXT", "__eh_frame", .{});
+    if (zld.eh_frame_section_index == null) {
+        zld.eh_frame_section_index = try MachO.initSection(gpa, zld, "__TEXT", "__eh_frame", .{});
     }
 
     const cpu_arch = zld.options.target.cpu.arch;
@@ -788,8 +788,14 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {
         // approach. However, we will only synthesise DWARF records and nothing more. For this reason,
         // we still create the output `__TEXT,__unwind_info` section.
         if (self.hasEhFrameRecords()) {
-            if (zld.getSectionByName("__TEXT", "__unwind_info") == null) {
-                _ = try MachO.initSection(gpa, zld, "__TEXT", "__unwind_info", .{});
+            if (zld.unwind_info_section_index == null) {
+                zld.unwind_info_section_index = try MachO.initSection(
+                    gpa,
+                    zld,
+                    "__TEXT",
+                    "__unwind_info",
+                    .{},
+                );
             }
         }
         return;
@@ -797,8 +803,8 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {
 
     log.debug("parsing unwind info in {s}", .{self.name});
 
-    if (zld.getSectionByName("__TEXT", "__unwind_info") == null) {
-        _ = try MachO.initSection(gpa, zld, "__TEXT", "__unwind_info", .{});
+    if (zld.unwind_info_section_index == null) {
+        zld.unwind_info_section_index = try MachO.initSection(gpa, zld, "__TEXT", "__unwind_info", .{});
     }
 
     const unwind_records = self.getUnwindRecords();
src/link/MachO/UnwindInfo.zig
@@ -204,7 +204,7 @@ pub fn deinit(info: *UnwindInfo) void {
 }
 
 pub fn scanRelocs(zld: *Zld) !void {
-    if (zld.getSectionByName("__TEXT", "__unwind_info") == null) return;
+    if (zld.unwind_info_section_index == null) return;
 
     const cpu_arch = zld.options.target.cpu.arch;
     for (zld.objects.items, 0..) |*object, object_id| {
@@ -233,7 +233,7 @@ pub fn scanRelocs(zld: *Zld) !void {
 }
 
 pub fn collect(info: *UnwindInfo, zld: *Zld) !void {
-    if (zld.getSectionByName("__TEXT", "__unwind_info") == null) return;
+    if (zld.unwind_info_section_index == null) return;
 
     const cpu_arch = zld.options.target.cpu.arch;
 
@@ -551,7 +551,7 @@ fn collectPersonalityFromDwarf(
 }
 
 pub fn calcSectionSize(info: UnwindInfo, zld: *Zld) !void {
-    const sect_id = zld.getSectionByName("__TEXT", "__unwind_info") orelse return;
+    const sect_id = zld.unwind_info_section_index orelse return;
     const sect = &zld.sections.items(.header)[sect_id];
     sect.@"align" = 2;
     sect.size = info.calcRequiredSize();
@@ -570,7 +570,7 @@ fn calcRequiredSize(info: UnwindInfo) usize {
 }
 
 pub fn write(info: *UnwindInfo, zld: *Zld) !void {
-    const sect_id = zld.getSectionByName("__TEXT", "__unwind_info") orelse return;
+    const sect_id = zld.unwind_info_section_index orelse return;
     const sect = &zld.sections.items(.header)[sect_id];
     const seg_id = zld.sections.items(.segment_index)[sect_id];
     const seg = zld.segments.items[seg_id];
src/link/MachO/zld.zig
@@ -74,6 +74,14 @@ pub const Zld = struct {
     linkedit_segment_cmd_index: ?u8 = null,
 
     text_section_index: ?u8 = null,
+    data_const_section_index: ?u8 = null,
+    data_section_index: ?u8 = null,
+    bss_section_index: ?u8 = null,
+    thread_vars_section_index: ?u8 = null,
+    thread_data_section_index: ?u8 = null,
+    thread_bss_section_index: ?u8 = null,
+    eh_frame_section_index: ?u8 = null,
+    unwind_info_section_index: ?u8 = null,
     got_section_index: ?u8 = null,
     tlv_ptr_section_index: ?u8 = null,
     stubs_section_index: ?u8 = null,
@@ -142,9 +150,10 @@ pub const Zld = struct {
         const sym = self.getSymbolPtr(.{ .sym_index = sym_index });
         sym.n_type = macho.N_SECT;
 
-        const sect_id = self.getSectionByName("__DATA", "__data") orelse
-            try MachO.initSection(self.gpa, self, "__DATA", "__data", .{});
-        sym.n_sect = sect_id + 1;
+        if (self.data_section_index == null) {
+            self.data_section_index = try MachO.initSection(self.gpa, self, "__DATA", "__data", .{});
+        }
+        sym.n_sect = self.data_section_index.? + 1;
         self.dyld_private_atom_index = atom_index;
 
         self.addAtomToSection(atom_index);
@@ -166,13 +175,17 @@ pub const Zld = struct {
             // text blocks for each tentative definition.
             const size = sym.n_value;
             const alignment = (sym.n_desc >> 8) & 0x0f;
-            const sect_id = self.getSectionByName("__DATA", "__bss") orelse
-                try MachO.initSection(gpa, self, "__DATA", "__bss", .{ .flags = macho.S_ZEROFILL });
+
+            if (self.bss_section_index == null) {
+                self.bss_section_index = try MachO.initSection(gpa, self, "__DATA", "__bss", .{
+                    .flags = macho.S_ZEROFILL,
+                });
+            }
 
             sym.* = .{
                 .n_strx = sym.n_strx,
                 .n_type = macho.N_SECT | macho.N_EXT,
-                .n_sect = sect_id + 1,
+                .n_sect = self.bss_section_index.? + 1,
                 .n_desc = 0,
                 .n_value = 0,
             };
@@ -768,7 +781,7 @@ pub const Zld = struct {
         const atom_index = self.dyld_private_atom_index orelse return;
         const atom = self.getAtom(atom_index);
         const sym = self.getSymbol(atom.getSymbolWithLoc());
-        const sect_id = self.getSectionByName("__DATA", "__data").?;
+        const sect_id = self.data_section_index.?;
         const header = self.sections.items(.header)[sect_id];
         const offset = sym.n_value - header.addr + header.offset;
         log.debug("writing __dyld_private at offset 0x{x}", .{offset});
@@ -918,6 +931,14 @@ pub const Zld = struct {
                 });
                 for (&[_]*?u8{
                     &self.text_section_index,
+                    &self.data_const_section_index,
+                    &self.data_section_index,
+                    &self.bss_section_index,
+                    &self.thread_vars_section_index,
+                    &self.thread_data_section_index,
+                    &self.thread_bss_section_index,
+                    &self.eh_frame_section_index,
+                    &self.unwind_info_section_index,
                     &self.got_section_index,
                     &self.tlv_ptr_section_index,
                     &self.stubs_section_index,
@@ -951,6 +972,14 @@ pub const Zld = struct {
 
         for (&[_]*?u8{
             &self.text_section_index,
+            &self.data_const_section_index,
+            &self.data_section_index,
+            &self.bss_section_index,
+            &self.thread_vars_section_index,
+            &self.thread_data_section_index,
+            &self.thread_bss_section_index,
+            &self.eh_frame_section_index,
+            &self.unwind_info_section_index,
             &self.got_section_index,
             &self.tlv_ptr_section_index,
             &self.stubs_section_index,
@@ -1964,7 +1993,7 @@ pub const Zld = struct {
             else => unreachable,
         }
 
-        if (self.getSectionByName("__DATA", "__thread_vars")) |sect_id| {
+        if (self.thread_vars_section_index) |sect_id| {
             header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;
             if (self.sections.items(.header)[sect_id].size > 0) {
                 header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;
src/link/MachO.zig
@@ -33,14 +33,19 @@ data_segment_cmd_index: ?u8 = null,
 linkedit_segment_cmd_index: ?u8 = null,
 
 text_section_index: ?u8 = null,
-stubs_section_index: ?u8 = null,
-stub_helper_section_index: ?u8 = null,
-got_section_index: ?u8 = null,
 data_const_section_index: ?u8 = null,
-la_symbol_ptr_section_index: ?u8 = null,
 data_section_index: ?u8 = null,
+bss_section_index: ?u8 = null,
 thread_vars_section_index: ?u8 = null,
 thread_data_section_index: ?u8 = null,
+thread_bss_section_index: ?u8 = null,
+eh_frame_section_index: ?u8 = null,
+unwind_info_section_index: ?u8 = null,
+stubs_section_index: ?u8 = null,
+stub_helper_section_index: ?u8 = null,
+got_section_index: ?u8 = null,
+la_symbol_ptr_section_index: ?u8 = null,
+tlv_ptr_section_index: ?u8 = null,
 
 locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
 globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{},