mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
macho: refactor common logic between synthetic tables
This commit is contained in:
parent
38ecaf3ab6
commit
ef645ab175
3 changed files with 147 additions and 161 deletions
|
|
@ -5,7 +5,6 @@ const build_options = @import("build_options");
|
|||
const builtin = @import("builtin");
|
||||
const assert = std.debug.assert;
|
||||
const dwarf = std.dwarf;
|
||||
const fmt = std.fmt;
|
||||
const fs = std.fs;
|
||||
const log = std.log.scoped(.link);
|
||||
const macho = std.macho;
|
||||
|
|
@ -155,13 +154,9 @@ stub_helper_preamble_atom_index: ?Atom.Index = null,
|
|||
|
||||
strtab: StringTable(.strtab) = .{},
|
||||
|
||||
got_entries: std.ArrayListUnmanaged(Entry) = .{},
|
||||
got_entries_free_list: std.ArrayListUnmanaged(u32) = .{},
|
||||
got_entries_table: std.AutoHashMapUnmanaged(SymbolWithLoc, u32) = .{},
|
||||
|
||||
stubs: std.ArrayListUnmanaged(Entry) = .{},
|
||||
stubs_free_list: std.ArrayListUnmanaged(u32) = .{},
|
||||
stubs_table: std.AutoHashMapUnmanaged(SymbolWithLoc, u32) = .{},
|
||||
got_table: SectionTable = .{},
|
||||
stubs_table: SectionTable = .{},
|
||||
tlvp_table: SectionTable = .{},
|
||||
|
||||
error_flags: File.ErrorFlags = File.ErrorFlags{},
|
||||
|
||||
|
|
@ -270,26 +265,120 @@ const DeclMetadata = struct {
|
|||
}
|
||||
};
|
||||
|
||||
const Entry = struct {
|
||||
target: SymbolWithLoc,
|
||||
// Index into the synthetic symbol table (i.e., file == null).
|
||||
sym_index: u32,
|
||||
const SectionTable = struct {
|
||||
entries: std.ArrayListUnmanaged(Entry) = .{},
|
||||
free_list: std.ArrayListUnmanaged(u32) = .{},
|
||||
lookup: std.AutoHashMapUnmanaged(SymbolWithLoc, u32) = .{},
|
||||
|
||||
pub fn getSymbol(entry: Entry, macho_file: *MachO) macho.nlist_64 {
|
||||
return macho_file.getSymbol(.{ .sym_index = entry.sym_index, .file = null });
|
||||
pub fn deinit(st: *ST, allocator: Allocator) void {
|
||||
st.entries.deinit(allocator);
|
||||
st.free_list.deinit(allocator);
|
||||
st.lookup.deinit(allocator);
|
||||
}
|
||||
|
||||
pub fn getSymbolPtr(entry: Entry, macho_file: *MachO) *macho.nlist_64 {
|
||||
return macho_file.getSymbolPtr(.{ .sym_index = entry.sym_index, .file = null });
|
||||
pub fn allocateEntry(st: *ST, allocator: Allocator, target: SymbolWithLoc) !u32 {
|
||||
try st.entries.ensureUnusedCapacity(allocator, 1);
|
||||
const index = blk: {
|
||||
if (st.free_list.popOrNull()) |index| {
|
||||
log.debug(" (reusing entry index {d})", .{index});
|
||||
break :blk index;
|
||||
} else {
|
||||
log.debug(" (allocating entry at index {d})", .{st.entries.items.len});
|
||||
const index = @intCast(u32, st.entries.items.len);
|
||||
_ = st.entries.addOneAssumeCapacity();
|
||||
break :blk index;
|
||||
}
|
||||
};
|
||||
st.entries.items[index] = .{ .target = target, .sym_index = 0 };
|
||||
try st.lookup.putNoClobber(allocator, target, index);
|
||||
return index;
|
||||
}
|
||||
|
||||
pub fn getAtomIndex(entry: Entry, macho_file: *MachO) ?Atom.Index {
|
||||
return macho_file.getAtomIndexForSymbol(.{ .sym_index = entry.sym_index, .file = null });
|
||||
pub fn freeEntry(st: *ST, allocator: Allocator, target: SymbolWithLoc) void {
|
||||
const index = st.lookup.get(target) orelse return;
|
||||
st.free_list.append(allocator, index) catch {};
|
||||
st.entries.items[index] = .{
|
||||
.target = .{ .sym_index = 0 },
|
||||
.sym_index = 0,
|
||||
};
|
||||
_ = st.lookup.remove(target);
|
||||
}
|
||||
|
||||
pub fn getName(entry: Entry, macho_file: *MachO) []const u8 {
|
||||
return macho_file.getSymbolName(.{ .sym_index = entry.sym_index, .file = null });
|
||||
pub fn getAtomIndex(st: *const ST, macho_file: *MachO, target: SymbolWithLoc) ?Atom.Index {
|
||||
const index = st.lookup.get(target) orelse return null;
|
||||
return st.entries.items[index].getAtomIndex(macho_file);
|
||||
}
|
||||
|
||||
const FormatContext = struct {
|
||||
macho_file: *MachO,
|
||||
st: *const ST,
|
||||
};
|
||||
|
||||
fn fmt(
|
||||
ctx: FormatContext,
|
||||
comptime unused_format_string: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
) @TypeOf(writer).Error!void {
|
||||
_ = options;
|
||||
comptime assert(unused_format_string.len == 0);
|
||||
try writer.writeAll("SectionTable:\n");
|
||||
for (ctx.st.entries.items, 0..) |entry, i| {
|
||||
const atom_sym = entry.getSymbol(ctx.macho_file);
|
||||
const target_sym = ctx.macho_file.getSymbol(entry.target);
|
||||
try writer.print(" {d}@{x} => ", .{ i, atom_sym.n_value });
|
||||
if (target_sym.undf()) {
|
||||
try writer.print("import('{s}')", .{
|
||||
ctx.macho_file.getSymbolName(entry.target),
|
||||
});
|
||||
} else {
|
||||
try writer.print("local(%{d}) in object({?d})", .{
|
||||
entry.target.sym_index,
|
||||
entry.target.file,
|
||||
});
|
||||
}
|
||||
try writer.writeByte('\n');
|
||||
}
|
||||
}
|
||||
|
||||
fn format(st: *const ST, comptime unused_format_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
|
||||
_ = st;
|
||||
_ = unused_format_string;
|
||||
_ = options;
|
||||
_ = writer;
|
||||
@compileError("do not format SectionTable directly; use st.fmtDebug()");
|
||||
}
|
||||
|
||||
pub fn fmtDebug(st: *const ST, macho_file: *MachO) std.fmt.Formatter(fmt) {
|
||||
return .{ .data = .{
|
||||
.macho_file = macho_file,
|
||||
.st = st,
|
||||
} };
|
||||
}
|
||||
|
||||
const ST = @This();
|
||||
|
||||
const Entry = struct {
|
||||
target: SymbolWithLoc,
|
||||
// Index into the synthetic symbol table (i.e., file == null).
|
||||
sym_index: u32,
|
||||
|
||||
pub fn getSymbol(entry: Entry, macho_file: *MachO) macho.nlist_64 {
|
||||
return macho_file.getSymbol(.{ .sym_index = entry.sym_index });
|
||||
}
|
||||
|
||||
pub fn getSymbolPtr(entry: Entry, macho_file: *MachO) *macho.nlist_64 {
|
||||
return macho_file.getSymbolPtr(.{ .sym_index = entry.sym_index });
|
||||
}
|
||||
|
||||
pub fn getAtomIndex(entry: Entry, macho_file: *MachO) ?Atom.Index {
|
||||
return macho_file.getAtomIndexForSymbol(.{ .sym_index = entry.sym_index });
|
||||
}
|
||||
|
||||
pub fn getName(entry: Entry, macho_file: *MachO) []const u8 {
|
||||
return macho_file.getSymbolName(.{ .sym_index = entry.sym_index });
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Binding));
|
||||
|
|
@ -399,7 +488,7 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
|
|||
// Create dSYM bundle.
|
||||
log.debug("creating {s}.dSYM bundle", .{sub_path});
|
||||
|
||||
const d_sym_path = try fmt.allocPrint(
|
||||
const d_sym_path = try std.fmt.allocPrint(
|
||||
allocator,
|
||||
"{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF",
|
||||
.{sub_path},
|
||||
|
|
@ -613,9 +702,9 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
|
|||
if (self.dyld_stub_binder_index == null) {
|
||||
self.dyld_stub_binder_index = try self.addUndefined("dyld_stub_binder", .add_got);
|
||||
}
|
||||
if (!self.base.options.single_threaded) {
|
||||
_ = try self.addUndefined("_tlv_bootstrap", .none);
|
||||
}
|
||||
// if (!self.base.options.single_threaded) {
|
||||
// _ = try self.addUndefined("_tlv_bootstrap", .none);
|
||||
// }
|
||||
|
||||
try self.createMhExecuteHeaderSymbol();
|
||||
|
||||
|
|
@ -1757,12 +1846,9 @@ pub fn deinit(self: *MachO) void {
|
|||
d_sym.deinit();
|
||||
}
|
||||
|
||||
self.got_entries.deinit(gpa);
|
||||
self.got_entries_free_list.deinit(gpa);
|
||||
self.got_entries_table.deinit(gpa);
|
||||
self.stubs.deinit(gpa);
|
||||
self.stubs_free_list.deinit(gpa);
|
||||
self.got_table.deinit(gpa);
|
||||
self.stubs_table.deinit(gpa);
|
||||
self.tlvp_table.deinit(gpa);
|
||||
self.strtab.deinit(gpa);
|
||||
|
||||
self.locals.deinit(gpa);
|
||||
|
|
@ -1895,20 +1981,10 @@ fn freeAtom(self: *MachO, atom_index: Atom.Index) void {
|
|||
self.locals_free_list.append(gpa, sym_index) catch {};
|
||||
|
||||
// Try freeing GOT atom if this decl had one
|
||||
const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null };
|
||||
if (self.got_entries_table.get(got_target)) |got_index| {
|
||||
self.got_entries_free_list.append(gpa, @intCast(u32, got_index)) catch {};
|
||||
self.got_entries.items[got_index] = .{
|
||||
.target = .{ .sym_index = 0, .file = null },
|
||||
.sym_index = 0,
|
||||
};
|
||||
_ = self.got_entries_table.remove(got_target);
|
||||
self.got_table.freeEntry(gpa, .{ .sym_index = sym_index });
|
||||
|
||||
if (self.d_sym) |*d_sym| {
|
||||
d_sym.swapRemoveRelocs(sym_index);
|
||||
}
|
||||
|
||||
log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index });
|
||||
if (self.d_sym) |*d_sym| {
|
||||
d_sym.swapRemoveRelocs(sym_index);
|
||||
}
|
||||
|
||||
self.locals.items[sym_index].n_type = 0;
|
||||
|
|
@ -1983,70 +2059,25 @@ fn allocateGlobal(self: *MachO) !u32 {
|
|||
return index;
|
||||
}
|
||||
|
||||
fn allocateGotEntry(self: *MachO, target: SymbolWithLoc) !u32 {
|
||||
const gpa = self.base.allocator;
|
||||
try self.got_entries.ensureUnusedCapacity(gpa, 1);
|
||||
|
||||
const index = blk: {
|
||||
if (self.got_entries_free_list.popOrNull()) |index| {
|
||||
log.debug(" (reusing GOT entry index {d})", .{index});
|
||||
break :blk index;
|
||||
} else {
|
||||
log.debug(" (allocating GOT entry at index {d})", .{self.got_entries.items.len});
|
||||
const index = @intCast(u32, self.got_entries.items.len);
|
||||
_ = self.got_entries.addOneAssumeCapacity();
|
||||
break :blk index;
|
||||
}
|
||||
};
|
||||
|
||||
self.got_entries.items[index] = .{ .target = target, .sym_index = 0 };
|
||||
try self.got_entries_table.putNoClobber(gpa, target, index);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
fn addGotEntry(self: *MachO, target: SymbolWithLoc) !void {
|
||||
if (self.got_entries_table.contains(target)) return;
|
||||
|
||||
const got_index = try self.allocateGotEntry(target);
|
||||
if (self.got_table.lookup.contains(target)) return;
|
||||
const got_index = try self.got_table.allocateEntry(self.base.allocator, target);
|
||||
const got_atom_index = try self.createGotAtom(target);
|
||||
const got_atom = self.getAtom(got_atom_index);
|
||||
self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?;
|
||||
self.got_table.entries.items[got_index].sym_index = got_atom.getSymbolIndex().?;
|
||||
try self.writePtrWidthAtom(got_atom_index);
|
||||
}
|
||||
|
||||
fn allocateStubEntry(self: *MachO, target: SymbolWithLoc) !u32 {
|
||||
try self.stubs.ensureUnusedCapacity(self.base.allocator, 1);
|
||||
|
||||
const index = blk: {
|
||||
if (self.stubs_free_list.popOrNull()) |index| {
|
||||
log.debug(" (reusing stub entry index {d})", .{index});
|
||||
break :blk index;
|
||||
} else {
|
||||
log.debug(" (allocating stub entry at index {d})", .{self.stubs.items.len});
|
||||
const index = @intCast(u32, self.stubs.items.len);
|
||||
_ = self.stubs.addOneAssumeCapacity();
|
||||
break :blk index;
|
||||
}
|
||||
};
|
||||
|
||||
self.stubs.items[index] = .{ .target = target, .sym_index = 0 };
|
||||
try self.stubs_table.putNoClobber(self.base.allocator, target, index);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {
|
||||
if (self.stubs_table.contains(target)) return;
|
||||
|
||||
const stub_index = try self.allocateStubEntry(target);
|
||||
if (self.stubs_table.lookup.contains(target)) return;
|
||||
const stub_index = try self.stubs_table.allocateEntry(self.base.allocator, target);
|
||||
const stub_helper_atom_index = try self.createStubHelperAtom();
|
||||
const stub_helper_atom = self.getAtom(stub_helper_atom_index);
|
||||
const laptr_atom_index = try self.createLazyPointerAtom(stub_helper_atom.getSymbolIndex().?, target);
|
||||
const laptr_atom = self.getAtom(laptr_atom_index);
|
||||
const stub_atom_index = try self.createStubAtom(laptr_atom.getSymbolIndex().?);
|
||||
const stub_atom = self.getAtom(stub_atom_index);
|
||||
self.stubs.items[stub_index].sym_index = stub_atom.getSymbolIndex().?;
|
||||
self.stubs_table.entries.items[stub_index].sym_index = stub_atom.getSymbolIndex().?;
|
||||
self.markRelocsDirtyByTarget(target);
|
||||
}
|
||||
|
||||
|
|
@ -2431,7 +2462,7 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []u8) !u64
|
|||
sym.n_value = vaddr;
|
||||
log.debug(" (updating GOT entry)", .{});
|
||||
const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null };
|
||||
const got_atom_index = self.getGotAtomIndexForSymbol(got_target).?;
|
||||
const got_atom_index = self.got_table.getAtomIndex(self, got_target).?;
|
||||
self.markRelocsDirtyByTarget(got_target);
|
||||
try self.writePtrWidthAtom(got_atom_index);
|
||||
}
|
||||
|
|
@ -3481,8 +3512,8 @@ const SymtabCtx = struct {
|
|||
|
||||
fn writeDysymtab(self: *MachO, ctx: SymtabCtx) !void {
|
||||
const gpa = self.base.allocator;
|
||||
const nstubs = @intCast(u32, self.stubs_table.count());
|
||||
const ngot_entries = @intCast(u32, self.got_entries_table.count());
|
||||
const nstubs = @intCast(u32, self.stubs_table.lookup.count());
|
||||
const ngot_entries = @intCast(u32, self.got_table.lookup.count());
|
||||
const nindirectsyms = nstubs * 2 + ngot_entries;
|
||||
const iextdefsym = ctx.nlocalsym;
|
||||
const iundefsym = iextdefsym + ctx.nextdefsym;
|
||||
|
|
@ -3504,7 +3535,7 @@ fn writeDysymtab(self: *MachO, ctx: SymtabCtx) !void {
|
|||
if (self.stubs_section_index) |sect_id| {
|
||||
const stubs = &self.sections.items(.header)[sect_id];
|
||||
stubs.reserved1 = 0;
|
||||
for (self.stubs.items) |entry| {
|
||||
for (self.stubs_table.entries.items) |entry| {
|
||||
if (entry.sym_index == 0) continue;
|
||||
const target_sym = self.getSymbol(entry.target);
|
||||
assert(target_sym.undf());
|
||||
|
|
@ -3515,7 +3546,7 @@ fn writeDysymtab(self: *MachO, ctx: SymtabCtx) !void {
|
|||
if (self.got_section_index) |sect_id| {
|
||||
const got = &self.sections.items(.header)[sect_id];
|
||||
got.reserved1 = nstubs;
|
||||
for (self.got_entries.items) |entry| {
|
||||
for (self.got_table.entries.items) |entry| {
|
||||
if (entry.sym_index == 0) continue;
|
||||
const target_sym = self.getSymbol(entry.target);
|
||||
if (target_sym.undf()) {
|
||||
|
|
@ -3529,7 +3560,7 @@ fn writeDysymtab(self: *MachO, ctx: SymtabCtx) !void {
|
|||
if (self.la_symbol_ptr_section_index) |sect_id| {
|
||||
const la_symbol_ptr = &self.sections.items(.header)[sect_id];
|
||||
la_symbol_ptr.reserved1 = nstubs + ngot_entries;
|
||||
for (self.stubs.items) |entry| {
|
||||
for (self.stubs_table.entries.items) |entry| {
|
||||
if (entry.sym_index == 0) continue;
|
||||
const target_sym = self.getSymbol(entry.target);
|
||||
assert(target_sym.undf());
|
||||
|
|
@ -3874,20 +3905,6 @@ pub fn getAtomIndexForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?Atom.In
|
|||
return self.atom_by_index_table.get(sym_with_loc.sym_index);
|
||||
}
|
||||
|
||||
/// Returns GOT atom that references `sym_with_loc` if one exists.
|
||||
/// Returns null otherwise.
|
||||
pub fn getGotAtomIndexForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?Atom.Index {
|
||||
const got_index = self.got_entries_table.get(sym_with_loc) orelse return null;
|
||||
return self.got_entries.items[got_index].getAtomIndex(self);
|
||||
}
|
||||
|
||||
/// Returns stubs atom that references `sym_with_loc` if one exists.
|
||||
/// Returns null otherwise.
|
||||
pub fn getStubsAtomIndexForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?Atom.Index {
|
||||
const stubs_index = self.stubs_table.get(sym_with_loc) orelse return null;
|
||||
return self.stubs.items[stubs_index].getAtomIndex(self);
|
||||
}
|
||||
|
||||
/// Returns symbol location corresponding to the set entrypoint.
|
||||
/// Asserts output mode is executable.
|
||||
pub fn getEntryPoint(self: MachO) error{MissingMainEntrypoint}!SymbolWithLoc {
|
||||
|
|
@ -4234,37 +4251,10 @@ pub fn logSymtab(self: *MachO) void {
|
|||
}
|
||||
|
||||
log.debug("GOT entries:", .{});
|
||||
for (self.got_entries.items, 0..) |entry, i| {
|
||||
const atom_sym = entry.getSymbol(self);
|
||||
const target_sym = self.getSymbol(entry.target);
|
||||
if (target_sym.undf()) {
|
||||
log.debug(" {d}@{x} => import('{s}')", .{
|
||||
i,
|
||||
atom_sym.n_value,
|
||||
self.getSymbolName(entry.target),
|
||||
});
|
||||
} else {
|
||||
log.debug(" {d}@{x} => local(%{d}) in object({?d}) {s}", .{
|
||||
i,
|
||||
atom_sym.n_value,
|
||||
entry.target.sym_index,
|
||||
entry.target.file,
|
||||
logSymAttributes(target_sym, &buf),
|
||||
});
|
||||
}
|
||||
}
|
||||
log.debug("{}", .{self.got_table.fmtDebug(self)});
|
||||
|
||||
log.debug("stubs entries:", .{});
|
||||
for (self.stubs.items, 0..) |entry, i| {
|
||||
const target_sym = self.getSymbol(entry.target);
|
||||
const atom_sym = entry.getSymbol(self);
|
||||
assert(target_sym.undf());
|
||||
log.debug(" {d}@{x} => import('{s}')", .{
|
||||
i,
|
||||
atom_sym.n_value,
|
||||
self.getSymbolName(entry.target),
|
||||
});
|
||||
}
|
||||
log.debug("{}", .{self.stubs_table.fmtDebug(self)});
|
||||
}
|
||||
|
||||
pub fn logAtoms(self: *MachO) void {
|
||||
|
|
|
|||
|
|
@ -226,26 +226,20 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
|
|||
|
||||
for (self.relocs.items) |*reloc| {
|
||||
const sym = switch (reloc.type) {
|
||||
.direct_load => macho_file.getSymbol(.{ .sym_index = reloc.target, .file = null }),
|
||||
.direct_load => macho_file.getSymbol(.{ .sym_index = reloc.target }),
|
||||
.got_load => blk: {
|
||||
const got_index = macho_file.got_entries_table.get(.{
|
||||
.sym_index = reloc.target,
|
||||
.file = null,
|
||||
}).?;
|
||||
const got_entry = macho_file.got_entries.items[got_index];
|
||||
const got_index = macho_file.got_table.lookup.get(.{ .sym_index = reloc.target }).?;
|
||||
const got_entry = macho_file.got_table.entries.items[got_index];
|
||||
break :blk got_entry.getSymbol(macho_file);
|
||||
},
|
||||
};
|
||||
if (sym.n_value == reloc.prev_vaddr) continue;
|
||||
|
||||
const sym_name = switch (reloc.type) {
|
||||
.direct_load => macho_file.getSymbolName(.{ .sym_index = reloc.target, .file = null }),
|
||||
.direct_load => macho_file.getSymbolName(.{ .sym_index = reloc.target }),
|
||||
.got_load => blk: {
|
||||
const got_index = macho_file.got_entries_table.get(.{
|
||||
.sym_index = reloc.target,
|
||||
.file = null,
|
||||
}).?;
|
||||
const got_entry = macho_file.got_entries.items[got_index];
|
||||
const got_index = macho_file.got_table.lookup.get(.{ .sym_index = reloc.target }).?;
|
||||
const got_entry = macho_file.got_table.entries.items[got_index];
|
||||
break :blk got_entry.getName(macho_file);
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -46,13 +46,15 @@ pub fn isResolvable(self: Relocation, macho_file: *MachO) bool {
|
|||
}
|
||||
|
||||
pub fn getTargetAtomIndex(self: Relocation, macho_file: *MachO) ?Atom.Index {
|
||||
switch (self.type) {
|
||||
.got, .got_page, .got_pageoff => return macho_file.getGotAtomIndexForSymbol(self.target),
|
||||
.tlv, .tlv_page, .tlv_pageoff => return macho_file.getTlvpAtomIndexForSymbol(self.target),
|
||||
else => {},
|
||||
}
|
||||
if (macho_file.getStubsAtomIndexForSymbol(self.target)) |stubs_atom| return stubs_atom;
|
||||
return macho_file.getAtomIndexForSymbol(self.target);
|
||||
return switch (self.type) {
|
||||
.got, .got_page, .got_pageoff => macho_file.got_table.getAtomIndex(macho_file, self.target),
|
||||
.tlv, .tlv_page, .tlv_pageoff => macho_file.tlvp_table.getAtomIndex(macho_file, self.target),
|
||||
.branch => if (macho_file.stubs_table.getAtomIndex(macho_file, self.target)) |index|
|
||||
index
|
||||
else
|
||||
macho_file.getAtomIndexForSymbol(self.target),
|
||||
else => macho_file.getAtomIndexForSymbol(self.target),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn resolve(self: Relocation, macho_file: *MachO, atom_index: Atom.Index, code: []u8) void {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue