mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
link: make MachO atoms fully owned by the linker
This commit is contained in:
parent
23b7d28896
commit
d42a931051
12 changed files with 495 additions and 432 deletions
|
|
@ -4098,7 +4098,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
|
|||
|
||||
// The exports this Decl performs will be re-discovered, so we remove them here
|
||||
// prior to re-analysis.
|
||||
mod.deleteDeclExports(decl_index);
|
||||
try mod.deleteDeclExports(decl_index);
|
||||
|
||||
// Similarly, `@setAlignStack` invocations will be re-discovered.
|
||||
if (decl.getFunction()) |func| {
|
||||
|
|
@ -5265,7 +5265,7 @@ pub fn clearDecl(
|
|||
assert(emit_h.decl_table.swapRemove(decl_index));
|
||||
}
|
||||
_ = mod.compile_log_decls.swapRemove(decl_index);
|
||||
mod.deleteDeclExports(decl_index);
|
||||
try mod.deleteDeclExports(decl_index);
|
||||
|
||||
if (decl.has_tv) {
|
||||
if (decl.ty.isFnOrHasRuntimeBits()) {
|
||||
|
|
@ -5276,7 +5276,7 @@ pub fn clearDecl(
|
|||
decl.link = switch (mod.comp.bin_file.tag) {
|
||||
.coff => .{ .coff = link.File.Coff.Atom.empty },
|
||||
.elf => .{ .elf = link.File.Elf.TextBlock.empty },
|
||||
.macho => .{ .macho = link.File.MachO.Atom.empty },
|
||||
.macho => .{ .macho = {} },
|
||||
.plan9 => .{ .plan9 = link.File.Plan9.DeclBlock.empty },
|
||||
.c => .{ .c = {} },
|
||||
.wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },
|
||||
|
|
@ -5358,7 +5358,7 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {
|
|||
|
||||
/// Delete all the Export objects that are caused by this Decl. Re-analysis of
|
||||
/// this Decl will cause them to be re-created (or not).
|
||||
fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) void {
|
||||
fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {
|
||||
var export_owners = (mod.export_owners.fetchSwapRemove(decl_index) orelse return).value;
|
||||
|
||||
for (export_owners.items) |exp| {
|
||||
|
|
@ -5384,7 +5384,7 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) void {
|
|||
elf.deleteExport(exp.link.elf);
|
||||
}
|
||||
if (mod.comp.bin_file.cast(link.File.MachO)) |macho| {
|
||||
macho.deleteExport(exp.link.macho);
|
||||
try macho.deleteDeclExport(decl_index, exp.options.name);
|
||||
}
|
||||
if (mod.comp.bin_file.cast(link.File.Wasm)) |wasm| {
|
||||
wasm.deleteExport(exp.link.wasm);
|
||||
|
|
@ -5696,7 +5696,7 @@ pub fn allocateNewDecl(
|
|||
.link = switch (mod.comp.bin_file.tag) {
|
||||
.coff => .{ .coff = link.File.Coff.Atom.empty },
|
||||
.elf => .{ .elf = link.File.Elf.TextBlock.empty },
|
||||
.macho => .{ .macho = link.File.MachO.Atom.empty },
|
||||
.macho => .{ .macho = {} },
|
||||
.plan9 => .{ .plan9 = link.File.Plan9.DeclBlock.empty },
|
||||
.c => .{ .c = {} },
|
||||
.wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },
|
||||
|
|
|
|||
|
|
@ -5567,7 +5567,7 @@ pub fn analyzeExport(
|
|||
.link = switch (mod.comp.bin_file.tag) {
|
||||
.coff => .{ .coff = .{} },
|
||||
.elf => .{ .elf = .{} },
|
||||
.macho => .{ .macho = .{} },
|
||||
.macho => .{ .macho = {} },
|
||||
.plan9 => .{ .plan9 = null },
|
||||
.c => .{ .c = {} },
|
||||
.wasm => .{ .wasm = .{} },
|
||||
|
|
|
|||
|
|
@ -4022,7 +4022,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
|
|||
const mod = self.bin_file.options.module.?;
|
||||
const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
|
||||
const atom_index = switch (self.bin_file.tag) {
|
||||
.macho => owner_decl.link.macho.getSymbolIndex().?,
|
||||
.macho => blk: {
|
||||
const macho_file = self.bin_file.cast(link.File.MachO).?;
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
break :blk macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
},
|
||||
.coff => owner_decl.link.coff.getSymbolIndex().?,
|
||||
else => unreachable, // unsupported target format
|
||||
};
|
||||
|
|
@ -4308,11 +4312,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
|||
const got_addr = @intCast(u32, fn_owner_decl.link.elf.getOffsetTableAddress(elf_file));
|
||||
try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = got_addr });
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
try fn_owner_decl.link.macho.ensureInitialized(macho_file);
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(func.owner_decl);
|
||||
const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
try self.genSetReg(Type.initTag(.u64), .x30, .{
|
||||
.linker_load = .{
|
||||
.type = .got,
|
||||
.sym_index = fn_owner_decl.link.macho.getSymbolIndex().?,
|
||||
.sym_index = sym_index,
|
||||
},
|
||||
});
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
|
|
@ -4349,11 +4354,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
|||
|
||||
if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
_ = try self.addInst(.{
|
||||
.tag = .call_extern,
|
||||
.data = .{
|
||||
.relocation = .{
|
||||
.atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.getSymbolIndex().?,
|
||||
.atom_index = atom_index,
|
||||
.sym_index = sym_index,
|
||||
},
|
||||
},
|
||||
|
|
@ -5491,7 +5498,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
|
|||
const mod = self.bin_file.options.module.?;
|
||||
const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
|
||||
const atom_index = switch (self.bin_file.tag) {
|
||||
.macho => owner_decl.link.macho.getSymbolIndex().?,
|
||||
.macho => blk: {
|
||||
const macho_file = self.bin_file.cast(link.File.MachO).?;
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
break :blk macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
},
|
||||
.coff => owner_decl.link.coff.getSymbolIndex().?,
|
||||
else => unreachable, // unsupported target format
|
||||
};
|
||||
|
|
@ -5605,7 +5616,11 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
|||
const mod = self.bin_file.options.module.?;
|
||||
const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
|
||||
const atom_index = switch (self.bin_file.tag) {
|
||||
.macho => owner_decl.link.macho.getSymbolIndex().?,
|
||||
.macho => blk: {
|
||||
const macho_file = self.bin_file.cast(link.File.MachO).?;
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
break :blk macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
},
|
||||
.coff => owner_decl.link.coff.getSymbolIndex().?,
|
||||
else => unreachable, // unsupported target format
|
||||
};
|
||||
|
|
@ -5799,7 +5814,11 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
|
|||
const mod = self.bin_file.options.module.?;
|
||||
const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
|
||||
const atom_index = switch (self.bin_file.tag) {
|
||||
.macho => owner_decl.link.macho.getSymbolIndex().?,
|
||||
.macho => blk: {
|
||||
const macho_file = self.bin_file.cast(link.File.MachO).?;
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
break :blk macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
},
|
||||
.coff => owner_decl.link.coff.getSymbolIndex().?,
|
||||
else => unreachable, // unsupported target format
|
||||
};
|
||||
|
|
@ -6122,10 +6141,11 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
|
|||
try decl.link.elf.ensureInitialized(elf_file);
|
||||
return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) };
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
try decl.link.macho.ensureInitialized(macho_file);
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(decl_index);
|
||||
const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
return MCValue{ .linker_load = .{
|
||||
.type = .got,
|
||||
.sym_index = decl.link.macho.getSymbolIndex().?,
|
||||
.sym_index = sym_index,
|
||||
} };
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
try decl.link.coff.ensureInitialized(coff_file);
|
||||
|
|
|
|||
|
|
@ -670,9 +670,9 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {
|
|||
|
||||
if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
// Add relocation to the decl.
|
||||
const atom = macho_file.getAtomForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
|
||||
const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
|
||||
const target = macho_file.getGlobalByIndex(relocation.sym_index);
|
||||
try atom.addRelocation(macho_file, .{
|
||||
try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
|
||||
.type = @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_BRANCH26),
|
||||
.target = target,
|
||||
.offset = offset,
|
||||
|
|
@ -883,10 +883,10 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
|
|||
}
|
||||
|
||||
if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
const atom = macho_file.getAtomForSymbol(.{ .sym_index = data.atom_index, .file = null }).?;
|
||||
const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = data.atom_index, .file = null }).?;
|
||||
// TODO this causes segfault in stage1
|
||||
// try atom.addRelocations(macho_file, 2, .{
|
||||
try atom.addRelocation(macho_file, .{
|
||||
try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
|
||||
.target = .{ .sym_index = data.sym_index, .file = null },
|
||||
.offset = offset,
|
||||
.addend = 0,
|
||||
|
|
@ -902,7 +902,7 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
|
|||
else => unreachable,
|
||||
},
|
||||
});
|
||||
try atom.addRelocation(macho_file, .{
|
||||
try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
|
||||
.target = .{ .sym_index = data.sym_index, .file = null },
|
||||
.offset = offset + 4,
|
||||
.addend = 0,
|
||||
|
|
|
|||
|
|
@ -2556,9 +2556,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
|
|||
try decl.link.elf.ensureInitialized(elf_file);
|
||||
return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) };
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |_| {
|
||||
// TODO I'm hacking my way through here by repurposing .memory for storing
|
||||
// index to the GOT target symbol index.
|
||||
return MCValue{ .memory = decl.link.macho.sym_index };
|
||||
unreachable;
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |_| {
|
||||
return self.fail("TODO codegen COFF const Decl pointer", .{});
|
||||
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
||||
|
|
|
|||
|
|
@ -2670,10 +2670,12 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
|
|||
const abi_size = @intCast(u32, ptr_ty.abiSize(self.target.*));
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl);
|
||||
const atom_index = if (self.bin_file.tag == link.File.MachO.base_tag)
|
||||
fn_owner_decl.link.macho.getSymbolIndex().?
|
||||
else
|
||||
fn_owner_decl.link.coff.getSymbolIndex().?;
|
||||
const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
break :blk macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |_| blk: {
|
||||
break :blk fn_owner_decl.link.coff.getSymbolIndex().?;
|
||||
} else unreachable;
|
||||
const flags: u2 = switch (load_struct.type) {
|
||||
.got => 0b00,
|
||||
.direct => 0b01,
|
||||
|
|
@ -4023,8 +4025,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
|||
.data = undefined,
|
||||
});
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
try fn_owner_decl.link.macho.ensureInitialized(macho_file);
|
||||
const sym_index = fn_owner_decl.link.macho.getSymbolIndex().?;
|
||||
const atom_index = try macho_file.getOrCreateAtomForDecl(func.owner_decl);
|
||||
const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
|
||||
try self.genSetReg(Type.initTag(.usize), .rax, .{
|
||||
.linker_load = .{
|
||||
.type = .got,
|
||||
|
|
@ -4080,15 +4082,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
|||
});
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
|
||||
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||
const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
|
||||
_ = try self.addInst(.{
|
||||
.tag = .call_extern,
|
||||
.ops = undefined,
|
||||
.data = .{
|
||||
.relocation = .{
|
||||
.atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.getSymbolIndex().?,
|
||||
.sym_index = sym_index,
|
||||
},
|
||||
},
|
||||
.data = .{ .relocation = .{
|
||||
.atom_index = atom_index,
|
||||
.sym_index = sym_index,
|
||||
} },
|
||||
});
|
||||
} else {
|
||||
return self.fail("TODO implement calling extern functions", .{});
|
||||
|
|
@ -6722,10 +6724,11 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
|
|||
try decl.link.elf.ensureInitialized(elf_file);
|
||||
return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) };
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
try decl.link.macho.ensureInitialized(macho_file);
|
||||
const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
|
||||
const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
|
||||
return MCValue{ .linker_load = .{
|
||||
.type = .got,
|
||||
.sym_index = decl.link.macho.getSymbolIndex().?,
|
||||
.sym_index = sym_index,
|
||||
} };
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
try decl.link.coff.ensureInitialized(coff_file);
|
||||
|
|
|
|||
|
|
@ -1001,8 +1001,8 @@ fn mirLeaPic(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
|
|||
0b01 => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
|
||||
else => unreachable,
|
||||
};
|
||||
const atom = macho_file.getAtomForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
|
||||
try atom.addRelocation(macho_file, .{
|
||||
const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
|
||||
try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
|
||||
.type = reloc_type,
|
||||
.target = .{ .sym_index = relocation.sym_index, .file = null },
|
||||
.offset = @intCast(u32, end_offset - 4),
|
||||
|
|
@ -1140,9 +1140,9 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
|
|||
|
||||
if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
// Add relocation to the decl.
|
||||
const atom = macho_file.getAtomForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
|
||||
const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
|
||||
const target = macho_file.getGlobalByIndex(relocation.sym_index);
|
||||
try atom.addRelocation(macho_file, .{
|
||||
try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
|
||||
.type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
|
||||
.target = target,
|
||||
.offset = offset,
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ pub const File = struct {
|
|||
pub const LinkBlock = union {
|
||||
elf: Elf.TextBlock,
|
||||
coff: Coff.Atom,
|
||||
macho: MachO.Atom,
|
||||
macho: void,
|
||||
plan9: Plan9.DeclBlock,
|
||||
c: void,
|
||||
wasm: Wasm.DeclBlock,
|
||||
|
|
@ -286,7 +286,7 @@ pub const File = struct {
|
|||
pub const Export = union {
|
||||
elf: Elf.Export,
|
||||
coff: Coff.Export,
|
||||
macho: MachO.Export,
|
||||
macho: void,
|
||||
plan9: Plan9.Export,
|
||||
c: void,
|
||||
wasm: Wasm.Export,
|
||||
|
|
|
|||
|
|
@ -2639,7 +2639,7 @@ fn getDbgInfoAtom(tag: File.Tag, mod: *Module, decl_index: Module.Decl.Index) *A
|
|||
const decl = mod.declPtr(decl_index);
|
||||
return switch (tag) {
|
||||
.elf => &decl.link.elf.dbg_info_atom,
|
||||
.macho => &decl.link.macho.dbg_info_atom,
|
||||
.macho => unreachable,
|
||||
.wasm => &decl.link.wasm.dbg_info_atom,
|
||||
else => unreachable,
|
||||
};
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -39,11 +39,14 @@ size: u64,
|
|||
alignment: u32,
|
||||
|
||||
/// Points to the previous and next neighbours
|
||||
next: ?*Atom,
|
||||
prev: ?*Atom,
|
||||
/// TODO use the same trick as with symbols: reserve index 0 as null atom
|
||||
next_index: ?Atom.Index,
|
||||
prev_index: ?Atom.Index,
|
||||
|
||||
dbg_info_atom: Dwarf.Atom,
|
||||
|
||||
pub const Index = u32;
|
||||
|
||||
pub const Binding = struct {
|
||||
target: SymbolWithLoc,
|
||||
offset: u64,
|
||||
|
|
@ -54,22 +57,6 @@ pub const SymbolAtOffset = struct {
|
|||
offset: u64,
|
||||
};
|
||||
|
||||
pub const empty = Atom{
|
||||
.sym_index = 0,
|
||||
.file = null,
|
||||
.size = 0,
|
||||
.alignment = 0,
|
||||
.prev = null,
|
||||
.next = null,
|
||||
.dbg_info_atom = undefined,
|
||||
};
|
||||
|
||||
pub fn ensureInitialized(self: *Atom, macho_file: *MachO) !void {
|
||||
if (self.getSymbolIndex() != null) return; // Already initialized
|
||||
self.sym_index = try macho_file.allocateSymbol();
|
||||
try macho_file.atom_by_index_table.putNoClobber(macho_file.base.allocator, self.sym_index, self);
|
||||
}
|
||||
|
||||
pub fn getSymbolIndex(self: Atom) ?u32 {
|
||||
if (self.sym_index == 0) return null;
|
||||
return self.sym_index;
|
||||
|
|
@ -108,7 +95,8 @@ pub fn getName(self: Atom, macho_file: *MachO) []const u8 {
|
|||
/// this calculation.
|
||||
pub fn capacity(self: Atom, macho_file: *MachO) u64 {
|
||||
const self_sym = self.getSymbol(macho_file);
|
||||
if (self.next) |next| {
|
||||
if (self.next_index) |next_index| {
|
||||
const next = macho_file.getAtom(next_index);
|
||||
const next_sym = next.getSymbol(macho_file);
|
||||
return next_sym.n_value - self_sym.n_value;
|
||||
} else {
|
||||
|
|
@ -120,7 +108,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 atom.
|
||||
const next = self.next orelse return false;
|
||||
const next_index = self.next_index orelse return false;
|
||||
const next = macho_file.getAtom(next_index);
|
||||
const self_sym = self.getSymbol(macho_file);
|
||||
const next_sym = next.getSymbol(macho_file);
|
||||
const cap = next_sym.n_value - self_sym.n_value;
|
||||
|
|
@ -130,19 +119,19 @@ pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {
|
|||
return surplus >= MachO.min_text_capacity;
|
||||
}
|
||||
|
||||
pub fn addRelocation(self: *Atom, macho_file: *MachO, reloc: Relocation) !void {
|
||||
return self.addRelocations(macho_file, 1, .{reloc});
|
||||
pub fn addRelocation(macho_file: *MachO, atom_index: Atom.Index, reloc: Relocation) !void {
|
||||
return addRelocations(macho_file, atom_index, 1, .{reloc});
|
||||
}
|
||||
|
||||
pub fn addRelocations(
|
||||
self: *Atom,
|
||||
macho_file: *MachO,
|
||||
atom_index: Atom.Index,
|
||||
comptime count: comptime_int,
|
||||
relocs: [count]Relocation,
|
||||
) !void {
|
||||
const gpa = macho_file.base.allocator;
|
||||
const target = macho_file.base.options.target;
|
||||
const gop = try macho_file.relocs.getOrPut(gpa, self);
|
||||
const gop = try macho_file.relocs.getOrPut(gpa, atom_index);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = .{};
|
||||
}
|
||||
|
|
@ -156,56 +145,72 @@ pub fn addRelocations(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn addRebase(self: *Atom, macho_file: *MachO, offset: u32) !void {
|
||||
pub fn addRebase(macho_file: *MachO, atom_index: Atom.Index, offset: u32) !void {
|
||||
const gpa = macho_file.base.allocator;
|
||||
log.debug(" (adding rebase at offset 0x{x} in %{?d})", .{ offset, self.getSymbolIndex() });
|
||||
const gop = try macho_file.rebases.getOrPut(gpa, self);
|
||||
const atom = macho_file.getAtom(atom_index);
|
||||
log.debug(" (adding rebase at offset 0x{x} in %{?d})", .{ offset, atom.getSymbolIndex() });
|
||||
const gop = try macho_file.rebases.getOrPut(gpa, atom_index);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = .{};
|
||||
}
|
||||
try gop.value_ptr.append(gpa, offset);
|
||||
}
|
||||
|
||||
pub fn addBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void {
|
||||
pub fn addBinding(macho_file: *MachO, atom_index: Atom.Index, binding: Binding) !void {
|
||||
const gpa = macho_file.base.allocator;
|
||||
const atom = macho_file.getAtom(atom_index);
|
||||
log.debug(" (adding binding to symbol {s} at offset 0x{x} in %{?d})", .{
|
||||
macho_file.getSymbolName(binding.target),
|
||||
binding.offset,
|
||||
self.getSymbolIndex(),
|
||||
atom.getSymbolIndex(),
|
||||
});
|
||||
const gop = try macho_file.bindings.getOrPut(gpa, self);
|
||||
const gop = try macho_file.bindings.getOrPut(gpa, atom_index);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = .{};
|
||||
}
|
||||
try gop.value_ptr.append(gpa, binding);
|
||||
}
|
||||
|
||||
pub fn addLazyBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void {
|
||||
pub fn addLazyBinding(macho_file: *MachO, atom_index: Atom.Index, binding: Binding) !void {
|
||||
const gpa = macho_file.base.allocator;
|
||||
const atom = macho_file.getAtom(atom_index);
|
||||
log.debug(" (adding lazy binding to symbol {s} at offset 0x{x} in %{?d})", .{
|
||||
macho_file.getSymbolName(binding.target),
|
||||
binding.offset,
|
||||
self.getSymbolIndex(),
|
||||
atom.getSymbolIndex(),
|
||||
});
|
||||
const gop = try macho_file.lazy_bindings.getOrPut(gpa, self);
|
||||
const gop = try macho_file.lazy_bindings.getOrPut(gpa, atom_index);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = .{};
|
||||
}
|
||||
try gop.value_ptr.append(gpa, binding);
|
||||
}
|
||||
|
||||
pub fn resolveRelocations(self: *Atom, macho_file: *MachO) !void {
|
||||
const relocs = macho_file.relocs.get(self) orelse return;
|
||||
const source_sym = self.getSymbol(macho_file);
|
||||
pub fn resolveRelocations(macho_file: *MachO, atom_index: Atom.Index) !void {
|
||||
const atom = macho_file.getAtom(atom_index);
|
||||
const relocs = macho_file.relocs.get(atom_index) orelse return;
|
||||
const source_sym = atom.getSymbol(macho_file);
|
||||
const source_section = macho_file.sections.get(source_sym.n_sect - 1).header;
|
||||
const file_offset = source_section.offset + source_sym.n_value - source_section.addr;
|
||||
|
||||
log.debug("relocating '{s}'", .{self.getName(macho_file)});
|
||||
log.debug("relocating '{s}'", .{atom.getName(macho_file)});
|
||||
|
||||
for (relocs.items) |*reloc| {
|
||||
if (!reloc.dirty) continue;
|
||||
|
||||
try reloc.resolve(self, macho_file, file_offset);
|
||||
try reloc.resolve(macho_file, atom_index, file_offset);
|
||||
reloc.dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn freeRelocations(macho_file: *MachO, atom_index: Atom.Index) void {
|
||||
const gpa = macho_file.base.allocator;
|
||||
var removed_relocs = macho_file.relocs.fetchOrderedRemove(atom_index);
|
||||
if (removed_relocs) |*relocs| relocs.value.deinit(gpa);
|
||||
var removed_rebases = macho_file.rebases.fetchOrderedRemove(atom_index);
|
||||
if (removed_rebases) |*rebases| rebases.value.deinit(gpa);
|
||||
var removed_bindings = macho_file.bindings.fetchOrderedRemove(atom_index);
|
||||
if (removed_bindings) |*bindings| bindings.value.deinit(gpa);
|
||||
var removed_lazy_bindings = macho_file.lazy_bindings.fetchOrderedRemove(atom_index);
|
||||
if (removed_lazy_bindings) |*lazy_bindings| lazy_bindings.value.deinit(gpa);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,33 +29,35 @@ pub fn fmtType(self: Relocation, target: std.Target) []const u8 {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn getTargetAtom(self: Relocation, macho_file: *MachO) ?*Atom {
|
||||
pub fn getTargetAtomIndex(self: Relocation, macho_file: *MachO) ?Atom.Index {
|
||||
switch (macho_file.base.options.target.cpu.arch) {
|
||||
.aarch64 => switch (@intToEnum(macho.reloc_type_arm64, self.type)) {
|
||||
.ARM64_RELOC_GOT_LOAD_PAGE21,
|
||||
.ARM64_RELOC_GOT_LOAD_PAGEOFF12,
|
||||
.ARM64_RELOC_POINTER_TO_GOT,
|
||||
=> return macho_file.getGotAtomForSymbol(self.target),
|
||||
=> return macho_file.getGotAtomIndexForSymbol(self.target),
|
||||
else => {},
|
||||
},
|
||||
.x86_64 => switch (@intToEnum(macho.reloc_type_x86_64, self.type)) {
|
||||
.X86_64_RELOC_GOT,
|
||||
.X86_64_RELOC_GOT_LOAD,
|
||||
=> return macho_file.getGotAtomForSymbol(self.target),
|
||||
=> return macho_file.getGotAtomIndexForSymbol(self.target),
|
||||
else => {},
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
if (macho_file.getStubsAtomForSymbol(self.target)) |stubs_atom| return stubs_atom;
|
||||
return macho_file.getAtomForSymbol(self.target);
|
||||
if (macho_file.getStubsAtomIndexForSymbol(self.target)) |stubs_atom| return stubs_atom;
|
||||
return macho_file.getAtomIndexForSymbol(self.target);
|
||||
}
|
||||
|
||||
pub fn resolve(self: Relocation, atom: *Atom, macho_file: *MachO, base_offset: u64) !void {
|
||||
pub fn resolve(self: Relocation, macho_file: *MachO, atom_index: Atom.Index, base_offset: u64) !void {
|
||||
const arch = macho_file.base.options.target.cpu.arch;
|
||||
const atom = macho_file.getAtom(atom_index);
|
||||
const source_sym = atom.getSymbol(macho_file);
|
||||
const source_addr = source_sym.n_value + self.offset;
|
||||
|
||||
const target_atom = self.getTargetAtom(macho_file) orelse return;
|
||||
const target_atom_index = self.getTargetAtomIndex(macho_file) orelse return;
|
||||
const target_atom = macho_file.getAtom(target_atom_index);
|
||||
const target_addr = @intCast(i64, target_atom.getSymbol(macho_file).n_value) + self.addend;
|
||||
|
||||
log.debug(" ({x}: [() => 0x{x} ({s})) ({s})", .{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue