Commit e1e0ccb0c7

Jakub Konka <kubkon@jakubkonka.com>
2023-08-21 22:17:34
macho: unify Section concept across drivers
1 parent 05c9d6c
src/link/MachO/dead_strip.zig
@@ -466,8 +466,8 @@ fn prune(zld: *Zld, alive: AtomTable) void {
                     section.last_atom_index = prev_index;
                 } else {
                     assert(section.header.size == 0);
-                    section.first_atom_index = 0;
-                    section.last_atom_index = 0;
+                    section.first_atom_index = null;
+                    section.last_atom_index = null;
                 }
             }
 
src/link/MachO/Object.zig
@@ -55,7 +55,7 @@ source_section_index_lookup: []Entry = undefined,
 /// Can be undefined as set together with in_symtab.
 strtab_lookup: []u32 = undefined,
 /// Can be undefined as set together with in_symtab.
-atom_by_index_table: []AtomIndex = undefined,
+atom_by_index_table: []?AtomIndex = undefined,
 /// Can be undefined as set together with in_symtab.
 globals_lookup: []i64 = undefined,
 /// Can be undefined as set together with in_symtab.
@@ -156,7 +156,7 @@ pub fn parse(self: *Object, allocator: Allocator) !void {
     self.reverse_symtab_lookup = try allocator.alloc(u32, self.in_symtab.?.len);
     self.strtab_lookup = try allocator.alloc(u32, self.in_symtab.?.len);
     self.globals_lookup = try allocator.alloc(i64, self.in_symtab.?.len);
-    self.atom_by_index_table = try allocator.alloc(AtomIndex, self.in_symtab.?.len + nsects);
+    self.atom_by_index_table = try allocator.alloc(?AtomIndex, self.in_symtab.?.len + nsects);
     self.relocs_lookup = try allocator.alloc(Entry, self.in_symtab.?.len + nsects);
     // This is wasteful but we need to be able to lookup source symbol address after stripping and
     // allocating of sections.
@@ -174,7 +174,7 @@ pub fn parse(self: *Object, allocator: Allocator) !void {
     }
 
     @memset(self.globals_lookup, -1);
-    @memset(self.atom_by_index_table, 0);
+    @memset(self.atom_by_index_table, null);
     @memset(self.source_section_index_lookup, .{});
     @memset(self.relocs_lookup, .{});
 
@@ -1060,9 +1060,7 @@ pub fn getGlobal(self: Object, sym_index: u32) ?u32 {
 }
 
 pub fn getAtomIndexForSymbol(self: Object, sym_index: u32) ?AtomIndex {
-    const atom_index = self.atom_by_index_table[sym_index];
-    if (atom_index == 0) return null;
-    return atom_index;
+    return self.atom_by_index_table[sym_index];
 }
 
 pub fn hasUnwindRecords(self: Object) bool {
src/link/MachO/thunks.zig
@@ -75,7 +75,7 @@ pub fn createThunks(zld: *Zld, sect_id: u8) !void {
     if (header.size == 0) return;
 
     const gpa = zld.gpa;
-    const first_atom_index = zld.sections.items(.first_atom_index)[sect_id];
+    const first_atom_index = zld.sections.items(.first_atom_index)[sect_id].?;
 
     header.size = 0;
     header.@"align" = 0;
src/link/MachO/zld.zig
@@ -31,6 +31,7 @@ const MachO = @import("../MachO.zig");
 const Md5 = std.crypto.hash.Md5;
 const LibStub = @import("../tapi.zig").LibStub;
 const Object = @import("Object.zig");
+const Section = MachO.Section;
 const StringTable = @import("../strtab.zig").StringTable;
 const SymbolWithLoc = MachO.SymbolWithLoc;
 const SymbolResolver = MachO.SymbolResolver;
@@ -231,7 +232,7 @@ pub const Zld = struct {
         const sym = self.getSymbol(atom.getSymbolWithLoc());
         var section = self.sections.get(sym.n_sect - 1);
         if (section.header.size > 0) {
-            const last_atom = self.getAtomPtr(section.last_atom_index);
+            const last_atom = self.getAtomPtr(section.last_atom_index.?);
             last_atom.next_index = atom_index;
             atom.prev_index = section.last_atom_index;
         } else {
@@ -445,7 +446,7 @@ pub const Zld = struct {
     fn writeLazyPointer(self: *Zld, stub_helper_index: u32, writer: anytype) !void {
         const target_addr = blk: {
             const sect_id = self.getSectionByName("__TEXT", "__stub_helper").?;
-            var atom_index = self.sections.items(.first_atom_index)[sect_id];
+            var atom_index = self.sections.items(.first_atom_index)[sect_id].?;
             var count: u32 = 0;
             while (count < stub_helper_index + 1) : (count += 1) {
                 const atom = self.getAtom(atom_index);
@@ -497,7 +498,7 @@ pub const Zld = struct {
         const target_addr = blk: {
             // TODO: cache this at stub atom creation; they always go in pairs anyhow
             const la_sect_id = self.getSectionByName("__DATA", "__la_symbol_ptr").?;
-            var la_atom_index = self.sections.items(.first_atom_index)[la_sect_id];
+            var la_atom_index = self.sections.items(.first_atom_index)[la_sect_id].?;
             var count: u32 = 0;
             while (count < stub_index) : (count += 1) {
                 const la_atom = self.getAtom(la_atom_index);
@@ -1012,11 +1013,10 @@ pub const Zld = struct {
 
         for (slice.items(.first_atom_index), 0..) |first_atom_index, sect_id| {
             const header = slice.items(.header)[sect_id];
-            var atom_index = first_atom_index;
-
-            if (atom_index == 0) continue;
             if (header.isZerofill()) continue;
 
+            var atom_index = first_atom_index orelse continue;
+
             var buffer = std.ArrayList(u8).init(gpa);
             defer buffer.deinit();
             try buffer.ensureTotalCapacity(math.cast(usize, header.size) orelse return error.Overflow);
@@ -1129,7 +1129,7 @@ pub const Zld = struct {
             while (i < slice.len) : (i += 1) {
                 const section = self.sections.get(i);
                 if (section.header.size == 0) {
-                    log.debug("pruning section {s},{s} {d}", .{
+                    log.debug("pruning section {s},{s} {?d}", .{
                         section.header.segName(),
                         section.header.sectName(),
                         section.first_atom_index,
@@ -1156,8 +1156,7 @@ pub const Zld = struct {
                 if (header.isCode() and !(header.type() == macho.S_SYMBOL_STUBS) and !mem.eql(u8, header.sectName(), "__stub_helper")) continue;
             }
 
-            var atom_index = slice.items(.first_atom_index)[sect_id];
-            if (atom_index == 0) continue;
+            var atom_index = slice.items(.first_atom_index)[sect_id] orelse continue;
 
             header.size = 0;
             header.@"align" = 0;
@@ -1195,8 +1194,7 @@ pub const Zld = struct {
         // We need to do this since our unwind info synthesiser relies on
         // traversing the symbols when synthesising unwind info and DWARF CFI records.
         for (slice.items(.first_atom_index)) |first_atom_index| {
-            if (first_atom_index == 0) continue;
-            var atom_index = first_atom_index;
+            var atom_index = first_atom_index orelse continue;
 
             while (true) {
                 const atom = self.getAtom(atom_index);
@@ -1278,8 +1276,9 @@ pub const Zld = struct {
                 @as(u32, @intCast(segment.fileoff + start_aligned));
             header.addr = segment.vmaddr + start_aligned;
 
-            var atom_index = slice.items(.first_atom_index)[indexes.start + sect_id];
-            if (atom_index > 0) {
+            if (slice.items(.first_atom_index)[indexes.start + sect_id]) |first_atom_index| {
+                var atom_index = first_atom_index;
+
                 log.debug("allocating local symbols in sect({d}, '{s},{s}')", .{
                     n_sect,
                     header.segName(),
@@ -1362,8 +1361,6 @@ pub const Zld = struct {
                 .reserved1 = opts.reserved1,
                 .reserved2 = opts.reserved2,
             },
-            .first_atom_index = 0,
-            .last_atom_index = 0,
         });
         return index;
     }
@@ -1491,7 +1488,7 @@ pub const Zld = struct {
         if (self.getSectionByName("__DATA", "__la_symbol_ptr")) |sect_id| {
             const segment_index = slice.items(.segment_index)[sect_id];
             const seg = self.getSegment(sect_id);
-            var atom_index = slice.items(.first_atom_index)[sect_id];
+            var atom_index = slice.items(.first_atom_index)[sect_id].?;
 
             try rebase.entries.ensureUnusedCapacity(self.gpa, self.stubs.items.len);
 
@@ -1531,8 +1528,7 @@ pub const Zld = struct {
             log.debug("{s},{s}", .{ header.segName(), header.sectName() });
 
             const cpu_arch = self.options.target.cpu.arch;
-            var atom_index = slice.items(.first_atom_index)[sect_id];
-            if (atom_index == 0) continue;
+            var atom_index = slice.items(.first_atom_index)[sect_id] orelse continue;
 
             while (true) {
                 const atom = self.getAtom(atom_index);
@@ -1668,8 +1664,7 @@ pub const Zld = struct {
             if (segment.maxprot & macho.PROT.WRITE == 0) continue;
 
             const cpu_arch = self.options.target.cpu.arch;
-            var atom_index = slice.items(.first_atom_index)[sect_id];
-            if (atom_index == 0) continue;
+            var atom_index = slice.items(.first_atom_index)[sect_id] orelse continue;
 
             log.debug("{s},{s}", .{ header.segName(), header.sectName() });
 
@@ -1757,7 +1752,7 @@ pub const Zld = struct {
         const slice = self.sections.slice();
         const segment_index = slice.items(.segment_index)[sect_id];
         const seg = self.getSegment(sect_id);
-        var atom_index = slice.items(.first_atom_index)[sect_id];
+        var atom_index = slice.items(.first_atom_index)[sect_id].?;
 
         // TODO: we actually don't need to store lazy pointer atoms as they are synthetically generated by the linker
         try lazy_bind.entries.ensureUnusedCapacity(self.gpa, self.stubs.items.len);
@@ -1920,7 +1915,7 @@ pub const Zld = struct {
         const section = self.sections.get(stub_helper_section_index);
         const stub_offset = stub_helpers.calcStubOffsetInStubHelper(self.options.target.cpu.arch);
         const header = section.header;
-        var atom_index = section.first_atom_index;
+        var atom_index = section.first_atom_index.?;
         atom_index = self.getAtom(atom_index).next_index.?; // skip preamble
 
         var index: usize = 0;
@@ -2923,9 +2918,7 @@ pub const Zld = struct {
         log.debug("atoms:", .{});
         const slice = self.sections.slice();
         for (slice.items(.first_atom_index), 0..) |first_atom_index, sect_id| {
-            var atom_index = first_atom_index;
-            if (atom_index == 0) continue;
-
+            var atom_index = first_atom_index orelse continue;
             const header = slice.items(.header)[sect_id];
 
             log.debug("{s},{s}", .{ header.segName(), header.sectName() });
@@ -2990,13 +2983,6 @@ pub const Zld = struct {
 
 pub const N_DEAD: u16 = @as(u16, @bitCast(@as(i16, -1)));
 
-const Section = struct {
-    header: macho.section_64,
-    segment_index: u8,
-    first_atom_index: AtomIndex,
-    last_atom_index: AtomIndex,
-};
-
 pub const AtomIndex = u32;
 
 const IndirectPointer = struct {
@@ -3183,7 +3169,6 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
         };
         defer zld.deinit();
 
-        try zld.atoms.append(gpa, Atom.empty); // AtomIndex at 0 is reserved as null atom
         try zld.strtab.buffer.append(gpa, 0);
 
         // Positional arguments to the linker such as object files and static archives.
src/link/MachO.zig
@@ -69,12 +69,10 @@ pub const Mode = enum {
     zld,
 };
 
-const Section = struct {
+pub const Section = struct {
     header: macho.section_64,
     segment_index: u8,
-
-    // TODO is null here necessary, or can we do away with tracking via section
-    // size in incremental context?
+    first_atom_index: ?Atom.Index = null,
     last_atom_index: ?Atom.Index = null,
 
     /// A list of atoms that have surplus capacity. This list can have false