mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
macho: use TableSection for TLV pointer entries in zld driver
This commit is contained in:
parent
04e93dd265
commit
5750620715
@ -360,7 +360,6 @@ pub fn parseRelocTarget(zld: *Zld, ctx: struct {
|
||||
|
||||
pub fn getRelocTargetAtomIndex(zld: *Zld, target: SymbolWithLoc) ?Index {
|
||||
if (zld.getStubsAtomIndexForSymbol(target)) |stubs_atom| return stubs_atom;
|
||||
if (zld.getTlvPtrAtomIndexForSymbol(target)) |tlv_ptr_atom| return tlv_ptr_atom;
|
||||
|
||||
if (target.getFile() == null) {
|
||||
const target_sym_name = zld.getSymbolName(target);
|
||||
@ -413,7 +412,8 @@ fn scanAtomRelocsArm64(zld: *Zld, atom_index: Index, relocs: []align(1) const ma
|
||||
.ARM64_RELOC_TLVP_LOAD_PAGE21,
|
||||
.ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
|
||||
=> {
|
||||
try addTlvPtrEntry(zld, target);
|
||||
const sym = zld.getSymbol(target);
|
||||
if (sym.undf()) try zld.addTlvPtrEntry(target);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
@ -454,28 +454,14 @@ fn scanAtomRelocsX86(zld: *Zld, atom_index: Index, relocs: []align(1) const mach
|
||||
try zld.addGotEntry(target);
|
||||
},
|
||||
.X86_64_RELOC_TLV => {
|
||||
try addTlvPtrEntry(zld, target);
|
||||
const sym = zld.getSymbol(target);
|
||||
if (sym.undf()) try zld.addTlvPtrEntry(target);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn addTlvPtrEntry(zld: *Zld, target: SymbolWithLoc) !void {
|
||||
const target_sym = zld.getSymbol(target);
|
||||
if (!target_sym.undf()) return;
|
||||
if (zld.tlv_ptr_table.contains(target)) return;
|
||||
|
||||
const gpa = zld.gpa;
|
||||
const atom_index = try zld.createTlvPtrAtom();
|
||||
const tlv_ptr_index = @as(u32, @intCast(zld.tlv_ptr_entries.items.len));
|
||||
try zld.tlv_ptr_entries.append(gpa, .{
|
||||
.target = target,
|
||||
.atom_index = atom_index,
|
||||
});
|
||||
try zld.tlv_ptr_table.putNoClobber(gpa, target, tlv_ptr_index);
|
||||
}
|
||||
|
||||
pub fn addStub(zld: *Zld, target: SymbolWithLoc) !void {
|
||||
const target_sym = zld.getSymbol(target);
|
||||
if (!target_sym.undf()) return;
|
||||
@ -641,10 +627,12 @@ fn resolveRelocsArm64(
|
||||
const header = zld.sections.items(.header)[source_sym.n_sect - 1];
|
||||
break :is_tlv header.type() == macho.S_THREAD_LOCAL_VARIABLES;
|
||||
};
|
||||
const target_addr = if (is_via_got)
|
||||
zld.getGotEntryAddress(target).?
|
||||
else
|
||||
try getRelocTargetAddress(zld, target, is_tlv);
|
||||
const target_addr = blk: {
|
||||
if (is_via_got) break :blk zld.getGotEntryAddress(target).?;
|
||||
if (relocIsTlv(zld, rel) and zld.getSymbol(target).undf())
|
||||
break :blk zld.getTlvPtrEntryAddress(target).?;
|
||||
break :blk try getRelocTargetAddress(zld, target, is_tlv);
|
||||
};
|
||||
|
||||
log.debug(" | source_addr = 0x{x}", .{source_addr});
|
||||
|
||||
@ -802,7 +790,7 @@ fn resolveRelocsArm64(
|
||||
}
|
||||
};
|
||||
|
||||
var inst = if (zld.tlv_ptr_table.contains(target)) aarch64.Instruction{
|
||||
var inst = if (zld.tlv_ptr_table.lookup.contains(target)) aarch64.Instruction{
|
||||
.load_store_register = .{
|
||||
.rt = reg_info.rd,
|
||||
.rn = reg_info.rn,
|
||||
@ -938,14 +926,15 @@ fn resolveRelocsX86(
|
||||
const header = zld.sections.items(.header)[source_sym.n_sect - 1];
|
||||
break :is_tlv header.type() == macho.S_THREAD_LOCAL_VARIABLES;
|
||||
};
|
||||
const target_addr = blk: {
|
||||
if (is_via_got) break :blk zld.getGotEntryAddress(target).?;
|
||||
if (relocIsTlv(zld, rel) and zld.getSymbol(target).undf())
|
||||
break :blk zld.getTlvPtrEntryAddress(target).?;
|
||||
break :blk try getRelocTargetAddress(zld, target, is_tlv);
|
||||
};
|
||||
|
||||
log.debug(" | source_addr = 0x{x}", .{source_addr});
|
||||
|
||||
const target_addr = if (is_via_got)
|
||||
zld.getGotEntryAddress(target).?
|
||||
else
|
||||
try getRelocTargetAddress(zld, target, is_tlv);
|
||||
|
||||
switch (rel_type) {
|
||||
.X86_64_RELOC_BRANCH => {
|
||||
const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]);
|
||||
@ -971,7 +960,7 @@ fn resolveRelocsX86(
|
||||
log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr});
|
||||
const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, 0);
|
||||
|
||||
if (zld.tlv_ptr_table.get(target) == null) {
|
||||
if (zld.tlv_ptr_table.lookup.get(target) == null) {
|
||||
// We need to rewrite the opcode from movq to leaq.
|
||||
atom_code[rel_offset - 2] = 0x8d;
|
||||
}
|
||||
@ -1112,3 +1101,19 @@ pub fn relocRequiresGot(zld: *Zld, rel: macho.relocation_info) bool {
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn relocIsTlv(zld: *Zld, rel: macho.relocation_info) bool {
|
||||
switch (zld.options.target.cpu.arch) {
|
||||
.aarch64 => switch (@as(macho.reloc_type_arm64, @enumFromInt(rel.r_type))) {
|
||||
.ARM64_RELOC_TLVP_LOAD_PAGE21,
|
||||
.ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
|
||||
=> return true,
|
||||
else => return false,
|
||||
},
|
||||
.x86_64 => switch (@as(macho.reloc_type_x86_64, @enumFromInt(rel.r_type))) {
|
||||
.X86_64_RELOC_TLV => return true,
|
||||
else => return false,
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,6 +68,7 @@ pub const Zld = struct {
|
||||
sections: std.MultiArrayList(Section) = .{},
|
||||
|
||||
got_section_index: ?u8 = null,
|
||||
tlv_ptr_section_index: ?u8 = null,
|
||||
|
||||
locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
|
||||
globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{},
|
||||
@ -81,9 +82,7 @@ pub const Zld = struct {
|
||||
|
||||
strtab: StringTable(.strtab) = .{},
|
||||
|
||||
tlv_ptr_entries: std.ArrayListUnmanaged(IndirectPointer) = .{},
|
||||
tlv_ptr_table: std.AutoHashMapUnmanaged(SymbolWithLoc, u32) = .{},
|
||||
|
||||
tlv_ptr_table: TableSection(SymbolWithLoc) = .{},
|
||||
got_table: TableSection(SymbolWithLoc) = .{},
|
||||
|
||||
stubs: std.ArrayListUnmanaged(IndirectPointer) = .{},
|
||||
@ -268,24 +267,6 @@ pub const Zld = struct {
|
||||
return index;
|
||||
}
|
||||
|
||||
pub fn createTlvPtrAtom(self: *Zld) !AtomIndex {
|
||||
const sym_index = try self.allocateSymbol();
|
||||
const atom_index = try self.createEmptyAtom(sym_index, @sizeOf(u64), 3);
|
||||
const sym = self.getSymbolPtr(.{ .sym_index = sym_index });
|
||||
sym.n_type = macho.N_SECT;
|
||||
|
||||
const sect_id = (try self.getOutputSection(.{
|
||||
.segname = makeStaticString("__DATA"),
|
||||
.sectname = makeStaticString("__thread_ptrs"),
|
||||
.flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
|
||||
})).?;
|
||||
sym.n_sect = sect_id + 1;
|
||||
|
||||
self.addAtomToSection(atom_index);
|
||||
|
||||
return atom_index;
|
||||
}
|
||||
|
||||
fn createDyldStubBinderGotAtom(self: *Zld) !void {
|
||||
const global_index = self.dyld_stub_binder_index orelse return;
|
||||
const target = self.globals.items[global_index];
|
||||
@ -841,7 +822,6 @@ pub const Zld = struct {
|
||||
pub fn deinit(self: *Zld) void {
|
||||
const gpa = self.gpa;
|
||||
|
||||
self.tlv_ptr_entries.deinit(gpa);
|
||||
self.tlv_ptr_table.deinit(gpa);
|
||||
self.got_table.deinit(gpa);
|
||||
self.stubs.deinit(gpa);
|
||||
@ -959,16 +939,26 @@ pub const Zld = struct {
|
||||
return global_index;
|
||||
}
|
||||
|
||||
pub fn addGotEntry(zld: *Zld, target: SymbolWithLoc) !void {
|
||||
if (zld.got_table.lookup.contains(target)) return;
|
||||
_ = try zld.got_table.allocateEntry(zld.gpa, target);
|
||||
if (zld.got_section_index == null) {
|
||||
zld.got_section_index = try zld.initSection("__DATA_CONST", "__got", .{
|
||||
pub fn addGotEntry(self: *Zld, target: SymbolWithLoc) !void {
|
||||
if (self.got_table.lookup.contains(target)) return;
|
||||
_ = try self.got_table.allocateEntry(self.gpa, target);
|
||||
if (self.got_section_index == null) {
|
||||
self.got_section_index = try self.initSection("__DATA_CONST", "__got", .{
|
||||
.flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addTlvPtrEntry(self: *Zld, target: SymbolWithLoc) !void {
|
||||
if (self.tlv_ptr_table.lookup.contains(target)) return;
|
||||
_ = try self.tlv_ptr_table.allocateEntry(self.gpa, target);
|
||||
if (self.tlv_ptr_section_index == null) {
|
||||
self.tlv_ptr_section_index = try self.initSection("__DATA", "__thread_ptrs", .{
|
||||
.flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn allocateSpecialSymbols(self: *Zld) !void {
|
||||
for (&[_]?u32{
|
||||
self.dso_handle_index,
|
||||
@ -1033,12 +1023,10 @@ pub const Zld = struct {
|
||||
} else if (atom.getFile() == null) outer: {
|
||||
switch (header.type()) {
|
||||
macho.S_NON_LAZY_SYMBOL_POINTERS => unreachable,
|
||||
macho.S_THREAD_LOCAL_VARIABLE_POINTERS => unreachable,
|
||||
macho.S_LAZY_SYMBOL_POINTERS => {
|
||||
try self.writeLazyPointer(count, buffer.writer());
|
||||
},
|
||||
macho.S_THREAD_LOCAL_VARIABLE_POINTERS => {
|
||||
buffer.appendSliceAssumeCapacity(&[_]u8{0} ** @sizeOf(u64));
|
||||
},
|
||||
else => {
|
||||
if (self.stub_helper_preamble_sym_index) |sym_index| {
|
||||
if (sym_index == atom.sym_index) {
|
||||
@ -1087,12 +1075,11 @@ pub const Zld = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn writeGotEntries(self: *Zld) !void {
|
||||
const sect_id = self.got_section_index orelse return;
|
||||
fn writePointerEntries(self: *Zld, sect_id: u8, table: anytype) !void {
|
||||
const header = self.sections.items(.header)[sect_id];
|
||||
var buffer = try std.ArrayList(u8).initCapacity(self.gpa, header.size);
|
||||
defer buffer.deinit();
|
||||
for (self.got_table.entries.items) |entry| {
|
||||
for (table.entries.items) |entry| {
|
||||
const sym = self.getSymbol(entry);
|
||||
buffer.writer().writeIntLittle(u64, sym.n_value) catch unreachable;
|
||||
}
|
||||
@ -1147,6 +1134,7 @@ pub const Zld = struct {
|
||||
|
||||
for (&[_]*?u8{
|
||||
&self.got_section_index,
|
||||
&self.tlv_ptr_section_index,
|
||||
}) |maybe_index| {
|
||||
if (maybe_index.*) |*index| {
|
||||
index.* = backlinks[index.*];
|
||||
@ -1236,6 +1224,12 @@ pub const Zld = struct {
|
||||
header.size = self.got_table.count() * @sizeOf(u64);
|
||||
header.@"align" = 3;
|
||||
}
|
||||
|
||||
if (self.tlv_ptr_section_index) |sect_id| {
|
||||
const header = &self.sections.items(.header)[sect_id];
|
||||
header.size = self.tlv_ptr_table.count() * @sizeOf(u64);
|
||||
header.@"align" = 3;
|
||||
}
|
||||
}
|
||||
|
||||
fn allocateSegments(self: *Zld) !void {
|
||||
@ -1579,44 +1573,6 @@ pub const Zld = struct {
|
||||
try rebase.finalize(self.gpa);
|
||||
}
|
||||
|
||||
fn collectBindDataFromContainer(
|
||||
self: *Zld,
|
||||
sect_id: u8,
|
||||
bind: *Bind,
|
||||
container: anytype,
|
||||
) !void {
|
||||
const slice = self.sections.slice();
|
||||
const segment_index = slice.items(.segment_index)[sect_id];
|
||||
const seg = self.getSegment(sect_id);
|
||||
|
||||
try bind.entries.ensureUnusedCapacity(self.gpa, container.items.len);
|
||||
|
||||
for (container.items) |entry| {
|
||||
const bind_sym_name = entry.getTargetSymbolName(self);
|
||||
const bind_sym = entry.getTargetSymbol(self);
|
||||
if (bind_sym.sect()) continue;
|
||||
|
||||
const sym = entry.getAtomSymbol(self);
|
||||
const base_offset = sym.n_value - seg.vmaddr;
|
||||
|
||||
const dylib_ordinal = @divTrunc(@as(i16, @bitCast(bind_sym.n_desc)), macho.N_SYMBOL_RESOLVER);
|
||||
log.debug(" | bind at {x}, import('{s}') in dylib({d})", .{
|
||||
base_offset,
|
||||
bind_sym_name,
|
||||
dylib_ordinal,
|
||||
});
|
||||
if (bind_sym.weakRef()) {
|
||||
log.debug(" | marking as weak ref ", .{});
|
||||
}
|
||||
bind.entries.appendAssumeCapacity(.{
|
||||
.target = entry.target,
|
||||
.offset = base_offset,
|
||||
.segment_id = segment_index,
|
||||
.addend = 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn collectBindData(
|
||||
self: *Zld,
|
||||
bind: *Bind,
|
||||
@ -1629,8 +1585,8 @@ pub const Zld = struct {
|
||||
}
|
||||
|
||||
// Next, unpack TLV pointers section
|
||||
if (self.getSectionByName("__DATA", "__thread_ptrs")) |sect_id| {
|
||||
try self.collectBindDataFromContainer(sect_id, bind, self.tlv_ptr_entries);
|
||||
if (self.tlv_ptr_section_index) |sect_id| {
|
||||
try MachO.collectBindDataFromTableSection(self.gpa, self, sect_id, bind, self.tlv_ptr_table);
|
||||
}
|
||||
|
||||
// Finally, unpack the rest.
|
||||
@ -2488,6 +2444,12 @@ pub const Zld = struct {
|
||||
return header.addr + @sizeOf(u64) * index;
|
||||
}
|
||||
|
||||
pub fn getTlvPtrEntryAddress(self: *Zld, sym_with_loc: SymbolWithLoc) ?u64 {
|
||||
const index = self.tlv_ptr_table.lookup.get(sym_with_loc) orelse return null;
|
||||
const header = self.sections.items(.header)[self.tlv_ptr_section_index.?];
|
||||
return header.addr + @sizeOf(u64) * index;
|
||||
}
|
||||
|
||||
/// Returns stubs atom that references `sym_with_loc` if one exists.
|
||||
/// Returns null otherwise.
|
||||
pub fn getStubsAtomIndexForSymbol(self: *Zld, sym_with_loc: SymbolWithLoc) ?AtomIndex {
|
||||
@ -2496,14 +2458,6 @@ pub const Zld = struct {
|
||||
return entry.atom_index;
|
||||
}
|
||||
|
||||
/// Returns TLV pointer atom that references `sym_with_loc` if one exists.
|
||||
/// Returns null otherwise.
|
||||
pub fn getTlvPtrAtomIndexForSymbol(self: *Zld, sym_with_loc: SymbolWithLoc) ?AtomIndex {
|
||||
const index = self.tlv_ptr_table.get(sym_with_loc) orelse return null;
|
||||
const entry = self.tlv_ptr_entries.items[index];
|
||||
return entry.atom_index;
|
||||
}
|
||||
|
||||
/// Returns symbol location corresponding to the set entrypoint.
|
||||
/// Asserts output mode is executable.
|
||||
pub fn getEntryPoint(self: Zld) SymbolWithLoc {
|
||||
@ -2835,18 +2789,8 @@ pub const Zld = struct {
|
||||
scoped_log.debug("GOT entries:", .{});
|
||||
scoped_log.debug("{}", .{self.got_table});
|
||||
|
||||
scoped_log.debug("__thread_ptrs entries:", .{});
|
||||
for (self.tlv_ptr_entries.items, 0..) |entry, i| {
|
||||
const atom_sym = entry.getAtomSymbol(self);
|
||||
const target_sym = entry.getTargetSymbol(self);
|
||||
const target_sym_name = entry.getTargetSymbolName(self);
|
||||
assert(target_sym.undf());
|
||||
scoped_log.debug(" {d}@{x} => import('{s}')", .{
|
||||
i,
|
||||
atom_sym.n_value,
|
||||
target_sym_name,
|
||||
});
|
||||
}
|
||||
scoped_log.debug("TLV pointers:", .{});
|
||||
scoped_log.debug("{}", .{self.tlv_ptr_table});
|
||||
|
||||
scoped_log.debug("stubs entries:", .{});
|
||||
for (self.stubs.items, 0..) |entry, i| {
|
||||
@ -3435,7 +3379,10 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
|
||||
}
|
||||
|
||||
try zld.writeAtoms();
|
||||
try zld.writeGotEntries();
|
||||
|
||||
if (zld.got_section_index) |sect_id| try zld.writePointerEntries(sect_id, &zld.got_table);
|
||||
if (zld.tlv_ptr_section_index) |sect_id| try zld.writePointerEntries(sect_id, &zld.tlv_ptr_table);
|
||||
|
||||
try eh_frame.write(&zld, &unwind_info);
|
||||
try unwind_info.write(&zld);
|
||||
try zld.writeLinkeditSegmentData();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user