aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/link/MachO/Atom.zig178
-rw-r--r--src/link/MachO/Object.zig6
-rw-r--r--src/link/MachO/zld.zig150
3 files changed, 166 insertions, 168 deletions
diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig
index 4095a1c333..eb5e76462f 100644
--- a/src/link/MachO/Atom.zig
+++ b/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;
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index 8c523779ea..c9f32aa4fd 100644
--- a/src/link/MachO/Object.zig
+++ b/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,
diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig
index 7fa506ce0e..d4dd599d2d 100644
--- a/src/link/MachO/zld.zig
+++ b/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,
};