From 02b67d7e19455cfc069daf9e665fe28d4d01a9f2 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 2 Aug 2026 16:02:49 +0100 Subject: [PATCH] link: simplify public API There was a bunch of legacy cruft in the linker's public API which was duplicating functionality, particularly regarding symbols and relocations. Move towards standardising on an interface based on `link.File.SymbolId`. The `navSymbol` and `uavSymbol` functions return `link.File.SymbolId`s representing a given NAV or UAV; then, with that `SymbolId`, codegen can call `relocSymAddr` to relocate that symbol's absolute address. The caller is responsible for writing placeholder bytes (probably zeroes) to be overwritten by that relocation. Previously the API told you an address to write in, but this was entirely redundant with the added relocation. --- src/codegen.zig | 86 +++++---------------------------- src/codegen/aarch64/Mir.zig | 8 +-- src/codegen/loongarch/Mir.zig | 15 ++---- src/codegen/riscv64/CodeGen.zig | 2 +- src/codegen/x86_64/Emit.zig | 12 ++--- src/link.zig | 28 ++++------- src/link/Coff.zig | 47 +++++------------- src/link/Elf.zig | 16 +++--- src/link/Elf/ZigObject.zig | 80 +++++++++++++----------------- src/link/Elf2.zig | 36 ++------------ src/link/MachO.zig | 16 +++--- src/link/MachO/ZigObject.zig | 74 +++++++++++----------------- 12 files changed, 126 insertions(+), 294 deletions(-) diff --git a/src/codegen.zig b/src/codegen.zig index 61932ba4f1ddf7d921156053c9c38cb785f69c41..2213e7ee506d2156be699188d8d666c1c22d4e7b 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -754,23 +754,15 @@ fn lowerUavRef( } const uav_align = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu); - _ = try lf.lowerUav(pt, uav_val, uav_align); - const vaddr = lf.getUavVAddr(uav_val, .{ + try lf.relocSymAddr(.{ .parent = reloc_parent, .offset = w.end, + .target = try lf.uavSymbol(pt, uav_val, uav_align), .addend = @intCast(offset), - }) catch |err| switch (err) { - error.OutOfMemory => |e| return e, - else => |e| std.debug.panic("TODO rework lowerUav. internal error: {t}", .{e}), - }; - const endian = target.cpu.arch.endian(); - switch (ptr_width_bytes) { - 2 => try w.writeInt(u16, @intCast(vaddr), endian), - 4 => try w.writeInt(u32, @intCast(vaddr), endian), - 8 => try w.writeInt(u64, vaddr, endian), - else => unreachable, - } + }); + + try w.splatByteAll(0, ptr_width_bytes); // overwritten by relocation } fn lowerNavRef( @@ -805,68 +797,14 @@ fn lowerNavRef( else => {}, } - const vaddr = lf.getNavVAddr(pt, nav_index, .{ + try lf.relocSymAddr(.{ .parent = reloc_parent, .offset = w.end, + .target = try lf.navSymbol(nav_index), .addend = @intCast(offset), - }) catch @panic("TODO rework getNavVAddr"); - const endian = target.cpu.arch.endian(); - switch (ptr_width_bytes) { - 2 => try w.writeInt(u16, @intCast(vaddr), endian), - 4 => try w.writeInt(u32, @intCast(vaddr), endian), - 8 => try w.writeInt(u64, vaddr, endian), - else => unreachable, - } -} + }); -pub fn genNavRef( - lf: *link.File, - pt: Zcu.PerThread, - nav_index: InternPool.Nav.Index, -) Error!link.File.SymbolId { - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - const nav = ip.getNav(nav_index); - log.debug("genNavRef({f})", .{nav.fqn.fmt(ip)}); - - const is_threadlocal = nav.resolved.?.@"threadlocal" and zcu.comp.config.any_non_single_threaded; - if (lf.cast(.elf)) |elf_file| { - const zo = elf_file.zigObjectPtr().?; - if (nav.getExtern(ip)) |e| { - const sym_index = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip)); - switch (e.linkage) { - .strong => {}, - .weak => zo.symbol(sym_index).flags.weak = true, - } - if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true; - return @fromBackingInt(@intCast(sym_index)); - } else { - const sym_index = try zo.getOrCreateMetadataForNav(zcu, nav_index); - if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true; - return @fromBackingInt(@intCast(sym_index)); - } - } else if (lf.cast(.elf2)) |elf| { - return elf.navSymbol(nav_index); - } else if (lf.cast(.macho)) |macho_file| { - const zo = macho_file.getZigObject().?; - if (nav.getExtern(ip)) |e| { - const sym_index = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip)); - switch (e.linkage) { - .strong => {}, - .weak => zo.symbols.items[sym_index].flags.weak = true, - } - if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true; - return @fromBackingInt(@intCast(sym_index)); - } else { - const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index); - if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true; - return @fromBackingInt(@intCast(sym_index)); - } - } else if (lf.cast(.coff)) |coff| { - return @fromBackingInt(@intCast(@backingInt(try coff.navSymbol(zcu, nav_index)))); - } else { - std.debug.panic("TODO genNavRef for '{t}'", .{lf.tag}); - } + try w.splatByteAll(0, ptr_width_bytes); // overwritten by relocation } /// deprecated legacy type @@ -908,13 +846,13 @@ pub fn genTypedValue( .none => .none, .undef => .undef, .immediate => |imm| .{ .immediate = imm }, - .lea_nav => |nav| .{ .lea_symbol = try genNavRef(lf, pt, nav) }, - .load_uav => |uav| .{ .load_symbol = try lf.lowerUav( + .lea_nav => |nav| .{ .lea_symbol = try lf.navSymbol(nav) }, + .load_uav => |uav| .{ .load_symbol = try lf.uavSymbol( pt, uav.val, Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu), ) }, - .lea_uav => |uav| .{ .lea_symbol = try lf.lowerUav( + .lea_uav => |uav| .{ .lea_symbol = try lf.uavSymbol( pt, uav.val, Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu), diff --git a/src/codegen/aarch64/Mir.zig b/src/codegen/aarch64/Mir.zig index ad40e86902d4273b2b558fa1b1b97add12b29345..1233a8180db0e726d2d2904eb2246734ad18ab56 100644 --- a/src/codegen/aarch64/Mir.zig +++ b/src/codegen/aarch64/Mir.zig @@ -93,11 +93,7 @@ pub fn emit( lf, zcu, atom_index, - try @import("../../codegen.zig").genNavRef( - lf, - pt, - nav_reloc.nav, - ), + try lf.navSymbol(nav_reloc.nav), mir.body[nav_reloc.reloc.label], body_end - Instruction.size * (1 + nav_reloc.reloc.label), nav_reloc.reloc.addend, @@ -107,7 +103,7 @@ pub fn emit( lf, zcu, atom_index, - try lf.lowerUav( + try lf.uavSymbol( pt, uav_reloc.uav.val, ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu), diff --git a/src/codegen/loongarch/Mir.zig b/src/codegen/loongarch/Mir.zig index f81843ff4e24ce3c395cd250844e1bed9bb368cb..e107984767b547ccb82c9ac1ab869c4ee4d02e24 100644 --- a/src/codegen/loongarch/Mir.zig +++ b/src/codegen/loongarch/Mir.zig @@ -83,11 +83,7 @@ pub fn emit( lf, zcu, atom_index, - try @import("../../codegen.zig").genNavRef( - lf, - pt, - nav_reloc.nav, - ), + try lf.navSymbol(nav_reloc.nav), nav_reloc.reloc.type, body_end - @sizeOf(Instruction) * (1 + nav_reloc.reloc.label), nav_reloc.reloc.addend, @@ -97,7 +93,7 @@ pub fn emit( lf, zcu, atom_index, - try lf.lowerUav( + try lf.uavSymbol( pt, uav_reloc.uav.val, ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu), @@ -142,16 +138,11 @@ pub fn emit( ) catch |err| return zcu.codegenFail(func.owner_nav, "emit reloc failed: {t}", .{err}); - const func_nav = try @import("../../codegen.zig").genNavRef( - lf, - pt, - func.owner_nav, - ); for (mir.internal_relocs) |internal_reloc| emitReloc( lf, zcu, atom_index, - func_nav, + try lf.navSymbol(func.owner_nav), internal_reloc.reloc.type, body_end - @sizeOf(Instruction) * (1 + internal_reloc.reloc.label), @sizeOf(Instruction) * (@as(i64, @intCast(mir.prologue.len + mir.body.len - internal_reloc.target))), diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig index 1db4dde0627e2ee00b6f65f9c48db0b53b29f8c2..aeb1dde892769fe1270542079b778ed6487d0cdf 100644 --- a/src/codegen/riscv64/CodeGen.zig +++ b/src/codegen/riscv64/CodeGen.zig @@ -8160,7 +8160,7 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue { const lf = func.bin_file; const result: codegen.MCValue = if (val.isUndef(pt.zcu)) - .{ .load_symbol = try lf.lowerUav(pt, val.toIntern(), .none) } + .{ .load_symbol = try lf.uavSymbol(pt, val.toIntern(), .none) } else try codegen.genTypedValue(lf, pt, val, func.target); const mcv: MCValue = switch (result) { diff --git a/src/codegen/x86_64/Emit.zig b/src/codegen/x86_64/Emit.zig index 6dcaf2173d2f1fb36cf8940a0146881de02cfb93..a82ae415ac502309854af8e9ca44636ee3c8ab43 100644 --- a/src/codegen/x86_64/Emit.zig +++ b/src/codegen/x86_64/Emit.zig @@ -100,11 +100,7 @@ pub fn emitMir(emit: *Emit) Error!void { .inst => |inst| .{ .inst = inst }, .table => .table, .nav => |nav| { - const symbol_id = try codegen.genNavRef( - emit.bin_file, - emit.pt, - nav, - ); + const symbol_id = try emit.bin_file.navSymbol(nav); const target_symbol: RelocInfo.Target.Symbol = if (ip.getNav(nav).getExtern(ip)) |@"extern"| .{ .symbol = symbol_id, .is_extern = switch (@"extern".visibility) { @@ -124,7 +120,7 @@ pub fn emitMir(emit: *Emit) Error!void { } }, .uav => |uav| .{ .symbol = .{ - .symbol = try emit.bin_file.lowerUav( + .symbol = try emit.bin_file.uavSymbol( emit.pt, uav.val, Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu), @@ -597,12 +593,12 @@ pub fn emitMir(emit: *Emit) Error!void { .nav => |nav| @unionInit( DwarfLoc, addr_loc, - try codegen.genNavRef(emit.bin_file, emit.pt, nav), + try emit.bin_file.navSymbol(nav), ), .uav => |uav| @unionInit( DwarfLoc, addr_loc, - try emit.bin_file.lowerUav( + try emit.bin_file.uavSymbol( emit.pt, uav.val, Type.fromInterned(uav.orig_ty) diff --git a/src/link.zig b/src/link.zig index 0e2d6e2ff5c54184fb473a25dee0a2488e3e746f..c72a65a888eb4489153569c6971c9eec6d63f217 100644 --- a/src/link.zig +++ b/src/link.zig @@ -1039,6 +1039,7 @@ pub const File = struct { pub const RelocInfo = struct { parent: Parent, offset: u64, + target: SymbolId, addend: u32, pub const Parent = union(enum) { @@ -1048,16 +1049,9 @@ pub const File = struct { }; }; - /// Get allocated `Nav`'s address in virtual memory. - /// The linker is passed information about the containing atom, `parent_atom_index`, and offset within it's - /// memory buffer, `offset`, so that it can make a note of potential relocation sites, should the - /// `Nav`'s address was not yet resolved, or the containing atom gets moved in virtual memory. - /// May be called before or after updateFunc/updateNav therefore it is up to the linker to allocate - /// the block/atom. /// Never called when LLVM is codegenning the ZCU. - pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) Error!u64 { - assert(pt.zcu.llvm_object == null); - + pub fn relocSymAddr(base: *File, reloc_info: RelocInfo) Error!void { + assert(base.comp.zcu.?.llvm_object == null); switch (base.tag) { .lld => unreachable, .c => unreachable, @@ -1067,20 +1061,19 @@ pub const File = struct { .spork8 => unreachable, inline else => |tag| { dev.check(tag.devFeature()); - return @as(*tag.Type(), @fieldParentPtr("base", base)).getNavVAddr(pt, nav_index, reloc_info); + return @as(*tag.Type(), @fieldParentPtr("base", base)).relocSymAddr(reloc_info); }, } } /// Never called when LLVM is codegenning the ZCU. - pub fn lowerUav( + pub fn uavSymbol( base: *File, pt: Zcu.PerThread, - decl_val: InternPool.Index, - decl_align: InternPool.Alignment, + uav_val: InternPool.Index, + uav_align: InternPool.Alignment, ) Error!SymbolId { assert(pt.zcu.llvm_object == null); - switch (base.tag) { .lld => unreachable, .c => unreachable, @@ -1090,15 +1083,14 @@ pub const File = struct { .spork8 => unreachable, inline else => |tag| { dev.check(tag.devFeature()); - return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerUav(pt, decl_val, decl_align); + return @as(*tag.Type(), @fieldParentPtr("base", base)).uavSymbol(pt, uav_val, uav_align); }, } } /// Never called when LLVM is codegenning the ZCU. - pub fn getUavVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) Error!u64 { + pub fn navSymbol(base: *File, nav: InternPool.Nav.Index) Error!SymbolId { assert(base.comp.zcu.?.llvm_object == null); - switch (base.tag) { .lld => unreachable, .c => unreachable, @@ -1108,7 +1100,7 @@ pub const File = struct { .spork8 => unreachable, inline else => |tag| { dev.check(tag.devFeature()); - return @as(*tag.Type(), @fieldParentPtr("base", base)).getUavVAddr(decl_val, reloc_info); + return @as(*tag.Type(), @fieldParentPtr("base", base)).navSymbol(nav); }, } } diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 1aa577aa45026387561fc81794ce7e43f42b71be..dbdea4966de0b5ba91b7e2b026a7b80c419d5854 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -2935,18 +2935,19 @@ fn navMapIndex(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.Na if (!sym_gop.found_existing) sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity(); return @fromBackingInt(@intCast(sym_gop.index)); } -pub fn navSymbol(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index { +pub fn navSymbol(coff: *Coff, nav_index: InternPool.Nav.Index) link.Error!link.File.SymbolId { + const zcu = coff.base.comp.zcu.?; const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); - if (nav.getExtern(ip)) |@"extern"| return coff.globalSymbol(.{ + if (nav.getExtern(ip)) |@"extern"| return @bitCast(try coff.globalSymbol(.{ .name = @"extern".name.toSlice(ip), .lib_name = @"extern".lib_name.toSlice(ip), // TODO: Threadlocal as well? .type = if (ip.isFunctionType(nav.resolved.?.type)) .code else .data, .dll_storage_class = if (@"extern".is_dll_import) .dllimport else .default, - }); + })); const nmi = try coff.navMapIndex(zcu, nav_index); - return nmi.symbol(coff); + return @bitCast(nmi.symbol(coff)); } fn uavMapIndex(coff: *Coff, uav_val: InternPool.Index) !Node.UavMapIndex { @@ -2956,10 +2957,6 @@ fn uavMapIndex(coff: *Coff, uav_val: InternPool.Index) !Node.UavMapIndex { if (!sym_gop.found_existing) sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity(); return @fromBackingInt(@intCast(sym_gop.index)); } -pub fn uavSymbol(coff: *Coff, uav_val: InternPool.Index) !Symbol.Index { - const umi = try coff.uavMapIndex(uav_val); - return umi.symbol(coff); -} pub fn lazySymbol(coff: *Coff, lazy: link.File.LazySymbol) !Symbol.Index { const gpa = coff.base.comp.gpa; @@ -2972,24 +2969,8 @@ pub fn lazySymbol(coff: *Coff, lazy: link.File.LazySymbol) !Symbol.Index { return sym_gop.value_ptr.*; } -pub fn getNavVAddr( - coff: *Coff, - pt: Zcu.PerThread, - nav: InternPool.Nav.Index, - reloc_info: link.File.RelocInfo, -) link.Error!u64 { - return coff.getVAddr(reloc_info, try coff.navSymbol(pt.zcu, nav)); -} - -pub fn getUavVAddr( - coff: *Coff, - uav: InternPool.Index, - reloc_info: link.File.RelocInfo, -) link.Error!u64 { - return coff.getVAddr(reloc_info, try coff.uavSymbol(uav)); -} - -pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol.Index) link.Error!u64 { +pub fn relocSymAddr(coff: *Coff, reloc_info: link.File.RelocInfo) link.Error!void { + const target_si: Symbol.Index = @bitCast(reloc_info.target); try coff.addReloc( @fromBackingInt(@intCast(@backingInt(reloc_info.parent.atom_index))), reloc_info.offset, @@ -3001,10 +2982,6 @@ pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol. .I386 => .{ .I386 = .DIR32 }, }, ); - - var vaddr: u64 = target_si.get(coff).rva; - if (coff.isImage()) vaddr += coff.optionalHeaderField(.image_base); - return vaddr; } /// Caller guarantees there is capacity for one member and two nodes @@ -5580,13 +5557,15 @@ pub fn updateContainerType( }; } -pub fn lowerUav( +pub fn uavSymbol( coff: *Coff, pt: Zcu.PerThread, uav_val: InternPool.Index, uav_align: InternPool.Alignment, ) link.Error!link.File.SymbolId { - const zcu = pt.zcu; + _ = pt; + + const zcu = coff.base.comp.zcu.?; const gpa = zcu.gpa; try coff.pending_uavs.ensureUnusedCapacity(gpa, 1); @@ -7471,8 +7450,8 @@ fn updateExportInner( try coff.symbols.ensureUnusedCapacity(gpa, 1); const exported_si: Symbol.Index = switch (exp.exported) { - .nav => |nav| try coff.navSymbol(zcu, nav), - .uav => |uav| @fromBackingInt(@intCast(@backingInt(try coff.lowerUav( + .nav => |nav| @bitCast(try coff.navSymbol(nav)), + .uav => |uav| @fromBackingInt(@intCast(@backingInt(try coff.uavSymbol( pt, uav, Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu), diff --git a/src/link/Elf.zig b/src/link/Elf.zig index b0e188390f24c3000d382aae4b76646fd6306644..3cbcc53361033b74e8ea1c69189f6909d3be7ad6 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -463,21 +463,21 @@ pub fn deinit(self: *Elf) void { self.dump_argv_list.deinit(gpa); } -pub fn getNavVAddr(self: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 { - return self.zigObjectPtr().?.getNavVAddr(self, pt, nav_index, reloc_info); +pub fn navSymbol(self: *Elf, nav: InternPool.Nav.Index) link.Error!link.File.SymbolId { + return self.zigObjectPtr().?.navSymbol(self, nav); } -pub fn lowerUav( +pub fn relocSymAddr(self: *Elf, reloc_info: link.File.RelocInfo) !void { + return self.zigObjectPtr().?.relocSymAddr(self, reloc_info); +} + +pub fn uavSymbol( self: *Elf, pt: Zcu.PerThread, uav: InternPool.Index, explicit_alignment: InternPool.Alignment, ) !link.File.SymbolId { - return self.zigObjectPtr().?.lowerUav(self, pt, uav, explicit_alignment); -} - -pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { - return self.zigObjectPtr().?.getUavVAddr(self, uav, reloc_info); + return self.zigObjectPtr().?.uavSymbol(self, pt, uav, explicit_alignment); } /// Returns end pos of collision, if any. diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index ea092197086be61f652433464a06f31a481e7ebe..551f4c626ddb3a0e819eb158a4290c271d5d34be 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -917,24 +917,42 @@ pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 return code; } -pub fn getNavVAddr( - self: *ZigObject, +pub fn navSymbol( + zo: *ZigObject, elf_file: *Elf, - pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, - reloc_info: link.File.RelocInfo, -) !u64 { - const zcu = pt.zcu; +) link.Error!link.File.SymbolId { + const zcu = elf_file.base.comp.zcu.?; const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); - log.debug("getNavVAddr {f}({d})", .{ nav.fqn.fmt(ip), nav_index }); - const this_sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol( - elf_file, - nav.name.toSlice(ip), - @"extern".lib_name.toSlice(ip), - ) else try self.getOrCreateMetadataForNav(zcu, nav_index); - const this_sym = self.symbol(this_sym_index); - const vaddr = this_sym.address(.{}, elf_file); + if (nav.getExtern(ip)) |@"extern"| { + const sym_index = try zo.getGlobalSymbol( + elf_file, + nav.name.toSlice(ip), + @"extern".lib_name.toSlice(ip), + ); + if (@"extern".linkage == .weak) { + zo.symbol(sym_index).flags.weak = true; + } + if (nav.resolved.?.@"threadlocal") { + zo.symbol(sym_index).flags.is_tls = true; + } + return @fromBackingInt(sym_index); + } else { + const sym_index = try zo.getOrCreateMetadataForNav(zcu, nav_index); + if (nav.resolved.?.@"threadlocal") { + zo.symbol(sym_index).flags.is_tls = true; + } + return @fromBackingInt(sym_index); + } +} + +pub fn relocSymAddr( + self: *ZigObject, + elf_file: *Elf, + reloc_info: link.File.RelocInfo, +) !void { + const this_sym_index = @backingInt(reloc_info.target); switch (reloc_info.parent) { .none => unreachable, .atom_index => |atom_index| { @@ -952,39 +970,9 @@ pub fn getNavVAddr( .target_off = reloc_info.addend, }), } - return @intCast(vaddr); } -pub fn getUavVAddr( - self: *ZigObject, - elf_file: *Elf, - uav: InternPool.Index, - reloc_info: link.File.RelocInfo, -) !u64 { - const sym_index = self.uavs.get(uav).?.symbol_index; - const sym = self.symbol(sym_index); - const vaddr = sym.address(.{}, elf_file); - switch (reloc_info.parent) { - .none => unreachable, - .atom_index => |atom_index| { - const parent_atom = self.symbol(@backingInt(atom_index)).atom(elf_file).?; - const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch); - try parent_atom.addReloc(elf_file.base.comp.gpa, .{ - .r_offset = reloc_info.offset, - .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type, - .r_addend = reloc_info.addend, - }, self); - }, - .debug_output => |debug_output| try debug_output.dwarf.infoExternalReloc(.{ - .source_off = @intCast(reloc_info.offset), - .target_sym = @fromBackingInt(@intCast(sym_index)), - .target_off = reloc_info.addend, - }), - } - return @intCast(vaddr); -} - -pub fn lowerUav( +pub fn uavSymbol( self: *ZigObject, elf_file: *Elf, pt: Zcu.PerThread, @@ -1889,7 +1877,7 @@ pub fn updateExports( break :blk self.navs.getPtr(nav).?; }, .uav => |uav| self.uavs.getPtr(uav) orelse blk: { - _ = try self.lowerUav(elf_file, pt, uav, .none); + _ = try self.uavSymbol(elf_file, pt, uav, .none); break :blk self.uavs.getPtr(uav).?; }, }; diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index 10043990722a7482f2a537aa8191b6c81020787f..5967cfe48e03369cd10f620035179e99b4f41904 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -4324,36 +4324,7 @@ pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.Fil const s: Symbol.Id = .local(nmi.symbol(elf)); return s.toTypeErased(); } -pub fn uavSymbol( - elf: *Elf, - uav_val: InternPool.Index, - uav_align: InternPool.Alignment, -) link.Error!link.File.SymbolId { - const diags = &elf.base.comp.link_diags; - const umi = elf.uavMapIndex(uav_val, uav_align) catch |err| switch (err) { - else => |e| return e, - error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), - }; - const s: Symbol.Id = .local(umi.symbol(elf)); - return s.toTypeErased(); -} -pub fn getNavVAddr( - elf: *Elf, - pt: Zcu.PerThread, - nav: InternPool.Nav.Index, - reloc_info: link.File.RelocInfo, -) link.Error!u64 { - _ = pt; - return elf.getVAddr(reloc_info, try elf.navSymbol(nav)); -} -pub fn getUavVAddr( - elf: *Elf, - uav_val: InternPool.Index, - reloc_info: link.File.RelocInfo, -) link.Error!u64 { - return elf.getVAddr(reloc_info, try elf.uavSymbol(uav_val, .none)); -} -pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target: link.File.SymbolId) link.Error!u64 { +pub fn relocSymAddr(elf: *Elf, reloc_info: link.File.RelocInfo) link.Error!void { try elf.addReloc( switch (reloc_info.parent) { .none => unreachable, @@ -4361,13 +4332,12 @@ pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target: link.File.Sy .debug_output => |debug_output| Node.toAtom(debug_output.dwarf2.info_writer.ni), }, reloc_info.offset, - target, + reloc_info.target, reloc_info.addend, .absAddr(elf), ); - return Symbol.Id.fromTypeErased(target).value(elf); } -pub fn lowerUav( +pub fn uavSymbol( elf: *Elf, pt: Zcu.PerThread, uav_val: InternPool.Index, diff --git a/src/link/MachO.zig b/src/link/MachO.zig index d321d45939cd883d40a3dadd32462071b442fe67..dbabc88a512ff37af5fd0caa9ece4562b8e06378 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3124,21 +3124,21 @@ pub fn freeNav(self: *MachO, nav: InternPool.Nav.Index) void { return self.getZigObject().?.freeNav(nav); } -pub fn getNavVAddr(self: *MachO, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 { - return self.getZigObject().?.getNavVAddr(self, pt, nav_index, reloc_info); +pub fn navSymbol(self: *MachO, nav: InternPool.Nav.Index) link.Error!link.File.SymbolId { + return self.getZigObject().?.navSymbol(self, nav); } -pub fn lowerUav( +pub fn relocSymAddr(self: *MachO, reloc_info: link.File.RelocInfo) link.Error!void { + return self.getZigObject().?.relocSymAddr(self, reloc_info); +} + +pub fn uavSymbol( self: *MachO, pt: Zcu.PerThread, uav: InternPool.Index, explicit_alignment: InternPool.Alignment, ) !link.File.SymbolId { - return self.getZigObject().?.lowerUav(self, pt, uav, explicit_alignment); -} - -pub fn getUavVAddr(self: *MachO, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { - return self.getZigObject().?.getUavVAddr(self, uav, reloc_info); + return self.getZigObject().?.uavSymbol(self, pt, uav, explicit_alignment); } pub fn getGlobalSymbol(self: *MachO, name: []const u8, lib_name: ?[]const u8) !u32 { diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index 6d7f9d19d3a63a102ec137c4a29f896e03b83572..a44846211834c8b96a52324ce218c7ea479de48f 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -611,60 +611,43 @@ pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.E assert(!self.debug_strtab_dirty); } -pub fn getNavVAddr( - self: *ZigObject, +pub fn navSymbol( + zo: *ZigObject, macho_file: *MachO, - pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, - reloc_info: link.File.RelocInfo, -) !u64 { - const zcu = pt.zcu; +) link.Error!link.File.SymbolId { + const zcu = macho_file.base.comp.zcu.?; const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); - log.debug("getNavVAddr {f}({d})", .{ nav.fqn.fmt(ip), nav_index }); - const sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol( - macho_file, - nav.name.toSlice(ip), - @"extern".lib_name.toSlice(ip), - ) else try self.getOrCreateMetadataForNav(macho_file, nav_index); - const sym = self.symbols.items[sym_index]; - const vaddr = sym.getAddress(.{}, macho_file); - switch (reloc_info.parent) { - .none => unreachable, - .atom_index => |atom_index| { - const parent_atom = self.symbols.items[@backingInt(atom_index)].getAtom(macho_file).?; - try parent_atom.addReloc(macho_file, .{ - .tag = .@"extern", - .offset = @intCast(reloc_info.offset), - .target = sym_index, - .addend = reloc_info.addend, - .type = .unsigned, - .meta = .{ - .pcrel = false, - .has_subtractor = false, - .length = 3, - .symbolnum = @intCast(sym.nlist_idx), - }, - }); - }, - .debug_output => |debug_output| try debug_output.dwarf.infoExternalReloc(.{ - .source_off = @intCast(reloc_info.offset), - .target_sym = @fromBackingInt(@intCast(sym_index)), - .target_off = reloc_info.addend, - }), + if (nav.getExtern(ip)) |@"extern"| { + const sym_index = try zo.getGlobalSymbol( + macho_file, + nav.name.toSlice(ip), + @"extern".lib_name.toSlice(ip), + ); + if (@"extern".linkage == .weak) { + zo.symbols.items[sym_index].flags.weak = true; + } + if (nav.resolved.?.@"threadlocal") { + zo.symbols.items[sym_index].flags.tlv = true; + } + return @fromBackingInt(sym_index); + } else { + const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index); + if (nav.resolved.?.@"threadlocal") { + zo.symbols.items[sym_index].flags.tlv = true; + } + return @fromBackingInt(sym_index); } - return vaddr; } -pub fn getUavVAddr( +pub fn relocSymAddr( self: *ZigObject, macho_file: *MachO, - uav: InternPool.Index, reloc_info: link.File.RelocInfo, -) !u64 { - const sym_index = self.uavs.get(uav).?.symbol_index; +) !void { + const sym_index = @backingInt(reloc_info.target); const sym = self.symbols.items[sym_index]; - const vaddr = sym.getAddress(.{}, macho_file); switch (reloc_info.parent) { .none => unreachable, .atom_index => |atom_index| { @@ -689,10 +672,9 @@ pub fn getUavVAddr( .target_off = reloc_info.addend, }), } - return vaddr; } -pub fn lowerUav( +pub fn uavSymbol( self: *ZigObject, macho_file: *MachO, pt: Zcu.PerThread, @@ -1281,7 +1263,7 @@ pub fn updateExports( break :blk self.navs.getPtr(nav).?; }, .uav => |uav| self.uavs.getPtr(uav) orelse blk: { - _ = try self.lowerUav(macho_file, pt, uav, .none); + _ = try self.uavSymbol(macho_file, pt, uav, .none); break :blk self.uavs.getPtr(uav).?; }, }; -- 2.54.0