Commit 180979ee41

Jakub Konka <kubkon@jakubkonka.com>
2023-08-26 07:56:49
macho: move getOutputSection into Atom
1 parent f29d9ec
Changed files (3)
src/link/MachO/Atom.zig
@@ -1,23 +1,3 @@
-const Atom = @This();
-
-const std = @import("std");
-const build_options = @import("build_options");
-const aarch64 = @import("../../arch/aarch64/bits.zig");
-const assert = std.debug.assert;
-const log = std.log.scoped(.link);
-const macho = std.macho;
-const math = std.math;
-const mem = std.mem;
-const meta = std.meta;
-const trace = @import("../../tracy.zig").trace;
-
-const Allocator = mem.Allocator;
-const Arch = std.Target.Cpu.Arch;
-const MachO = @import("../MachO.zig");
-pub const Relocation = @import("Relocation.zig");
-const SymbolWithLoc = MachO.SymbolWithLoc;
-const Zld = @import("zld.zig").Zld;
-
 /// Each Atom always gets a symbol with the fully qualified name.
 /// The symbol can reside in any object file context structure in `symtab` array
 /// (see `Object`), or if the symbol is a synthetic symbol such as a GOT cell or
@@ -125,6 +105,144 @@ pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {
     return surplus >= MachO.min_text_capacity;
 }
 
+pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
+    const segname = sect.segName();
+    const sectname = sect.sectName();
+    const res: ?u8 = blk: {
+        if (mem.eql(u8, "__LLVM", segname)) {
+            log.debug("TODO LLVM section: type 0x{x}, name '{s},{s}'", .{
+                sect.flags, segname, sectname,
+            });
+            break :blk null;
+        }
+
+        // We handle unwind info separately.
+        if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {
+            break :blk null;
+        }
+        if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
+            break :blk null;
+        }
+
+        if (sect.isCode()) {
+            if (zld.text_section_index == null) {
+                zld.text_section_index = try zld.initSection(
+                    "__TEXT",
+                    "__text",
+                    .{
+                        .flags = macho.S_REGULAR |
+                            macho.S_ATTR_PURE_INSTRUCTIONS |
+                            macho.S_ATTR_SOME_INSTRUCTIONS,
+                    },
+                );
+            }
+            break :blk zld.text_section_index.?;
+        }
+
+        if (sect.isDebug()) {
+            break :blk null;
+        }
+
+        switch (sect.type()) {
+            macho.S_4BYTE_LITERALS,
+            macho.S_8BYTE_LITERALS,
+            macho.S_16BYTE_LITERALS,
+            => {
+                break :blk zld.getSectionByName("__TEXT", "__const") orelse try zld.initSection(
+                    "__TEXT",
+                    "__const",
+                    .{},
+                );
+            },
+            macho.S_CSTRING_LITERALS => {
+                if (mem.startsWith(u8, sectname, "__objc")) {
+                    break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(
+                        segname,
+                        sectname,
+                        .{},
+                    );
+                }
+                break :blk zld.getSectionByName("__TEXT", "__cstring") orelse try zld.initSection(
+                    "__TEXT",
+                    "__cstring",
+                    .{ .flags = macho.S_CSTRING_LITERALS },
+                );
+            },
+            macho.S_MOD_INIT_FUNC_POINTERS,
+            macho.S_MOD_TERM_FUNC_POINTERS,
+            => {
+                break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try zld.initSection(
+                    "__DATA_CONST",
+                    sectname,
+                    .{ .flags = sect.flags },
+                );
+            },
+            macho.S_LITERAL_POINTERS,
+            macho.S_ZEROFILL,
+            macho.S_THREAD_LOCAL_VARIABLES,
+            macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
+            macho.S_THREAD_LOCAL_REGULAR,
+            macho.S_THREAD_LOCAL_ZEROFILL,
+            => {
+                break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(
+                    segname,
+                    sectname,
+                    .{ .flags = sect.flags },
+                );
+            },
+            macho.S_COALESCED => {
+                break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(
+                    segname,
+                    sectname,
+                    .{},
+                );
+            },
+            macho.S_REGULAR => {
+                if (mem.eql(u8, segname, "__TEXT")) {
+                    if (mem.eql(u8, sectname, "__rodata") or
+                        mem.eql(u8, sectname, "__typelink") or
+                        mem.eql(u8, sectname, "__itablink") or
+                        mem.eql(u8, sectname, "__gosymtab") or
+                        mem.eql(u8, sectname, "__gopclntab"))
+                    {
+                        break :blk zld.getSectionByName("__TEXT", sectname) orelse try zld.initSection(
+                            "__TEXT",
+                            sectname,
+                            .{},
+                        );
+                    }
+                }
+                if (mem.eql(u8, segname, "__DATA")) {
+                    if (mem.eql(u8, sectname, "__const") or
+                        mem.eql(u8, sectname, "__cfstring") or
+                        mem.eql(u8, sectname, "__objc_classlist") or
+                        mem.eql(u8, sectname, "__objc_imageinfo"))
+                    {
+                        break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try zld.initSection(
+                            "__DATA_CONST",
+                            sectname,
+                            .{},
+                        );
+                    } else if (mem.eql(u8, sectname, "__data")) {
+                        break :blk zld.getSectionByName("__DATA", "__data") orelse try zld.initSection(
+                            "__DATA",
+                            "__data",
+                            .{},
+                        );
+                    }
+                }
+                break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(
+                    segname,
+                    sectname,
+                    .{},
+                );
+            },
+            else => break :blk null,
+        }
+    };
+    return res;
+}
+
 pub fn addRelocation(macho_file: *MachO, atom_index: Index, reloc: Relocation) !void {
     return addRelocations(macho_file, atom_index, &[_]Relocation{reloc});
 }
@@ -1112,3 +1230,23 @@ pub fn relocIsStub(zld: *Zld, rel: macho.relocation_info) bool {
         else => unreachable,
     }
 }
+
+const Atom = @This();
+
+const std = @import("std");
+const build_options = @import("build_options");
+const aarch64 = @import("../../arch/aarch64/bits.zig");
+const assert = std.debug.assert;
+const log = std.log.scoped(.link);
+const macho = std.macho;
+const math = std.math;
+const mem = std.mem;
+const meta = std.meta;
+const trace = @import("../../tracy.zig").trace;
+
+const Allocator = mem.Allocator;
+const Arch = std.Target.Cpu.Arch;
+const MachO = @import("../MachO.zig");
+pub const Relocation = @import("Relocation.zig");
+const SymbolWithLoc = MachO.SymbolWithLoc;
+const Zld = @import("zld.zig").Zld;
src/link/MachO/Object.zig
@@ -377,7 +377,7 @@ pub fn splitRegularSections(self: *Object, zld: *Zld, object_id: u32) !void {
     const sections = self.getSourceSections();
     for (sections, 0..) |sect, id| {
         if (sect.isDebug()) continue;
-        const out_sect_id = (try zld.getOutputSection(sect)) orelse {
+        const out_sect_id = (try Atom.getOutputSection(zld, sect)) orelse {
             log.debug("  unhandled section '{s},{s}'", .{ sect.segName(), sect.sectName() });
             continue;
         };
@@ -397,7 +397,7 @@ pub fn splitRegularSections(self: *Object, zld: *Zld, object_id: u32) !void {
     if (self.in_symtab == null) {
         for (sections, 0..) |sect, id| {
             if (sect.isDebug()) continue;
-            const out_sect_id = (try zld.getOutputSection(sect)) orelse continue;
+            const out_sect_id = (try Atom.getOutputSection(zld, sect)) orelse continue;
             if (sect.size == 0) continue;
 
             const sect_id = @as(u8, @intCast(id));
@@ -456,7 +456,7 @@ pub fn splitRegularSections(self: *Object, zld: *Zld, object_id: u32) !void {
         log.debug("splitting section '{s},{s}' into atoms", .{ sect.segName(), sect.sectName() });
 
         // Get output segment/section in the final artifact.
-        const out_sect_id = (try zld.getOutputSection(sect)) orelse continue;
+        const out_sect_id = (try Atom.getOutputSection(zld, sect)) orelse continue;
 
         log.debug("  output sect({d}, '{s},{s}')", .{
             out_sect_id + 1,
src/link/MachO/zld.zig
@@ -95,144 +95,6 @@ pub const Zld = struct {
 
     atoms: std.ArrayListUnmanaged(Atom) = .{},
 
-    pub fn getOutputSection(self: *Zld, sect: macho.section_64) !?u8 {
-        const segname = sect.segName();
-        const sectname = sect.sectName();
-        const res: ?u8 = blk: {
-            if (mem.eql(u8, "__LLVM", segname)) {
-                log.debug("TODO LLVM section: type 0x{x}, name '{s},{s}'", .{
-                    sect.flags, segname, sectname,
-                });
-                break :blk null;
-            }
-
-            // We handle unwind info separately.
-            if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {
-                break :blk null;
-            }
-            if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
-                break :blk null;
-            }
-
-            if (sect.isCode()) {
-                if (self.text_section_index == null) {
-                    self.text_section_index = try self.initSection(
-                        "__TEXT",
-                        "__text",
-                        .{
-                            .flags = macho.S_REGULAR |
-                                macho.S_ATTR_PURE_INSTRUCTIONS |
-                                macho.S_ATTR_SOME_INSTRUCTIONS,
-                        },
-                    );
-                }
-                break :blk self.text_section_index.?;
-            }
-
-            if (sect.isDebug()) {
-                break :blk null;
-            }
-
-            switch (sect.type()) {
-                macho.S_4BYTE_LITERALS,
-                macho.S_8BYTE_LITERALS,
-                macho.S_16BYTE_LITERALS,
-                => {
-                    break :blk self.getSectionByName("__TEXT", "__const") orelse try self.initSection(
-                        "__TEXT",
-                        "__const",
-                        .{},
-                    );
-                },
-                macho.S_CSTRING_LITERALS => {
-                    if (mem.startsWith(u8, sectname, "__objc")) {
-                        break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
-                            segname,
-                            sectname,
-                            .{},
-                        );
-                    }
-                    break :blk self.getSectionByName("__TEXT", "__cstring") orelse try self.initSection(
-                        "__TEXT",
-                        "__cstring",
-                        .{ .flags = macho.S_CSTRING_LITERALS },
-                    );
-                },
-                macho.S_MOD_INIT_FUNC_POINTERS,
-                macho.S_MOD_TERM_FUNC_POINTERS,
-                => {
-                    break :blk self.getSectionByName("__DATA_CONST", sectname) orelse try self.initSection(
-                        "__DATA_CONST",
-                        sectname,
-                        .{ .flags = sect.flags },
-                    );
-                },
-                macho.S_LITERAL_POINTERS,
-                macho.S_ZEROFILL,
-                macho.S_THREAD_LOCAL_VARIABLES,
-                macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
-                macho.S_THREAD_LOCAL_REGULAR,
-                macho.S_THREAD_LOCAL_ZEROFILL,
-                => {
-                    break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
-                        segname,
-                        sectname,
-                        .{ .flags = sect.flags },
-                    );
-                },
-                macho.S_COALESCED => {
-                    break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
-                        segname,
-                        sectname,
-                        .{},
-                    );
-                },
-                macho.S_REGULAR => {
-                    if (mem.eql(u8, segname, "__TEXT")) {
-                        if (mem.eql(u8, sectname, "__rodata") or
-                            mem.eql(u8, sectname, "__typelink") or
-                            mem.eql(u8, sectname, "__itablink") or
-                            mem.eql(u8, sectname, "__gosymtab") or
-                            mem.eql(u8, sectname, "__gopclntab"))
-                        {
-                            break :blk self.getSectionByName("__TEXT", sectname) orelse try self.initSection(
-                                "__TEXT",
-                                sectname,
-                                .{},
-                            );
-                        }
-                    }
-                    if (mem.eql(u8, segname, "__DATA")) {
-                        if (mem.eql(u8, sectname, "__const") or
-                            mem.eql(u8, sectname, "__cfstring") or
-                            mem.eql(u8, sectname, "__objc_classlist") or
-                            mem.eql(u8, sectname, "__objc_imageinfo"))
-                        {
-                            break :blk self.getSectionByName("__DATA_CONST", sectname) orelse try self.initSection(
-                                "__DATA_CONST",
-                                sectname,
-                                .{},
-                            );
-                        } else if (mem.eql(u8, sectname, "__data")) {
-                            break :blk self.getSectionByName("__DATA", "__data") orelse try self.initSection(
-                                "__DATA",
-                                "__data",
-                                .{},
-                            );
-                        }
-                    }
-                    break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
-                        segname,
-                        sectname,
-                        .{},
-                    );
-                },
-                else => break :blk null,
-            }
-        };
-        return res;
-    }
-
     pub fn addAtomToSection(self: *Zld, atom_index: Atom.Index) void {
         const atom = self.getAtomPtr(atom_index);
         const sym = self.getSymbol(atom.getSymbolWithLoc());
@@ -278,7 +140,8 @@ 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 self.initSection("__DATA", "__data", .{});
+        const sect_id = self.getSectionByName("__DATA", "__data") orelse
+            try self.initSection("__DATA", "__data", .{});
         sym.n_sect = sect_id + 1;
         self.dyld_private_atom_index = atom_index;
 
@@ -301,16 +164,13 @@ pub const Zld = struct {
             // text blocks for each tentative definition.
             const size = sym.n_value;
             const alignment = (sym.n_desc >> 8) & 0x0f;
-            const n_sect = (try self.getOutputSection(.{
-                .segname = makeStaticString("__DATA"),
-                .sectname = makeStaticString("__bss"),
-                .flags = macho.S_ZEROFILL,
-            })).? + 1;
+            const sect_id = self.getSectionByName("__DATA", "__bss") orelse
+                try self.initSection("__DATA", "__bss", .{ .flags = macho.S_ZEROFILL });
 
             sym.* = .{
                 .n_strx = sym.n_strx,
                 .n_type = macho.N_SECT | macho.N_EXT,
-                .n_sect = n_sect,
+                .n_sect = sect_id + 1,
                 .n_desc = 0,
                 .n_value = 0,
             };