zld: use index to symbol in reloc

instead of pointer to the Symbol struct in the hope that we
can overwrite the Symbol in the object's symbol table with the
resolved Symbol later down the line.
This commit is contained in:
Jakub Konka 2021-07-02 11:58:28 +02:00
parent ee6e25bc13
commit 980f2915fa
5 changed files with 29 additions and 34 deletions

View File

@ -377,7 +377,6 @@ pub fn parseSections(self: *Object) !void {
self.arch.?,
section.code,
mem.bytesAsSlice(macho.relocation_info, raw_relocs),
self.symbols.items,
);
}
@ -395,7 +394,8 @@ pub fn parseInitializers(self: *Object) !void {
const relocs = section.relocs orelse unreachable;
try self.initializers.ensureCapacity(self.allocator, relocs.len);
for (relocs) |rel| {
self.initializers.appendAssumeCapacity(rel.target.symbol);
const sym = self.symbols.items[rel.target.symbol];
self.initializers.appendAssumeCapacity(sym);
}
mem.reverse(*Symbol, self.initializers.items);

View File

@ -1172,7 +1172,7 @@ fn allocateProxyBindAddresses(self: *Zld) !void {
if (rel.@"type" != .unsigned) continue; // GOT is currently special-cased
if (rel.target != .symbol) continue;
const sym = rel.target.symbol.getTopmostAlias();
const sym = object.symbols.items[rel.target.symbol].getTopmostAlias();
if (sym.cast(Symbol.Proxy)) |proxy| {
const target_map = sect.target_map orelse continue;
const target_seg = self.load_commands.items[target_map.segment_id].Segment;
@ -1670,7 +1670,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
switch (rel.@"type") {
.unsigned => continue,
.got_page, .got_page_off, .got_load, .got, .pointer_to_got => {
const sym = rel.target.symbol.getTopmostAlias();
const sym = object.symbols.items[rel.target.symbol].getTopmostAlias();
if (sym.got_index != null) continue;
const index = @intCast(u32, self.got_entries.items.len);
@ -1682,7 +1682,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
else => {
if (rel.target != .symbol) continue;
const sym = rel.target.symbol.getTopmostAlias();
const sym = object.symbols.items[rel.target.symbol].getTopmostAlias();
assert(sym.@"type" != .unresolved);
if (sym.stubs_index != null) continue;
@ -1781,7 +1781,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
break :rebase false;
}
if (rel.target == .symbol) {
const final = rel.target.symbol.getTopmostAlias();
const final = object.symbols.items[rel.target.symbol].getTopmostAlias();
if (final.cast(Symbol.Proxy)) |_| {
break :rebase false;
}
@ -1801,7 +1801,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
// Calculate the offset to the initializer.
if (flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {
// TODO we don't want to save offset to tlv_bootstrap
if (mem.eql(u8, rel.target.symbol.name, "__tlv_bootstrap")) break :tlv;
if (mem.eql(u8, object.symbols.items[rel.target.symbol].name, "__tlv_bootstrap")) break :tlv;
const base_addr = blk: {
if (self.tlv_data_section_index) |index| {
@ -1823,7 +1823,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
.got_page, .got_page_off, .got_load, .got, .pointer_to_got => {
const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
const got = dc_seg.sections.items[self.got_section_index.?];
const final = rel.target.symbol.getTopmostAlias();
const sym = object.symbols.items[rel.target.symbol];
const final = sym.getTopmostAlias();
const got_index = final.got_index orelse {
log.err("expected GOT index relocating symbol '{s}'", .{final.name});
log.err("this is an internal linker error", .{});
@ -1879,7 +1880,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.Target) !u64 {
const target_addr = blk: {
switch (target) {
.symbol => |sym| {
.symbol => |sym_id| {
const sym = object.symbols.items[sym_id];
const final = sym.getTopmostAlias();
if (final.cast(Symbol.Regular)) |reg| {
log.debug(" | regular '{s}'", .{sym.name});

View File

@ -10,7 +10,6 @@ const aarch64 = @import("reloc/aarch64.zig");
const x86_64 = @import("reloc/x86_64.zig");
const Allocator = mem.Allocator;
const Symbol = @import("Symbol.zig");
pub const Relocation = struct {
@"type": Type,
@ -81,12 +80,12 @@ pub const Relocation = struct {
};
pub const Target = union(enum) {
symbol: *Symbol,
symbol: u32,
section: u16,
pub fn from_reloc(reloc: macho.relocation_info, symbols: []*Symbol) Target {
pub fn fromReloc(reloc: macho.relocation_info) Target {
return if (reloc.r_extern == 1) .{
.symbol = symbols[reloc.r_symbolnum],
.symbol = reloc.r_symbolnum,
} else .{
.section = @intCast(u16, reloc.r_symbolnum - 1),
};
@ -142,7 +141,6 @@ pub fn parse(
arch: std.Target.Cpu.Arch,
code: []u8,
relocs: []const macho.relocation_info,
symbols: []*Symbol,
) ![]*Relocation {
var it = RelocIterator{
.buffer = relocs,
@ -155,7 +153,6 @@ pub fn parse(
.it = &it,
.code = code,
.parsed = std.ArrayList(*Relocation).init(allocator),
.symbols = symbols,
};
defer parser.deinit();
try parser.parse();
@ -168,7 +165,6 @@ pub fn parse(
.it = &it,
.code = code,
.parsed = std.ArrayList(*Relocation).init(allocator),
.symbols = symbols,
};
defer parser.deinit();
try parser.parse();

View File

@ -203,7 +203,6 @@ pub const Parser = struct {
it: *reloc.RelocIterator,
code: []u8,
parsed: std.ArrayList(*Relocation),
symbols: []*Symbol,
addend: ?u32 = null,
subtractor: ?Relocation.Target = null,
@ -287,7 +286,7 @@ pub const Parser = struct {
var branch = try parser.allocator.create(Branch);
errdefer parser.allocator.destroy(branch);
const target = Relocation.Target.from_reloc(rel, parser.symbols);
const target = Relocation.Target.fromReloc(rel);
branch.* = .{
.base = .{
@ -308,7 +307,7 @@ pub const Parser = struct {
assert(rel.r_length == 2);
const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type);
const target = Relocation.Target.from_reloc(rel, parser.symbols);
const target = Relocation.Target.fromReloc(rel);
const offset = @intCast(u32, rel.r_address);
const inst = parser.code[offset..][0..4];
@ -414,7 +413,7 @@ pub const Parser = struct {
aarch64.Instruction.load_store_register,
), inst) };
}
const target = Relocation.Target.from_reloc(rel, parser.symbols);
const target = Relocation.Target.fromReloc(rel);
var page_off = try parser.allocator.create(PageOff);
errdefer parser.allocator.destroy(page_off);
@ -451,7 +450,7 @@ pub const Parser = struct {
), inst);
assert(parsed_inst.size == 3);
const target = Relocation.Target.from_reloc(rel, parser.symbols);
const target = Relocation.Target.fromReloc(rel);
var page_off = try parser.allocator.create(GotPageOff);
errdefer parser.allocator.destroy(page_off);
@ -510,7 +509,7 @@ pub const Parser = struct {
}
};
const target = Relocation.Target.from_reloc(rel, parser.symbols);
const target = Relocation.Target.fromReloc(rel);
var page_off = try parser.allocator.create(TlvpPageOff);
errdefer parser.allocator.destroy(page_off);
@ -545,7 +544,7 @@ pub const Parser = struct {
assert(rel.r_pcrel == 0);
assert(parser.subtractor == null);
parser.subtractor = Relocation.Target.from_reloc(rel, parser.symbols);
parser.subtractor = Relocation.Target.fromReloc(rel);
// Verify SUBTRACTOR is followed by UNSIGNED.
const next = @intToEnum(macho.reloc_type_arm64, parser.it.peek().r_type);
@ -568,7 +567,7 @@ pub const Parser = struct {
var unsigned = try parser.allocator.create(reloc.Unsigned);
errdefer parser.allocator.destroy(unsigned);
const target = Relocation.Target.from_reloc(rel, parser.symbols);
const target = Relocation.Target.fromReloc(rel);
const is_64bit: bool = switch (rel.r_length) {
3 => true,
2 => false,
@ -605,7 +604,7 @@ pub const Parser = struct {
var ptr_to_got = try parser.allocator.create(PointerToGot);
errdefer parser.allocator.destroy(ptr_to_got);
const target = Relocation.Target.from_reloc(rel, parser.symbols);
const target = Relocation.Target.fromReloc(rel);
const offset = @intCast(u32, rel.r_address);
ptr_to_got.* = .{

View File

@ -9,7 +9,6 @@ const reloc = @import("../reloc.zig");
const Allocator = mem.Allocator;
const Relocation = reloc.Relocation;
const Symbol = @import("../Symbol.zig");
pub const Branch = struct {
base: Relocation,
@ -103,7 +102,6 @@ pub const Parser = struct {
it: *reloc.RelocIterator,
code: []u8,
parsed: std.ArrayList(*Relocation),
symbols: []*Symbol,
subtractor: ?Relocation.Target = null,
pub fn deinit(parser: *Parser) void {
@ -154,7 +152,7 @@ pub const Parser = struct {
var branch = try parser.allocator.create(Branch);
errdefer parser.allocator.destroy(branch);
const target = Relocation.Target.from_reloc(rel, parser.symbols);
const target = Relocation.Target.fromReloc(rel);
branch.* = .{
.base = .{
@ -174,7 +172,7 @@ pub const Parser = struct {
assert(rel.r_length == 2);
const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type);
const target = Relocation.Target.from_reloc(rel, parser.symbols);
const target = Relocation.Target.fromReloc(rel);
const offset = @intCast(u32, rel.r_address);
const inst = parser.code[offset..][0..4];
@ -213,7 +211,7 @@ pub const Parser = struct {
const offset = @intCast(u32, rel.r_address);
const inst = parser.code[offset..][0..4];
const target = Relocation.Target.from_reloc(rel, parser.symbols);
const target = Relocation.Target.fromReloc(rel);
var got_load = try parser.allocator.create(GotLoad);
errdefer parser.allocator.destroy(got_load);
@ -239,7 +237,7 @@ pub const Parser = struct {
const offset = @intCast(u32, rel.r_address);
const inst = parser.code[offset..][0..4];
const target = Relocation.Target.from_reloc(rel, parser.symbols);
const target = Relocation.Target.fromReloc(rel);
const addend = mem.readIntLittle(i32, inst);
var got = try parser.allocator.create(Got);
@ -267,7 +265,7 @@ pub const Parser = struct {
const offset = @intCast(u32, rel.r_address);
const inst = parser.code[offset..][0..4];
const target = Relocation.Target.from_reloc(rel, parser.symbols);
const target = Relocation.Target.fromReloc(rel);
var tlv = try parser.allocator.create(Tlv);
errdefer parser.allocator.destroy(tlv);
@ -292,7 +290,7 @@ pub const Parser = struct {
assert(rel.r_pcrel == 0);
assert(parser.subtractor == null);
parser.subtractor = Relocation.Target.from_reloc(rel, parser.symbols);
parser.subtractor = Relocation.Target.fromReloc(rel);
// Verify SUBTRACTOR is followed by UNSIGNED.
const next = @intToEnum(macho.reloc_type_x86_64, parser.it.peek().r_type);
@ -315,7 +313,7 @@ pub const Parser = struct {
var unsigned = try parser.allocator.create(reloc.Unsigned);
errdefer parser.allocator.destroy(unsigned);
const target = Relocation.Target.from_reloc(rel, parser.symbols);
const target = Relocation.Target.fromReloc(rel);
const is_64bit: bool = switch (rel.r_length) {
3 => true,
2 => false,