From 980f2915fa15ab35029e8f3cab21d309811f6e30 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Fri, 2 Jul 2021 11:58:28 +0200 Subject: [PATCH] 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. --- src/link/MachO/Object.zig | 4 ++-- src/link/MachO/Zld.zig | 16 +++++++++------- src/link/MachO/reloc.zig | 10 +++------- src/link/MachO/reloc/aarch64.zig | 17 ++++++++--------- src/link/MachO/reloc/x86_64.zig | 16 +++++++--------- 5 files changed, 29 insertions(+), 34 deletions(-) diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 952fbb794c..1e169e93eb 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -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); diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig index 64e5a2af20..b0677f2604 100644 --- a/src/link/MachO/Zld.zig +++ b/src/link/MachO/Zld.zig @@ -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}); diff --git a/src/link/MachO/reloc.zig b/src/link/MachO/reloc.zig index 1e1b938196..02484923ff 100644 --- a/src/link/MachO/reloc.zig +++ b/src/link/MachO/reloc.zig @@ -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(); diff --git a/src/link/MachO/reloc/aarch64.zig b/src/link/MachO/reloc/aarch64.zig index 16b982bf90..3eaeb65a9d 100644 --- a/src/link/MachO/reloc/aarch64.zig +++ b/src/link/MachO/reloc/aarch64.zig @@ -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.* = .{ diff --git a/src/link/MachO/reloc/x86_64.zig b/src/link/MachO/reloc/x86_64.zig index 6df68b6b3e..9f3c4702c8 100644 --- a/src/link/MachO/reloc/x86_64.zig +++ b/src/link/MachO/reloc/x86_64.zig @@ -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,