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 952fbb794c0052f61f03f01121817247496d0298..1e169e93eba8b96add754c70ab0b7db063ecdebd 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 64e5a2af2010e5ce906912aafae811532cb9de3a..b0677f260446a40e78ad4a2510eb6893da73001a 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 1e1b938196411856231769762bee449746da1992..02484923ffda2ce8616d09b076f56121c7795668 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 16b982bf90d2c9705c29f2844c2551fd3bfb93bc..3eaeb65a9d8b6748721b1b76a94f2946b5ff9761 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 6df68b6b3ea36c976ec44c190ec036f56fa6307a..9f3c4702c84255c62b7b6a31989de7e224651473 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, -- 2.54.0