mirror of
https://github.com/ziglang/zig.git
synced 2026-01-02 03:25:01 +00:00
zld: move tracking binding for proxies into TextBlock
which is the source of binding rather than its target. That is, we now track by source.
This commit is contained in:
parent
0135b46659
commit
ec874a9b2b
@ -121,20 +121,11 @@ pub const Tentative = struct {
|
||||
};
|
||||
|
||||
pub const Proxy = struct {
|
||||
/// Dynamic binding info - spots within the final
|
||||
/// executable where this proxy is referenced from.
|
||||
bind_info: std.ArrayListUnmanaged(struct {
|
||||
local_sym_index: u32,
|
||||
offset: u32,
|
||||
}) = .{},
|
||||
|
||||
/// Dylib where to locate this symbol.
|
||||
/// null means self-reference.
|
||||
file: ?*Dylib = null,
|
||||
|
||||
pub fn deinit(proxy: *Proxy, allocator: *Allocator) void {
|
||||
proxy.bind_info.deinit(allocator);
|
||||
}
|
||||
local_sym_index: u32 = 0,
|
||||
|
||||
pub fn dylibOrdinal(proxy: Proxy) u16 {
|
||||
const dylib = proxy.file orelse return 0;
|
||||
@ -145,13 +136,10 @@ pub const Proxy = struct {
|
||||
_ = fmt;
|
||||
_ = options;
|
||||
try std.fmt.format(writer, "Proxy {{ ", .{});
|
||||
if (self.bind_info.items.len > 0) {
|
||||
// TODO
|
||||
try std.fmt.format(writer, ".bind_info = {}, ", .{self.bind_info.items.len});
|
||||
}
|
||||
if (self.file) |file| {
|
||||
try std.fmt.format(writer, ".file = {s}, ", .{file.name.?});
|
||||
}
|
||||
try std.fmt.format(writer, ".local_sym_index = {d}, ", .{self.local_sym_index});
|
||||
try std.fmt.format(writer, "}}", .{});
|
||||
}
|
||||
};
|
||||
@ -284,11 +272,6 @@ pub fn asNlist(symbol: *Symbol, zld: *Zld) !macho.nlist_64 {
|
||||
|
||||
pub fn deinit(symbol: *Symbol, allocator: *Allocator) void {
|
||||
allocator.free(symbol.name);
|
||||
|
||||
switch (symbol.payload) {
|
||||
.proxy => |*proxy| proxy.deinit(allocator),
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn isStab(sym: macho.nlist_64) bool {
|
||||
|
||||
@ -136,6 +136,7 @@ pub const TextBlock = struct {
|
||||
size: u64,
|
||||
alignment: u32,
|
||||
rebases: std.ArrayList(u64),
|
||||
bindings: std.ArrayList(SymbolAtOffset),
|
||||
dices: std.ArrayList(macho.data_in_code_entry),
|
||||
next: ?*TextBlock = null,
|
||||
prev: ?*TextBlock = null,
|
||||
@ -226,6 +227,7 @@ pub const TextBlock = struct {
|
||||
.size = undefined,
|
||||
.alignment = undefined,
|
||||
.rebases = std.ArrayList(u64).init(allocator),
|
||||
.bindings = std.ArrayList(SymbolAtOffset).init(allocator),
|
||||
.dices = std.ArrayList(macho.data_in_code_entry).init(allocator),
|
||||
};
|
||||
}
|
||||
@ -239,6 +241,7 @@ pub const TextBlock = struct {
|
||||
self.allocator.free(self.code);
|
||||
self.relocs.deinit();
|
||||
self.rebases.deinit();
|
||||
self.bindings.deinit();
|
||||
self.dices.deinit();
|
||||
}
|
||||
|
||||
@ -293,6 +296,9 @@ pub const TextBlock = struct {
|
||||
if (self.rebases.items.len > 0) {
|
||||
log.warn(" rebases: {any}", .{self.rebases.items});
|
||||
}
|
||||
if (self.bindings.items.len > 0) {
|
||||
log.warn(" bindings: {any}", .{self.bindings.items});
|
||||
}
|
||||
if (self.dices.items.len > 0) {
|
||||
log.warn(" dices: {any}", .{self.dices.items});
|
||||
}
|
||||
@ -1745,9 +1751,11 @@ fn resolveSymbols(self: *Zld) !void {
|
||||
if (!dylib.symbols.contains(symbol.name)) continue;
|
||||
|
||||
try referenced.put(dylib, {});
|
||||
const index = @intCast(u32, self.imports.items.len);
|
||||
symbol.payload = .{
|
||||
.proxy = .{
|
||||
.file = dylib,
|
||||
.local_sym_index = index,
|
||||
},
|
||||
};
|
||||
try self.imports.append(self.allocator, symbol);
|
||||
@ -2341,23 +2349,37 @@ fn writeBindInfoTable(self: *Zld) !void {
|
||||
}
|
||||
}
|
||||
|
||||
for (self.globals.values()) |sym| {
|
||||
if (sym.payload != .proxy) continue;
|
||||
{
|
||||
var it = self.blocks.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const match = entry.key_ptr.*;
|
||||
var block: *TextBlock = entry.value_ptr.*;
|
||||
|
||||
const proxy = sym.payload.proxy;
|
||||
for (proxy.bind_info.items) |info| {
|
||||
const bind_sym = self.locals.items[info.local_sym_index];
|
||||
assert(bind_sym.payload == .regular);
|
||||
const reg = bind_sym.payload.regular;
|
||||
const base_address = self.load_commands.items[reg.segment_id].Segment.inner.vmaddr;
|
||||
const offset = reg.address + info.offset - base_address;
|
||||
if (match.seg == self.text_segment_cmd_index.?) continue; // __TEXT is non-writable
|
||||
|
||||
try pointers.append(.{
|
||||
.offset = offset,
|
||||
.segment_id = reg.segment_id,
|
||||
.dylib_ordinal = proxy.dylibOrdinal(),
|
||||
.name = sym.name,
|
||||
});
|
||||
const seg = self.load_commands.items[match.seg].Segment;
|
||||
|
||||
while (true) {
|
||||
const sym = self.locals.items[block.local_sym_index];
|
||||
assert(sym.payload == .regular);
|
||||
const base_offset = sym.payload.regular.address - seg.inner.vmaddr;
|
||||
|
||||
for (block.bindings.items) |binding| {
|
||||
const bind_sym = self.imports.items[binding.local_sym_index];
|
||||
const proxy = bind_sym.payload.proxy;
|
||||
|
||||
try pointers.append(.{
|
||||
.offset = binding.offset + base_offset,
|
||||
.segment_id = match.seg,
|
||||
.dylib_ordinal = proxy.dylibOrdinal(),
|
||||
.name = bind_sym.name,
|
||||
});
|
||||
}
|
||||
|
||||
if (block.prev) |prev| {
|
||||
block = prev;
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -449,22 +449,13 @@ pub const Relocation = struct {
|
||||
.proxy => |proxy| {
|
||||
if (mem.eql(u8, self.target.name, "__tlv_bootstrap")) {
|
||||
break :blk 0; // Dynamically bound by dyld.
|
||||
// const segment = zld.load_commands.items[zld.data_segment_cmd_index.?].Segment;
|
||||
// const tlv = segment.sections.items[zld.tlv_section_index.?];
|
||||
// break :blk tlv.addr;
|
||||
}
|
||||
|
||||
const segment = zld.load_commands.items[zld.text_segment_cmd_index.?].Segment;
|
||||
const stubs = segment.sections.items[zld.stubs_section_index.?];
|
||||
const stubs_index = self.target.stubs_index orelse {
|
||||
if (proxy.bind_info.items.len > 0) {
|
||||
break :blk 0; // Dynamically bound by dyld.
|
||||
}
|
||||
log.err("expected stubs index or dynamic bind address for symbol '{s}'", .{
|
||||
self.target.name,
|
||||
});
|
||||
log.err(" this is an internal linker error", .{});
|
||||
return error.FailedToResolveRelocationTarget;
|
||||
// TODO verify in TextBlock that the symbol is indeed dynamically bound.
|
||||
break :blk 0; // Dynamically bound by dyld.
|
||||
};
|
||||
break :blk stubs.addr + stubs_index * stubs.reserved2;
|
||||
},
|
||||
@ -647,9 +638,9 @@ pub const Parser = struct {
|
||||
} else if (out_rel.payload == .unsigned) {
|
||||
const sym = out_rel.target;
|
||||
switch (sym.payload) {
|
||||
.proxy => {
|
||||
try sym.payload.proxy.bind_info.append(self.zld.allocator, .{
|
||||
.local_sym_index = self.block.local_sym_index,
|
||||
.proxy => |proxy| {
|
||||
try self.block.bindings.append(.{
|
||||
.local_sym_index = proxy.local_sym_index,
|
||||
.offset = out_rel.offset,
|
||||
});
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user