Commit 174de37cef
Changed files (17)
src/arch/x86_64/CodeGen.zig
@@ -12362,8 +12362,9 @@ fn genCall(self: *Self, info: union(enum) {
try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index }, .{});
try self.asmRegister(.{ ._, .call }, .rax);
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
- const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, func.owner_decl);
- const sym = macho_file.getSymbol(sym_index);
+ const zo = macho_file.getZigObject().?;
+ const sym_index = try zo.getOrCreateMetadataForDecl(macho_file, func.owner_decl);
+ const sym = zo.symbols.items[sym_index];
try self.genSetReg(
.rax,
Type.usize,
@@ -15396,9 +15397,10 @@ fn genLazySymbolRef(
else => unreachable,
}
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
- const sym_index = macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_sym) catch |err|
+ const zo = macho_file.getZigObject().?;
+ const sym_index = zo.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_sym) catch |err|
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
- const sym = macho_file.getSymbol(sym_index);
+ const sym = zo.symbols.items[sym_index];
switch (tag) {
.lea, .call => try self.genSetReg(
reg,
src/arch/x86_64/Emit.zig
@@ -162,7 +162,7 @@ pub fn emitMir(emit: *Emit) Error!void {
};
const zo = macho_file.getZigObject().?;
const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?;
- const sym = zo.symbols.items[data.sym_index];
+ const sym = &zo.symbols.items[data.sym_index];
if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {
_ = try sym.getOrCreateZigGotEntry(data.sym_index, macho_file);
}
src/link/MachO/dyld_info/bind.zig
@@ -1,17 +1,19 @@
pub const Entry = struct {
- target: Symbol.Index,
+ target: MachO.Ref,
offset: u64,
segment_id: u8,
addend: i64,
pub fn lessThan(ctx: *MachO, entry: Entry, other: Entry) bool {
+ _ = ctx;
if (entry.segment_id == other.segment_id) {
- if (entry.target == other.target) {
+ if (entry.target.eql(other.target)) {
return entry.offset < other.offset;
}
- const entry_name = ctx.getSymbol(entry.target).getName(ctx);
- const other_name = ctx.getSymbol(other.target).getName(ctx);
- return std.mem.lessThan(u8, entry_name, other_name);
+ if (entry.target.file == other.target.file) {
+ return entry.target.index < other.target.index;
+ }
+ return entry.target.file < other.target.file;
}
return entry.segment_id < other.segment_id;
}
@@ -44,7 +46,7 @@ pub const Bind = struct {
for (objects.items) |index| {
const file = macho_file.getFile(index).?;
for (file.getAtoms()) |atom_index| {
- const atom = macho_file.getAtom(atom_index) orelse continue;
+ const atom = file.getAtom(atom_index) orelse continue;
if (!atom.flags.alive) continue;
if (atom.getInputSection(macho_file).isZerofill()) continue;
const atom_addr = atom.getAddress(macho_file);
@@ -55,10 +57,10 @@ pub const Bind = struct {
if (rel.type != .unsigned or rel.meta.length != 3 or rel.tag != .@"extern") continue;
const rel_offset = rel.offset - atom.off;
const addend = rel.addend + rel.getRelocAddend(cpu_arch);
- const sym = rel.getTargetSymbol(macho_file);
+ const sym = rel.getTargetSymbol(atom.*, macho_file);
if (sym.isTlvInit(macho_file)) continue;
const entry = Entry{
- .target = rel.target,
+ .target = rel.getTargetSymbolRef(atom.*, macho_file),
.offset = atom_addr + rel_offset - seg.vmaddr,
.segment_id = seg_id,
.addend = addend,
@@ -74,7 +76,7 @@ pub const Bind = struct {
const seg_id = macho_file.sections.items(.segment_id)[sid];
const seg = macho_file.segments.items[seg_id];
for (macho_file.got.symbols.items, 0..) |ref, idx| {
- const sym = macho_file.getSymbol(ref);
+ const sym = ref.getSymbol(macho_file).?;
const addr = macho_file.got.getAddress(@intCast(idx), macho_file);
const entry = Entry{
.target = ref,
@@ -93,7 +95,7 @@ pub const Bind = struct {
const seg_id = macho_file.sections.items(.segment_id)[sid];
const seg = macho_file.segments.items[seg_id];
for (macho_file.stubs.symbols.items, 0..) |ref, idx| {
- const sym = macho_file.getSymbol(ref);
+ const sym = ref.getSymbol(macho_file).?;
const addr = sect.addr + idx * @sizeOf(u64);
const bind_entry = Entry{
.target = ref,
@@ -112,7 +114,7 @@ pub const Bind = struct {
const seg = macho_file.segments.items[seg_id];
for (macho_file.tlv_ptr.symbols.items, 0..) |ref, idx| {
- const sym = macho_file.getSymbol(ref);
+ const sym = ref.getSymbol(macho_file).?;
const addr = macho_file.tlv_ptr.getAddress(@intCast(idx), macho_file);
const entry = Entry{
.target = ref,
@@ -162,7 +164,7 @@ pub const Bind = struct {
var addend: i64 = 0;
var count: usize = 0;
var skip: u64 = 0;
- var target: ?Symbol.Index = null;
+ var target: ?MachO.Ref = null;
var state: enum {
start,
@@ -173,7 +175,7 @@ pub const Bind = struct {
var i: usize = 0;
while (i < entries.len) : (i += 1) {
const current = entries[i];
- if (target == null or target.? != current.target) {
+ if (target == null or !target.?.eql(current.target)) {
switch (state) {
.start => {},
.bind_single => try doBind(writer),
@@ -182,7 +184,7 @@ pub const Bind = struct {
state = .start;
target = current.target;
- const sym = ctx.getSymbol(current.target);
+ const sym = current.target.getSymbol(ctx).?;
const name = sym.getName(ctx);
const flags: u8 = if (sym.weakRef(ctx)) macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT else 0;
const ordinal: i16 = ord: {
@@ -296,7 +298,7 @@ pub const WeakBind = struct {
for (objects.items) |index| {
const file = macho_file.getFile(index).?;
for (file.getAtoms()) |atom_index| {
- const atom = macho_file.getAtom(atom_index) orelse continue;
+ const atom = file.getAtom(atom_index) orelse continue;
if (!atom.flags.alive) continue;
if (atom.getInputSection(macho_file).isZerofill()) continue;
const atom_addr = atom.getAddress(macho_file);
@@ -307,10 +309,10 @@ pub const WeakBind = struct {
if (rel.type != .unsigned or rel.meta.length != 3 or rel.tag != .@"extern") continue;
const rel_offset = rel.offset - atom.off;
const addend = rel.addend + rel.getRelocAddend(cpu_arch);
- const sym = rel.getTargetSymbol(macho_file);
+ const sym = rel.getTargetSymbol(atom.*, macho_file);
if (sym.isTlvInit(macho_file)) continue;
const entry = Entry{
- .target = rel.target,
+ .target = rel.getTargetSymbolRef(atom.*, macho_file),
.offset = atom_addr + rel_offset - seg.vmaddr,
.segment_id = seg_id,
.addend = addend,
@@ -326,7 +328,7 @@ pub const WeakBind = struct {
const seg_id = macho_file.sections.items(.segment_id)[sid];
const seg = macho_file.segments.items[seg_id];
for (macho_file.got.symbols.items, 0..) |ref, idx| {
- const sym = macho_file.getSymbol(ref);
+ const sym = ref.getSymbol(macho_file).?;
const addr = macho_file.got.getAddress(@intCast(idx), macho_file);
const entry = Entry{
.target = ref,
@@ -346,7 +348,7 @@ pub const WeakBind = struct {
const seg = macho_file.segments.items[seg_id];
for (macho_file.stubs.symbols.items, 0..) |ref, idx| {
- const sym = macho_file.getSymbol(ref);
+ const sym = ref.getSymbol(macho_file).?;
const addr = sect.addr + idx * @sizeOf(u64);
const bind_entry = Entry{
.target = ref,
@@ -365,7 +367,7 @@ pub const WeakBind = struct {
const seg = macho_file.segments.items[seg_id];
for (macho_file.tlv_ptr.symbols.items, 0..) |ref, idx| {
- const sym = macho_file.getSymbol(ref);
+ const sym = ref.getSymbol(macho_file).?;
const addr = macho_file.tlv_ptr.getAddress(@intCast(idx), macho_file);
const entry = Entry{
.target = ref,
@@ -415,7 +417,7 @@ pub const WeakBind = struct {
var addend: i64 = 0;
var count: usize = 0;
var skip: u64 = 0;
- var target: ?Symbol.Index = null;
+ var target: ?MachO.Ref = null;
var state: enum {
start,
@@ -426,7 +428,7 @@ pub const WeakBind = struct {
var i: usize = 0;
while (i < entries.len) : (i += 1) {
const current = entries[i];
- if (target == null or target.? != current.target) {
+ if (target == null or !target.?.eql(current.target)) {
switch (state) {
.start => {},
.bind_single => try doBind(writer),
@@ -435,7 +437,7 @@ pub const WeakBind = struct {
state = .start;
target = current.target;
- const sym = ctx.getSymbol(current.target);
+ const sym = current.target.getSymbol(ctx).?;
const name = sym.getName(ctx);
const flags: u8 = 0; // TODO NON_WEAK_DEFINITION
@@ -536,7 +538,7 @@ pub const LazyBind = struct {
const seg = macho_file.segments.items[seg_id];
for (macho_file.stubs.symbols.items, 0..) |ref, idx| {
- const sym = macho_file.getSymbol(ref);
+ const sym = ref.getSymbol(macho_file).?;
const addr = sect.addr + idx * @sizeOf(u64);
const bind_entry = Entry{
.target = ref,
@@ -565,7 +567,7 @@ pub const LazyBind = struct {
for (self.entries.items) |entry| {
self.offsets.appendAssumeCapacity(@intCast(self.buffer.items.len));
- const sym = ctx.getSymbol(entry.target);
+ const sym = entry.target.getSymbol(ctx).?;
const name = sym.getName(ctx);
const flags: u8 = if (sym.weakRef(ctx)) macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT else 0;
const ordinal: i16 = ord: {
src/link/MachO/dyld_info/Rebase.zig
@@ -34,7 +34,7 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void {
for (objects.items) |index| {
const file = macho_file.getFile(index).?;
for (file.getAtoms()) |atom_index| {
- const atom = macho_file.getAtom(atom_index) orelse continue;
+ const atom = file.getAtom(atom_index) orelse continue;
if (!atom.flags.alive) continue;
if (atom.getInputSection(macho_file).isZerofill()) continue;
const atom_addr = atom.getAddress(macho_file);
@@ -43,7 +43,7 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void {
for (atom.getRelocs(macho_file)) |rel| {
if (rel.type != .unsigned or rel.meta.length != 3) continue;
if (rel.tag == .@"extern") {
- const sym = rel.getTargetSymbol(macho_file);
+ const sym = rel.getTargetSymbol(atom.*, macho_file);
if (sym.isTlvInit(macho_file)) continue;
if (sym.flags.import) continue;
}
@@ -72,7 +72,7 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void {
const seg_id = macho_file.sections.items(.segment_id)[sid];
const seg = macho_file.segments.items[seg_id];
for (macho_file.got.symbols.items, 0..) |ref, idx| {
- const sym = macho_file.getSymbol(ref);
+ const sym = ref.getSymbol(macho_file).?;
const addr = macho_file.got.getAddress(@intCast(idx), macho_file);
if (!sym.flags.import) {
try rebase.entries.append(gpa, .{
@@ -88,7 +88,7 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void {
const seg_id = macho_file.sections.items(.segment_id)[sid];
const seg = macho_file.segments.items[seg_id];
for (macho_file.stubs.symbols.items, 0..) |ref, idx| {
- const sym = macho_file.getSymbol(ref);
+ const sym = ref.getSymbol(macho_file).?;
const addr = sect.addr + idx * @sizeOf(u64);
const rebase_entry = Rebase.Entry{
.offset = addr - seg.vmaddr,
@@ -104,7 +104,7 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void {
const seg_id = macho_file.sections.items(.segment_id)[sid];
const seg = macho_file.segments.items[seg_id];
for (macho_file.tlv_ptr.symbols.items, 0..) |ref, idx| {
- const sym = macho_file.getSymbol(ref);
+ const sym = ref.getSymbol(macho_file).?;
const addr = macho_file.tlv_ptr.getAddress(@intCast(idx), macho_file);
if (!sym.flags.import) {
try rebase.entries.append(gpa, .{
src/link/MachO/dyld_info/Trie.zig
@@ -94,33 +94,31 @@ pub fn updateSize(self: *Trie, macho_file: *MachO) !void {
const gpa = macho_file.base.comp.gpa;
try self.init(gpa);
- // TODO
- // try self.nodes.ensureUnusedCapacity(gpa, macho_file.resolver.values.items.len * 2);
- // try self.edges.ensureUnusedCapacity(gpa, macho_file.resolver.values.items.len * 2);
+ try self.nodes.ensureUnusedCapacity(gpa, macho_file.resolver.values.items.len * 2);
+ try self.edges.ensureUnusedCapacity(gpa, macho_file.resolver.values.items.len * 2);
const seg = macho_file.getTextSegment();
- for (macho_file.objects.items) |index| {
- for (macho_file.getFile(index).?.getSymbols()) |ref| {
- const sym = macho_file.getSymbol(ref);
- if (!sym.flags.@"export") continue;
- if (sym.getAtom(macho_file)) |atom| if (!atom.flags.alive) continue;
- var flags: u64 = if (sym.flags.abs)
- macho.EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE
- else if (sym.flags.tlv)
- macho.EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
- else
- macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR;
- if (sym.flags.weak) {
- flags |= macho.EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
- macho_file.weak_defines = true;
- macho_file.binds_to_weak = true;
- }
- try self.put(gpa, .{
- .name = sym.getName(macho_file),
- .vmaddr_offset = sym.getAddress(.{ .stubs = false }, macho_file) - seg.vmaddr,
- .export_flags = flags,
- });
+ for (macho_file.resolver.values.items) |ref| {
+ if (ref.getFile(macho_file) == null) continue;
+ const sym = ref.getSymbol(macho_file).?;
+ if (!sym.flags.@"export") continue;
+ if (sym.getAtom(macho_file)) |atom| if (!atom.flags.alive) continue;
+ var flags: u64 = if (sym.flags.abs)
+ macho.EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE
+ else if (sym.flags.tlv)
+ macho.EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
+ else
+ macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR;
+ if (sym.flags.weak) {
+ flags |= macho.EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
+ macho_file.weak_defines = true;
+ macho_file.binds_to_weak = true;
}
+ try self.put(gpa, .{
+ .name = sym.getName(macho_file),
+ .vmaddr_offset = sym.getAddress(.{ .stubs = false }, macho_file) - seg.vmaddr,
+ .export_flags = flags,
+ });
}
try self.finalize(gpa);
src/link/MachO/Atom.zig
@@ -213,7 +213,8 @@ pub fn initOutputSection(sect: macho.section_64, macho_file: *MachO) !u8 {
/// File offset relocation happens transparently, so it is not included in
/// this calculation.
pub fn capacity(self: Atom, macho_file: *MachO) u64 {
- const next_addr = if (macho_file.getAtom(self.next_index)) |next|
+ const zo = macho_file.getZigObject().?;
+ const next_addr = if (zo.getAtom(self.next_index)) |next|
next.getAddress(macho_file)
else
std.math.maxInt(u32);
@@ -222,7 +223,8 @@ pub fn capacity(self: Atom, macho_file: *MachO) u64 {
pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {
// No need to keep a free list node for the last block.
- const next = macho_file.getAtom(self.next_index) orelse return false;
+ const zo = macho_file.getZigObject().?;
+ const next = zo.getAtom(self.next_index) orelse return false;
const cap = next.getAddress(macho_file) - self.getAddress(macho_file);
const ideal_cap = MachO.padToIdeal(self.size);
if (cap <= ideal_cap) return false;
@@ -231,6 +233,7 @@ pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {
}
pub fn allocate(self: *Atom, macho_file: *MachO) !void {
+ const zo = macho_file.getZigObject().?;
const sect = &macho_file.sections.items(.header)[self.out_n_sect];
const free_list = &macho_file.sections.items(.free_list)[self.out_n_sect];
const last_atom_index = &macho_file.sections.items(.last_atom_index)[self.out_n_sect];
@@ -250,7 +253,7 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void {
var i: usize = free_list.items.len;
while (i < free_list.items.len) {
const big_atom_index = free_list.items[i];
- const big_atom = macho_file.getAtom(big_atom_index).?;
+ const big_atom = zo.getAtom(big_atom_index).?;
// We now have a pointer to a live atom that has too much capacity.
// Is it enough that we could fit this new atom?
const cap = big_atom.capacity(macho_file);
@@ -282,7 +285,7 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void {
free_list_removal = i;
}
break :blk new_start_vaddr;
- } else if (macho_file.getAtom(last_atom_index.*)) |last| {
+ } else if (zo.getAtom(last_atom_index.*)) |last| {
const ideal_capacity = MachO.padToIdeal(last.size);
const ideal_capacity_end_vaddr = last.value + ideal_capacity;
const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr);
@@ -302,7 +305,7 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void {
});
const expand_section = if (atom_placement) |placement_index|
- macho_file.getAtom(placement_index).?.next_index == 0
+ zo.getAtom(placement_index).?.next_index == 0
else
true;
if (expand_section) {
@@ -327,15 +330,15 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void {
// This function can also reallocate an atom.
// In this case we need to "unplug" it from its previous location before
// plugging it in to its new location.
- if (macho_file.getAtom(self.prev_index)) |prev| {
+ if (zo.getAtom(self.prev_index)) |prev| {
prev.next_index = self.next_index;
}
- if (macho_file.getAtom(self.next_index)) |next| {
+ if (zo.getAtom(self.next_index)) |next| {
next.prev_index = self.prev_index;
}
if (atom_placement) |big_atom_index| {
- const big_atom = macho_file.getAtom(big_atom_index).?;
+ const big_atom = zo.getAtom(big_atom_index).?;
self.prev_index = big_atom_index;
self.next_index = big_atom.next_index;
big_atom.next_index = self.atom_index;
@@ -365,6 +368,7 @@ pub fn free(self: *Atom, macho_file: *MachO) void {
const comp = macho_file.base.comp;
const gpa = comp.gpa;
+ const zo = macho_file.getZigObject().?;
const free_list = &macho_file.sections.items(.free_list)[self.out_n_sect];
const last_atom_index = &macho_file.sections.items(.last_atom_index)[self.out_n_sect];
var already_have_free_list_node = false;
@@ -383,9 +387,9 @@ pub fn free(self: *Atom, macho_file: *MachO) void {
}
}
- if (macho_file.getAtom(last_atom_index.*)) |last_atom| {
+ if (zo.getAtom(last_atom_index.*)) |last_atom| {
if (last_atom.atom_index == self.atom_index) {
- if (macho_file.getAtom(self.prev_index)) |_| {
+ if (zo.getAtom(self.prev_index)) |_| {
// TODO shrink the section size here
last_atom_index.* = self.prev_index;
} else {
@@ -394,7 +398,7 @@ pub fn free(self: *Atom, macho_file: *MachO) void {
}
}
- if (macho_file.getAtom(self.prev_index)) |prev| {
+ if (zo.getAtom(self.prev_index)) |prev| {
prev.next_index = self.next_index;
if (!already_have_free_list_node and prev.*.freeListEligible(macho_file)) {
// The free list is heuristics, it doesn't have to be perfect, so we can
@@ -405,7 +409,7 @@ pub fn free(self: *Atom, macho_file: *MachO) void {
self.prev_index = 0;
}
- if (macho_file.getAtom(self.next_index)) |next| {
+ if (zo.getAtom(self.next_index)) |next| {
next.prev_index = self.prev_index;
} else {
self.next_index = 0;
@@ -423,7 +427,7 @@ pub fn addReloc(self: *Atom, macho_file: *MachO, reloc: Relocation) !void {
const gpa = macho_file.base.comp.gpa;
const file = self.getFile(macho_file);
assert(file == .zig_object);
- var extra = self.getExtra(macho_file).?;
+ var extra = self.getExtra(macho_file);
const rels = &file.zig_object.relocs.items[extra.rel_index];
try rels.append(gpa, reloc);
extra.rel_count += 1;
@@ -432,7 +436,7 @@ pub fn addReloc(self: *Atom, macho_file: *MachO, reloc: Relocation) !void {
pub fn freeRelocs(self: *Atom, macho_file: *MachO) void {
self.getFile(macho_file).zig_object.freeAtomRelocs(self.*, macho_file);
- var extra = self.getExtra(macho_file).?;
+ var extra = self.getExtra(macho_file);
extra.rel_count = 0;
self.setExtra(extra, macho_file);
}
@@ -630,7 +634,7 @@ fn resolveRelocInner(
const TLS = @as(i64, @intCast(macho_file.getTlsAddress()));
const SUB = if (subtractor) |sub| @as(i64, @intCast(sub.getTargetAddress(self, macho_file))) else 0;
// Address of the __got_zig table entry if any.
- const ZIG_GOT = @as(i64, @intCast(rel.getZigGotTargetAddress(self, macho_file)));
+ const ZIG_GOT = @as(i64, @intCast(rel.getZigGotTargetAddress(macho_file)));
const divExact = struct {
fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 {
src/link/MachO/DebugSymbols.zig
@@ -175,8 +175,9 @@ fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) u64
}
pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
+ const zo = macho_file.getZigObject().?;
for (self.relocs.items) |*reloc| {
- const sym = macho_file.getSymbol(reloc.target);
+ const sym = zo.symbols.items[reloc.target];
const sym_name = sym.getName(macho_file);
const addr = switch (reloc.type) {
.direct_load => sym.getAddress(.{}, macho_file),
@@ -382,23 +383,22 @@ pub fn writeSymtab(self: *DebugSymbols, off: u32, macho_file: *MachO) !u32 {
cmd.symoff = off;
try self.symtab.resize(gpa, cmd.nsyms);
- try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1);
+ try self.strtab.resize(gpa, cmd.strsize);
+ self.strtab.items[0] = 0;
if (macho_file.getZigObject()) |zo| {
zo.writeSymtab(macho_file, self);
}
for (macho_file.objects.items) |index| {
- try macho_file.getFile(index).?.writeSymtab(macho_file, self);
+ macho_file.getFile(index).?.writeSymtab(macho_file, self);
}
for (macho_file.dylibs.items) |index| {
- try macho_file.getFile(index).?.writeSymtab(macho_file, self);
+ macho_file.getFile(index).?.writeSymtab(macho_file, self);
}
if (macho_file.getInternalObject()) |internal| {
internal.writeSymtab(macho_file, self);
}
- assert(self.strtab.items.len == cmd.strsize);
-
try self.file.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff);
return off + cmd.nsyms * @sizeOf(macho.nlist_64);
src/link/MachO/Dylib.zig
@@ -6,7 +6,7 @@ strtab: std.ArrayListUnmanaged(u8) = .{},
id: ?Id = null,
ordinal: u16 = 0,
-symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
+symbols: std.ArrayListUnmanaged(Symbol) = .{},
symbols_extra: std.ArrayListUnmanaged(u32) = .{},
globals: std.ArrayListUnmanaged(MachO.SymbolResolver.Index) = .{},
dependents: std.ArrayListUnmanaged(Id) = .{},
@@ -516,7 +516,7 @@ pub fn initSymbols(self: *Dylib, macho_file: *MachO) !void {
}
}
-pub fn resolveSymbols(self: *Dylib, macho_file: *MachO) void {
+pub fn resolveSymbols(self: *Dylib, macho_file: *MachO) !void {
const tracy = trace(@src());
defer tracy.end();
@@ -584,7 +584,7 @@ pub fn calcSymtabSize(self: *Dylib, macho_file: *MachO) void {
}
}
-pub fn writeSymtab(self: Dylib, macho_file: *MachO) void {
+pub fn writeSymtab(self: Dylib, macho_file: *MachO, ctx: anytype) void {
const tracy = trace(@src());
defer tracy.end();
@@ -594,13 +594,13 @@ pub fn writeSymtab(self: Dylib, macho_file: *MachO) void {
const file = ref.getFile(macho_file) orelse continue;
if (file.getIndex() != self.index) continue;
const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
- const out_sym = &macho_file.symtab.items[idx];
+ const out_sym = &ctx.symtab.items[idx];
out_sym.n_strx = n_strx;
sym.setOutputSym(macho_file, out_sym);
const name = sym.getName(macho_file);
- @memcpy(macho_file.strtab.items[n_strx..][0..name.len], name);
+ @memcpy(ctx.strtab.items[n_strx..][0..name.len], name);
n_strx += @intCast(name.len);
- macho_file.strtab.items[n_strx] = 0;
+ ctx.strtab.items[n_strx] = 0;
n_strx += 1;
}
}
@@ -718,10 +718,16 @@ fn formatSymtab(
_ = unused_fmt_string;
_ = options;
const dylib = ctx.dylib;
+ const macho_file = ctx.macho_file;
try writer.writeAll(" globals\n");
- for (dylib.symbols.items) |index| {
- const global = ctx.macho_file.getSymbol(index);
- try writer.print(" {}\n", .{global.fmt(ctx.macho_file)});
+ for (dylib.symbols.items, 0..) |sym, i| {
+ const ref = dylib.getSymbolRef(@intCast(i), macho_file);
+ if (ref.getFile(macho_file) == null) {
+ // TODO any better way of handling this?
+ try writer.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
+ } else {
+ try writer.print(" {}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
+ }
}
}
src/link/MachO/file.zig
@@ -30,10 +30,10 @@ pub const File = union(enum) {
}
}
- pub fn resolveSymbols(file: File, macho_file: *MachO) void {
- switch (file) {
+ pub fn resolveSymbols(file: File, macho_file: *MachO) !void {
+ return switch (file) {
inline else => |x| x.resolveSymbols(macho_file),
- }
+ };
}
pub fn scanRelocs(file: File, macho_file: *MachO) !void {
@@ -147,19 +147,19 @@ pub const File = union(enum) {
if (ref.getFile(macho_file) == null) continue;
if (ref.file != file.getIndex()) continue;
const sym = ref.getSymbol(macho_file).?;
- if (sym.getSectionFlags().got) {
+ if (sym.flags.needs_got) {
log.debug("'{s}' needs GOT", .{sym.getName(macho_file)});
try macho_file.got.addSymbol(ref, macho_file);
}
- if (sym.getSectionFlags().stubs) {
+ if (sym.flags.stubs) {
log.debug("'{s}' needs STUBS", .{sym.getName(macho_file)});
try macho_file.stubs.addSymbol(ref, macho_file);
}
- if (sym.getSectionFlags().tlv_ptr) {
+ if (sym.flags.tlv_ptr) {
log.debug("'{s}' needs TLV pointer", .{sym.getName(macho_file)});
try macho_file.tlv_ptr.addSymbol(ref, macho_file);
}
- if (sym.getSectionFlags().objc_stubs) {
+ if (sym.flags.objc_stubs) {
log.debug("'{s}' needs OBJC STUBS", .{sym.getName(macho_file)});
try macho_file.objc_stubs.addSymbol(ref, macho_file);
}
@@ -171,7 +171,7 @@ pub const File = union(enum) {
defer tracy.end();
for (file.getAtoms()) |atom_index| {
const atom = file.getAtom(atom_index) orelse continue;
- if (!atom.alive.load(.seq_cst)) continue;
+ if (!atom.flags.alive) continue;
atom.out_n_sect = try Atom.initOutputSection(atom.getInputSection(macho_file), macho_file);
}
}
@@ -185,18 +185,18 @@ pub const File = union(enum) {
pub fn writeAtoms(file: File, macho_file: *MachO) !void {
return switch (file) {
- .dylib => unreachable,
+ .dylib, .zig_object => unreachable,
inline else => |x| x.writeAtoms(macho_file),
};
}
- pub fn calcSymtabSize(file: File, macho_file: *MachO) !void {
+ pub fn calcSymtabSize(file: File, macho_file: *MachO) void {
return switch (file) {
inline else => |x| x.calcSymtabSize(macho_file),
};
}
- pub fn writeSymtab(file: File, macho_file: *MachO, ctx: anytype) !void {
+ pub fn writeSymtab(file: File, macho_file: *MachO, ctx: anytype) void {
return switch (file) {
inline else => |x| x.writeSymtab(macho_file, ctx),
};
src/link/MachO/InternalObject.zig
@@ -16,7 +16,7 @@ objc_selrefs: [@sizeOf(u64)]u8 = [_]u8{0} ** @sizeOf(u64),
force_undefined: std.ArrayListUnmanaged(Symbol.Index) = .{},
entry_index: ?Symbol.Index = null,
dyld_stub_binder_index: ?Symbol.Index = null,
-dyld_private: ?Symbol.Index = null,
+dyld_private_index: ?Symbol.Index = null,
objc_msg_send_index: ?Symbol.Index = null,
mh_execute_header_index: ?Symbol.Index = null,
mh_dylib_header_index: ?Symbol.Index = null,
@@ -206,7 +206,7 @@ pub fn resolveBoundarySymbols(self: *InternalObject, macho_file: *MachO) !void {
const nlist_idx: u32 = @intCast(self.symtab.items.len);
const nlist = self.symtab.addOneAssumeCapacity();
nlist.* = .{
- .n_strx = name_off.pos,
+ .n_strx = name_off,
.n_type = macho.N_SECT,
.n_sect = 0,
.n_desc = 0,
@@ -273,7 +273,7 @@ fn addObjcMethnameSection(self: *InternalObject, methname: []const u8, macho_fil
const nlist_idx: u32 = @intCast(self.symtab.items.len);
const nlist = try self.symtab.addOne(gpa);
nlist.* = .{
- .n_strx = name_str.pos,
+ .n_strx = name_str,
.n_type = macho.N_SECT,
.n_sect = @intCast(n_sect + 1),
.n_desc = 0,
@@ -286,12 +286,12 @@ fn addObjcMethnameSection(self: *InternalObject, methname: []const u8, macho_fil
}
fn addObjcSelrefsSection(self: *InternalObject, methname_sym_index: Symbol.Index, macho_file: *MachO) !Symbol.Index {
- const gpa = macho_file.base.allocator;
+ const gpa = macho_file.base.comp.gpa;
const atom_index = try self.addAtom(gpa);
try self.atoms_indexes.append(gpa, atom_index);
const atom = self.getAtom(atom_index).?;
atom.size = @sizeOf(u64);
- atom.alignment = 3;
+ atom.alignment = .@"8";
const n_sect = try self.addSection(gpa, "__DATA", "__objc_selrefs");
const sect = &self.sections.items(.header)[n_sect];
@@ -389,7 +389,7 @@ pub fn resolveObjcMsgSendSymbols(self: *InternalObject, macho_file: *MachO) !voi
};
sym.nlist_idx = nlist_idx;
sym.extra = try self.addSymbolExtra(gpa, .{ .objc_selrefs = selrefs_index });
- sym.setSectionFlags(.{ .objc_stubs = true });
+ sym.flags.objc_stubs = true;
const idx = ref.getFile(macho_file).?.object.globals.items[ref.index];
try self.globals.append(gpa, idx);
@@ -417,7 +417,7 @@ pub fn resolveLiterals(self: *InternalObject, lp: *MachO.LiteralPool, macho_file
const target = rel.getTargetSymbol(atom.*, macho_file).getAtom(macho_file).?;
try buffer.ensureUnusedCapacity(target.size);
buffer.resize(target.size) catch unreachable;
- @memcpy(buffer.items, self.getSectionData(target.n_sect));
+ @memcpy(buffer.items, try self.getSectionData(target.n_sect));
const res = try lp.insert(gpa, header.type(), buffer.items);
buffer.clearRetainingCapacity();
if (!res.found_existing) {
@@ -425,7 +425,7 @@ pub fn resolveLiterals(self: *InternalObject, lp: *MachO.LiteralPool, macho_file
} else {
const lp_sym = lp.getSymbol(res.index, macho_file);
const lp_atom = lp_sym.getAtom(macho_file).?;
- lp_atom.alignment = @max(lp_atom.alignment, atom.alignment);
+ lp_atom.alignment = lp_atom.alignment.max(atom.alignment);
atom.flags.alive = false;
}
atom.addExtra(.{ .literal_pool_index = res.index }, macho_file);
@@ -438,7 +438,7 @@ pub fn dedupLiterals(self: *InternalObject, lp: MachO.LiteralPool, macho_file: *
for (self.getAtoms()) |atom_index| {
const atom = self.getAtom(atom_index) orelse continue;
- if (!atom.alive.load(.seq_cst)) continue;
+ if (!atom.flags.alive) continue;
const relocs = blk: {
const extra = atom.getExtra(macho_file);
@@ -463,7 +463,7 @@ pub fn dedupLiterals(self: *InternalObject, lp: MachO.LiteralPool, macho_file: *
}
for (self.symbols.items) |*sym| {
- if (!sym.getSectionFlags().objc_stubs) continue;
+ if (!sym.flags.objc_stubs) continue;
const extra = sym.getExtra(macho_file);
const file = sym.getFile(macho_file).?;
if (file.getIndex() != self.index) continue;
@@ -495,14 +495,14 @@ pub fn scanRelocs(self: *InternalObject, macho_file: *MachO) void {
if (self.getDyldStubBinderRef(macho_file)) |ref| {
if (ref.getFile(macho_file) != null) {
const sym = ref.getSymbol(macho_file).?;
- sym.flags.got = true;
+ sym.flags.needs_got = true;
}
}
if (self.getObjcMsgSendRef(macho_file)) |ref| {
if (ref.getFile(macho_file) != null) {
const sym = ref.getSymbol(macho_file).?;
// TODO is it always needed, or only if we are synthesising fast stubs
- sym.flags.got = true;
+ sym.flags.needs_got = true;
}
}
}
@@ -569,30 +569,30 @@ pub fn writeAtoms(self: *InternalObject, macho_file: *MachO) !void {
for (self.getAtoms()) |atom_index| {
const atom = self.getAtom(atom_index) orelse continue;
- if (!atom.alive.load(.seq_cst)) continue;
+ if (!atom.flags.alive) continue;
const sect = atom.getInputSection(macho_file);
if (sect.isZerofill()) continue;
const off = atom.value;
const buffer = macho_file.sections.items(.out)[atom.out_n_sect].items[off..][0..atom.size];
- @memcpy(buffer, self.getSectionData(atom.n_sect));
+ @memcpy(buffer, try self.getSectionData(atom.n_sect));
try atom.resolveRelocs(macho_file, buffer);
}
}
-pub fn writeSymtab(self: InternalObject, macho_file: *MachO) void {
+pub fn writeSymtab(self: InternalObject, macho_file: *MachO, ctx: anytype) void {
var n_strx = self.output_symtab_ctx.stroff;
for (self.symbols.items, 0..) |sym, i| {
const ref = self.getSymbolRef(@intCast(i), macho_file);
const file = ref.getFile(macho_file) orelse continue;
if (file.getIndex() != self.index) continue;
const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
- const out_sym = &macho_file.symtab.items[idx];
+ const out_sym = &ctx.symtab.items[idx];
out_sym.n_strx = n_strx;
sym.setOutputSym(macho_file, out_sym);
const name = sym.getName(macho_file);
- @memcpy(macho_file.strtab.items[n_strx..][0..name.len], name);
+ @memcpy(ctx.strtab.items[n_strx..][0..name.len], name);
n_strx += @intCast(name.len);
- macho_file.strtab.items[n_strx] = 0;
+ ctx.strtab.items[n_strx] = 0;
n_strx += 1;
}
}
@@ -640,7 +640,7 @@ pub fn asFile(self: *InternalObject) File {
}
pub fn getAtomRelocs(self: *const InternalObject, atom: Atom, macho_file: *MachO) []const Relocation {
- const extra = atom.getExtra(macho_file).?;
+ const extra = atom.getExtra(macho_file);
const relocs = self.sections.items(.relocs)[atom.n_sect];
return relocs.items[extra.rel_index..][0..extra.rel_count];
}
src/link/MachO/Object.zig
@@ -11,10 +11,10 @@ sections: std.MultiArrayList(Section) = .{},
symtab: std.MultiArrayList(Nlist) = .{},
strtab: std.ArrayListUnmanaged(u8) = .{},
-symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
+symbols: std.ArrayListUnmanaged(Symbol) = .{},
symbols_extra: std.ArrayListUnmanaged(u32) = .{},
globals: std.ArrayListUnmanaged(MachO.SymbolResolver.Index) = .{},
-atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
+atoms: std.ArrayListUnmanaged(Atom) = .{},
atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{},
atoms_extra: std.ArrayListUnmanaged(u32) = .{},
@@ -228,7 +228,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {
// Parse DWARF __TEXT,__eh_frame section
if (self.eh_frame_sect_index) |index| {
- try self.initEhFrameRecords(index, macho_file);
+ try self.initEhFrameRecords(gpa, index, handle, macho_file);
}
// Parse Apple's __LD,__compact_unwind section
@@ -261,7 +261,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {
try self.parseDebugInfo(macho_file);
- for (self.atoms.items) |atom_index| {
+ for (self.getAtoms()) |atom_index| {
const atom = self.getAtom(atom_index) orelse continue;
const isec = atom.getInputSection(macho_file);
if (mem.eql(u8, isec.sectName(), "__eh_frame") or
@@ -606,7 +606,7 @@ fn initPointerLiterals(self: *Object, allocator: Allocator, macho_file: *MachO)
}
}
-pub fn resolveLiterals(self: Object, lp: *MachO.LiteralPool, macho_file: *MachO) !void {
+pub fn resolveLiterals(self: *Object, lp: *MachO.LiteralPool, macho_file: *MachO) !void {
const tracy = trace(@src());
defer tracy.end();
@@ -646,7 +646,7 @@ pub fn resolveLiterals(self: Object, lp: *MachO.LiteralPool, macho_file: *MachO)
} else {
const lp_sym = lp.getSymbol(res.index, macho_file);
const lp_atom = lp_sym.getAtom(macho_file).?;
- lp_atom.alignment = @max(lp_atom.alignment, atom.alignment);
+ lp_atom.alignment = lp_atom.alignment.max(atom.alignment);
atom.flags.alive = false;
}
atom.addExtra(.{ .literal_pool_index = res.index }, macho_file);
@@ -684,7 +684,7 @@ pub fn resolveLiterals(self: Object, lp: *MachO.LiteralPool, macho_file: *MachO)
} else {
const lp_sym = lp.getSymbol(res.index, macho_file);
const lp_atom = lp_sym.getAtom(macho_file).?;
- lp_atom.alignment = @max(lp_atom.alignment, atom.alignment);
+ lp_atom.alignment = lp_atom.alignment.max(atom.alignment);
atom.flags.alive = false;
}
atom.addExtra(.{ .literal_pool_index = res.index }, macho_file);
@@ -823,7 +823,7 @@ fn initSymbols(self: *Object, allocator: Allocator, macho_file: *MachO) !void {
const index = self.addSymbolAssumeCapacity();
const symbol = &self.symbols.items[index];
symbol.value = nlist.n_value;
- symbol.name = .{ .pos = nlist.n_strx, .len = @intCast(self.getNStrx(nlist.n_strx).len + 1) };
+ symbol.name = nlist.n_strx;
symbol.nlist_idx = @intCast(i);
symbol.extra = self.addSymbolExtraAssumeCapacity(.{});
@@ -838,7 +838,9 @@ fn initSymbols(self: *Object, allocator: Allocator, macho_file: *MachO) !void {
symbol.flags.tentative = nlist.tentative();
symbol.flags.no_dead_strip = symbol.flags.no_dead_strip or nlist.noDeadStrip();
symbol.flags.dyn_ref = nlist.n_desc & macho.REFERENCED_DYNAMICALLY != 0;
- symbol.flags.interposable = nlist.ext() and (nlist.sect() or nlist.abs()) and macho_file.options.dylib and macho_file.options.namespace == .flat and !nlist.pext();
+ symbol.flags.interposable = nlist.ext() and (nlist.sect() or nlist.abs()) and macho_file.base.isDynLib() and !nlist.pext();
+ // TODO
+ // symbol.flags.interposable = nlist.ext() and (nlist.sect() or nlist.abs()) and macho_file.base.isDynLib() and macho_file.options.namespace == .flat and !nlist.pext();
if (nlist.sect() and
self.sections.items(.header)[nlist.n_sect - 1].type() == macho.S_THREAD_LOCAL_VARIABLES)
@@ -869,7 +871,7 @@ fn initSymbolStabs(self: *Object, allocator: Allocator, nlists: anytype, macho_f
fn find(fs: @This(), addr: u64) ?Symbol.Index {
// TODO binary search since we have the list sorted
for (fs.entries) |nlist| {
- if (nlist.nlist.n_value == addr) return fs.ctx.symbols.items[nlist.idx];
+ if (nlist.nlist.n_value == addr) return @intCast(nlist.idx);
}
return null;
}
@@ -920,17 +922,17 @@ fn initSymbolStabs(self: *Object, allocator: Allocator, nlists: anytype, macho_f
switch (nlist.n_type) {
macho.N_BNSYM => {
stab.is_func = true;
- stab.symbol = sym_lookup.find(nlist.n_value);
+ stab.index = sym_lookup.find(nlist.n_value);
// TODO validate
i += 3;
},
macho.N_GSYM => {
stab.is_func = false;
- stab.symbol = sym_lookup.find(addr_lookup.get(self.getString(nlist.n_strx)).?);
+ stab.index = sym_lookup.find(addr_lookup.get(self.getString(nlist.n_strx)).?);
},
macho.N_STSYM => {
stab.is_func = false;
- stab.symbol = sym_lookup.find(nlist.n_value);
+ stab.index = sym_lookup.find(nlist.n_value);
},
else => {
try macho_file.reportParseError2(self.index, "unhandled symbol stab type 0x{x}", .{
@@ -1103,9 +1105,9 @@ fn initUnwindRecords(self: *Object, allocator: Allocator, sect_id: u8, file: Fil
ctx: *const Object,
fn find(fs: @This(), addr: u64) ?Symbol.Index {
- for (fs.ctx.symbols.items, 0..) |sym_index, i| {
+ for (0..fs.ctx.symbols.items.len) |i| {
const nlist = fs.ctx.symtab.items(.nlist)[i];
- if (nlist.ext() and nlist.n_value == addr) return sym_index;
+ if (nlist.ext() and nlist.n_value == addr) return @intCast(i);
}
return null;
}
@@ -1274,7 +1276,7 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target.
// Create a null record
const rec_index = try self.addUnwindRecord(allocator);
const rec = self.getUnwindRecord(rec_index);
- const atom = macho_file.getAtom(meta.atom).?;
+ const atom = self.getAtom(meta.atom).?;
try self.unwind_records_indexes.append(allocator, rec_index);
rec.length = @intCast(meta.size);
rec.atom = meta.atom;
@@ -1468,17 +1470,17 @@ fn findCompileUnit(self: *Object, args: struct {
};
}
-pub fn resolveSymbols(self: *Object, macho_file: *MachO) void {
+pub fn resolveSymbols(self: *Object, macho_file: *MachO) !void {
const tracy = trace(@src());
defer tracy.end();
- const gpa = macho_file.base.allocator;
+ const gpa = macho_file.base.comp.gpa;
for (self.symtab.items(.nlist), self.symtab.items(.atom), self.globals.items, 0..) |nlist, atom_index, *global, i| {
if (!nlist.ext()) continue;
if (nlist.sect()) {
const atom = self.getAtom(atom_index).?;
- if (!atom.alive.load(.seq_cst)) continue;
+ if (!atom.flags.alive) continue;
}
const gop = try macho_file.resolver.getOrPut(gpa, .{
@@ -1643,7 +1645,7 @@ pub fn claimUnresolved(self: *Object, macho_file: *MachO) void {
if (self.getSymbolRef(@intCast(i), macho_file).getFile(macho_file) != null) continue;
- const is_import = switch (macho_file.options.undefined_treatment) {
+ const is_import = switch (macho_file.undefined_treatment) {
.@"error" => false,
.warn, .suppress => nlist.weakRef(),
.dynamic_lookup => true,
@@ -1682,8 +1684,8 @@ pub fn claimUnresolvedRelocatable(self: *Object, macho_file: *MachO) void {
}
}
-fn addSection(self: *Object, allocator: Allocator, segname: []const u8, sectname: []const u8) !u32 {
- const n_sect = @as(u32, @intCast(try self.sections.addOne(allocator)));
+fn addSection(self: *Object, allocator: Allocator, segname: []const u8, sectname: []const u8) !u8 {
+ const n_sect = @as(u8, @intCast(try self.sections.addOne(allocator)));
self.sections.set(n_sect, .{
.header = .{
.sectname = MachO.makeStaticString(sectname),
@@ -1799,7 +1801,7 @@ pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writ
try writer.writeAll(data);
}
-pub fn calcSymtabSize(self: *Object, macho_file: *MachO) !void {
+pub fn calcSymtabSize(self: *Object, macho_file: *MachO) void {
const tracy = trace(@src());
defer tracy.end();
@@ -1821,27 +1823,27 @@ pub fn calcSymtabSize(self: *Object, macho_file: *MachO) !void {
continue;
sym.flags.output_symtab = true;
if (sym.isLocal()) {
- try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, macho_file);
+ sym.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, macho_file);
self.output_symtab_ctx.nlocals += 1;
} else if (sym.flags.@"export") {
- try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nexports }, macho_file);
+ sym.addExtra(.{ .symtab = self.output_symtab_ctx.nexports }, macho_file);
self.output_symtab_ctx.nexports += 1;
} else {
assert(sym.flags.import);
- try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nimports }, macho_file);
+ sym.addExtra(.{ .symtab = self.output_symtab_ctx.nimports }, macho_file);
self.output_symtab_ctx.nimports += 1;
}
self.output_symtab_ctx.strsize += @as(u32, @intCast(sym.getName(macho_file).len + 1));
}
if (macho_file.base.comp.config.debug_format != .strip and self.hasDebugInfo())
- try self.calcStabsSize(macho_file);
+ self.calcStabsSize(macho_file);
}
-pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void {
+pub fn calcStabsSize(self: *Object, macho_file: *MachO) void {
if (self.compile_unit) |cu| {
- const comp_dir = cu.getCompDir(self);
- const tu_name = cu.getTuName(self);
+ const comp_dir = cu.getCompDir(self.*);
+ const tu_name = cu.getTuName(self.*);
self.output_symtab_ctx.nstabs += 4; // N_SO, N_SO, N_OSO, N_SO
self.output_symtab_ctx.strsize += @as(u32, @intCast(comp_dir.len + 1)); // comp_dir
@@ -1876,12 +1878,12 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void {
for (self.stab_files.items) |sf| {
self.output_symtab_ctx.nstabs += 4; // N_SO, N_SO, N_OSO, N_SO
- self.output_symtab_ctx.strsize += @as(u32, @intCast(sf.getCompDir(self).len + 1)); // comp_dir
- self.output_symtab_ctx.strsize += @as(u32, @intCast(sf.getTuName(self).len + 1)); // tu_name
- self.output_symtab_ctx.strsize += @as(u32, @intCast(sf.getOsoPath(self).len + 1)); // path
+ self.output_symtab_ctx.strsize += @as(u32, @intCast(sf.getCompDir(self.*).len + 1)); // comp_dir
+ self.output_symtab_ctx.strsize += @as(u32, @intCast(sf.getTuName(self.*).len + 1)); // tu_name
+ self.output_symtab_ctx.strsize += @as(u32, @intCast(sf.getOsoPath(self.*).len + 1)); // path
for (sf.stabs.items) |stab| {
- const sym = stab.getSymbol(macho_file) orelse continue;
+ const sym = stab.getSymbol(self.*) orelse continue;
const file = sym.getFile(macho_file).?;
if (file.getIndex() != self.index) continue;
if (!sym.flags.output_symtab) continue;
@@ -2065,7 +2067,7 @@ pub fn writeCompactUnwindRelocatable(self: *Object, macho_file: *MachO) !void {
}
}
-pub fn writeSymtab(self: Object, macho_file: *MachO) void {
+pub fn writeSymtab(self: Object, macho_file: *MachO, ctx: anytype) void {
const tracy = trace(@src());
defer tracy.end();
@@ -2075,21 +2077,21 @@ pub fn writeSymtab(self: Object, macho_file: *MachO) void {
const file = ref.getFile(macho_file) orelse continue;
if (file.getIndex() != self.index) continue;
const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
- const out_sym = &macho_file.symtab.items[idx];
+ const out_sym = &ctx.symtab.items[idx];
out_sym.n_strx = n_strx;
sym.setOutputSym(macho_file, out_sym);
const name = sym.getName(macho_file);
- @memcpy(macho_file.strtab.items[n_strx..][0..name.len], name);
+ @memcpy(ctx.strtab.items[n_strx..][0..name.len], name);
n_strx += @intCast(name.len);
- macho_file.strtab.items[n_strx] = 0;
+ ctx.strtab.items[n_strx] = 0;
n_strx += 1;
}
if (macho_file.base.comp.config.debug_format != .strip and self.hasDebugInfo())
- try self.writeStabs(n_strx, macho_file);
+ self.writeStabs(n_strx, macho_file, ctx);
}
-pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
+pub fn writeStabs(self: Object, stroff: u32, macho_file: *MachO, ctx: anytype) void {
const writeFuncStab = struct {
inline fn writeFuncStab(
n_strx: u32,
@@ -2097,7 +2099,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
n_value: u64,
size: u64,
index: u32,
- context: *MachO,
+ context: anytype,
) void {
context.symtab.items[index] = .{
.n_strx = 0,
@@ -2139,7 +2141,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
// Open scope
// N_SO comp_dir
- macho_file.symtab.items[index] = .{
+ ctx.symtab.items[index] = .{
.n_strx = n_strx,
.n_type = macho.N_SO,
.n_sect = 0,
@@ -2147,9 +2149,9 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
.n_value = 0,
};
index += 1;
- @memcpy(macho_file.strtab.items[n_strx..][0..comp_dir.len], comp_dir);
+ @memcpy(ctx.strtab.items[n_strx..][0..comp_dir.len], comp_dir);
n_strx += @intCast(comp_dir.len);
- macho_file.strtab.items[n_strx] = 0;
+ ctx.strtab.items[n_strx] = 0;
n_strx += 1;
// N_SO tu_name
macho_file.symtab.items[index] = .{
@@ -2160,12 +2162,12 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
.n_value = 0,
};
index += 1;
- @memcpy(macho_file.strtab.items[n_strx..][0..tu_name.len], tu_name);
+ @memcpy(ctx.strtab.items[n_strx..][0..tu_name.len], tu_name);
n_strx += @intCast(tu_name.len);
- macho_file.strtab.items[n_strx] = 0;
+ ctx.strtab.items[n_strx] = 0;
n_strx += 1;
// N_OSO path
- macho_file.symtab.items[index] = .{
+ ctx.symtab.items[index] = .{
.n_strx = n_strx,
.n_type = macho.N_OSO,
.n_sect = 0,
@@ -2174,20 +2176,20 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
};
index += 1;
if (self.in_archive) |ar| {
- @memcpy(macho_file.strtab.items[n_strx..][0..ar.path.len], ar.path);
+ @memcpy(ctx.strtab.items[n_strx..][0..ar.path.len], ar.path);
n_strx += @intCast(ar.path.len);
- macho_file.strtab.items[n_strx] = '(';
+ ctx.strtab.items[n_strx] = '(';
n_strx += 1;
- @memcpy(macho_file.strtab.items[n_strx..][0..self.path.len], self.path);
+ @memcpy(ctx.strtab.items[n_strx..][0..self.path.len], self.path);
n_strx += @intCast(self.path.len);
- macho_file.strtab.items[n_strx] = ')';
+ ctx.strtab.items[n_strx] = ')';
n_strx += 1;
- macho_file.strtab.items[n_strx] = 0;
+ ctx.strtab.items[n_strx] = 0;
n_strx += 1;
} else {
- @memcpy(macho_file.strtab.items[n_strx..][0..self.path.len], self.path);
+ @memcpy(ctx.strtab.items[n_strx..][0..self.path.len], self.path);
n_strx += @intCast(self.path.len);
- macho_file.strtab.items[n_strx] = 0;
+ ctx.strtab.items[n_strx] = 0;
n_strx += 1;
}
@@ -2203,17 +2205,17 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
const sect = macho_file.sections.items(.header)[sym.getOutputSectionIndex(macho_file)];
const sym_n_strx = n_strx: {
const symtab_index = sym.getOutputSymtabIndex(macho_file).?;
- const osym = macho_file.symtab.items[symtab_index];
+ const osym = ctx.symtab.items[symtab_index];
break :n_strx osym.n_strx;
};
const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.getOutputSectionIndex(macho_file) + 1) else 0;
const sym_n_value = sym.getAddress(.{}, macho_file);
const sym_size = sym.getSize(macho_file);
if (sect.isCode()) {
- writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, macho_file);
+ writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, ctx);
index += 4;
} else if (sym.visibility == .global) {
- macho_file.symtab.items[index] = .{
+ ctx.symtab.items[index] = .{
.n_strx = sym_n_strx,
.n_type = macho.N_GSYM,
.n_sect = sym_n_sect,
@@ -2222,7 +2224,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
};
index += 1;
} else {
- macho_file.symtab.items[index] = .{
+ ctx.symtab.items[index] = .{
.n_strx = sym_n_strx,
.n_type = macho.N_STSYM,
.n_sect = sym_n_sect,
@@ -2235,7 +2237,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
// Close scope
// N_SO
- macho_file.symtab.items[index] = .{
+ ctx.symtab.items[index] = .{
.n_strx = 0,
.n_type = macho.N_SO,
.n_sect = 0,
@@ -2246,13 +2248,13 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
assert(self.hasSymbolStabs());
for (self.stab_files.items) |sf| {
- const comp_dir = sf.getCombDir(self);
+ const comp_dir = sf.getCompDir(self);
const tu_name = sf.getTuName(self);
const oso_path = sf.getOsoPath(self);
// Open scope
// N_SO comp_dir
- macho_file.symtab.items[index] = .{
+ ctx.symtab.items[index] = .{
.n_strx = n_strx,
.n_type = macho.N_SO,
.n_sect = 0,
@@ -2260,12 +2262,12 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
.n_value = 0,
};
index += 1;
- @memcpy(macho_file.strtab.items[n_strx..][0..comp_dir.len], comp_dir);
+ @memcpy(ctx.strtab.items[n_strx..][0..comp_dir.len], comp_dir);
n_strx += @intCast(comp_dir.len);
- macho_file.strtab.items[n_strx] = 0;
+ ctx.strtab.items[n_strx] = 0;
n_strx += 1;
// N_SO tu_name
- macho_file.symtab.items[index] = .{
+ ctx.symtab.items[index] = .{
.n_strx = n_strx,
.n_type = macho.N_SO,
.n_sect = 0,
@@ -2273,12 +2275,12 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
.n_value = 0,
};
index += 1;
- @memcpy(macho_file.strtab.items[n_strx..][0..tu_name.len], tu_name);
+ @memcpy(ctx.strtab.items[n_strx..][0..tu_name.len], tu_name);
n_strx += @intCast(tu_name.len);
- macho_file.strtab.items[n_strx] = 0;
+ ctx.strtab.items[n_strx] = 0;
n_strx += 1;
// N_OSO path
- macho_file.symtab.items[index] = .{
+ ctx.symtab.items[index] = .{
.n_strx = n_strx,
.n_type = macho.N_OSO,
.n_sect = 0,
@@ -2286,29 +2288,29 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
.n_value = sf.getOsoModTime(self),
};
index += 1;
- @memcpy(macho_file.strtab.items[n_strx..][0..oso_path.len], oso_path);
+ @memcpy(ctx.strtab.items[n_strx..][0..oso_path.len], oso_path);
n_strx += @intCast(oso_path.len);
- macho_file.strtab.items[n_strx] = 0;
+ ctx.strtab.items[n_strx] = 0;
n_strx += 1;
for (sf.stabs.items) |stab| {
- const sym = stab.getSymbol(macho_file) orelse continue;
+ const sym = stab.getSymbol(self) orelse continue;
const file = sym.getFile(macho_file).?;
if (file.getIndex() != self.index) continue;
if (!sym.flags.output_symtab) continue;
const sym_n_strx = n_strx: {
const symtab_index = sym.getOutputSymtabIndex(macho_file).?;
- const osym = macho_file.symtab.items[symtab_index];
+ const osym = ctx.symtab.items[symtab_index];
break :n_strx osym.n_strx;
};
const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.getOutputSectionIndex(macho_file) + 1) else 0;
const sym_n_value = sym.getAddress(.{}, macho_file);
const sym_size = sym.getSize(macho_file);
if (stab.is_func) {
- writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, macho_file);
+ writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, ctx);
index += 4;
} else if (sym.visibility == .global) {
- macho_file.symtab.items[index] = .{
+ ctx.symtab.items[index] = .{
.n_strx = sym_n_strx,
.n_type = macho.N_GSYM,
.n_sect = sym_n_sect,
@@ -2317,7 +2319,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
};
index += 1;
} else {
- macho_file.symtab.items[index] = .{
+ ctx.symtab.items[index] = .{
.n_strx = sym_n_strx,
.n_type = macho.N_STSYM,
.n_sect = sym_n_sect,
@@ -2330,7 +2332,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
// Close scope
// N_SO
- macho_file.symtab.items[index] = .{
+ ctx.symtab.items[index] = .{
.n_strx = 0,
.n_type = macho.N_SO,
.n_sect = 0,
@@ -2343,7 +2345,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
}
pub fn getAtomRelocs(self: *const Object, atom: Atom, macho_file: *MachO) []const Relocation {
- const extra = atom.getExtra(macho_file).?;
+ const extra = atom.getExtra(macho_file);
const relocs = self.sections.items(.relocs)[atom.n_sect];
return relocs.items[extra.rel_index..][0..extra.rel_count];
}
@@ -2402,7 +2404,7 @@ pub fn asFile(self: *Object) File {
}
const AddAtomArgs = struct {
- name: MachO.String,
+ name: u32,
n_sect: u8,
off: u64,
size: u64,
@@ -2420,7 +2422,7 @@ fn addAtom(self: *Object, allocator: Allocator, args: AddAtomArgs) !Atom.Index {
.size = args.size,
.off = args.off,
.extra = try self.addAtomExtra(allocator, .{}),
- .alignment = args.alignment,
+ .alignment = Atom.Alignment.fromLog2Units(args.alignment),
};
return atom_index;
}
@@ -2693,12 +2695,12 @@ fn formatSymtab(
}
for (object.stab_files.items) |sf| {
try writer.print(" stabs({s},{s},{s})\n", .{
- sf.getCompDir(object),
- sf.getTuName(object),
- sf.getOsoPath(object),
+ sf.getCompDir(object.*),
+ sf.getTuName(object.*),
+ sf.getOsoPath(object.*),
});
for (sf.stabs.items) |stab| {
- try writer.print(" {}", .{stab.fmt(object)});
+ try writer.print(" {}", .{stab.fmt(object.*)});
}
}
}
@@ -2744,33 +2746,33 @@ const StabFile = struct {
comp_dir: u32,
stabs: std.ArrayListUnmanaged(Stab) = .{},
- fn getCompDir(sf: StabFile, object: *const Object) [:0]const u8 {
+ fn getCompDir(sf: StabFile, object: Object) [:0]const u8 {
const nlist = object.symtab.items(.nlist)[sf.comp_dir];
return object.getString(nlist.n_strx);
}
- fn getTuName(sf: StabFile, object: *const Object) [:0]const u8 {
+ fn getTuName(sf: StabFile, object: Object) [:0]const u8 {
const nlist = object.symtab.items(.nlist)[sf.comp_dir + 1];
return object.getString(nlist.n_strx);
}
- fn getOsoPath(sf: StabFile, object: *const Object) [:0]const u8 {
+ fn getOsoPath(sf: StabFile, object: Object) [:0]const u8 {
const nlist = object.symtab.items(.nlist)[sf.comp_dir + 2];
return object.getString(nlist.n_strx);
}
- fn getOsoModTime(sf: StabFile, object: *const Object) u64 {
+ fn getOsoModTime(sf: StabFile, object: Object) u64 {
const nlist = object.symtab.items(.nlist)[sf.comp_dir + 2];
return nlist.n_value;
}
const Stab = struct {
is_func: bool = true,
- symbol: ?Symbol.Index = null,
+ index: ?Symbol.Index = null,
- fn getSymbol(stab: Stab, object: *const Object) ?*Symbol {
+ fn getSymbol(stab: Stab, object: Object) ?Symbol {
const index = stab.index orelse return null;
- return &object.symbols.items[index];
+ return object.symbols.items[index];
}
pub fn format(
@@ -2786,9 +2788,9 @@ const StabFile = struct {
@compileError("do not format stabs directly");
}
- const StabFormatContext = struct { Stab, *const Object };
+ const StabFormatContext = struct { Stab, Object };
- pub fn fmt(stab: Stab, object: *const Object) std.fmt.Formatter(format2) {
+ pub fn fmt(stab: Stab, object: Object) std.fmt.Formatter(format2) {
return .{ .data = .{ stab, object } };
}
@@ -2817,11 +2819,11 @@ const CompileUnit = struct {
comp_dir: u32,
tu_name: u32,
- fn getCompDir(cu: CompileUnit, object: *const Object) [:0]const u8 {
+ fn getCompDir(cu: CompileUnit, object: Object) [:0]const u8 {
return object.getString(cu.comp_dir);
}
- fn getTuName(cu: CompileUnit, object: *const Object) [:0]const u8 {
+ fn getTuName(cu: CompileUnit, object: Object) [:0]const u8 {
return object.getString(cu.tu_name);
}
};
@@ -2840,15 +2842,14 @@ const CompactUnwindCtx = struct {
const x86_64 = struct {
fn parseRelocs(
- self: *const Object,
- n_sect: u8,
+ self: *Object,
sect: macho.section_64,
out: *std.ArrayListUnmanaged(Relocation),
+ handle: File.Handle,
macho_file: *MachO,
) !void {
const gpa = macho_file.base.comp.gpa;
- const handle = macho_file.getFileHandle(self.file_handle);
const relocs_buffer = try gpa.alloc(u8, sect.nreloc * @sizeOf(macho.relocation_info));
defer gpa.free(relocs_buffer);
{
@@ -2857,8 +2858,12 @@ const x86_64 = struct {
}
const relocs = @as([*]align(1) const macho.relocation_info, @ptrCast(relocs_buffer.ptr))[0..sect.nreloc];
- const code = try self.getSectionData(@intCast(n_sect), macho_file);
+ const code = try gpa.alloc(u8, sect.size);
defer gpa.free(code);
+ {
+ const amt = try handle.preadAll(code, sect.offset + self.offset);
+ if (amt != code.len) return error.InputOutput;
+ }
try out.ensureTotalCapacityPrecise(gpa, relocs.len);
@@ -2880,8 +2885,9 @@ const x86_64 = struct {
.X86_64_RELOC_SIGNED_4 => 4,
else => 0,
};
+ var is_extern = rel.r_extern == 1;
- const target = if (rel.r_extern == 0) blk: {
+ const target = if (!is_extern) blk: {
const nsect = rel.r_symbolnum - 1;
const taddr: i64 = if (rel.r_pcrel == 1)
@as(i64, @intCast(sect.addr)) + rel.r_address + addend + 4
@@ -2893,9 +2899,15 @@ const x86_64 = struct {
});
return error.MalformedObject;
};
- addend = taddr - @as(i64, @intCast(macho_file.getAtom(target).?.getInputAddress(macho_file)));
+ const target_atom = self.getAtom(target).?;
+ addend = taddr - @as(i64, @intCast(target_atom.getInputAddress(macho_file)));
+ const isec = target_atom.getInputSection(macho_file);
+ if (isCstringLiteral(isec) or isFixedSizeLiteral(isec) or isPtrLiteral(isec)) {
+ is_extern = true;
+ break :blk target_atom.getExtra(macho_file).literal_symbol_index;
+ }
break :blk target;
- } else self.symbols.items[rel.r_symbolnum];
+ } else rel.r_symbolnum;
const has_subtractor = if (i > 0 and
@as(macho.reloc_type_x86_64, @enumFromInt(relocs[i - 1].r_type)) == .X86_64_RELOC_SUBTRACTOR)
@@ -2909,7 +2921,7 @@ const x86_64 = struct {
break :blk true;
} else false;
- const @"type": Relocation.Type = validateRelocType(rel, rel_type) catch |err| {
+ const @"type": Relocation.Type = validateRelocType(rel, rel_type, is_extern) catch |err| {
switch (err) {
error.Pcrel => try macho_file.reportParseError2(
self.index,
@@ -2936,7 +2948,7 @@ const x86_64 = struct {
};
out.appendAssumeCapacity(.{
- .tag = if (rel.r_extern == 1) .@"extern" else .local,
+ .tag = if (is_extern) .@"extern" else .local,
.offset = @as(u32, @intCast(rel.r_address)),
.target = target,
.addend = addend,
@@ -2951,7 +2963,7 @@ const x86_64 = struct {
}
}
- fn validateRelocType(rel: macho.relocation_info, rel_type: macho.reloc_type_x86_64) !Relocation.Type {
+ fn validateRelocType(rel: macho.relocation_info, rel_type: macho.reloc_type_x86_64, is_extern: bool) !Relocation.Type {
switch (rel_type) {
.X86_64_RELOC_UNSIGNED => {
if (rel.r_pcrel == 1) return error.Pcrel;
@@ -2971,7 +2983,7 @@ const x86_64 = struct {
=> {
if (rel.r_pcrel == 0) return error.NonPcrel;
if (rel.r_length != 2) return error.InvalidLength;
- if (rel.r_extern == 0) return error.NonExtern;
+ if (!is_extern) return error.NonExtern;
return switch (rel_type) {
.X86_64_RELOC_BRANCH => .branch,
.X86_64_RELOC_GOT_LOAD => .got_load,
@@ -3002,15 +3014,14 @@ const x86_64 = struct {
const aarch64 = struct {
fn parseRelocs(
- self: *const Object,
- n_sect: u8,
+ self: *Object,
sect: macho.section_64,
out: *std.ArrayListUnmanaged(Relocation),
+ handle: File.Handle,
macho_file: *MachO,
) !void {
const gpa = macho_file.base.comp.gpa;
- const handle = macho_file.getFileHandle(self.file_handle);
const relocs_buffer = try gpa.alloc(u8, sect.nreloc * @sizeOf(macho.relocation_info));
defer gpa.free(relocs_buffer);
{
@@ -3019,8 +3030,12 @@ const aarch64 = struct {
}
const relocs = @as([*]align(1) const macho.relocation_info, @ptrCast(relocs_buffer.ptr))[0..sect.nreloc];
- const code = try self.getSectionData(@intCast(n_sect), macho_file);
+ const code = try gpa.alloc(u8, sect.size);
defer gpa.free(code);
+ {
+ const amt = try handle.preadAll(code, sect.offset + self.offset);
+ if (amt != code.len) return error.InputOutput;
+ }
try out.ensureTotalCapacityPrecise(gpa, relocs.len);
@@ -3066,8 +3081,9 @@ const aarch64 = struct {
}
const rel_type: macho.reloc_type_arm64 = @enumFromInt(rel.r_type);
+ var is_extern = rel.r_extern == 1;
- const target = if (rel.r_extern == 0) blk: {
+ const target = if (!is_extern) blk: {
const nsect = rel.r_symbolnum - 1;
const taddr: i64 = if (rel.r_pcrel == 1)
@as(i64, @intCast(sect.addr)) + rel.r_address + addend
@@ -3079,9 +3095,15 @@ const aarch64 = struct {
});
return error.MalformedObject;
};
- addend = taddr - @as(i64, @intCast(macho_file.getAtom(target).?.getInputAddress(macho_file)));
+ const target_atom = self.getAtom(target).?;
+ addend = taddr - @as(i64, @intCast(target_atom.getInputAddress(macho_file)));
+ const isec = target_atom.getInputSection(macho_file);
+ if (isCstringLiteral(isec) or isFixedSizeLiteral(isec) or isPtrLiteral(isec)) {
+ is_extern = true;
+ break :blk target_atom.getExtra(macho_file).literal_symbol_index;
+ }
break :blk target;
- } else self.symbols.items[rel.r_symbolnum];
+ } else rel.r_symbolnum;
const has_subtractor = if (i > 0 and
@as(macho.reloc_type_arm64, @enumFromInt(relocs[i - 1].r_type)) == .ARM64_RELOC_SUBTRACTOR)
@@ -3095,7 +3117,7 @@ const aarch64 = struct {
break :blk true;
} else false;
- const @"type": Relocation.Type = validateRelocType(rel, rel_type) catch |err| {
+ const @"type": Relocation.Type = validateRelocType(rel, rel_type, is_extern) catch |err| {
switch (err) {
error.Pcrel => try macho_file.reportParseError2(
self.index,
@@ -3122,7 +3144,7 @@ const aarch64 = struct {
};
out.appendAssumeCapacity(.{
- .tag = if (rel.r_extern == 1) .@"extern" else .local,
+ .tag = if (is_extern) .@"extern" else .local,
.offset = @as(u32, @intCast(rel.r_address)),
.target = target,
.addend = addend,
@@ -3137,7 +3159,7 @@ const aarch64 = struct {
}
}
- fn validateRelocType(rel: macho.relocation_info, rel_type: macho.reloc_type_arm64) !Relocation.Type {
+ fn validateRelocType(rel: macho.relocation_info, rel_type: macho.reloc_type_arm64, is_extern: bool) !Relocation.Type {
switch (rel_type) {
.ARM64_RELOC_UNSIGNED => {
if (rel.r_pcrel == 1) return error.Pcrel;
@@ -3158,7 +3180,7 @@ const aarch64 = struct {
=> {
if (rel.r_pcrel == 0) return error.NonPcrel;
if (rel.r_length != 2) return error.InvalidLength;
- if (rel.r_extern == 0) return error.NonExtern;
+ if (!is_extern) return error.NonExtern;
return switch (rel_type) {
.ARM64_RELOC_BRANCH26 => .branch,
.ARM64_RELOC_PAGE21 => .page,
@@ -3175,7 +3197,7 @@ const aarch64 = struct {
=> {
if (rel.r_pcrel == 1) return error.Pcrel;
if (rel.r_length != 2) return error.InvalidLength;
- if (rel.r_extern == 0) return error.NonExtern;
+ if (!is_extern) return error.NonExtern;
return switch (rel_type) {
.ARM64_RELOC_PAGEOFF12 => .pageoff,
.ARM64_RELOC_GOT_LOAD_PAGEOFF12 => .got_load_pageoff,
src/link/MachO/Symbol.zig
@@ -150,7 +150,7 @@ pub fn getObjcSelrefsAddress(symbol: Symbol, macho_file: *MachO) u64 {
const file = symbol.getFile(macho_file).?;
return switch (file) {
.dylib, .zig_object => unreachable,
- .object, .internal => |x| x.symbols.items[extra.objc_selrefs].getAddress(.{}, macho_file),
+ inline else => |x| x.symbols.items[extra.objc_selrefs].getAddress(.{}, macho_file),
};
}
@@ -186,7 +186,7 @@ pub fn getOutputSymtabIndex(symbol: Symbol, macho_file: *MachO) ?u32 {
const symtab_ctx = switch (file) {
inline else => |x| x.output_symtab_ctx,
};
- var idx = symbol.getExtra(macho_file).?.symtab;
+ var idx = symbol.getExtra(macho_file).symtab;
if (symbol.isLocal()) {
idx += symtab_ctx.ilocal;
} else if (symbol.flags.@"export") {
src/link/MachO/synthetic.zig
@@ -23,7 +23,7 @@ pub const ZigGotSection = struct {
const index = try zig_got.allocateEntry(gpa);
const entry = &zig_got.entries.items[index];
entry.* = sym_index;
- const symbol = zo.getSymbol(sym_index);
+ const symbol = &zo.symbols.items[sym_index];
assert(symbol.flags.needs_zig_got);
symbol.flags.has_zig_got = true;
symbol.addExtra(.{ .zig_got = index }, macho_file);
@@ -56,7 +56,7 @@ pub const ZigGotSection = struct {
const zo = macho_file.getZigObject().?;
const off = zig_got.entryOffset(index, macho_file);
const entry = zig_got.entries.items[index];
- const value = zo.getSymbol(entry).getAddress(.{ .stubs = false }, macho_file);
+ const value = zo.symbols.items[entry].getAddress(.{ .stubs = false }, macho_file);
var buf: [8]u8 = undefined;
std.mem.writeInt(u64, &buf, value, .little);
@@ -66,7 +66,7 @@ pub const ZigGotSection = struct {
pub fn writeAll(zig_got: ZigGotSection, macho_file: *MachO, writer: anytype) !void {
const zo = macho_file.getZigObject().?;
for (zig_got.entries.items) |entry| {
- const symbol = zo.getSymbol(entry);
+ const symbol = zo.symbols.items[entry];
const value = symbol.address(.{ .stubs = false }, macho_file);
try writer.writeInt(u64, value, .little);
}
@@ -94,7 +94,7 @@ pub const ZigGotSection = struct {
const zo = macho_file.getZigObject().?;
try writer.writeAll("__zig_got\n");
for (zig_got.entries.items, 0..) |entry, index| {
- const symbol = zo.getSymbol(entry);
+ const symbol = zo.symbols.items[entry];
try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
index,
zig_got.entryAddress(@intCast(index), macho_file),
@@ -694,7 +694,7 @@ pub const DataInCode = struct {
dices[next_dice].offset < end_off) : (next_dice += 1)
{}
- if (atom.alive.load(.seq_cst)) for (dices[start_dice..next_dice]) |d| {
+ if (atom.flags.alive) for (dices[start_dice..next_dice]) |d| {
dice.entries.appendAssumeCapacity(.{
.offset = @intCast(atom.getAddress(macho_file) + d.offset - start_off - base_address),
.length = d.length,
src/link/MachO/thunks.zig
@@ -37,7 +37,7 @@ pub fn createThunks(sect_id: u8, macho_file: *MachO) !void {
// Scan relocs in the group and create trampolines for any unreachable callsite
try scanRelocs(thunk_index, gpa, atoms[start..i], macho_file);
- thunk.value = try advance(header, thunk.size(), .@"4");
+ thunk.value = advance(header, thunk.size(), .@"4");
log.debug("thunk({d}) : {}", .{ thunk_index, thunk.fmt(macho_file) });
}
@@ -99,8 +99,8 @@ pub const Thunk = struct {
return header.addr + thunk.value;
}
- pub fn getTargetAddress(thunk: Thunk, sym_index: Symbol.Index, macho_file: *MachO) u64 {
- return thunk.getAddress(macho_file) + thunk.symbols.getIndex(sym_index).? * trampoline_size;
+ pub fn getTargetAddress(thunk: Thunk, ref: MachO.Ref, macho_file: *MachO) u64 {
+ return thunk.getAddress(macho_file) + thunk.symbols.getIndex(ref).? * trampoline_size;
}
pub fn write(thunk: Thunk, macho_file: *MachO, writer: anytype) !void {
src/link/MachO/UnwindInfo.zig
@@ -473,11 +473,11 @@ pub const Record = struct {
}
pub fn getAtom(rec: Record, macho_file: *MachO) *Atom {
- return macho_file.getAtom(rec.atom).?;
+ return rec.getObject(macho_file).getAtom(rec.atom).?;
}
pub fn getLsdaAtom(rec: Record, macho_file: *MachO) ?*Atom {
- return macho_file.getAtom(rec.lsda);
+ return rec.getObject(macho_file).getAtom(rec.lsda);
}
pub fn getPersonality(rec: Record, macho_file: *MachO) ?*Symbol {
src/link/MachO/ZigObject.zig
@@ -343,6 +343,36 @@ pub fn writeAr(self: ZigObject, ar_format: Archive.Format, writer: anytype) !voi
try writer.writeAll(self.data.items);
}
+pub fn claimUnresolved(self: *ZigObject, macho_file: *MachO) void {
+ const tracy = trace(@src());
+ defer tracy.end();
+
+ for (self.symbols.items, 0..) |*sym, i| {
+ const nlist = self.symtab.items(.nlist)[i];
+ if (!nlist.ext()) continue;
+ if (!nlist.undf()) continue;
+
+ if (self.getSymbolRef(@intCast(i), macho_file).getFile(macho_file) != null) continue;
+
+ const is_import = switch (macho_file.undefined_treatment) {
+ .@"error" => false,
+ .warn, .suppress => nlist.weakRef(),
+ .dynamic_lookup => true,
+ };
+ if (is_import) {
+ sym.value = 0;
+ sym.atom_ref = .{ .index = 0, .file = 0 };
+ sym.flags.weak = false;
+ sym.flags.weak_ref = nlist.weakRef();
+ sym.flags.import = is_import;
+ sym.visibility = .global;
+
+ const idx = self.globals.items[i];
+ macho_file.resolver.values.items[idx - 1] = .{ .index = @intCast(i), .file = self.index };
+ }
+ }
+}
+
pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void {
for (self.getAtoms()) |atom_index| {
const atom = self.getAtom(atom_index) orelse continue;
@@ -378,7 +408,7 @@ pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) void {
}
}
-pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void {
+pub fn writeSymtab(self: ZigObject, macho_file: *MachO, ctx: anytype) void {
const tracy = trace(@src());
defer tracy.end();
@@ -388,13 +418,13 @@ pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void {
const file = ref.getFile(macho_file) orelse continue;
if (file.getIndex() != self.index) continue;
const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
- const out_sym = &macho_file.symtab.items[idx];
+ const out_sym = &ctx.symtab.items[idx];
out_sym.n_strx = n_strx;
sym.setOutputSym(macho_file, out_sym);
const name = sym.getName(macho_file);
- @memcpy(macho_file.strtab.items[n_strx..][0..name.len], name);
+ @memcpy(ctx.strtab.items[n_strx..][0..name.len], name);
n_strx += @intCast(name.len);
- macho_file.strtab.items[n_strx] = 0;
+ ctx.strtab.items[n_strx] = 0;
n_strx += 1;
}
}
@@ -1098,7 +1128,7 @@ pub fn lowerUnnamedConst(
},
};
const sym = self.symbols.items[sym_index];
- try unnamed_consts.append(gpa, sym.atom);
+ try unnamed_consts.append(gpa, sym.atom_ref.index);
return sym_index;
}
src/link/MachO.zig
@@ -529,7 +529,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
dylib.ordinal = @intCast(ord);
}
- try self.claimUnresolved();
+ self.claimUnresolved();
self.scanRelocs() catch |err| switch (err) {
error.HasUndefinedSymbols => return error.FlushFailure,
@@ -603,7 +603,12 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
if (has_resolve_error) return error.FlushFailure;
}
- try self.writeSectionsAndUpdateLinkeditSizes();
+ self.writeSectionsAndUpdateLinkeditSizes() catch |err| {
+ switch (err) {
+ error.ResolveFailed => return error.FlushFailure,
+ else => |e| return e,
+ }
+ };
try self.writeSectionsToFile();
try self.allocateLinkeditSegment();
@@ -1450,12 +1455,12 @@ pub fn dedupLiterals(self: *MachO) !void {
}
}
-fn claimUnresolved(self: *MachO) error{OutOfMemory}!void {
+fn claimUnresolved(self: *MachO) void {
if (self.getZigObject()) |zo| {
- try zo.asFile().claimUnresolved(self);
+ zo.claimUnresolved(self);
}
for (self.objects.items) |index| {
- try self.getFile(index).?.claimUnresolved(self);
+ self.getFile(index).?.object.claimUnresolved(self);
}
}
@@ -2402,7 +2407,7 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {
}
if (self.la_symbol_ptr_sect_index) |_| {
- try self.updatelazyBindSize();
+ try self.updateLazyBindSize();
}
try self.rebase.updateSize(self);
@@ -2412,16 +2417,16 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {
try self.data_in_code.updateSize(self);
if (self.getZigObject()) |zo| {
- zo.asFile().writeSymtab(self);
+ zo.asFile().writeSymtab(self, self);
}
for (self.objects.items) |index| {
- self.getFile(index).?.writeSymtab(self);
+ self.getFile(index).?.writeSymtab(self, self);
}
for (self.dylibs.items) |index| {
- self.getFile(index).?.writeSymtab(self);
+ self.getFile(index).?.writeSymtab(self, self);
}
if (self.getInternalObject()) |obj| {
- obj.asFile().writeSymtab(self);
+ obj.asFile().writeSymtab(self, self);
}
}
@@ -2484,7 +2489,7 @@ fn writeSectionsToFile(self: *MachO) !void {
const slice = self.sections.slice();
for (slice.items(.header), slice.items(.out)) |header, out| {
- try self.base.file.pwriteAll(out.items, header.offset);
+ try self.base.file.?.pwriteAll(out.items, header.offset);
}
}
@@ -2501,7 +2506,7 @@ fn writeDyldInfo(self: *MachO) !void {
const tracy = trace(@src());
defer tracy.end();
- const gpa = self.base.allocator;
+ const gpa = self.base.comp.gpa;
const base_off = self.getLinkeditSegment().fileoff;
const cmd = self.dyld_info_cmd;
var needed_size: u32 = 0;
@@ -2527,14 +2532,14 @@ fn writeDyldInfo(self: *MachO) !void {
try self.lazy_bind.write(writer);
try stream.seekTo(cmd.export_off - base_off);
try self.export_trie.write(writer);
- try self.base.file.pwriteAll(buffer, cmd.rebase_off);
+ try self.base.file.?.pwriteAll(buffer, cmd.rebase_off);
}
pub fn writeDataInCode(self: *MachO) !void {
const tracy = trace(@src());
defer tracy.end();
const cmd = self.data_in_code_cmd;
- try self.base.file.pwriteAll(mem.sliceAsBytes(self.data_in_code.entries.items), cmd.dataoff);
+ try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.data_in_code.entries.items), cmd.dataoff);
}
fn writeIndsymtab(self: *MachO) !void {
@@ -2546,15 +2551,15 @@ fn writeIndsymtab(self: *MachO) !void {
var buffer = try std.ArrayList(u8).initCapacity(gpa, needed_size);
defer buffer.deinit();
try self.indsymtab.write(self, buffer.writer());
- try self.base.file.pwriteAll(buffer.items, cmd.indirectsymoff);
+ try self.base.file.?.pwriteAll(buffer.items, cmd.indirectsymoff);
}
pub fn writeSymtabToFile(self: *MachO) !void {
const tracy = trace(@src());
defer tracy.end();
const cmd = self.symtab_cmd;
- try self.base.file.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff);
- try self.base.file.pwriteAll(self.strtab.items, cmd.stroff);
+ try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff);
+ try self.base.file.?.pwriteAll(self.strtab.items, cmd.stroff);
}
fn writeUnwindInfo(self: *MachO) !void {
@@ -2687,18 +2692,20 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
try load_commands.writeDylinkerLC(writer);
ncmds += 1;
- if (self.entry_index) |global_index| {
- const sym = self.getSymbol(global_index);
- const seg = self.getTextSegment();
- const entryoff: u32 = if (sym.getFile(self) == null)
- 0
- else
- @as(u32, @intCast(sym.getAddress(.{ .stubs = true }, self) - seg.vmaddr));
- try writer.writeStruct(macho.entry_point_command{
- .entryoff = entryoff,
- .stacksize = self.base.stack_size,
- });
- ncmds += 1;
+ if (self.getInternalObject()) |obj| {
+ if (obj.getEntryRef(self)) |ref| {
+ const sym = ref.getSymbol(self).?;
+ const seg = self.getTextSegment();
+ const entryoff: u32 = if (sym.getFile(self) == null)
+ 0
+ else
+ @as(u32, @intCast(sym.getAddress(.{ .stubs = true }, self) - seg.vmaddr));
+ try writer.writeStruct(macho.entry_point_command{
+ .entryoff = entryoff,
+ .stacksize = self.base.stack_size,
+ });
+ ncmds += 1;
+ }
}
if (self.base.isDynLib()) {