| author | |
| committer | |
| log | 41e9b8b6c84a1787ffa647fc42980dcce4942b7d |
| tree | b50e763ea1b13fb6afd36e1e169991e2ad6592fb |
| parent | deeaa1bb0cb8a8c7ccebb23cc68be64e4b013ab2 |
22 files changed, 649 insertions(+), 521 deletions(-)
src/arch/aarch64/CodeGen.zig+3-2| ... | ... | @@ -4354,8 +4354,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4354 | 4354 | if (try self.air.value(callee, pt)) |func_value| { |
| 4355 | 4355 | if (func_value.getFunction(mod)) |func| { |
| 4356 | 4356 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 4357 | const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl); | |
| 4358 | const sym = elf_file.symbol(sym_index); | |
| 4357 | const zo = elf_file.zigObjectPtr().?; | |
| 4358 | const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl); | |
| 4359 | const sym = zo.symbol(sym_index); | |
| 4359 | 4360 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); |
| 4360 | 4361 | const got_addr = @as(u32, @intCast(sym.zigGotAddress(elf_file))); |
| 4361 | 4362 | try self.genSetReg(Type.usize, .x30, .{ .memory = got_addr }); |
src/arch/arm/CodeGen.zig+3-2| ... | ... | @@ -4336,8 +4336,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4336 | 4336 | if (try self.air.value(callee, pt)) |func_value| { |
| 4337 | 4337 | if (func_value.getFunction(mod)) |func| { |
| 4338 | 4338 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 4339 | const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl); | |
| 4340 | const sym = elf_file.symbol(sym_index); | |
| 4339 | const zo = elf_file.zigObjectPtr().?; | |
| 4340 | const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl); | |
| 4341 | const sym = zo.symbol(sym_index); | |
| 4341 | 4342 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); |
| 4342 | 4343 | const got_addr: u32 = @intCast(sym.zigGotAddress(elf_file)); |
| 4343 | 4344 | try self.genSetReg(Type.usize, .lr, .{ .memory = got_addr }); |
src/arch/riscv64/CodeGen.zig+11-7| ... | ... | @@ -1409,12 +1409,13 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 1409 | 1409 | defer func.register_manager.unlockReg(data_lock); |
| 1410 | 1410 | |
| 1411 | 1411 | const elf_file = func.bin_file.cast(link.File.Elf).?; |
| 1412 | const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, .{ | |
| 1412 | const zo = elf_file.zigObjectPtr().?; | |
| 1413 | const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, .{ | |
| 1413 | 1414 | .kind = .const_data, |
| 1414 | 1415 | .ty = enum_ty, |
| 1415 | 1416 | }) catch |err| |
| 1416 | 1417 | return func.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 1417 | const sym = elf_file.symbol(sym_index); | |
| 1418 | const sym = zo.symbol(sym_index); | |
| 1418 | 1419 | |
| 1419 | 1420 | try func.genSetReg(Type.u64, data_reg, .{ .lea_symbol = .{ .sym = sym.esym_index } }); |
| 1420 | 1421 | |
| ... | ... | @@ -4946,8 +4947,9 @@ fn genCall( |
| 4946 | 4947 | }) { |
| 4947 | 4948 | .func => |func_val| { |
| 4948 | 4949 | if (func.bin_file.cast(link.File.Elf)) |elf_file| { |
| 4949 | const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func_val.owner_decl); | |
| 4950 | const sym = elf_file.symbol(sym_index); | |
| 4950 | const zo = elf_file.zigObjectPtr().?; | |
| 4951 | const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func_val.owner_decl); | |
| 4952 | const sym = zo.symbol(sym_index); | |
| 4951 | 4953 | |
| 4952 | 4954 | if (func.mod.pic) { |
| 4953 | 4955 | return func.fail("TODO: genCall pic", .{}); |
| ... | ... | @@ -7822,9 +7824,10 @@ fn airTagName(func: *Func, inst: Air.Inst.Index) !void { |
| 7822 | 7824 | |
| 7823 | 7825 | const lazy_sym = link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(zcu), zcu); |
| 7824 | 7826 | const elf_file = func.bin_file.cast(link.File.Elf).?; |
| 7825 | const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err| | |
| 7827 | const zo = elf_file.zigObjectPtr().?; | |
| 7828 | const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err| | |
| 7826 | 7829 | return func.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 7827 | const sym = elf_file.symbol(sym_index); | |
| 7830 | const sym = zo.symbol(sym_index); | |
| 7828 | 7831 | |
| 7829 | 7832 | if (func.mod.pic) { |
| 7830 | 7833 | return func.fail("TODO: airTagName pic", .{}); |
| ... | ... | @@ -8049,7 +8052,8 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue { |
| 8049 | 8052 | switch (lf.tag) { |
| 8050 | 8053 | .elf => { |
| 8051 | 8054 | const elf_file = lf.cast(link.File.Elf).?; |
| 8052 | const local = elf_file.symbol(local_sym_index); | |
| 8055 | const zo = elf_file.zigObjectPtr().?; | |
| 8056 | const local = zo.symbol(local_sym_index); | |
| 8053 | 8057 | return MCValue{ .undef = local.esym_index }; |
| 8054 | 8058 | }, |
| 8055 | 8059 | else => unreachable, |
src/arch/riscv64/Emit.zig+8-6| ... | ... | @@ -50,16 +50,16 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 50 | 50 | }; |
| 51 | 51 | |
| 52 | 52 | const elf_file = emit.bin_file.cast(link.File.Elf).?; |
| 53 | const zo = elf_file.zigObjectPtr().?; | |
| 53 | 54 | |
| 54 | const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?; | |
| 55 | const sym_index = elf_file.zigObjectPtr().?.symbol(symbol.sym_index); | |
| 56 | const sym = elf_file.symbol(sym_index); | |
| 55 | const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?; | |
| 56 | const sym = zo.symbol(symbol.sym_index); | |
| 57 | 57 | |
| 58 | 58 | var hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20); |
| 59 | 59 | var lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I); |
| 60 | 60 | |
| 61 | 61 | if (sym.flags.needs_zig_got and !is_obj_or_static_lib) { |
| 62 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); | |
| 62 | _ = try sym.getOrCreateZigGotEntry(symbol.sym_index, elf_file); | |
| 63 | 63 | |
| 64 | 64 | hi_r_type = Elf.R_ZIG_GOT_HI20; |
| 65 | 65 | lo_r_type = Elf.R_ZIG_GOT_LO12; |
| ... | ... | @@ -82,8 +82,9 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 82 | 82 | }, |
| 83 | 83 | .load_tlv_reloc => |symbol| { |
| 84 | 84 | const elf_file = emit.bin_file.cast(link.File.Elf).?; |
| 85 | const zo = elf_file.zigObjectPtr().?; | |
| 85 | 86 | |
| 86 | const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?; | |
| 87 | const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?; | |
| 87 | 88 | |
| 88 | 89 | const R_RISCV = std.elf.R_RISCV; |
| 89 | 90 | |
| ... | ... | @@ -107,7 +108,8 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 107 | 108 | }, |
| 108 | 109 | .call_extern_fn_reloc => |symbol| { |
| 109 | 110 | const elf_file = emit.bin_file.cast(link.File.Elf).?; |
| 110 | const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?; | |
| 111 | const zo = elf_file.zigObjectPtr().?; | |
| 112 | const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?; | |
| 111 | 113 | |
| 112 | 114 | const r_type: u32 = @intFromEnum(std.elf.R_RISCV.CALL_PLT); |
| 113 | 115 |
src/arch/sparc64/CodeGen.zig+3-2| ... | ... | @@ -1354,8 +1354,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 1354 | 1354 | switch (mod.intern_pool.indexToKey(func_value.ip_index)) { |
| 1355 | 1355 | .func => |func| { |
| 1356 | 1356 | const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: { |
| 1357 | const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl); | |
| 1358 | const sym = elf_file.symbol(sym_index); | |
| 1357 | const zo = elf_file.zigObjectPtr().?; | |
| 1358 | const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl); | |
| 1359 | const sym = zo.symbol(sym_index); | |
| 1359 | 1360 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); |
| 1360 | 1361 | break :blk @as(u32, @intCast(sym.zigGotAddress(elf_file))); |
| 1361 | 1362 | } else unreachable; |
src/arch/x86_64/CodeGen.zig+6-4| ... | ... | @@ -12327,8 +12327,9 @@ fn genCall(self: *Self, info: union(enum) { |
| 12327 | 12327 | }) { |
| 12328 | 12328 | .func => |func| { |
| 12329 | 12329 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 12330 | const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl); | |
| 12331 | const sym = elf_file.symbol(sym_index); | |
| 12330 | const zo = elf_file.zigObjectPtr().?; | |
| 12331 | const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl); | |
| 12332 | const sym = zo.symbol(sym_index); | |
| 12332 | 12333 | if (self.mod.pic) { |
| 12333 | 12334 | const callee_reg: Register = switch (resolved_cc) { |
| 12334 | 12335 | .SysV => callee: { |
| ... | ... | @@ -15320,9 +15321,10 @@ fn genLazySymbolRef( |
| 15320 | 15321 | ) InnerError!void { |
| 15321 | 15322 | const pt = self.pt; |
| 15322 | 15323 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 15323 | const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err| | |
| 15324 | const zo = elf_file.zigObjectPtr().?; | |
| 15325 | const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err| | |
| 15324 | 15326 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 15325 | const sym = elf_file.symbol(sym_index); | |
| 15327 | const sym = zo.symbol(sym_index); | |
| 15326 | 15328 | if (self.mod.pic) { |
| 15327 | 15329 | switch (tag) { |
| 15328 | 15330 | .lea, .call => try self.genSetReg(reg, Type.usize, .{ |
src/arch/x86_64/Emit.zig+10-7| ... | ... | @@ -42,7 +42,8 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 42 | 42 | }), |
| 43 | 43 | .linker_extern_fn => |symbol| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| { |
| 44 | 44 | // Add relocation to the decl. |
| 45 | const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?; | |
| 45 | const zo = elf_file.zigObjectPtr().?; | |
| 46 | const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?; | |
| 46 | 47 | const r_type = @intFromEnum(std.elf.R_X86_64.PLT32); |
| 47 | 48 | try atom_ptr.addReloc(elf_file, .{ |
| 48 | 49 | .r_offset = end_offset - 4, |
| ... | ... | @@ -88,7 +89,8 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 88 | 89 | }), |
| 89 | 90 | .linker_tlsld => |data| { |
| 90 | 91 | const elf_file = emit.lower.bin_file.cast(link.File.Elf).?; |
| 91 | const atom = elf_file.symbol(data.atom_index).atom(elf_file).?; | |
| 92 | const zo = elf_file.zigObjectPtr().?; | |
| 93 | const atom = zo.symbol(data.atom_index).atom(elf_file).?; | |
| 92 | 94 | const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD); |
| 93 | 95 | try atom.addReloc(elf_file, .{ |
| 94 | 96 | .r_offset = end_offset - 4, |
| ... | ... | @@ -98,7 +100,8 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 98 | 100 | }, |
| 99 | 101 | .linker_dtpoff => |data| { |
| 100 | 102 | const elf_file = emit.lower.bin_file.cast(link.File.Elf).?; |
| 101 | const atom = elf_file.symbol(data.atom_index).atom(elf_file).?; | |
| 103 | const zo = elf_file.zigObjectPtr().?; | |
| 104 | const atom = zo.symbol(data.atom_index).atom(elf_file).?; | |
| 102 | 105 | const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32); |
| 103 | 106 | try atom.addReloc(elf_file, .{ |
| 104 | 107 | .r_offset = end_offset - 4, |
| ... | ... | @@ -112,11 +115,11 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 112 | 115 | .Obj => true, |
| 113 | 116 | .Lib => emit.lower.link_mode == .static, |
| 114 | 117 | }; |
| 115 | const atom = elf_file.symbol(data.atom_index).atom(elf_file).?; | |
| 116 | const sym_index = elf_file.zigObjectPtr().?.symbol(data.sym_index); | |
| 117 | const sym = elf_file.symbol(sym_index); | |
| 118 | const zo = elf_file.zigObjectPtr().?; | |
| 119 | const atom = zo.symbol(data.atom_index).atom(elf_file).?; | |
| 120 | const sym = zo.symbol(data.sym_index); | |
| 118 | 121 | if (sym.flags.needs_zig_got and !is_obj_or_static_lib) { |
| 119 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); | |
| 122 | _ = try sym.getOrCreateZigGotEntry(data.sym_index, elf_file); | |
| 120 | 123 | } |
| 121 | 124 | if (emit.lower.pic) { |
| 122 | 125 | const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj_or_static_lib) |
src/arch/x86_64/Lower.zig+2-2| ... | ... | @@ -349,8 +349,8 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 349 | 349 | assert(mem_op.sib.scale_index.scale == 0); |
| 350 | 350 | |
| 351 | 351 | if (lower.bin_file.cast(link.File.Elf)) |elf_file| { |
| 352 | const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index); | |
| 353 | const elf_sym = elf_file.symbol(sym_index); | |
| 352 | const zo = elf_file.zigObjectPtr().?; | |
| 353 | const elf_sym = zo.symbol(sym.sym_index); | |
| 354 | 354 | |
| 355 | 355 | if (elf_sym.flags.is_tls) { |
| 356 | 356 | // TODO handle extern TLS vars, i.e., emit GD model |
src/codegen.zig+6-8| ... | ... | @@ -906,20 +906,20 @@ fn genDeclRef( |
| 906 | 906 | const is_extern = decl.isExtern(zcu); |
| 907 | 907 | |
| 908 | 908 | if (lf.cast(link.File.Elf)) |elf_file| { |
| 909 | const zo = elf_file.zigObjectPtr().?; | |
| 909 | 910 | if (is_extern) { |
| 910 | 911 | const name = decl.name.toSlice(ip); |
| 911 | 912 | // TODO audit this |
| 912 | 913 | const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null; |
| 913 | 914 | const sym_index = try elf_file.getGlobalSymbol(name, lib_name); |
| 914 | elf_file.symbol(elf_file.zigObjectPtr().?.symbol(sym_index)).flags.needs_got = true; | |
| 915 | zo.symbol(sym_index).flags.needs_got = true; | |
| 915 | 916 | return GenResult.mcv(.{ .load_symbol = sym_index }); |
| 916 | 917 | } |
| 917 | const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index); | |
| 918 | const sym = elf_file.symbol(sym_index); | |
| 918 | const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, decl_index); | |
| 919 | 919 | if (is_threadlocal) { |
| 920 | return GenResult.mcv(.{ .load_tlv = sym.esym_index }); | |
| 920 | return GenResult.mcv(.{ .load_tlv = sym_index }); | |
| 921 | 921 | } |
| 922 | return GenResult.mcv(.{ .load_symbol = sym.esym_index }); | |
| 922 | return GenResult.mcv(.{ .load_symbol = sym_index }); | |
| 923 | 923 | } else if (lf.cast(link.File.MachO)) |macho_file| { |
| 924 | 924 | const zo = macho_file.getZigObject().?; |
| 925 | 925 | if (is_extern) { |
| ... | ... | @@ -971,9 +971,7 @@ fn genUnnamedConst( |
| 971 | 971 | }; |
| 972 | 972 | switch (lf.tag) { |
| 973 | 973 | .elf => { |
| 974 | const elf_file = lf.cast(link.File.Elf).?; | |
| 975 | const local = elf_file.symbol(local_sym_index); | |
| 976 | return GenResult.mcv(.{ .load_symbol = local.esym_index }); | |
| 974 | return GenResult.mcv(.{ .load_symbol = local_sym_index }); | |
| 977 | 975 | }, |
| 978 | 976 | .macho => { |
| 979 | 977 | const macho_file = lf.cast(link.File.MachO).?; |
src/link/Elf.zig+50-81| ... | ... | @@ -2013,11 +2013,10 @@ fn claimUnresolved(self: *Elf) void { |
| 2013 | 2013 | fn scanRelocs(self: *Elf) !void { |
| 2014 | 2014 | const gpa = self.base.comp.gpa; |
| 2015 | 2015 | |
| 2016 | var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Ref)).init(gpa); | |
| 2016 | var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa); | |
| 2017 | 2017 | defer { |
| 2018 | var it = undefs.iterator(); | |
| 2019 | while (it.next()) |entry| { | |
| 2020 | entry.value_ptr.deinit(); | |
| 2018 | for (undefs.values()) |*refs| { | |
| 2019 | refs.deinit(); | |
| 2021 | 2020 | } |
| 2022 | 2021 | undefs.deinit(); |
| 2023 | 2022 | } |
| ... | ... | @@ -2028,7 +2027,18 @@ fn scanRelocs(self: *Elf) !void { |
| 2028 | 2027 | objects.appendSliceAssumeCapacity(self.objects.items); |
| 2029 | 2028 | |
| 2030 | 2029 | var has_reloc_errors = false; |
| 2031 | for (objects.items) |index| { | |
| 2030 | if (self.zigObjectPtr()) |zo| { | |
| 2031 | zo.asFile().scanRelocs(self, &undefs) catch |err| switch (err) { | |
| 2032 | error.RelaxFailure => unreachable, | |
| 2033 | error.UnsupportedCpuArch => { | |
| 2034 | try self.reportUnsupportedCpuArch(); | |
| 2035 | return error.FlushFailure; | |
| 2036 | }, | |
| 2037 | error.RelocFailure => has_reloc_errors = true, | |
| 2038 | else => |e| return e, | |
| 2039 | }; | |
| 2040 | } | |
| 2041 | for (self.objects.items) |index| { | |
| 2032 | 2042 | self.file(index).?.scanRelocs(self, &undefs) catch |err| switch (err) { |
| 2033 | 2043 | error.RelaxFailure => unreachable, |
| 2034 | 2044 | error.UnsupportedCpuArch => { |
| ... | ... | @@ -2044,47 +2054,12 @@ fn scanRelocs(self: *Elf) !void { |
| 2044 | 2054 | |
| 2045 | 2055 | if (has_reloc_errors) return error.FlushFailure; |
| 2046 | 2056 | |
| 2047 | for (self.symbols.items, 0..) |*sym, i| { | |
| 2048 | const index = @as(u32, @intCast(i)); | |
| 2049 | if (!sym.isLocal(self) and !sym.flags.has_dynamic) { | |
| 2050 | log.debug("'{s}' is non-local", .{sym.name(self)}); | |
| 2051 | try self.dynsym.addSymbol(index, self); | |
| 2052 | } | |
| 2053 | if (sym.flags.needs_got) { | |
| 2054 | log.debug("'{s}' needs GOT", .{sym.name(self)}); | |
| 2055 | _ = try self.got.addGotSymbol(index, self); | |
| 2056 | } | |
| 2057 | if (sym.flags.needs_plt) { | |
| 2058 | if (sym.flags.is_canonical) { | |
| 2059 | log.debug("'{s}' needs CPLT", .{sym.name(self)}); | |
| 2060 | sym.flags.@"export" = true; | |
| 2061 | try self.plt.addSymbol(index, self); | |
| 2062 | } else if (sym.flags.needs_got) { | |
| 2063 | log.debug("'{s}' needs PLTGOT", .{sym.name(self)}); | |
| 2064 | try self.plt_got.addSymbol(index, self); | |
| 2065 | } else { | |
| 2066 | log.debug("'{s}' needs PLT", .{sym.name(self)}); | |
| 2067 | try self.plt.addSymbol(index, self); | |
| 2068 | } | |
| 2069 | } | |
| 2070 | if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) { | |
| 2071 | log.debug("'{s}' needs COPYREL", .{sym.name(self)}); | |
| 2072 | try self.copy_rel.addSymbol(index, self); | |
| 2073 | } | |
| 2074 | if (sym.flags.needs_tlsgd) { | |
| 2075 | log.debug("'{s}' needs TLSGD", .{sym.name(self)}); | |
| 2076 | try self.got.addTlsGdSymbol(index, self); | |
| 2077 | } | |
| 2078 | if (sym.flags.needs_gottp) { | |
| 2079 | log.debug("'{s}' needs GOTTP", .{sym.name(self)}); | |
| 2080 | try self.got.addGotTpSymbol(index, self); | |
| 2081 | } | |
| 2082 | if (sym.flags.needs_tlsdesc) { | |
| 2083 | log.debug("'{s}' needs TLSDESC", .{sym.name(self)}); | |
| 2084 | try self.got.addTlsDescSymbol(index, self); | |
| 2085 | } | |
| 2057 | if (self.zigObjectPtr()) |zo| { | |
| 2058 | try zo.asFile().createSymbolIndirection(self); | |
| 2059 | } | |
| 2060 | for (self.objects.items) |index| { | |
| 2061 | try self.file(index).?.createSymbolIndirection(self); | |
| 2086 | 2062 | } |
| 2087 | ||
| 2088 | 2063 | if (self.got.flags.needs_tlsld) { |
| 2089 | 2064 | log.debug("program needs TLSLD", .{}); |
| 2090 | 2065 | try self.got.addTlsLdSymbol(self); |
| ... | ... | @@ -2861,8 +2836,8 @@ pub fn writeElfHeader(self: *Elf) !void { |
| 2861 | 2836 | index += 4; |
| 2862 | 2837 | |
| 2863 | 2838 | const e_entry: u64 = if (self.linkerDefinedPtr()) |obj| blk: { |
| 2864 | const entry_index = obj.entry_index orelse break :blk 0; | |
| 2865 | break :blk @intCast(self.symbol(entry_index).address(.{}, self)); | |
| 2839 | const entry_sym = obj.entrySymbol(self) orelse break :blk 0; | |
| 2840 | break :blk @intCast(entry_sym.address(.{}, self)); | |
| 2866 | 2841 | } else 0; |
| 2867 | 2842 | const phdr_table_offset = if (self.phdr_table_index) |phndx| self.phdrs.items[phndx].p_offset else 0; |
| 2868 | 2843 | switch (self.ptr_width) { |
| ... | ... | @@ -2993,7 +2968,7 @@ pub fn deleteExport( |
| 2993 | 2968 | fn checkDuplicates(self: *Elf) !void { |
| 2994 | 2969 | const gpa = self.base.comp.gpa; |
| 2995 | 2970 | |
| 2996 | var dupes = std.AutoArrayHashMap(Symbol.Index, std.ArrayListUnmanaged(File.Index)).init(gpa); | |
| 2971 | var dupes = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayListUnmanaged(File.Index)).init(gpa); | |
| 2997 | 2972 | defer { |
| 2998 | 2973 | for (dupes.values()) |*list| { |
| 2999 | 2974 | list.deinit(gpa); |
| ... | ... | @@ -3301,7 +3276,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3301 | 3276 | }); |
| 3302 | 3277 | |
| 3303 | 3278 | const needs_versions = for (self.dynsym.entries.items) |entry| { |
| 3304 | const sym = self.symbol(entry.symbol_index); | |
| 3279 | const sym = self.symbol(entry.ref).?; | |
| 3305 | 3280 | if (sym.flags.import and sym.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) break true; |
| 3306 | 3281 | } else false; |
| 3307 | 3282 | if (needs_versions) { |
| ... | ... | @@ -3515,7 +3490,7 @@ fn setVersionSymtab(self: *Elf) !void { |
| 3515 | 3490 | try self.versym.resize(gpa, self.dynsym.count()); |
| 3516 | 3491 | self.versym.items[0] = elf.VER_NDX_LOCAL; |
| 3517 | 3492 | for (self.dynsym.entries.items, 1..) |entry, i| { |
| 3518 | const sym = self.symbol(entry.symbol_index); | |
| 3493 | const sym = self.symbol(entry.ref).?; | |
| 3519 | 3494 | self.versym.items[i] = sym.version_index; |
| 3520 | 3495 | } |
| 3521 | 3496 | |
| ... | ... | @@ -4307,11 +4282,10 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 4307 | 4282 | fn writeAtoms(self: *Elf) !void { |
| 4308 | 4283 | const gpa = self.base.comp.gpa; |
| 4309 | 4284 | |
| 4310 | var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Ref)).init(gpa); | |
| 4285 | var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa); | |
| 4311 | 4286 | defer { |
| 4312 | var it = undefs.iterator(); | |
| 4313 | while (it.next()) |entry| { | |
| 4314 | entry.value_ptr.deinit(); | |
| 4287 | for (undefs.values()) |*refs| { | |
| 4288 | refs.deinit(); | |
| 4315 | 4289 | } |
| 4316 | 4290 | undefs.deinit(); |
| 4317 | 4291 | } |
| ... | ... | @@ -5261,7 +5235,7 @@ pub fn calcNumIRelativeRelocs(self: *Elf) usize { |
| 5261 | 5235 | |
| 5262 | 5236 | for (self.got.entries.items) |entry| { |
| 5263 | 5237 | if (entry.tag != .got) continue; |
| 5264 | const sym = self.symbol(entry.symbol_index); | |
| 5238 | const sym = self.symbol(entry.ref).?; | |
| 5265 | 5239 | if (sym.isIFunc(self)) count += 1; |
| 5266 | 5240 | } |
| 5267 | 5241 | |
| ... | ... | @@ -5443,36 +5417,34 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { |
| 5443 | 5417 | |
| 5444 | 5418 | try self.base.comp.link_errors.ensureUnusedCapacity(gpa, undefs.count()); |
| 5445 | 5419 | |
| 5446 | var it = undefs.iterator(); | |
| 5447 | while (it.next()) |entry| { | |
| 5448 | const undef_index = entry.key_ptr.*; | |
| 5449 | const atoms = entry.value_ptr.*.items; | |
| 5450 | const natoms = @min(atoms.len, max_notes); | |
| 5451 | const nnotes = natoms + @intFromBool(atoms.len > max_notes); | |
| 5420 | for (undefs.keys(), undefs.values()) |key, refs| { | |
| 5421 | const undef_sym = self.resolver.keys.items[key - 1]; | |
| 5422 | const nrefs = @min(refs.items.len, max_notes); | |
| 5423 | const nnotes = nrefs + @intFromBool(refs.items.len > max_notes); | |
| 5452 | 5424 | |
| 5453 | 5425 | var err = try self.base.addErrorWithNotesAssumeCapacity(nnotes); |
| 5454 | try err.addMsg("undefined symbol: {s}", .{self.symbol(undef_index).name(self)}); | |
| 5426 | try err.addMsg("undefined symbol: {s}", .{undef_sym.name(self)}); | |
| 5455 | 5427 | |
| 5456 | for (atoms[0..natoms]) |ref| { | |
| 5428 | for (refs.items[0..nrefs]) |ref| { | |
| 5457 | 5429 | const atom_ptr = self.atom(ref).?; |
| 5458 | const file_ptr = self.file(ref.file).?; | |
| 5430 | const file_ptr = atom_ptr.file(self).?; | |
| 5459 | 5431 | try err.addNote("referenced by {s}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) }); |
| 5460 | 5432 | } |
| 5461 | 5433 | |
| 5462 | if (atoms.len > max_notes) { | |
| 5463 | const remaining = atoms.len - max_notes; | |
| 5434 | if (refs.items.len > max_notes) { | |
| 5435 | const remaining = refs.items.len - max_notes; | |
| 5464 | 5436 | try err.addNote("referenced {d} more times", .{remaining}); |
| 5465 | 5437 | } |
| 5466 | 5438 | } |
| 5467 | 5439 | } |
| 5468 | 5440 | |
| 5469 | 5441 | fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemory }!void { |
| 5442 | if (dupes.keys().len == 0) return; // Nothing to do | |
| 5443 | ||
| 5470 | 5444 | const max_notes = 3; |
| 5471 | var has_dupes = false; | |
| 5472 | var it = dupes.iterator(); | |
| 5473 | while (it.next()) |entry| { | |
| 5474 | const sym = self.symbol(entry.key_ptr.*); | |
| 5475 | const notes = entry.value_ptr.*; | |
| 5445 | ||
| 5446 | for (dupes.keys(), dupes.values()) |key, notes| { | |
| 5447 | const sym = self.resolver.keys.items[key - 1]; | |
| 5476 | 5448 | const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes); |
| 5477 | 5449 | |
| 5478 | 5450 | var err = try self.base.addErrorWithNotes(nnotes + 1); |
| ... | ... | @@ -5489,11 +5461,9 @@ fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemor |
| 5489 | 5461 | const remaining = notes.items.len - max_notes; |
| 5490 | 5462 | try err.addNote("defined {d} more times", .{remaining}); |
| 5491 | 5463 | } |
| 5492 | ||
| 5493 | has_dupes = true; | |
| 5494 | 5464 | } |
| 5495 | 5465 | |
| 5496 | if (has_dupes) return error.HasDuplicates; | |
| 5466 | return error.HasDuplicates; | |
| 5497 | 5467 | } |
| 5498 | 5468 | |
| 5499 | 5469 | fn reportMissingLibraryError( |
| ... | ... | @@ -5918,7 +5888,7 @@ pub const SymbolResolver = struct { |
| 5918 | 5888 | elf_file: *Elf, |
| 5919 | 5889 | ) !Result { |
| 5920 | 5890 | const adapter = Adapter{ .keys = resolver.keys.items, .elf_file = elf_file }; |
| 5921 | const key = Key{ .index = ref.index, .file = ref.file }; | |
| 5891 | const key = Key{ .index = ref.index, .file_index = ref.file }; | |
| 5922 | 5892 | const gop = try resolver.table.getOrPutAdapted(allocator, key, adapter); |
| 5923 | 5893 | if (!gop.found_existing) { |
| 5924 | 5894 | try resolver.keys.append(allocator, key); |
| ... | ... | @@ -5944,16 +5914,15 @@ pub const SymbolResolver = struct { |
| 5944 | 5914 | |
| 5945 | 5915 | const Key = struct { |
| 5946 | 5916 | index: Symbol.Index, |
| 5947 | file: File.Index, | |
| 5917 | file_index: File.Index, | |
| 5948 | 5918 | |
| 5949 | 5919 | fn name(key: Key, elf_file: *Elf) [:0]const u8 { |
| 5950 | const ref = Ref{ .index = key.index, .file = key.file }; | |
| 5951 | return ref.symbol(elf_file).?.name(elf_file); | |
| 5920 | const ref = Ref{ .index = key.index, .file = key.file_index }; | |
| 5921 | return elf_file.symbol(ref).?.name(elf_file); | |
| 5952 | 5922 | } |
| 5953 | 5923 | |
| 5954 | pub fn file(key: Key, elf_file: *Elf) ?File { | |
| 5955 | const ref = Ref{ .index = key.index, .file = key.file }; | |
| 5956 | return ref.file(elf_file); | |
| 5924 | fn file(key: Key, elf_file: *Elf) ?File { | |
| 5925 | return elf_file.file(key.file_index); | |
| 5957 | 5926 | } |
| 5958 | 5927 | |
| 5959 | 5928 | fn eql(key: Key, other: Key, elf_file: *Elf) bool { |
src/link/Elf/Atom.zig+48-61| ... | ... | @@ -326,12 +326,8 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El |
| 326 | 326 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 327 | 327 | const file_ptr = self.file(elf_file).?; |
| 328 | 328 | for (self.relocs(elf_file)) |rel| { |
| 329 | const target_index = switch (file_ptr) { | |
| 330 | .zig_object => |x| x.symbol(rel.r_sym()), | |
| 331 | .object => |x| x.symbols.items[rel.r_sym()], | |
| 332 | else => unreachable, | |
| 333 | }; | |
| 334 | const target = elf_file.symbol(target_index); | |
| 329 | const target_ref = file_ptr.resolveSymbol(rel.r_sym(), elf_file); | |
| 330 | const target = elf_file.symbol(target_ref).?; | |
| 335 | 331 | const r_type = rel.r_type(); |
| 336 | 332 | const r_offset: u64 = @intCast(self.value + @as(i64, @intCast(rel.r_offset))); |
| 337 | 333 | var r_addend = rel.r_addend; |
| ... | ... | @@ -422,12 +418,21 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype |
| 422 | 418 | const r_kind = relocation.decode(rel.r_type(), cpu_arch); |
| 423 | 419 | if (r_kind == .none) continue; |
| 424 | 420 | |
| 425 | const symbol_index = switch (file_ptr) { | |
| 426 | .zig_object => |x| x.symbol(rel.r_sym()), | |
| 427 | .object => |x| x.symbols.items[rel.r_sym()], | |
| 428 | else => unreachable, | |
| 421 | const symbol_ref = file_ptr.resolveSymbol(rel.r_sym(), elf_file); | |
| 422 | const symbol = elf_file.symbol(symbol_ref) orelse { | |
| 423 | const sym_name = switch (file_ptr) { | |
| 424 | .zig_object => |x| x.symbol(rel.r_sym()).name(elf_file), | |
| 425 | inline else => |x| x.symbols.items[rel.r_sym()].name(elf_file), | |
| 426 | }; | |
| 427 | // Violation of One Definition Rule for COMDATs. | |
| 428 | // TODO convert into an error | |
| 429 | log.debug("{}: {s}: {s} refers to a discarded COMDAT section", .{ | |
| 430 | file_ptr.fmtPath(), | |
| 431 | self.name(elf_file), | |
| 432 | sym_name, | |
| 433 | }); | |
| 434 | continue; | |
| 429 | 435 | }; |
| 430 | const symbol = elf_file.symbol(symbol_index); | |
| 431 | 436 | |
| 432 | 437 | const is_synthetic_symbol = switch (file_ptr) { |
| 433 | 438 | .zig_object => false, // TODO: implement this once we support merge sections in ZigObject |
| ... | ... | @@ -435,19 +440,8 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype |
| 435 | 440 | else => unreachable, |
| 436 | 441 | }; |
| 437 | 442 | |
| 438 | // Check for violation of One Definition Rule for COMDATs. | |
| 439 | if (symbol.file(elf_file) == null) { | |
| 440 | // TODO convert into an error | |
| 441 | log.debug("{}: {s}: {s} refers to a discarded COMDAT section", .{ | |
| 442 | file_ptr.fmtPath(), | |
| 443 | self.name(elf_file), | |
| 444 | symbol.name(elf_file), | |
| 445 | }); | |
| 446 | continue; | |
| 447 | } | |
| 448 | ||
| 449 | 443 | // Report an undefined symbol. |
| 450 | if (!is_synthetic_symbol and (try self.reportUndefined(elf_file, symbol, symbol_index, rel, undefs))) | |
| 444 | if (!is_synthetic_symbol and (try self.reportUndefined(elf_file, symbol, rel, undefs))) | |
| 451 | 445 | continue; |
| 452 | 446 | |
| 453 | 447 | if (symbol.isIFunc(elf_file)) { |
| ... | ... | @@ -694,16 +688,15 @@ fn reportUndefined( |
| 694 | 688 | self: Atom, |
| 695 | 689 | elf_file: *Elf, |
| 696 | 690 | sym: *const Symbol, |
| 697 | sym_index: Symbol.Index, | |
| 698 | 691 | rel: elf.Elf64_Rela, |
| 699 | 692 | undefs: anytype, |
| 700 | 693 | ) !bool { |
| 701 | 694 | const comp = elf_file.base.comp; |
| 702 | 695 | const gpa = comp.gpa; |
| 703 | const rel_esym = switch (self.file(elf_file).?) { | |
| 704 | .zig_object => |x| x.elfSym(rel.r_sym()).*, | |
| 705 | .object => |x| x.symtab.items[rel.r_sym()], | |
| 706 | else => unreachable, | |
| 696 | const file_ptr = self.file(elf_file).?; | |
| 697 | const rel_esym = switch (file_ptr) { | |
| 698 | .zig_object => |x| x.symbol(rel.r_sym()).elfSym(elf_file), | |
| 699 | inline else => |x| x.symtab.items[rel.r_sym()], | |
| 707 | 700 | }; |
| 708 | 701 | const esym = sym.elfSym(elf_file); |
| 709 | 702 | if (rel_esym.st_shndx == elf.SHN_UNDEF and |
| ... | ... | @@ -712,7 +705,12 @@ fn reportUndefined( |
| 712 | 705 | !sym.flags.import and |
| 713 | 706 | esym.st_shndx == elf.SHN_UNDEF) |
| 714 | 707 | { |
| 715 | const gop = try undefs.getOrPut(sym_index); | |
| 708 | const idx = switch (file_ptr) { | |
| 709 | .zig_object => |x| x.symbols_resolver.items[rel.r_sym() & ZigObject.symbol_mask], | |
| 710 | .object => |x| x.symbols_resolver.items[rel.r_sym() - x.first_global.?], | |
| 711 | inline else => |x| x.symbols_resolver.items[rel.r_sym()], | |
| 712 | }; | |
| 713 | const gop = try undefs.getOrPut(idx); | |
| 716 | 714 | if (!gop.found_existing) { |
| 717 | 715 | gop.value_ptr.* = std.ArrayList(Elf.Ref).init(gpa); |
| 718 | 716 | } |
| ... | ... | @@ -737,11 +735,8 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi |
| 737 | 735 | const r_kind = relocation.decode(rel.r_type(), cpu_arch); |
| 738 | 736 | if (r_kind == .none) continue; |
| 739 | 737 | |
| 740 | const target = switch (file_ptr) { | |
| 741 | .zig_object => |x| elf_file.symbol(x.symbol(rel.r_sym())), | |
| 742 | .object => |x| elf_file.symbol(x.symbols.items[rel.r_sym()]), | |
| 743 | else => unreachable, | |
| 744 | }; | |
| 738 | const target_ref = file_ptr.resolveSymbol(rel.r_sym(), elf_file); | |
| 739 | const target = elf_file.symbol(target_ref).?; | |
| 745 | 740 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; |
| 746 | 741 | |
| 747 | 742 | // We will use equation format to resolve relocations: |
| ... | ... | @@ -923,31 +918,29 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any |
| 923 | 918 | |
| 924 | 919 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; |
| 925 | 920 | |
| 926 | const target_index = switch (file_ptr) { | |
| 927 | .zig_object => |x| x.symbol(rel.r_sym()), | |
| 928 | .object => |x| x.symbols.items[rel.r_sym()], | |
| 929 | else => unreachable, | |
| 930 | }; | |
| 931 | const target = elf_file.symbol(target_index); | |
| 932 | const is_synthetic_symbol = switch (file_ptr) { | |
| 933 | .zig_object => false, // TODO: implement this once we support merge sections in ZigObject | |
| 934 | .object => |x| rel.r_sym() >= x.symtab.items.len, | |
| 935 | else => unreachable, | |
| 936 | }; | |
| 937 | ||
| 938 | // Check for violation of One Definition Rule for COMDATs. | |
| 939 | if (target.file(elf_file) == null) { | |
| 921 | const target_ref = file_ptr.resolveSymbol(rel.r_sym(), elf_file); | |
| 922 | const target = elf_file.symbol(target_ref) orelse { | |
| 923 | const sym_name = switch (file_ptr) { | |
| 924 | .zig_object => |x| x.symbol(rel.r_sym()).name(elf_file), | |
| 925 | inline else => |x| x.symbols.items[rel.r_sym()].name(elf_file), | |
| 926 | }; | |
| 927 | // Violation of One Definition Rule for COMDATs. | |
| 940 | 928 | // TODO convert into an error |
| 941 | 929 | log.debug("{}: {s}: {s} refers to a discarded COMDAT section", .{ |
| 942 | 930 | file_ptr.fmtPath(), |
| 943 | 931 | self.name(elf_file), |
| 944 | target.name(elf_file), | |
| 932 | sym_name, | |
| 945 | 933 | }); |
| 946 | 934 | continue; |
| 947 | } | |
| 935 | }; | |
| 936 | const is_synthetic_symbol = switch (file_ptr) { | |
| 937 | .zig_object => false, // TODO: implement this once we support merge sections in ZigObject | |
| 938 | .object => |x| rel.r_sym() >= x.symtab.items.len, | |
| 939 | else => unreachable, | |
| 940 | }; | |
| 948 | 941 | |
| 949 | 942 | // Report an undefined symbol. |
| 950 | if (!is_synthetic_symbol and (try self.reportUndefined(elf_file, target, target_index, rel, undefs))) | |
| 943 | if (!is_synthetic_symbol and (try self.reportUndefined(elf_file, target, rel, undefs))) | |
| 951 | 944 | continue; |
| 952 | 945 | |
| 953 | 946 | // We will use equation format to resolve relocations: |
| ... | ... | @@ -1766,11 +1759,7 @@ const aarch64 = struct { |
| 1766 | 1759 | => { |
| 1767 | 1760 | const disp: i28 = math.cast(i28, S + A - P) orelse blk: { |
| 1768 | 1761 | const th = atom.thunk(elf_file); |
| 1769 | const target_index = switch (file_ptr) { | |
| 1770 | .zig_object => |x| x.symbol(rel.r_sym()), | |
| 1771 | .object => |x| x.symbols.items[rel.r_sym()], | |
| 1772 | else => unreachable, | |
| 1773 | }; | |
| 1762 | const target_index = file_ptr.resolveSymbol(rel.r_sym(), elf_file); | |
| 1774 | 1763 | const S_ = th.targetAddress(target_index, elf_file); |
| 1775 | 1764 | break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow; |
| 1776 | 1765 | }; |
| ... | ... | @@ -2106,11 +2095,8 @@ const riscv = struct { |
| 2106 | 2095 | return error.RelocFailure; |
| 2107 | 2096 | }; |
| 2108 | 2097 | it.pos = pos; |
| 2109 | const target_ = switch (file_ptr) { | |
| 2110 | .zig_object => |x| elf_file.symbol(x.symbol(pair.r_sym())), | |
| 2111 | .object => |x| elf_file.symbol(x.symbols.items[pair.r_sym()]), | |
| 2112 | else => unreachable, | |
| 2113 | }; | |
| 2098 | const target_ref_ = file_ptr.resolveSymbol(pair.r_sym(), elf_file); | |
| 2099 | const target_ = elf_file.symbol(target_ref_).?; | |
| 2114 | 2100 | const S_ = target_.address(.{}, elf_file); |
| 2115 | 2101 | const A_ = pair.r_addend; |
| 2116 | 2102 | const P_ = atom_addr + @as(i64, @intCast(pair.r_offset)); |
| ... | ... | @@ -2313,4 +2299,5 @@ const File = @import("file.zig").File; |
| 2313 | 2299 | const Object = @import("Object.zig"); |
| 2314 | 2300 | const Symbol = @import("Symbol.zig"); |
| 2315 | 2301 | const Thunk = @import("thunks.zig").Thunk; |
| 2302 | const ZigObject = @import("ZigObject.zig"); | |
| 2316 | 2303 | const dev = @import("../../dev.zig"); |
src/link/Elf/LinkerDefined.zig+46-28| ... | ... | @@ -44,7 +44,7 @@ pub fn init(self: *LinkerDefined, allocator: Allocator) !void { |
| 44 | 44 | |
| 45 | 45 | pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void { |
| 46 | 46 | const newSymbolAssumeCapacity = struct { |
| 47 | fn newSymbolAssumeCapacity(ld: *LinkerDefined, name_off: u32) Symbol.Index { | |
| 47 | fn newSymbolAssumeCapacity(ld: *LinkerDefined, name_off: u32, ef: *Elf) Symbol.Index { | |
| 48 | 48 | const esym_index: u32 = @intCast(ld.symtab.items.len); |
| 49 | 49 | const esym = ld.symtab.addOneAssumeCapacity(); |
| 50 | 50 | esym.* = .{ |
| ... | ... | @@ -61,7 +61,8 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void { |
| 61 | 61 | symbol.extra_index = ld.addSymbolExtraAssumeCapacity(.{}); |
| 62 | 62 | symbol.ref = .{ .index = 0, .file = 0 }; |
| 63 | 63 | symbol.esym_index = esym_index; |
| 64 | symbol.version_index = elf_file.default_sym_version; | |
| 64 | symbol.version_index = ef.default_sym_version; | |
| 65 | return index; | |
| 65 | 66 | } |
| 66 | 67 | }.newSymbolAssumeCapacity; |
| 67 | 68 | |
| ... | ... | @@ -111,31 +112,31 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void { |
| 111 | 112 | @memset(self.symbols_resolver.items, 0); |
| 112 | 113 | |
| 113 | 114 | if (elf_file.entry_name) |name| { |
| 114 | self.entry_index = newSymbolAssumeCapacity(self, try self.addString(gpa, name)); | |
| 115 | self.entry_index = newSymbolAssumeCapacity(self, try self.addString(gpa, name), elf_file); | |
| 115 | 116 | } |
| 116 | 117 | |
| 117 | self.dynamic_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_DYNAMIC")); | |
| 118 | self.ehdr_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__ehdr_start")); | |
| 119 | self.init_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_start")); | |
| 120 | self.init_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_end")); | |
| 121 | self.fini_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_start")); | |
| 122 | self.fini_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_end")); | |
| 123 | self.preinit_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_start")); | |
| 124 | self.preinit_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_end")); | |
| 125 | self.got_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_GLOBAL_OFFSET_TABLE_")); | |
| 126 | self.plt_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_PROCEDURE_LINKAGE_TABLE_")); | |
| 127 | self.end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_end")); | |
| 118 | self.dynamic_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_DYNAMIC"), elf_file); | |
| 119 | self.ehdr_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__ehdr_start"), elf_file); | |
| 120 | self.init_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_start"), elf_file); | |
| 121 | self.init_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_end"), elf_file); | |
| 122 | self.fini_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_start"), elf_file); | |
| 123 | self.fini_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_end"), elf_file); | |
| 124 | self.preinit_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_start"), elf_file); | |
| 125 | self.preinit_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_end"), elf_file); | |
| 126 | self.got_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_GLOBAL_OFFSET_TABLE_"), elf_file); | |
| 127 | self.plt_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_PROCEDURE_LINKAGE_TABLE_"), elf_file); | |
| 128 | self.end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_end"), elf_file); | |
| 128 | 129 | |
| 129 | 130 | if (elf_file.base.comp.link_eh_frame_hdr) { |
| 130 | self.gnu_eh_frame_hdr_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__GNU_EH_FRAME_HDR")); | |
| 131 | self.gnu_eh_frame_hdr_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__GNU_EH_FRAME_HDR"), elf_file); | |
| 131 | 132 | } |
| 132 | 133 | |
| 133 | self.dso_handle_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__dso_handle")); | |
| 134 | self.rela_iplt_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_start")); | |
| 135 | self.rela_iplt_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_end")); | |
| 134 | self.dso_handle_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__dso_handle"), elf_file); | |
| 135 | self.rela_iplt_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_start"), elf_file); | |
| 136 | self.rela_iplt_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_end"), elf_file); | |
| 136 | 137 | |
| 137 | 138 | if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) { |
| 138 | self.global_pointer_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__global_pointer$")); | |
| 139 | self.global_pointer_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__global_pointer$"), elf_file); | |
| 139 | 140 | } |
| 140 | 141 | |
| 141 | 142 | for (elf_file.objects.items) |index| { |
| ... | ... | @@ -145,8 +146,8 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void { |
| 145 | 146 | defer gpa.free(start_name); |
| 146 | 147 | const stop_name = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name}); |
| 147 | 148 | defer gpa.free(stop_name); |
| 148 | const start = newSymbolAssumeCapacity(self, try self.addString(gpa, start_name)); | |
| 149 | const stop = newSymbolAssumeCapacity(self, try self.addString(gpa, stop_name)); | |
| 149 | const start = newSymbolAssumeCapacity(self, try self.addString(gpa, start_name), elf_file); | |
| 150 | const stop = newSymbolAssumeCapacity(self, try self.addString(gpa, stop_name), elf_file); | |
| 150 | 151 | self.start_stop_indexes.appendSliceAssumeCapacity(&.{ start, stop }); |
| 151 | 152 | } |
| 152 | 153 | } |
| ... | ... | @@ -268,7 +269,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { |
| 268 | 269 | for (elf_file.shdrs.items, 0..) |shdr, shndx| { |
| 269 | 270 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) { |
| 270 | 271 | value = shdr.sh_addr + shdr.sh_size; |
| 271 | osec = shndx; | |
| 272 | osec = @intCast(shndx); | |
| 272 | 273 | } |
| 273 | 274 | } |
| 274 | 275 | allocSymbol(self, self.end_index.?, value, osec, elf_file); |
| ... | ... | @@ -287,10 +288,10 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { |
| 287 | 288 | { |
| 288 | 289 | var index: usize = 0; |
| 289 | 290 | while (index < self.start_stop_indexes.items.len) : (index += 2) { |
| 290 | const start_ref = self.resolveSymbol(self.start_stop_indexes.items[index]); | |
| 291 | const start_ref = self.resolveSymbol(self.start_stop_indexes.items[index], elf_file); | |
| 291 | 292 | const start = elf_file.symbol(start_ref).?; |
| 292 | 293 | const name = start.name(elf_file); |
| 293 | const stop_ref = self.resolveSymbol(self.start_stop_indexes.items[index + 1]); | |
| 294 | const stop_ref = self.resolveSymbol(self.start_stop_indexes.items[index + 1], elf_file); | |
| 294 | 295 | const stop = elf_file.symbol(stop_ref).?; |
| 295 | 296 | const shndx = elf_file.sectionByName(name["__start_".len..]).?; |
| 296 | 297 | const shdr = &elf_file.shdrs.items[shndx]; |
| ... | ... | @@ -334,6 +335,18 @@ pub fn writeSymtab(self: *LinkerDefined, elf_file: *Elf) void { |
| 334 | 335 | } |
| 335 | 336 | } |
| 336 | 337 | |
| 338 | pub fn dynamicSymbol(self: LinkerDefined, elf_file: *Elf) ?*Symbol { | |
| 339 | const index = self.dynamic_index orelse return null; | |
| 340 | const resolv = self.resolveSymbol(index, elf_file); | |
| 341 | return elf_file.symbol(resolv); | |
| 342 | } | |
| 343 | ||
| 344 | pub fn entrySymbol(self: LinkerDefined, elf_file: *Elf) ?*Symbol { | |
| 345 | const index = self.entry_index orelse return null; | |
| 346 | const resolv = self.resolveSymbol(index, elf_file); | |
| 347 | return elf_file.symbol(resolv); | |
| 348 | } | |
| 349 | ||
| 337 | 350 | pub fn asFile(self: *LinkerDefined) File { |
| 338 | 351 | return .{ .linker_defined = self }; |
| 339 | 352 | } |
| ... | ... | @@ -356,8 +369,12 @@ pub fn resolveSymbol(self: LinkerDefined, index: Symbol.Index, elf_file: *Elf) E |
| 356 | 369 | return elf_file.resolver.get(resolv).?; |
| 357 | 370 | } |
| 358 | 371 | |
| 359 | pub fn addSymbol(self: *LinkerDefined, allocator: Allocator) !Symbol.Index { | |
| 372 | fn addSymbol(self: *LinkerDefined, allocator: Allocator) !Symbol.Index { | |
| 360 | 373 | try self.symbols.ensureUnusedCapacity(allocator, 1); |
| 374 | return self.addSymbolAssumeCapacity(); | |
| 375 | } | |
| 376 | ||
| 377 | fn addSymbolAssumeCapacity(self: *LinkerDefined) Symbol.Index { | |
| 361 | 378 | const index: Symbol.Index = @intCast(self.symbols.items.len); |
| 362 | 379 | self.symbols.appendAssumeCapacity(.{ .file_index = self.index }); |
| 363 | 380 | return index; |
| ... | ... | @@ -425,10 +442,11 @@ fn formatSymtab( |
| 425 | 442 | ) !void { |
| 426 | 443 | _ = unused_fmt_string; |
| 427 | 444 | _ = options; |
| 445 | const self = ctx.self; | |
| 446 | const elf_file = ctx.elf_file; | |
| 428 | 447 | try writer.writeAll(" globals\n"); |
| 429 | for (ctx.self.globals()) |index| { | |
| 430 | const global = ctx.elf_file.symbol(index); | |
| 431 | try writer.print(" {}\n", .{global.fmt(ctx.elf_file)}); | |
| 448 | for (self.symbols.items) |sym| { | |
| 449 | try writer.print(" {}\n", .{sym.fmt(elf_file)}); | |
| 432 | 450 | } |
| 433 | 451 | } |
| 434 | 452 |
src/link/Elf/Object.zig+63-16| ... | ... | @@ -394,10 +394,9 @@ fn initSymbols(self: *Object, allocator: Allocator, elf_file: *Elf) !void { |
| 394 | 394 | sym_ptr.value = @intCast(sym.st_value); |
| 395 | 395 | sym_ptr.name_offset = sym.st_name; |
| 396 | 396 | sym_ptr.esym_index = @intCast(i); |
| 397 | sym_ptr.extra_index = self.addSymbolExtraAssumeCapacity(.{ | |
| 398 | .weak = sym.st_bind() == elf.STB_WEAK, | |
| 399 | }); | |
| 397 | sym_ptr.extra_index = self.addSymbolExtraAssumeCapacity(.{}); | |
| 400 | 398 | sym_ptr.version_index = if (i >= first_global) elf_file.default_sym_version else elf.VER_NDX_LOCAL; |
| 399 | sym_ptr.flags.weak = sym.st_bind() == elf.STB_WEAK; | |
| 401 | 400 | if (sym.st_shndx != elf.SHN_ABS and sym.st_shndx != elf.SHN_COMMON) { |
| 402 | 401 | sym_ptr.ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index }; |
| 403 | 402 | } |
| ... | ... | @@ -548,7 +547,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { |
| 548 | 547 | |
| 549 | 548 | for (self.cies.items) |cie| { |
| 550 | 549 | for (cie.relocs(elf_file)) |rel| { |
| 551 | const sym = elf_file.symbol(self.resolveSymbol(rel.r_sym())); | |
| 550 | const sym = elf_file.symbol(self.resolveSymbol(rel.r_sym(), elf_file)).?; | |
| 552 | 551 | if (sym.flags.import) { |
| 553 | 552 | if (sym.type(elf_file) != elf.STT_FUNC) |
| 554 | 553 | // TODO convert into an error |
| ... | ... | @@ -562,6 +561,51 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { |
| 562 | 561 | } |
| 563 | 562 | } |
| 564 | 563 | |
| 564 | pub fn createSymbolIndirection(self: *Object, elf_file: *Elf) !void { | |
| 565 | for (self.symbols.items, 0..) |*sym, i| { | |
| 566 | const ref = self.resolveSymbol(@intCast(i), elf_file); | |
| 567 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 568 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 569 | if (!sym.isLocal(elf_file) and !sym.flags.has_dynamic) { | |
| 570 | log.debug("'{s}' is non-local", .{sym.name(elf_file)}); | |
| 571 | try elf_file.dynsym.addSymbol(ref, elf_file); | |
| 572 | } | |
| 573 | if (sym.flags.needs_got) { | |
| 574 | log.debug("'{s}' needs GOT", .{sym.name(elf_file)}); | |
| 575 | _ = try elf_file.got.addGotSymbol(ref, elf_file); | |
| 576 | } | |
| 577 | if (sym.flags.needs_plt) { | |
| 578 | if (sym.flags.is_canonical) { | |
| 579 | log.debug("'{s}' needs CPLT", .{sym.name(elf_file)}); | |
| 580 | sym.flags.@"export" = true; | |
| 581 | try elf_file.plt.addSymbol(ref, elf_file); | |
| 582 | } else if (sym.flags.needs_got) { | |
| 583 | log.debug("'{s}' needs PLTGOT", .{sym.name(elf_file)}); | |
| 584 | try elf_file.plt_got.addSymbol(ref, elf_file); | |
| 585 | } else { | |
| 586 | log.debug("'{s}' needs PLT", .{sym.name(elf_file)}); | |
| 587 | try elf_file.plt.addSymbol(ref, elf_file); | |
| 588 | } | |
| 589 | } | |
| 590 | if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) { | |
| 591 | log.debug("'{s}' needs COPYREL", .{sym.name(elf_file)}); | |
| 592 | try elf_file.copy_rel.addSymbol(ref, elf_file); | |
| 593 | } | |
| 594 | if (sym.flags.needs_tlsgd) { | |
| 595 | log.debug("'{s}' needs TLSGD", .{sym.name(elf_file)}); | |
| 596 | try elf_file.got.addTlsGdSymbol(ref, elf_file); | |
| 597 | } | |
| 598 | if (sym.flags.needs_gottp) { | |
| 599 | log.debug("'{s}' needs GOTTP", .{sym.name(elf_file)}); | |
| 600 | try elf_file.got.addGotTpSymbol(ref, elf_file); | |
| 601 | } | |
| 602 | if (sym.flags.needs_tlsdesc) { | |
| 603 | log.debug("'{s}' needs TLSDESC", .{sym.name(elf_file)}); | |
| 604 | try elf_file.got.addTlsDescSymbol(ref, elf_file); | |
| 605 | } | |
| 606 | } | |
| 607 | } | |
| 608 | ||
| 565 | 609 | pub fn resolveSymbols(self: *Object, elf_file: *Elf) !void { |
| 566 | 610 | const gpa = elf_file.base.comp.gpa; |
| 567 | 611 | |
| ... | ... | @@ -643,7 +687,7 @@ pub fn claimUnresolvedObject(self: *Object, elf_file: *Elf) void { |
| 643 | 687 | sym.file_index = self.index; |
| 644 | 688 | |
| 645 | 689 | const idx = self.symbols_resolver.items[i]; |
| 646 | elf_file.resolver.items[idx - 1] = .{ .index = esym_index, .file = self.index }; | |
| 690 | elf_file.resolver.values.items[idx - 1] = .{ .index = esym_index, .file = self.index }; | |
| 647 | 691 | } |
| 648 | 692 | } |
| 649 | 693 | |
| ... | ... | @@ -1120,7 +1164,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) void { |
| 1120 | 1164 | } |
| 1121 | 1165 | |
| 1122 | 1166 | for (self.globals(), self.symbols_resolver.items) |*global, resolv| { |
| 1123 | const ref = elf_file.resolver.items[resolv]; | |
| 1167 | const ref = elf_file.resolver.values.items[resolv]; | |
| 1124 | 1168 | const ref_sym = elf_file.symbol(ref) orelse continue; |
| 1125 | 1169 | if (ref_sym.file(elf_file).?.index() != self.index) continue; |
| 1126 | 1170 | if (!isAlive(global, elf_file)) continue; |
| ... | ... | @@ -1136,7 +1180,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) void { |
| 1136 | 1180 | } |
| 1137 | 1181 | } |
| 1138 | 1182 | |
| 1139 | pub fn writeSymtab(self: Object, elf_file: *Elf) void { | |
| 1183 | pub fn writeSymtab(self: *Object, elf_file: *Elf) void { | |
| 1140 | 1184 | for (self.locals()) |local| { |
| 1141 | 1185 | const idx = local.outputSymtabIndex(elf_file) orelse continue; |
| 1142 | 1186 | const out_sym = &elf_file.symtab.items[idx]; |
| ... | ... | @@ -1147,7 +1191,7 @@ pub fn writeSymtab(self: Object, elf_file: *Elf) void { |
| 1147 | 1191 | } |
| 1148 | 1192 | |
| 1149 | 1193 | for (self.globals(), self.symbols_resolver.items) |global, resolv| { |
| 1150 | const ref = elf_file.resolver.items[resolv]; | |
| 1194 | const ref = elf_file.resolver.values.items[resolv]; | |
| 1151 | 1195 | const ref_sym = elf_file.symbol(ref) orelse continue; |
| 1152 | 1196 | if (ref_sym.file(elf_file).?.index() != self.index) continue; |
| 1153 | 1197 | const idx = global.outputSymtabIndex(elf_file) orelse continue; |
| ... | ... | @@ -1199,7 +1243,7 @@ fn locals(self: *Object) []Symbol { |
| 1199 | 1243 | return self.symbols.items[0..end]; |
| 1200 | 1244 | } |
| 1201 | 1245 | |
| 1202 | fn globals(self: *Object) []Symbol { | |
| 1246 | pub fn globals(self: *Object) []Symbol { | |
| 1203 | 1247 | if (self.symbols.items.len == 0) return &[0]Symbol{}; |
| 1204 | 1248 | assert(self.symbols.items.len >= self.symtab.items.len); |
| 1205 | 1249 | const start = self.first_global orelse self.symtab.items.len; |
| ... | ... | @@ -1214,8 +1258,12 @@ pub fn resolveSymbol(self: Object, index: Symbol.Index, elf_file: *Elf) Elf.Ref |
| 1214 | 1258 | return elf_file.resolver.get(resolv).?; |
| 1215 | 1259 | } |
| 1216 | 1260 | |
| 1217 | pub fn addSymbol(self: *Object, allocator: Allocator) !Symbol.Index { | |
| 1261 | fn addSymbol(self: *Object, allocator: Allocator) !Symbol.Index { | |
| 1218 | 1262 | try self.symbols.ensureUnusedCapacity(allocator, 1); |
| 1263 | return self.addSymbolAssumeCapacity(); | |
| 1264 | } | |
| 1265 | ||
| 1266 | fn addSymbolAssumeCapacity(self: *Object) Symbol.Index { | |
| 1219 | 1267 | const index: Symbol.Index = @intCast(self.symbols.items.len); |
| 1220 | 1268 | self.symbols.appendAssumeCapacity(.{ .file_index = self.index }); |
| 1221 | 1269 | return index; |
| ... | ... | @@ -1430,15 +1478,14 @@ fn formatSymtab( |
| 1430 | 1478 | _ = unused_fmt_string; |
| 1431 | 1479 | _ = options; |
| 1432 | 1480 | const object = ctx.object; |
| 1481 | const elf_file = ctx.elf_file; | |
| 1433 | 1482 | try writer.writeAll(" locals\n"); |
| 1434 | for (object.locals()) |index| { | |
| 1435 | const local = ctx.elf_file.symbol(index); | |
| 1436 | try writer.print(" {}\n", .{local.fmt(ctx.elf_file)}); | |
| 1483 | for (object.locals()) |sym| { | |
| 1484 | try writer.print(" {}\n", .{sym.fmt(elf_file)}); | |
| 1437 | 1485 | } |
| 1438 | 1486 | try writer.writeAll(" globals\n"); |
| 1439 | for (object.globals()) |index| { | |
| 1440 | const global = ctx.elf_file.symbol(index); | |
| 1441 | try writer.print(" {}\n", .{global.fmt(ctx.elf_file)}); | |
| 1487 | for (object.globals()) |sym| { | |
| 1488 | try writer.print(" {}\n", .{sym.fmt(elf_file)}); | |
| 1442 | 1489 | } |
| 1443 | 1490 | } |
| 1444 | 1491 |
src/link/Elf/SharedObject.zig+22-15| ... | ... | @@ -286,8 +286,8 @@ pub fn markImportExports(self: *SharedObject, elf_file: *Elf) void { |
| 286 | 286 | for (0..self.symbols.items.len) |i| { |
| 287 | 287 | const ref = self.resolveSymbol(@intCast(i), elf_file); |
| 288 | 288 | const ref_sym = elf_file.symbol(ref) orelse continue; |
| 289 | const ref_file = ref_sym.file(self).?; | |
| 290 | const vis = @as(elf.STV, @enumFromInt(ref_sym.elfSym(self).st_other)); | |
| 289 | const ref_file = ref_sym.file(elf_file).?; | |
| 290 | const vis = @as(elf.STV, @enumFromInt(ref_sym.elfSym(elf_file).st_other)); | |
| 291 | 291 | if (ref_file != .shared_object and vis != .HIDDEN) ref_sym.flags.@"export" = true; |
| 292 | 292 | } |
| 293 | 293 | } |
| ... | ... | @@ -349,9 +349,12 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void { |
| 349 | 349 | assert(self.aliases == null); |
| 350 | 350 | |
| 351 | 351 | const SortAlias = struct { |
| 352 | pub fn lessThan(ctx: *Elf, lhs: Symbol.Index, rhs: Symbol.Index) bool { | |
| 353 | const lhs_sym = ctx.symbol(lhs).elfSym(ctx); | |
| 354 | const rhs_sym = ctx.symbol(rhs).elfSym(ctx); | |
| 352 | so: *SharedObject, | |
| 353 | ef: *Elf, | |
| 354 | ||
| 355 | pub fn lessThan(ctx: @This(), lhs: Symbol.Index, rhs: Symbol.Index) bool { | |
| 356 | const lhs_sym = ctx.so.symbols.items[lhs].elfSym(ctx.ef); | |
| 357 | const rhs_sym = ctx.so.symbols.items[rhs].elfSym(ctx.ef); | |
| 355 | 358 | return lhs_sym.st_value < rhs_sym.st_value; |
| 356 | 359 | } |
| 357 | 360 | }; |
| ... | ... | @@ -362,14 +365,14 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void { |
| 362 | 365 | defer aliases.deinit(); |
| 363 | 366 | try aliases.ensureTotalCapacityPrecise(self.symbols.items.len); |
| 364 | 367 | |
| 365 | for (self.symbols_resolvers.items, 0..) |resolv, index| { | |
| 368 | for (self.symbols_resolver.items, 0..) |resolv, index| { | |
| 366 | 369 | const ref = elf_file.resolver.get(resolv).?; |
| 367 | 370 | const ref_sym = elf_file.symbol(ref) orelse continue; |
| 368 | 371 | if (ref_sym.file(elf_file).?.index() != self.index) continue; |
| 369 | aliases.appendAssumeCapacity(index); | |
| 372 | aliases.appendAssumeCapacity(@intCast(index)); | |
| 370 | 373 | } |
| 371 | 374 | |
| 372 | std.mem.sort(u32, aliases.items, elf_file, SortAlias.lessThan); | |
| 375 | std.mem.sort(u32, aliases.items, SortAlias{ .so = self, .ef = elf_file }, SortAlias.lessThan); | |
| 373 | 376 | |
| 374 | 377 | self.aliases = aliases.moveToUnmanaged(); |
| 375 | 378 | } |
| ... | ... | @@ -377,16 +380,16 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void { |
| 377 | 380 | pub fn symbolAliases(self: *SharedObject, index: u32, elf_file: *Elf) []const u32 { |
| 378 | 381 | assert(self.aliases != null); |
| 379 | 382 | |
| 380 | const symbol = self.symbol(index).elfSym(elf_file); | |
| 383 | const symbol = self.symbols.items[index].elfSym(elf_file); | |
| 381 | 384 | const aliases = self.aliases.?; |
| 382 | 385 | |
| 383 | 386 | const start = for (aliases.items, 0..) |alias, i| { |
| 384 | const alias_sym = self.symbol(alias).elfSym(elf_file); | |
| 387 | const alias_sym = self.symbols.items[alias].elfSym(elf_file); | |
| 385 | 388 | if (symbol.st_value == alias_sym.st_value) break i; |
| 386 | 389 | } else aliases.items.len; |
| 387 | 390 | |
| 388 | 391 | const end = for (aliases.items[start..], 0..) |alias, i| { |
| 389 | const alias_sym = self.symbol(alias).elfSym(elf_file); | |
| 392 | const alias_sym = self.symbols.items[alias].elfSym(elf_file); | |
| 390 | 393 | if (symbol.st_value < alias_sym.st_value) break i + start; |
| 391 | 394 | } else aliases.items.len; |
| 392 | 395 | |
| ... | ... | @@ -403,8 +406,12 @@ pub fn resolveSymbol(self: SharedObject, index: Symbol.Index, elf_file: *Elf) El |
| 403 | 406 | return elf_file.resolver.get(resolv).?; |
| 404 | 407 | } |
| 405 | 408 | |
| 406 | pub fn addSymbol(self: *SharedObject, allocator: Allocator) !Symbol.Index { | |
| 409 | fn addSymbol(self: *SharedObject, allocator: Allocator) !Symbol.Index { | |
| 407 | 410 | try self.symbols.ensureUnusedCapacity(allocator, 1); |
| 411 | return self.addSymbolAssumeCapacity(); | |
| 412 | } | |
| 413 | ||
| 414 | fn addSymbolAssumeCapacity(self: *SharedObject) Symbol.Index { | |
| 408 | 415 | const index: Symbol.Index = @intCast(self.symbols.items.len); |
| 409 | 416 | self.symbols.appendAssumeCapacity(.{ .file_index = self.index }); |
| 410 | 417 | return index; |
| ... | ... | @@ -486,10 +493,10 @@ fn formatSymtab( |
| 486 | 493 | _ = unused_fmt_string; |
| 487 | 494 | _ = options; |
| 488 | 495 | const shared = ctx.shared; |
| 496 | const elf_file = ctx.elf_file; | |
| 489 | 497 | try writer.writeAll(" globals\n"); |
| 490 | for (shared.symbols.items) |index| { | |
| 491 | const global = ctx.elf_file.symbol(index); | |
| 492 | try writer.print(" {}\n", .{global.fmt(ctx.elf_file)}); | |
| 498 | for (shared.symbols.items) |sym| { | |
| 499 | try writer.print(" {}\n", .{sym.fmt(elf_file)}); | |
| 493 | 500 | } |
| 494 | 501 | } |
| 495 | 502 |
src/link/Elf/Symbol.zig+8-3| ... | ... | @@ -86,6 +86,7 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File { |
| 86 | 86 | |
| 87 | 87 | pub fn elfSym(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym { |
| 88 | 88 | return switch (symbol.file(elf_file).?) { |
| 89 | .zig_object => |x| x.symtab.items(.elf_sym)[symbol.esym_index], | |
| 89 | 90 | inline else => |x| x.symtab.items[symbol.esym_index], |
| 90 | 91 | }; |
| 91 | 92 | } |
| ... | ... | @@ -261,7 +262,7 @@ const AddExtraOpts = struct { |
| 261 | 262 | zig_got: ?u32 = null, |
| 262 | 263 | }; |
| 263 | 264 | |
| 264 | pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void { | |
| 265 | pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) void { | |
| 265 | 266 | var extras = symbol.extra(elf_file); |
| 266 | 267 | inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| { |
| 267 | 268 | if (@field(opts, field.name)) |x| { |
| ... | ... | @@ -272,11 +273,15 @@ pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void { |
| 272 | 273 | } |
| 273 | 274 | |
| 274 | 275 | pub fn extra(symbol: Symbol, elf_file: *Elf) Extra { |
| 275 | return elf_file.symbolExtra(symbol.extra_index); | |
| 276 | return switch (symbol.file(elf_file).?) { | |
| 277 | inline else => |x| x.symbolExtra(symbol.extra_index), | |
| 278 | }; | |
| 276 | 279 | } |
| 277 | 280 | |
| 278 | 281 | pub fn setExtra(symbol: Symbol, extras: Extra, elf_file: *Elf) void { |
| 279 | elf_file.setSymbolExtra(symbol.extra_index, extras); | |
| 282 | return switch (symbol.file(elf_file).?) { | |
| 283 | inline else => |x| x.setSymbolExtra(symbol.extra_index, extras), | |
| 284 | }; | |
| 280 | 285 | } |
| 281 | 286 | |
| 282 | 287 | pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { |
src/link/Elf/ZigObject.zig+108-53| ... | ... | @@ -89,19 +89,11 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void { |
| 89 | 89 | try self.strtab.buffer.append(gpa, 0); |
| 90 | 90 | |
| 91 | 91 | const name_off = try self.strtab.insert(gpa, self.path); |
| 92 | const symbol_index = try elf_file.addSymbol(); | |
| 93 | try self.local_symbols.append(gpa, symbol_index); | |
| 94 | const symbol_ptr = elf_file.symbol(symbol_index); | |
| 95 | symbol_ptr.file_index = self.index; | |
| 96 | symbol_ptr.name_offset = name_off; | |
| 97 | symbol_ptr.extra_index = try elf_file.addSymbolExtra(.{}); | |
| 98 | ||
| 99 | const esym_index = try self.addLocalEsym(gpa); | |
| 100 | const esym = &self.local_esyms.items(.elf_sym)[esym_index]; | |
| 101 | esym.st_name = name_off; | |
| 92 | const symbol_index = try self.newLocalSymbol(gpa, name_off); | |
| 93 | const sym = self.symbol(symbol_index); | |
| 94 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; | |
| 102 | 95 | esym.st_info = elf.STT_FILE; |
| 103 | 96 | esym.st_shndx = elf.SHN_ABS; |
| 104 | symbol_ptr.esym_index = esym_index; | |
| 105 | 97 | |
| 106 | 98 | switch (comp.config.debug_format) { |
| 107 | 99 | .strip => {}, |
| ... | ... | @@ -275,7 +267,7 @@ fn newSymbol(self: *ZigObject, allocator: Allocator, name_off: u32, st_bind: u4) |
| 275 | 267 | const index = self.addSymbolAssumeCapacity(); |
| 276 | 268 | const sym = &self.symbols.items[index]; |
| 277 | 269 | sym.name_offset = name_off; |
| 278 | sym.extra = self.addSymbolExtraAssumeCapacity(.{}); | |
| 270 | sym.extra_index = self.addSymbolExtraAssumeCapacity(.{}); | |
| 279 | 271 | |
| 280 | 272 | const esym_idx: u32 = @intCast(self.symtab.addOneAssumeCapacity()); |
| 281 | 273 | const esym = ElfSym{ .elf_sym = .{ |
| ... | ... | @@ -377,7 +369,7 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) !void { |
| 377 | 369 | continue; |
| 378 | 370 | } |
| 379 | 371 | |
| 380 | if (self.asFile().symbolRank(esym, !self.alive) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) { | |
| 372 | if (self.asFile().symbolRank(esym, false) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) { | |
| 381 | 373 | gop.ref.* = .{ .index = @intCast(i | global_symbol_bit), .file = self.index }; |
| 382 | 374 | } |
| 383 | 375 | } |
| ... | ... | @@ -428,7 +420,7 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void { |
| 428 | 420 | global.file_index = self.index; |
| 429 | 421 | |
| 430 | 422 | const idx = self.symbols_resolver.items[i]; |
| 431 | elf_file.resolver.items[idx - 1] = .{ .index = @intCast(i | global_symbol_bit), .file = self.index }; | |
| 423 | elf_file.resolver.values.items[idx - 1] = .{ .index = @intCast(i | global_symbol_bit), .file = self.index }; | |
| 432 | 424 | } |
| 433 | 425 | } |
| 434 | 426 | |
| ... | ... | @@ -450,6 +442,64 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void { |
| 450 | 442 | } |
| 451 | 443 | } |
| 452 | 444 | |
| 445 | pub fn createSymbolIndirection(self: *ZigObject, elf_file: *Elf) !void { | |
| 446 | const impl = struct { | |
| 447 | fn impl(sym: *Symbol, ref: Elf.Ref, ef: *Elf) !void { | |
| 448 | if (!sym.isLocal(ef) and !sym.flags.has_dynamic) { | |
| 449 | log.debug("'{s}' is non-local", .{sym.name(ef)}); | |
| 450 | try ef.dynsym.addSymbol(ref, ef); | |
| 451 | } | |
| 452 | if (sym.flags.needs_got) { | |
| 453 | log.debug("'{s}' needs GOT", .{sym.name(ef)}); | |
| 454 | _ = try ef.got.addGotSymbol(ref, ef); | |
| 455 | } | |
| 456 | if (sym.flags.needs_plt) { | |
| 457 | if (sym.flags.is_canonical) { | |
| 458 | log.debug("'{s}' needs CPLT", .{sym.name(ef)}); | |
| 459 | sym.flags.@"export" = true; | |
| 460 | try ef.plt.addSymbol(ref, ef); | |
| 461 | } else if (sym.flags.needs_got) { | |
| 462 | log.debug("'{s}' needs PLTGOT", .{sym.name(ef)}); | |
| 463 | try ef.plt_got.addSymbol(ref, ef); | |
| 464 | } else { | |
| 465 | log.debug("'{s}' needs PLT", .{sym.name(ef)}); | |
| 466 | try ef.plt.addSymbol(ref, ef); | |
| 467 | } | |
| 468 | } | |
| 469 | if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) { | |
| 470 | log.debug("'{s}' needs COPYREL", .{sym.name(ef)}); | |
| 471 | try ef.copy_rel.addSymbol(ref, ef); | |
| 472 | } | |
| 473 | if (sym.flags.needs_tlsgd) { | |
| 474 | log.debug("'{s}' needs TLSGD", .{sym.name(ef)}); | |
| 475 | try ef.got.addTlsGdSymbol(ref, ef); | |
| 476 | } | |
| 477 | if (sym.flags.needs_gottp) { | |
| 478 | log.debug("'{s}' needs GOTTP", .{sym.name(ef)}); | |
| 479 | try ef.got.addGotTpSymbol(ref, ef); | |
| 480 | } | |
| 481 | if (sym.flags.needs_tlsdesc) { | |
| 482 | log.debug("'{s}' needs TLSDESC", .{sym.name(ef)}); | |
| 483 | try ef.got.addTlsDescSymbol(ref, ef); | |
| 484 | } | |
| 485 | } | |
| 486 | }.impl; | |
| 487 | for (self.local_symbols.items, 0..) |index, i| { | |
| 488 | const sym = &self.symbols.items[index]; | |
| 489 | const ref = self.resolveSymbol(@intCast(i), elf_file); | |
| 490 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 491 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 492 | try impl(sym, ref, elf_file); | |
| 493 | } | |
| 494 | for (self.global_symbols.items, 0..) |index, i| { | |
| 495 | const sym = &self.symbols.items[index]; | |
| 496 | const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file); | |
| 497 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 498 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 499 | try impl(sym, ref, elf_file); | |
| 500 | } | |
| 501 | } | |
| 502 | ||
| 453 | 503 | pub fn markLive(self: *ZigObject, elf_file: *Elf) void { |
| 454 | 504 | for (self.global_symbols.items, 0..) |index, i| { |
| 455 | 505 | const global = self.symbols.items[index]; |
| ... | ... | @@ -468,7 +518,7 @@ pub fn markLive(self: *ZigObject, elf_file: *Elf) void { |
| 468 | 518 | } |
| 469 | 519 | } |
| 470 | 520 | |
| 471 | pub fn markImportsExports(self: *Object, elf_file: *Elf) void { | |
| 521 | pub fn markImportsExports(self: *ZigObject, elf_file: *Elf) void { | |
| 472 | 522 | for (0..self.global_symbols.items.len) |i| { |
| 473 | 523 | const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file); |
| 474 | 524 | const sym = elf_file.symbol(ref) orelse continue; |
| ... | ... | @@ -604,7 +654,7 @@ pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void { |
| 604 | 654 | |
| 605 | 655 | for (self.global_symbols.items, self.symbols_resolver.items) |index, resolv| { |
| 606 | 656 | const global = &self.symbols.items[index]; |
| 607 | const ref = elf_file.resolver.items[resolv]; | |
| 657 | const ref = elf_file.resolver.values.items[resolv]; | |
| 608 | 658 | const ref_sym = elf_file.symbol(ref) orelse continue; |
| 609 | 659 | if (ref_sym.file(elf_file).?.index() != self.index) continue; |
| 610 | 660 | if (global.atom(elf_file)) |atom_ptr| if (!atom_ptr.alive) continue; |
| ... | ... | @@ -633,7 +683,7 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void { |
| 633 | 683 | |
| 634 | 684 | for (self.global_symbols.items, self.symbols_resolver.items) |index, resolv| { |
| 635 | 685 | const global = self.symbols.items[index]; |
| 636 | const ref = elf_file.resolver.items[resolv]; | |
| 686 | const ref = elf_file.resolver.values.items[resolv]; | |
| 637 | 687 | const ref_sym = elf_file.symbol(ref) orelse continue; |
| 638 | 688 | if (ref_sym.file(elf_file).?.index() != self.index) continue; |
| 639 | 689 | const idx = global.outputSymtabIndex(elf_file) orelse continue; |
| ... | ... | @@ -678,13 +728,13 @@ pub fn getDeclVAddr( |
| 678 | 728 | reloc_info: link.File.RelocInfo, |
| 679 | 729 | ) !u64 { |
| 680 | 730 | const this_sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index); |
| 681 | const this_sym = elf_file.symbol(this_sym_index); | |
| 731 | const this_sym = self.symbol(this_sym_index); | |
| 682 | 732 | const vaddr = this_sym.address(.{}, elf_file); |
| 683 | const parent_atom = elf_file.symbol(reloc_info.parent_atom_index).atom(elf_file).?; | |
| 733 | const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?; | |
| 684 | 734 | const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch); |
| 685 | 735 | try parent_atom.addReloc(elf_file, .{ |
| 686 | 736 | .r_offset = reloc_info.offset, |
| 687 | .r_info = (@as(u64, @intCast(this_sym.esym_index)) << 32) | r_type, | |
| 737 | .r_info = (@as(u64, @intCast(this_sym_index)) << 32) | r_type, | |
| 688 | 738 | .r_addend = reloc_info.addend, |
| 689 | 739 | }); |
| 690 | 740 | return @intCast(vaddr); |
| ... | ... | @@ -697,13 +747,13 @@ pub fn getAnonDeclVAddr( |
| 697 | 747 | reloc_info: link.File.RelocInfo, |
| 698 | 748 | ) !u64 { |
| 699 | 749 | const sym_index = self.anon_decls.get(decl_val).?.symbol_index; |
| 700 | const sym = elf_file.symbol(sym_index); | |
| 750 | const sym = self.symbol(sym_index); | |
| 701 | 751 | const vaddr = sym.address(.{}, elf_file); |
| 702 | const parent_atom = elf_file.symbol(reloc_info.parent_atom_index).atom(elf_file).?; | |
| 752 | const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?; | |
| 703 | 753 | const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch); |
| 704 | 754 | try parent_atom.addReloc(elf_file, .{ |
| 705 | 755 | .r_offset = reloc_info.offset, |
| 706 | .r_info = (@as(u64, @intCast(sym.esym_index)) << 32) | r_type, | |
| 756 | .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type, | |
| 707 | 757 | .r_addend = reloc_info.addend, |
| 708 | 758 | }); |
| 709 | 759 | return @intCast(vaddr); |
| ... | ... | @@ -725,7 +775,7 @@ pub fn lowerAnonDecl( |
| 725 | 775 | else => explicit_alignment, |
| 726 | 776 | }; |
| 727 | 777 | if (self.anon_decls.get(decl_val)) |metadata| { |
| 728 | const existing_alignment = elf_file.symbol(metadata.symbol_index).atom(elf_file).?.alignment; | |
| 778 | const existing_alignment = self.symbol(metadata.symbol_index).atom(elf_file).?.alignment; | |
| 729 | 779 | if (decl_alignment.order(existing_alignment).compare(.lte)) |
| 730 | 780 | return .ok; |
| 731 | 781 | } |
| ... | ... | @@ -811,11 +861,10 @@ fn freeUnnamedConsts(self: *ZigObject, elf_file: *Elf, decl_index: InternPool.De |
| 811 | 861 | } |
| 812 | 862 | |
| 813 | 863 | fn freeDeclMetadata(self: *ZigObject, elf_file: *Elf, sym_index: Symbol.Index) void { |
| 814 | _ = self; | |
| 815 | const sym = elf_file.symbol(sym_index); | |
| 864 | const sym = self.symbol(sym_index); | |
| 816 | 865 | sym.atom(elf_file).?.free(elf_file); |
| 817 | 866 | log.debug("adding %{d} to local symbols free list", .{sym_index}); |
| 818 | elf_file.symbols.items[sym_index] = .{}; | |
| 867 | self.symbols.items[sym_index] = .{}; | |
| 819 | 868 | // TODO free GOT entry here |
| 820 | 869 | } |
| 821 | 870 | |
| ... | ... | @@ -940,8 +989,8 @@ fn updateDeclCode( |
| 940 | 989 | target_util.minFunctionAlignment(mod.getTarget()), |
| 941 | 990 | ); |
| 942 | 991 | |
| 943 | const sym = elf_file.symbol(sym_index); | |
| 944 | const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index]; | |
| 992 | const sym = self.symbol(sym_index); | |
| 993 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; | |
| 945 | 994 | const atom_ptr = sym.atom(elf_file).?; |
| 946 | 995 | const name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip)); |
| 947 | 996 | |
| ... | ... | @@ -1038,8 +1087,8 @@ fn updateTlv( |
| 1038 | 1087 | |
| 1039 | 1088 | const required_alignment = decl.getAlignment(pt); |
| 1040 | 1089 | |
| 1041 | const sym = elf_file.symbol(sym_index); | |
| 1042 | const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index]; | |
| 1090 | const sym = self.symbol(sym_index); | |
| 1091 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; | |
| 1043 | 1092 | const atom_ptr = sym.atom(elf_file).?; |
| 1044 | 1093 | const name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip)); |
| 1045 | 1094 | |
| ... | ... | @@ -1264,9 +1313,9 @@ fn updateLazySymbol( |
| 1264 | 1313 | .code => elf_file.zig_text_section_index.?, |
| 1265 | 1314 | .const_data => elf_file.zig_data_rel_ro_section_index.?, |
| 1266 | 1315 | }; |
| 1267 | const local_sym = elf_file.symbol(symbol_index); | |
| 1316 | const local_sym = self.symbol(symbol_index); | |
| 1268 | 1317 | local_sym.name_offset = name_str_index; |
| 1269 | const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index]; | |
| 1318 | const local_esym = &self.symtab.items(.elf_sym)[local_sym.esym_index]; | |
| 1270 | 1319 | local_esym.st_name = name_str_index; |
| 1271 | 1320 | local_esym.st_info |= elf.STT_OBJECT; |
| 1272 | 1321 | local_esym.st_size = code.len; |
| ... | ... | @@ -1372,7 +1421,7 @@ fn lowerConst( |
| 1372 | 1421 | }; |
| 1373 | 1422 | |
| 1374 | 1423 | const local_sym = self.symbol(sym_index); |
| 1375 | const local_esym = local_sym.elfSym(elf_file); | |
| 1424 | const local_esym = &self.symtab.items(.elf_sym)[local_sym.esym_index]; | |
| 1376 | 1425 | local_esym.st_info |= elf.STT_OBJECT; |
| 1377 | 1426 | local_esym.st_size = code.len; |
| 1378 | 1427 | const atom_ptr = local_sym.atom(elf_file).?; |
| ... | ... | @@ -1473,9 +1522,9 @@ pub fn updateExports( |
| 1473 | 1522 | const global_sym = self.symbol(global_sym_index); |
| 1474 | 1523 | global_sym.value = value; |
| 1475 | 1524 | global_sym.flags.weak = exp.opts.linkage == .weak; |
| 1476 | global_sym.version_index = elf_file.default_version_index; | |
| 1525 | global_sym.version_index = elf_file.default_sym_version; | |
| 1477 | 1526 | global_sym.ref = .{ .index = esym_shndx, .file = self.index }; |
| 1478 | const global_esym = global_sym.elfSym(elf_file); | |
| 1527 | const global_esym = &self.symtab.items(.elf_sym)[global_sym.esym_index]; | |
| 1479 | 1528 | global_esym.st_value = @intCast(value); |
| 1480 | 1529 | global_esym.st_shndx = esym.st_shndx; |
| 1481 | 1530 | global_esym.st_info = (stb_bits << 4) | stt_bits; |
| ... | ... | @@ -1517,16 +1566,16 @@ pub fn deleteExport( |
| 1517 | 1566 | const exp_name = name.toSlice(&mod.intern_pool); |
| 1518 | 1567 | const esym_index = metadata.@"export"(self, exp_name) orelse return; |
| 1519 | 1568 | log.debug("deleting export '{s}'", .{exp_name}); |
| 1520 | const esym = &self.global_esyms.items(.elf_sym)[esym_index.*]; | |
| 1569 | const esym = &self.symtab.items(.elf_sym)[esym_index.*]; | |
| 1521 | 1570 | _ = self.globals_lookup.remove(esym.st_name); |
| 1522 | const sym_index = elf_file.resolver.get(esym.st_name).?; | |
| 1523 | const sym = elf_file.symbol(sym_index); | |
| 1524 | if (sym.file_index == self.index) { | |
| 1525 | _ = elf_file.resolver.swapRemove(esym.st_name); | |
| 1526 | sym.* = .{}; | |
| 1527 | } | |
| 1571 | // const sym_index = elf_file.resolver.get(esym.st_name).?; | |
| 1572 | // const sym = elf_file.symbol(sym_index); | |
| 1573 | // if (sym.file_index == self.index) { | |
| 1574 | // _ = elf_file.resolver.swapRemove(esym.st_name); | |
| 1575 | // sym.* = .{}; | |
| 1576 | // } | |
| 1528 | 1577 | esym.* = Elf.null_sym; |
| 1529 | self.global_esyms.items(.shndx)[esym_index.*] = elf.SHN_UNDEF; | |
| 1578 | self.symtab.items(.shndx)[esym_index.*] = elf.SHN_UNDEF; | |
| 1530 | 1579 | } |
| 1531 | 1580 | |
| 1532 | 1581 | pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 { |
| ... | ... | @@ -1535,7 +1584,7 @@ pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_n |
| 1535 | 1584 | const off = try self.strtab.insert(gpa, name); |
| 1536 | 1585 | const lookup_gop = try self.globals_lookup.getOrPut(gpa, off); |
| 1537 | 1586 | if (!lookup_gop.found_existing) { |
| 1538 | lookup_gop.value_ptr.* = try self.newSymbol(gpa, off); | |
| 1587 | lookup_gop.value_ptr.* = try self.newGlobalSymbol(gpa, off); | |
| 1539 | 1588 | } |
| 1540 | 1589 | return lookup_gop.value_ptr.*; |
| 1541 | 1590 | } |
| ... | ... | @@ -1636,8 +1685,12 @@ pub fn resolveSymbol(self: ZigObject, index: Symbol.Index, elf_file: *Elf) Elf.R |
| 1636 | 1685 | return .{ .index = index, .file = self.index }; |
| 1637 | 1686 | } |
| 1638 | 1687 | |
| 1639 | pub fn addSymbol(self: *ZigObject, allocator: Allocator) !Symbol.Index { | |
| 1688 | fn addSymbol(self: *ZigObject, allocator: Allocator) !Symbol.Index { | |
| 1640 | 1689 | try self.symbols.ensureUnusedCapacity(allocator, 1); |
| 1690 | return self.addSymbolAssumeCapacity(); | |
| 1691 | } | |
| 1692 | ||
| 1693 | fn addSymbolAssumeCapacity(self: *ZigObject) Symbol.Index { | |
| 1641 | 1694 | const index: Symbol.Index = @intCast(self.symbols.items.len); |
| 1642 | 1695 | self.symbols.appendAssumeCapacity(.{ .file_index = self.index }); |
| 1643 | 1696 | return index; |
| ... | ... | @@ -1705,15 +1758,17 @@ fn formatSymtab( |
| 1705 | 1758 | ) !void { |
| 1706 | 1759 | _ = unused_fmt_string; |
| 1707 | 1760 | _ = options; |
| 1761 | const self = ctx.self; | |
| 1762 | const elf_file = ctx.elf_file; | |
| 1708 | 1763 | try writer.writeAll(" locals\n"); |
| 1709 | for (ctx.self.locals()) |index| { | |
| 1710 | const local = ctx.elf_file.symbol(index); | |
| 1711 | try writer.print(" {}\n", .{local.fmt(ctx.elf_file)}); | |
| 1764 | for (self.local_symbols.items) |index| { | |
| 1765 | const local = self.symbols.items[index]; | |
| 1766 | try writer.print(" {}\n", .{local.fmt(elf_file)}); | |
| 1712 | 1767 | } |
| 1713 | 1768 | try writer.writeAll(" globals\n"); |
| 1714 | for (ctx.self.globals()) |index| { | |
| 1715 | const global = ctx.elf_file.symbol(index); | |
| 1716 | try writer.print(" {}\n", .{global.fmt(ctx.elf_file)}); | |
| 1769 | for (ctx.self.global_symbols.items) |index| { | |
| 1770 | const global = self.symbols.items[index]; | |
| 1771 | try writer.print(" {}\n", .{global.fmt(elf_file)}); | |
| 1717 | 1772 | } |
| 1718 | 1773 | } |
| 1719 | 1774 | |
| ... | ... | @@ -1759,7 +1814,7 @@ const DeclMetadata = struct { |
| 1759 | 1814 | |
| 1760 | 1815 | fn @"export"(m: DeclMetadata, zo: *ZigObject, name: []const u8) ?*u32 { |
| 1761 | 1816 | for (m.exports.items) |*exp| { |
| 1762 | const exp_name = zo.getString(zo.symbol(exp.*).name_off); | |
| 1817 | const exp_name = zo.getString(zo.symbol(exp.*).name_offset); | |
| 1763 | 1818 | if (mem.eql(u8, name, exp_name)) return exp; |
| 1764 | 1819 | } |
| 1765 | 1820 | return null; |
src/link/Elf/eh_frame.zig+10-5| ... | ... | @@ -339,7 +339,8 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { |
| 339 | 339 | const contents = cie.data(elf_file); |
| 340 | 340 | |
| 341 | 341 | for (cie.relocs(elf_file)) |rel| { |
| 342 | const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]); | |
| 342 | const ref = object.resolveSymbol(rel.r_sym(), elf_file); | |
| 343 | const sym = elf_file.symbol(ref).?; | |
| 343 | 344 | resolveReloc(cie, sym, rel, elf_file, contents) catch |err| switch (err) { |
| 344 | 345 | error.RelocFailure => has_reloc_errors = true, |
| 345 | 346 | else => |e| return e, |
| ... | ... | @@ -366,7 +367,8 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { |
| 366 | 367 | ); |
| 367 | 368 | |
| 368 | 369 | for (fde.relocs(elf_file)) |rel| { |
| 369 | const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]); | |
| 370 | const ref = object.resolveSymbol(rel.r_sym(), elf_file); | |
| 371 | const sym = elf_file.symbol(ref).?; | |
| 370 | 372 | resolveReloc(fde, sym, rel, elf_file, contents) catch |err| switch (err) { |
| 371 | 373 | error.RelocFailure => has_reloc_errors = true, |
| 372 | 374 | else => |e| return e, |
| ... | ... | @@ -452,7 +454,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { |
| 452 | 454 | for (object.cies.items) |cie| { |
| 453 | 455 | if (!cie.alive) continue; |
| 454 | 456 | for (cie.relocs(elf_file)) |rel| { |
| 455 | const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]); | |
| 457 | const ref = object.resolveSymbol(rel.r_sym(), elf_file); | |
| 458 | const sym = elf_file.symbol(ref).?; | |
| 456 | 459 | const out_rel = emitReloc(elf_file, cie, sym, rel); |
| 457 | 460 | try writer.writeStruct(out_rel); |
| 458 | 461 | } |
| ... | ... | @@ -461,7 +464,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { |
| 461 | 464 | for (object.fdes.items) |fde| { |
| 462 | 465 | if (!fde.alive) continue; |
| 463 | 466 | for (fde.relocs(elf_file)) |rel| { |
| 464 | const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]); | |
| 467 | const ref = object.resolveSymbol(rel.r_sym(), elf_file); | |
| 468 | const sym = elf_file.symbol(ref).?; | |
| 465 | 469 | const out_rel = emitReloc(elf_file, fde, sym, rel); |
| 466 | 470 | try writer.writeStruct(out_rel); |
| 467 | 471 | } |
| ... | ... | @@ -513,7 +517,8 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void { |
| 513 | 517 | const relocs = fde.relocs(elf_file); |
| 514 | 518 | assert(relocs.len > 0); // Should this be an error? Things are completely broken anyhow if this trips... |
| 515 | 519 | const rel = relocs[0]; |
| 516 | const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]); | |
| 520 | const ref = object.resolveSymbol(rel.r_sym(), elf_file); | |
| 521 | const sym = elf_file.symbol(ref).?; | |
| 517 | 522 | const P = @as(i64, @intCast(fde.address(elf_file))); |
| 518 | 523 | const S = @as(i64, @intCast(sym.address(.{}, elf_file))); |
| 519 | 524 | const A = rel.r_addend; |
src/link/Elf/file.zig+18-5| ... | ... | @@ -61,10 +61,10 @@ pub const File = union(enum) { |
| 61 | 61 | return (@as(u32, base) << 24) + file.index(); |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | pub fn resolveSymbols(file: File, elf_file: *Elf) void { | |
| 65 | switch (file) { | |
| 64 | pub fn resolveSymbols(file: File, elf_file: *Elf) !void { | |
| 65 | return switch (file) { | |
| 66 | 66 | inline else => |x| x.resolveSymbols(elf_file), |
| 67 | } | |
| 67 | }; | |
| 68 | 68 | } |
| 69 | 69 | |
| 70 | 70 | pub fn resetGlobals(file: File, elf_file: *Elf) void { |
| ... | ... | @@ -100,6 +100,13 @@ pub const File = union(enum) { |
| 100 | 100 | } |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | pub fn createSymbolIndirection(file: File, elf_file: *Elf) !void { | |
| 104 | return switch (file) { | |
| 105 | .linker_defined, .shared_object => unreachable, | |
| 106 | inline else => |x| x.createSymbolIndirection(elf_file), | |
| 107 | }; | |
| 108 | } | |
| 109 | ||
| 103 | 110 | pub fn atom(file: File, atom_index: Atom.Index) ?*Atom { |
| 104 | 111 | return switch (file) { |
| 105 | 112 | .shared_object => unreachable, |
| ... | ... | @@ -146,10 +153,16 @@ pub const File = union(enum) { |
| 146 | 153 | }; |
| 147 | 154 | } |
| 148 | 155 | |
| 149 | pub fn symbol(file: File, ind: Symbol.Index) Symbol.Index { | |
| 156 | pub fn resolveSymbol(file: File, ind: Symbol.Index, elf_file: *Elf) Elf.Ref { | |
| 157 | return switch (file) { | |
| 158 | inline else => |x| x.resolveSymbol(ind, elf_file), | |
| 159 | }; | |
| 160 | } | |
| 161 | ||
| 162 | pub fn symbol(file: File, ind: Symbol.Index) *Symbol { | |
| 150 | 163 | return switch (file) { |
| 151 | 164 | .zig_object => |x| x.symbol(ind), |
| 152 | inline else => |x| x.symbols.items[ind], | |
| 165 | inline else => |x| &x.symbols.items[ind], | |
| 153 | 166 | }; |
| 154 | 167 | } |
| 155 | 168 |
src/link/Elf/gc.zig+81-58| ... | ... | @@ -1,71 +1,84 @@ |
| 1 | 1 | pub fn gcAtoms(elf_file: *Elf) !void { |
| 2 | 2 | const comp = elf_file.base.comp; |
| 3 | 3 | const gpa = comp.gpa; |
| 4 | const num_files = elf_file.objects.items.len + @intFromBool(elf_file.zig_object_index != null); | |
| 5 | var files = try std.ArrayList(File.Index).initCapacity(gpa, num_files); | |
| 6 | defer files.deinit(); | |
| 7 | if (elf_file.zig_object_index) |index| files.appendAssumeCapacity(index); | |
| 8 | for (elf_file.objects.items) |index| files.appendAssumeCapacity(index); | |
| 9 | ||
| 10 | 4 | var roots = std.ArrayList(*Atom).init(gpa); |
| 11 | 5 | defer roots.deinit(); |
| 12 | try collectRoots(&roots, files.items, elf_file); | |
| 13 | ||
| 6 | try collectRoots(&roots, elf_file); | |
| 14 | 7 | mark(roots, elf_file); |
| 15 | prune(files.items, elf_file); | |
| 8 | prune(elf_file); | |
| 16 | 9 | } |
| 17 | 10 | |
| 18 | fn collectRoots(roots: *std.ArrayList(*Atom), files: []const File.Index, elf_file: *Elf) !void { | |
| 11 | fn collectRoots(roots: *std.ArrayList(*Atom), elf_file: *Elf) !void { | |
| 19 | 12 | if (elf_file.linkerDefinedPtr()) |obj| { |
| 20 | if (obj.entry_index) |index| { | |
| 21 | const global = elf_file.symbol(index); | |
| 22 | try markSymbol(global, roots, elf_file); | |
| 13 | if (obj.entrySymbol(elf_file)) |sym| { | |
| 14 | try markSymbol(sym, roots, elf_file); | |
| 23 | 15 | } |
| 24 | 16 | } |
| 25 | 17 | |
| 26 | for (files) |index| { | |
| 27 | for (elf_file.file(index).?.globals()) |global_index| { | |
| 28 | const global = elf_file.symbol(global_index); | |
| 29 | if (global.file(elf_file)) |file| { | |
| 30 | if (file.index() == index and global.flags.@"export") | |
| 31 | try markSymbol(global, roots, elf_file); | |
| 18 | if (elf_file.zigObjectPtr()) |zo| { | |
| 19 | for (0..zo.global_symbols.items.len) |i| { | |
| 20 | const ref = zo.resolveSymbol(@intCast(i | ZigObject.global_symbol_bit), elf_file); | |
| 21 | const sym = elf_file.symbol(ref) orelse continue; | |
| 22 | if (sym.file(elf_file).?.index() != zo.index) continue; | |
| 23 | if (sym.flags.@"export") { | |
| 24 | try markSymbol(sym, roots, elf_file); | |
| 32 | 25 | } |
| 33 | 26 | } |
| 34 | 27 | } |
| 35 | 28 | |
| 36 | for (files) |index| { | |
| 37 | const file = elf_file.file(index).?; | |
| 38 | ||
| 39 | for (file.atoms()) |atom_index| { | |
| 40 | const atom = file.atom(atom_index) orelse continue; | |
| 41 | if (!atom.alive) continue; | |
| 42 | ||
| 43 | const shdr = atom.inputShdr(elf_file); | |
| 44 | const name = atom.name(elf_file); | |
| 45 | const is_gc_root = blk: { | |
| 46 | if (shdr.sh_flags & elf.SHF_GNU_RETAIN != 0) break :blk true; | |
| 47 | if (shdr.sh_type == elf.SHT_NOTE) break :blk true; | |
| 48 | if (shdr.sh_type == elf.SHT_PREINIT_ARRAY) break :blk true; | |
| 49 | if (shdr.sh_type == elf.SHT_INIT_ARRAY) break :blk true; | |
| 50 | if (shdr.sh_type == elf.SHT_FINI_ARRAY) break :blk true; | |
| 51 | if (mem.startsWith(u8, name, ".ctors")) break :blk true; | |
| 52 | if (mem.startsWith(u8, name, ".dtors")) break :blk true; | |
| 53 | if (mem.startsWith(u8, name, ".init")) break :blk true; | |
| 54 | if (mem.startsWith(u8, name, ".fini")) break :blk true; | |
| 55 | if (Elf.isCIdentifier(name)) break :blk true; | |
| 56 | break :blk false; | |
| 57 | }; | |
| 58 | if (is_gc_root and markAtom(atom)) try roots.append(atom); | |
| 59 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) atom.visited = true; | |
| 29 | for (elf_file.objects.items) |index| { | |
| 30 | const object = elf_file.file(index).?.object; | |
| 31 | for (0..object.globals().len) |i| { | |
| 32 | const ref = object.resolveSymbol(@intCast(i), elf_file); | |
| 33 | const sym = elf_file.symbol(ref) orelse continue; | |
| 34 | if (sym.file(elf_file).?.index() != object.index) continue; | |
| 35 | if (sym.flags.@"export") { | |
| 36 | try markSymbol(sym, roots, elf_file); | |
| 37 | } | |
| 60 | 38 | } |
| 39 | } | |
| 61 | 40 | |
| 62 | // Mark every atom referenced by CIE as alive. | |
| 63 | for (file.cies()) |cie| { | |
| 64 | for (cie.relocs(elf_file)) |rel| { | |
| 65 | const sym = elf_file.symbol(file.symbol(rel.r_sym())); | |
| 66 | try markSymbol(sym, roots, elf_file); | |
| 41 | const atomRoots = struct { | |
| 42 | fn atomRoots(file: File, rs: anytype, ef: *Elf) !void { | |
| 43 | for (file.atoms()) |atom_index| { | |
| 44 | const atom = file.atom(atom_index) orelse continue; | |
| 45 | if (!atom.alive) continue; | |
| 46 | ||
| 47 | const shdr = atom.inputShdr(ef); | |
| 48 | const name = atom.name(ef); | |
| 49 | const is_gc_root = blk: { | |
| 50 | if (shdr.sh_flags & elf.SHF_GNU_RETAIN != 0) break :blk true; | |
| 51 | if (shdr.sh_type == elf.SHT_NOTE) break :blk true; | |
| 52 | if (shdr.sh_type == elf.SHT_PREINIT_ARRAY) break :blk true; | |
| 53 | if (shdr.sh_type == elf.SHT_INIT_ARRAY) break :blk true; | |
| 54 | if (shdr.sh_type == elf.SHT_FINI_ARRAY) break :blk true; | |
| 55 | if (mem.startsWith(u8, name, ".ctors")) break :blk true; | |
| 56 | if (mem.startsWith(u8, name, ".dtors")) break :blk true; | |
| 57 | if (mem.startsWith(u8, name, ".init")) break :blk true; | |
| 58 | if (mem.startsWith(u8, name, ".fini")) break :blk true; | |
| 59 | if (Elf.isCIdentifier(name)) break :blk true; | |
| 60 | break :blk false; | |
| 61 | }; | |
| 62 | if (is_gc_root and markAtom(atom)) try rs.append(atom); | |
| 63 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) atom.visited = true; | |
| 64 | } | |
| 65 | ||
| 66 | // Mark every atom referenced by CIE as alive. | |
| 67 | for (file.cies()) |cie| { | |
| 68 | for (cie.relocs(ef)) |rel| { | |
| 69 | const ref = file.resolveSymbol(rel.r_sym(), ef); | |
| 70 | const sym = ef.symbol(ref) orelse continue; | |
| 71 | try markSymbol(sym, rs, ef); | |
| 72 | } | |
| 67 | 73 | } |
| 68 | 74 | } |
| 75 | }.atomRoots; | |
| 76 | ||
| 77 | if (elf_file.zigObjectPtr()) |zo| { | |
| 78 | try atomRoots(zo.asFile(), roots, elf_file); | |
| 79 | } | |
| 80 | for (elf_file.objects.items) |index| { | |
| 81 | try atomRoots(elf_file.file(index).?, roots, elf_file); | |
| 69 | 82 | } |
| 70 | 83 | } |
| 71 | 84 | |
| ... | ... | @@ -92,7 +105,8 @@ fn markLive(atom: *Atom, elf_file: *Elf) void { |
| 92 | 105 | |
| 93 | 106 | for (atom.fdes(elf_file)) |fde| { |
| 94 | 107 | for (fde.relocs(elf_file)[1..]) |rel| { |
| 95 | const target_sym = elf_file.symbol(file.symbol(rel.r_sym())); | |
| 108 | const ref = file.resolveSymbol(rel.r_sym(), elf_file); | |
| 109 | const target_sym = elf_file.symbol(ref) orelse continue; | |
| 96 | 110 | const target_atom = target_sym.atom(elf_file) orelse continue; |
| 97 | 111 | target_atom.alive = true; |
| 98 | 112 | gc_track_live_log.debug("{}marking live atom({d})", .{ track_live_level, target_atom.atom_index }); |
| ... | ... | @@ -101,7 +115,8 @@ fn markLive(atom: *Atom, elf_file: *Elf) void { |
| 101 | 115 | } |
| 102 | 116 | |
| 103 | 117 | for (atom.relocs(elf_file)) |rel| { |
| 104 | const target_sym = elf_file.symbol(file.symbol(rel.r_sym())); | |
| 118 | const ref = file.resolveSymbol(rel.r_sym(), elf_file); | |
| 119 | const target_sym = elf_file.symbol(ref) orelse continue; | |
| 105 | 120 | if (target_sym.mergeSubsection(elf_file)) |msub| { |
| 106 | 121 | msub.alive = true; |
| 107 | 122 | continue; |
| ... | ... | @@ -120,16 +135,23 @@ fn mark(roots: std.ArrayList(*Atom), elf_file: *Elf) void { |
| 120 | 135 | } |
| 121 | 136 | } |
| 122 | 137 | |
| 123 | fn prune(files: []const File.Index, elf_file: *Elf) void { | |
| 124 | for (files) |index| { | |
| 125 | const file = elf_file.file(index).?; | |
| 126 | for (file.atoms()) |atom_index| { | |
| 127 | const atom = file.atom(atom_index) orelse continue; | |
| 128 | if (atom.alive and !atom.visited) { | |
| 129 | atom.alive = false; | |
| 130 | atom.markFdesDead(elf_file); | |
| 138 | fn prune(elf_file: *Elf) void { | |
| 139 | const pruneInFile = struct { | |
| 140 | fn pruneInFile(file: File, ef: *Elf) void { | |
| 141 | for (file.atoms()) |atom_index| { | |
| 142 | const atom = file.atom(atom_index) orelse continue; | |
| 143 | if (atom.alive and !atom.visited) { | |
| 144 | atom.alive = false; | |
| 145 | atom.markFdesDead(ef); | |
| 146 | } | |
| 131 | 147 | } |
| 132 | 148 | } |
| 149 | }.pruneInFile; | |
| 150 | if (elf_file.zigObjectPtr()) |zo| { | |
| 151 | pruneInFile(zo.asFile(), elf_file); | |
| 152 | } | |
| 153 | for (elf_file.objects.items) |index| { | |
| 154 | pruneInFile(elf_file.file(index).?, elf_file); | |
| 133 | 155 | } |
| 134 | 156 | } |
| 135 | 157 | |
| ... | ... | @@ -181,3 +203,4 @@ const Atom = @import("Atom.zig"); |
| 181 | 203 | const Elf = @import("../Elf.zig"); |
| 182 | 204 | const File = @import("file.zig").File; |
| 183 | 205 | const Symbol = @import("Symbol.zig"); |
| 206 | const ZigObject = @import("ZigObject.zig"); |
src/link/Elf/relocatable.zig+2-2| ... | ... | @@ -37,7 +37,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co |
| 37 | 37 | |
| 38 | 38 | // First, we flush relocatable object file generated with our backends. |
| 39 | 39 | if (elf_file.zigObjectPtr()) |zig_object| { |
| 40 | zig_object.resolveSymbols(elf_file); | |
| 40 | try zig_object.resolveSymbols(elf_file); | |
| 41 | 41 | try elf_file.addCommentString(); |
| 42 | 42 | try elf_file.finalizeMergeSections(); |
| 43 | 43 | zig_object.claimUnresolvedObject(elf_file); |
| ... | ... | @@ -383,7 +383,7 @@ fn updateComdatGroupsSizes(elf_file: *Elf) void { |
| 383 | 383 | shdr.sh_size = cg.size(elf_file); |
| 384 | 384 | shdr.sh_link = elf_file.symtab_section_index.?; |
| 385 | 385 | |
| 386 | const sym = elf_file.symbol(cg.symbol(elf_file)); | |
| 386 | const sym = cg.symbol(elf_file); | |
| 387 | 387 | shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse |
| 388 | 388 | elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx(elf_file).?); |
| 389 | 389 | } |
src/link/Elf/synthetic_sections.zig+125-130| ... | ... | @@ -251,15 +251,16 @@ pub const ZigGotSection = struct { |
| 251 | 251 | pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index { |
| 252 | 252 | const comp = elf_file.base.comp; |
| 253 | 253 | const gpa = comp.gpa; |
| 254 | const zo = elf_file.zigObjectPtr().?; | |
| 254 | 255 | const index = try zig_got.allocateEntry(gpa); |
| 255 | 256 | const entry = &zig_got.entries.items[index]; |
| 256 | 257 | entry.* = sym_index; |
| 257 | const symbol = elf_file.symbol(sym_index); | |
| 258 | const symbol = zo.symbol(sym_index); | |
| 258 | 259 | symbol.flags.has_zig_got = true; |
| 259 | 260 | if (elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) { |
| 260 | 261 | zig_got.flags.needs_rela = true; |
| 261 | 262 | } |
| 262 | try symbol.addExtra(.{ .zig_got = index }, elf_file); | |
| 263 | symbol.addExtra(.{ .zig_got = index }, elf_file); | |
| 263 | 264 | return index; |
| 264 | 265 | } |
| 265 | 266 | |
| ... | ... | @@ -282,6 +283,7 @@ pub const ZigGotSection = struct { |
| 282 | 283 | } |
| 283 | 284 | |
| 284 | 285 | pub fn writeOne(zig_got: *ZigGotSection, elf_file: *Elf, index: Index) !void { |
| 286 | const zo = elf_file.zigObjectPtr().?; | |
| 285 | 287 | if (zig_got.flags.dirty) { |
| 286 | 288 | const needed_size = zig_got.size(elf_file); |
| 287 | 289 | try elf_file.growAllocSection(elf_file.zig_got_section_index.?, needed_size); |
| ... | ... | @@ -293,7 +295,7 @@ pub const ZigGotSection = struct { |
| 293 | 295 | const off = zig_got.entryOffset(index, elf_file); |
| 294 | 296 | const vaddr: u64 = @intCast(zig_got.entryAddress(index, elf_file)); |
| 295 | 297 | const entry = zig_got.entries.items[index]; |
| 296 | const value = elf_file.symbol(entry).address(.{}, elf_file); | |
| 298 | const value = zo.symbol(entry).address(.{}, elf_file); | |
| 297 | 299 | switch (entry_size) { |
| 298 | 300 | 2 => { |
| 299 | 301 | var buf: [2]u8 = undefined; |
| ... | ... | @@ -336,8 +338,9 @@ pub const ZigGotSection = struct { |
| 336 | 338 | } |
| 337 | 339 | |
| 338 | 340 | pub fn writeAll(zig_got: ZigGotSection, elf_file: *Elf, writer: anytype) !void { |
| 341 | const zo = elf_file.zigObjectPtr().?; | |
| 339 | 342 | for (zig_got.entries.items) |entry| { |
| 340 | const symbol = elf_file.symbol(entry); | |
| 343 | const symbol = zo.symbol(entry); | |
| 341 | 344 | const value = symbol.address(.{ .plt = false }, elf_file); |
| 342 | 345 | try writeInt(value, elf_file, writer); |
| 343 | 346 | } |
| ... | ... | @@ -351,9 +354,10 @@ pub const ZigGotSection = struct { |
| 351 | 354 | const comp = elf_file.base.comp; |
| 352 | 355 | const gpa = comp.gpa; |
| 353 | 356 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 357 | const zo = elf_file.zigObjectPtr().?; | |
| 354 | 358 | try elf_file.rela_dyn.ensureUnusedCapacity(gpa, zig_got.numRela()); |
| 355 | 359 | for (zig_got.entries.items) |entry| { |
| 356 | const symbol = elf_file.symbol(entry); | |
| 360 | const symbol = zo.symbol(entry); | |
| 357 | 361 | const offset = symbol.zigGotAddress(elf_file); |
| 358 | 362 | elf_file.addRelaDynAssumeCapacity(.{ |
| 359 | 363 | .offset = @intCast(offset), |
| ... | ... | @@ -364,16 +368,18 @@ pub const ZigGotSection = struct { |
| 364 | 368 | } |
| 365 | 369 | |
| 366 | 370 | pub fn updateSymtabSize(zig_got: *ZigGotSection, elf_file: *Elf) void { |
| 371 | const zo = elf_file.zigObjectPtr().?; | |
| 367 | 372 | zig_got.output_symtab_ctx.nlocals = @as(u32, @intCast(zig_got.entries.items.len)); |
| 368 | 373 | for (zig_got.entries.items) |entry| { |
| 369 | const name = elf_file.symbol(entry).name(elf_file); | |
| 374 | const name = zo.symbol(entry).name(elf_file); | |
| 370 | 375 | zig_got.output_symtab_ctx.strsize += @as(u32, @intCast(name.len + "$ziggot".len)) + 1; |
| 371 | 376 | } |
| 372 | 377 | } |
| 373 | 378 | |
| 374 | 379 | pub fn writeSymtab(zig_got: ZigGotSection, elf_file: *Elf) void { |
| 380 | const zo = elf_file.zigObjectPtr().?; | |
| 375 | 381 | for (zig_got.entries.items, zig_got.output_symtab_ctx.ilocal.., 0..) |entry, ilocal, index| { |
| 376 | const symbol = elf_file.symbol(entry); | |
| 382 | const symbol = zo.symbol(entry); | |
| 377 | 383 | const symbol_name = symbol.name(elf_file); |
| 378 | 384 | const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); |
| 379 | 385 | elf_file.strtab.appendSliceAssumeCapacity(symbol_name); |
| ... | ... | @@ -409,15 +415,18 @@ pub const ZigGotSection = struct { |
| 409 | 415 | ) !void { |
| 410 | 416 | _ = options; |
| 411 | 417 | _ = unused_fmt_string; |
| 418 | const zig_got = ctx.zig_got; | |
| 419 | const elf_file = ctx.elf_file; | |
| 420 | const zo = elf_file.zigObjectPtr().?; | |
| 412 | 421 | try writer.writeAll(".zig.got\n"); |
| 413 | for (ctx.zig_got.entries.items, 0..) |entry, index| { | |
| 414 | const symbol = ctx.elf_file.symbol(entry); | |
| 422 | for (zig_got.entries.items, 0..) |entry, index| { | |
| 423 | const symbol = zo.symbol(entry); | |
| 415 | 424 | try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{ |
| 416 | 425 | index, |
| 417 | ctx.zig_got.entryAddress(@intCast(index), ctx.elf_file), | |
| 426 | zig_got.entryAddress(@intCast(index), elf_file), | |
| 418 | 427 | entry, |
| 419 | symbol.address(.{}, ctx.elf_file), | |
| 420 | symbol.name(ctx.elf_file), | |
| 428 | symbol.address(.{}, elf_file), | |
| 429 | symbol.name(elf_file), | |
| 421 | 430 | }); |
| 422 | 431 | } |
| 423 | 432 | } |
| ... | ... | @@ -446,7 +455,7 @@ pub const GotSection = struct { |
| 446 | 455 | |
| 447 | 456 | const Entry = struct { |
| 448 | 457 | tag: Tag, |
| 449 | symbol_index: Symbol.Index, | |
| 458 | ref: Elf.Ref, | |
| 450 | 459 | cell_index: Index, |
| 451 | 460 | |
| 452 | 461 | /// Returns how many indexes in the GOT this entry uses. |
| ... | ... | @@ -477,25 +486,25 @@ pub const GotSection = struct { |
| 477 | 486 | const last = got.entries.items[index - 1]; |
| 478 | 487 | break :blk last.cell_index + @as(Index, @intCast(last.len())); |
| 479 | 488 | } else 0; |
| 480 | entry.* = .{ .tag = undefined, .symbol_index = undefined, .cell_index = cell_index }; | |
| 489 | entry.* = .{ .tag = undefined, .ref = undefined, .cell_index = cell_index }; | |
| 481 | 490 | return index; |
| 482 | 491 | } |
| 483 | 492 | |
| 484 | pub fn addGotSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index { | |
| 493 | pub fn addGotSymbol(got: *GotSection, ref: Elf.Ref, elf_file: *Elf) !Index { | |
| 485 | 494 | const comp = elf_file.base.comp; |
| 486 | 495 | const gpa = comp.gpa; |
| 487 | 496 | const index = try got.allocateEntry(gpa); |
| 488 | 497 | const entry = &got.entries.items[index]; |
| 489 | 498 | entry.tag = .got; |
| 490 | entry.symbol_index = sym_index; | |
| 491 | const symbol = elf_file.symbol(sym_index); | |
| 499 | entry.ref = ref; | |
| 500 | const symbol = elf_file.symbol(ref).?; | |
| 492 | 501 | symbol.flags.has_got = true; |
| 493 | 502 | if (symbol.flags.import or symbol.isIFunc(elf_file) or |
| 494 | 503 | ((elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) and !symbol.isAbs(elf_file))) |
| 495 | 504 | { |
| 496 | 505 | got.flags.needs_rela = true; |
| 497 | 506 | } |
| 498 | try symbol.addExtra(.{ .got = index }, elf_file); | |
| 507 | symbol.addExtra(.{ .got = index }, elf_file); | |
| 499 | 508 | return index; |
| 500 | 509 | } |
| 501 | 510 | |
| ... | ... | @@ -506,48 +515,48 @@ pub const GotSection = struct { |
| 506 | 515 | const index = try got.allocateEntry(gpa); |
| 507 | 516 | const entry = &got.entries.items[index]; |
| 508 | 517 | entry.tag = .tlsld; |
| 509 | entry.symbol_index = undefined; // unused | |
| 518 | entry.ref = .{ .index = 0, .file = 0 }; // unused | |
| 510 | 519 | got.flags.needs_rela = true; |
| 511 | 520 | got.tlsld_index = index; |
| 512 | 521 | } |
| 513 | 522 | |
| 514 | pub fn addTlsGdSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !void { | |
| 523 | pub fn addTlsGdSymbol(got: *GotSection, ref: Elf.Ref, elf_file: *Elf) !void { | |
| 515 | 524 | const comp = elf_file.base.comp; |
| 516 | 525 | const gpa = comp.gpa; |
| 517 | 526 | const index = try got.allocateEntry(gpa); |
| 518 | 527 | const entry = &got.entries.items[index]; |
| 519 | 528 | entry.tag = .tlsgd; |
| 520 | entry.symbol_index = sym_index; | |
| 521 | const symbol = elf_file.symbol(sym_index); | |
| 529 | entry.ref = ref; | |
| 530 | const symbol = elf_file.symbol(ref).?; | |
| 522 | 531 | symbol.flags.has_tlsgd = true; |
| 523 | 532 | if (symbol.flags.import or elf_file.isEffectivelyDynLib()) got.flags.needs_rela = true; |
| 524 | try symbol.addExtra(.{ .tlsgd = index }, elf_file); | |
| 533 | symbol.addExtra(.{ .tlsgd = index }, elf_file); | |
| 525 | 534 | } |
| 526 | 535 | |
| 527 | pub fn addGotTpSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !void { | |
| 536 | pub fn addGotTpSymbol(got: *GotSection, ref: Elf.Ref, elf_file: *Elf) !void { | |
| 528 | 537 | const comp = elf_file.base.comp; |
| 529 | 538 | const gpa = comp.gpa; |
| 530 | 539 | const index = try got.allocateEntry(gpa); |
| 531 | 540 | const entry = &got.entries.items[index]; |
| 532 | 541 | entry.tag = .gottp; |
| 533 | entry.symbol_index = sym_index; | |
| 534 | const symbol = elf_file.symbol(sym_index); | |
| 542 | entry.ref = ref; | |
| 543 | const symbol = elf_file.symbol(ref).?; | |
| 535 | 544 | symbol.flags.has_gottp = true; |
| 536 | 545 | if (symbol.flags.import or elf_file.isEffectivelyDynLib()) got.flags.needs_rela = true; |
| 537 | try symbol.addExtra(.{ .gottp = index }, elf_file); | |
| 546 | symbol.addExtra(.{ .gottp = index }, elf_file); | |
| 538 | 547 | } |
| 539 | 548 | |
| 540 | pub fn addTlsDescSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !void { | |
| 549 | pub fn addTlsDescSymbol(got: *GotSection, ref: Elf.Ref, elf_file: *Elf) !void { | |
| 541 | 550 | const comp = elf_file.base.comp; |
| 542 | 551 | const gpa = comp.gpa; |
| 543 | 552 | const index = try got.allocateEntry(gpa); |
| 544 | 553 | const entry = &got.entries.items[index]; |
| 545 | 554 | entry.tag = .tlsdesc; |
| 546 | entry.symbol_index = sym_index; | |
| 547 | const symbol = elf_file.symbol(sym_index); | |
| 555 | entry.ref = ref; | |
| 556 | const symbol = elf_file.symbol(ref).?; | |
| 548 | 557 | symbol.flags.has_tlsdesc = true; |
| 549 | 558 | got.flags.needs_rela = true; |
| 550 | try symbol.addExtra(.{ .tlsdesc = index }, elf_file); | |
| 559 | symbol.addExtra(.{ .tlsdesc = index }, elf_file); | |
| 551 | 560 | } |
| 552 | 561 | |
| 553 | 562 | pub fn size(got: GotSection, elf_file: *Elf) usize { |
| ... | ... | @@ -564,10 +573,7 @@ pub const GotSection = struct { |
| 564 | 573 | const apply_relocs = true; // TODO add user option for this |
| 565 | 574 | |
| 566 | 575 | for (got.entries.items) |entry| { |
| 567 | const symbol = switch (entry.tag) { | |
| 568 | .tlsld => null, | |
| 569 | inline else => elf_file.symbol(entry.symbol_index), | |
| 570 | }; | |
| 576 | const symbol = elf_file.symbol(entry.ref); | |
| 571 | 577 | switch (entry.tag) { |
| 572 | 578 | .got => { |
| 573 | 579 | const value = blk: { |
| ... | ... | @@ -637,10 +643,7 @@ pub const GotSection = struct { |
| 637 | 643 | try elf_file.rela_dyn.ensureUnusedCapacity(gpa, got.numRela(elf_file)); |
| 638 | 644 | |
| 639 | 645 | for (got.entries.items) |entry| { |
| 640 | const symbol = switch (entry.tag) { | |
| 641 | .tlsld => null, | |
| 642 | inline else => elf_file.symbol(entry.symbol_index), | |
| 643 | }; | |
| 646 | const symbol = elf_file.symbol(entry.ref); | |
| 644 | 647 | const extra = if (symbol) |s| s.extra(elf_file) else null; |
| 645 | 648 | |
| 646 | 649 | switch (entry.tag) { |
| ... | ... | @@ -740,10 +743,7 @@ pub const GotSection = struct { |
| 740 | 743 | const is_dyn_lib = elf_file.isEffectivelyDynLib(); |
| 741 | 744 | var num: usize = 0; |
| 742 | 745 | for (got.entries.items) |entry| { |
| 743 | const symbol = switch (entry.tag) { | |
| 744 | .tlsld => null, | |
| 745 | inline else => elf_file.symbol(entry.symbol_index), | |
| 746 | }; | |
| 746 | const symbol = elf_file.symbol(entry.ref); | |
| 747 | 747 | switch (entry.tag) { |
| 748 | 748 | .got => if (symbol.?.flags.import or symbol.?.isIFunc(elf_file) or |
| 749 | 749 | ((elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) and |
| ... | ... | @@ -775,24 +775,15 @@ pub const GotSection = struct { |
| 775 | 775 | pub fn updateSymtabSize(got: *GotSection, elf_file: *Elf) void { |
| 776 | 776 | got.output_symtab_ctx.nlocals = @as(u32, @intCast(got.entries.items.len)); |
| 777 | 777 | for (got.entries.items) |entry| { |
| 778 | const symbol_name = switch (entry.tag) { | |
| 779 | .tlsld => "", | |
| 780 | inline else => elf_file.symbol(entry.symbol_index).name(elf_file), | |
| 781 | }; | |
| 778 | const symbol_name = if (elf_file.symbol(entry.ref)) |sym| sym.name(elf_file) else ""; | |
| 782 | 779 | got.output_symtab_ctx.strsize += @as(u32, @intCast(symbol_name.len + @tagName(entry.tag).len)) + 1 + 1; |
| 783 | 780 | } |
| 784 | 781 | } |
| 785 | 782 | |
| 786 | 783 | pub fn writeSymtab(got: GotSection, elf_file: *Elf) void { |
| 787 | 784 | for (got.entries.items, got.output_symtab_ctx.ilocal..) |entry, ilocal| { |
| 788 | const symbol = switch (entry.tag) { | |
| 789 | .tlsld => null, | |
| 790 | inline else => elf_file.symbol(entry.symbol_index), | |
| 791 | }; | |
| 792 | const symbol_name = switch (entry.tag) { | |
| 793 | .tlsld => "", | |
| 794 | inline else => symbol.?.name(elf_file), | |
| 795 | }; | |
| 785 | const symbol = elf_file.symbol(entry.ref); | |
| 786 | const symbol_name = if (symbol) |s| s.name(elf_file) else ""; | |
| 796 | 787 | const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); |
| 797 | 788 | elf_file.strtab.appendSliceAssumeCapacity(symbol_name); |
| 798 | 789 | elf_file.strtab.appendAssumeCapacity('$'); |
| ... | ... | @@ -828,36 +819,38 @@ pub const GotSection = struct { |
| 828 | 819 | ) !void { |
| 829 | 820 | _ = options; |
| 830 | 821 | _ = unused_fmt_string; |
| 822 | const got = ctx.got; | |
| 823 | const elf_file = ctx.elf_file; | |
| 831 | 824 | try writer.writeAll("GOT\n"); |
| 832 | for (ctx.got.entries.items) |entry| { | |
| 833 | const symbol = ctx.elf_file.symbol(entry.symbol_index); | |
| 834 | try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{ | |
| 825 | for (got.entries.items) |entry| { | |
| 826 | const symbol = elf_file.symbol(entry.ref).?; | |
| 827 | try writer.print(" {d}@0x{x} => {}@0x{x} ({s})\n", .{ | |
| 835 | 828 | entry.cell_index, |
| 836 | entry.address(ctx.elf_file), | |
| 837 | entry.symbol_index, | |
| 838 | symbol.address(.{}, ctx.elf_file), | |
| 839 | symbol.name(ctx.elf_file), | |
| 829 | entry.address(elf_file), | |
| 830 | entry.ref, | |
| 831 | symbol.address(.{}, elf_file), | |
| 832 | symbol.name(elf_file), | |
| 840 | 833 | }); |
| 841 | 834 | } |
| 842 | 835 | } |
| 843 | 836 | }; |
| 844 | 837 | |
| 845 | 838 | pub const PltSection = struct { |
| 846 | symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, | |
| 839 | symbols: std.ArrayListUnmanaged(Elf.Ref) = .{}, | |
| 847 | 840 | output_symtab_ctx: Elf.SymtabCtx = .{}, |
| 848 | 841 | |
| 849 | 842 | pub fn deinit(plt: *PltSection, allocator: Allocator) void { |
| 850 | 843 | plt.symbols.deinit(allocator); |
| 851 | 844 | } |
| 852 | 845 | |
| 853 | pub fn addSymbol(plt: *PltSection, sym_index: Symbol.Index, elf_file: *Elf) !void { | |
| 846 | pub fn addSymbol(plt: *PltSection, ref: Elf.Ref, elf_file: *Elf) !void { | |
| 854 | 847 | const comp = elf_file.base.comp; |
| 855 | 848 | const gpa = comp.gpa; |
| 856 | 849 | const index = @as(u32, @intCast(plt.symbols.items.len)); |
| 857 | const symbol = elf_file.symbol(sym_index); | |
| 850 | const symbol = elf_file.symbol(ref).?; | |
| 858 | 851 | symbol.flags.has_plt = true; |
| 859 | try symbol.addExtra(.{ .plt = index }, elf_file); | |
| 860 | try plt.symbols.append(gpa, sym_index); | |
| 852 | symbol.addExtra(.{ .plt = index }, elf_file); | |
| 853 | try plt.symbols.append(gpa, ref); | |
| 861 | 854 | } |
| 862 | 855 | |
| 863 | 856 | pub fn size(plt: PltSection, elf_file: *Elf) usize { |
| ... | ... | @@ -895,8 +888,8 @@ pub const PltSection = struct { |
| 895 | 888 | const gpa = comp.gpa; |
| 896 | 889 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 897 | 890 | try elf_file.rela_plt.ensureUnusedCapacity(gpa, plt.numRela()); |
| 898 | for (plt.symbols.items) |sym_index| { | |
| 899 | const sym = elf_file.symbol(sym_index); | |
| 891 | for (plt.symbols.items) |ref| { | |
| 892 | const sym = elf_file.symbol(ref).?; | |
| 900 | 893 | assert(sym.flags.import); |
| 901 | 894 | const extra = sym.extra(elf_file); |
| 902 | 895 | const r_offset: u64 = @intCast(sym.gotPltAddress(elf_file)); |
| ... | ... | @@ -916,16 +909,16 @@ pub const PltSection = struct { |
| 916 | 909 | |
| 917 | 910 | pub fn updateSymtabSize(plt: *PltSection, elf_file: *Elf) void { |
| 918 | 911 | plt.output_symtab_ctx.nlocals = @as(u32, @intCast(plt.symbols.items.len)); |
| 919 | for (plt.symbols.items) |sym_index| { | |
| 920 | const name = elf_file.symbol(sym_index).name(elf_file); | |
| 912 | for (plt.symbols.items) |ref| { | |
| 913 | const name = elf_file.symbol(ref).?.name(elf_file); | |
| 921 | 914 | plt.output_symtab_ctx.strsize += @as(u32, @intCast(name.len + "$plt".len)) + 1; |
| 922 | 915 | } |
| 923 | 916 | } |
| 924 | 917 | |
| 925 | 918 | pub fn writeSymtab(plt: PltSection, elf_file: *Elf) void { |
| 926 | 919 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 927 | for (plt.symbols.items, plt.output_symtab_ctx.ilocal..) |sym_index, ilocal| { | |
| 928 | const sym = elf_file.symbol(sym_index); | |
| 920 | for (plt.symbols.items, plt.output_symtab_ctx.ilocal..) |ref, ilocal| { | |
| 921 | const sym = elf_file.symbol(ref).?; | |
| 929 | 922 | const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); |
| 930 | 923 | elf_file.strtab.appendSliceAssumeCapacity(sym.name(elf_file)); |
| 931 | 924 | elf_file.strtab.appendSliceAssumeCapacity("$plt"); |
| ... | ... | @@ -958,15 +951,17 @@ pub const PltSection = struct { |
| 958 | 951 | ) !void { |
| 959 | 952 | _ = options; |
| 960 | 953 | _ = unused_fmt_string; |
| 954 | const plt = ctx.plt; | |
| 955 | const elf_file = ctx.elf_file; | |
| 961 | 956 | try writer.writeAll("PLT\n"); |
| 962 | for (ctx.plt.symbols.items, 0..) |symbol_index, i| { | |
| 963 | const symbol = ctx.elf_file.symbol(symbol_index); | |
| 964 | try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{ | |
| 957 | for (plt.symbols.items, 0..) |ref, i| { | |
| 958 | const symbol = elf_file.symbol(ref).?; | |
| 959 | try writer.print(" {d}@0x{x} => {}@0x{x} ({s})\n", .{ | |
| 965 | 960 | i, |
| 966 | symbol.pltAddress(ctx.elf_file), | |
| 967 | symbol_index, | |
| 968 | symbol.address(.{}, ctx.elf_file), | |
| 969 | symbol.name(ctx.elf_file), | |
| 961 | symbol.pltAddress(elf_file), | |
| 962 | ref, | |
| 963 | symbol.address(.{}, elf_file), | |
| 964 | symbol.name(elf_file), | |
| 970 | 965 | }); |
| 971 | 966 | } |
| 972 | 967 | } |
| ... | ... | @@ -988,8 +983,8 @@ pub const PltSection = struct { |
| 988 | 983 | try writer.writeAll(&preamble); |
| 989 | 984 | try writer.writeByteNTimes(0xcc, preambleSize(.x86_64) - preamble.len); |
| 990 | 985 | |
| 991 | for (plt.symbols.items, 0..) |sym_index, i| { | |
| 992 | const sym = elf_file.symbol(sym_index); | |
| 986 | for (plt.symbols.items, 0..) |ref, i| { | |
| 987 | const sym = elf_file.symbol(ref).?; | |
| 993 | 988 | const target_addr = sym.gotPltAddress(elf_file); |
| 994 | 989 | const source_addr = sym.pltAddress(elf_file); |
| 995 | 990 | disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 12)) - 4; |
| ... | ... | @@ -1037,8 +1032,8 @@ pub const PltSection = struct { |
| 1037 | 1032 | } |
| 1038 | 1033 | } |
| 1039 | 1034 | |
| 1040 | for (plt.symbols.items) |sym_index| { | |
| 1041 | const sym = elf_file.symbol(sym_index); | |
| 1035 | for (plt.symbols.items) |ref| { | |
| 1036 | const sym = elf_file.symbol(ref).?; | |
| 1042 | 1037 | const target_addr = sym.gotPltAddress(elf_file); |
| 1043 | 1038 | const source_addr = sym.pltAddress(elf_file); |
| 1044 | 1039 | const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr); |
| ... | ... | @@ -1075,7 +1070,7 @@ pub const GotPltSection = struct { |
| 1075 | 1070 | _ = got_plt; |
| 1076 | 1071 | { |
| 1077 | 1072 | // [0]: _DYNAMIC |
| 1078 | const symbol = elf_file.symbol(elf_file.linkerDefinedPtr().?.dynamic_index.?); | |
| 1073 | const symbol = elf_file.linkerDefinedPtr().?.dynamicSymbol(elf_file).?; | |
| 1079 | 1074 | try writer.writeInt(u64, @intCast(symbol.address(.{}, elf_file)), .little); |
| 1080 | 1075 | } |
| 1081 | 1076 | // [1]: 0x0 |
| ... | ... | @@ -1093,22 +1088,22 @@ pub const GotPltSection = struct { |
| 1093 | 1088 | }; |
| 1094 | 1089 | |
| 1095 | 1090 | pub const PltGotSection = struct { |
| 1096 | symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, | |
| 1091 | symbols: std.ArrayListUnmanaged(Elf.Ref) = .{}, | |
| 1097 | 1092 | output_symtab_ctx: Elf.SymtabCtx = .{}, |
| 1098 | 1093 | |
| 1099 | 1094 | pub fn deinit(plt_got: *PltGotSection, allocator: Allocator) void { |
| 1100 | 1095 | plt_got.symbols.deinit(allocator); |
| 1101 | 1096 | } |
| 1102 | 1097 | |
| 1103 | pub fn addSymbol(plt_got: *PltGotSection, sym_index: Symbol.Index, elf_file: *Elf) !void { | |
| 1098 | pub fn addSymbol(plt_got: *PltGotSection, ref: Elf.Ref, elf_file: *Elf) !void { | |
| 1104 | 1099 | const comp = elf_file.base.comp; |
| 1105 | 1100 | const gpa = comp.gpa; |
| 1106 | 1101 | const index = @as(u32, @intCast(plt_got.symbols.items.len)); |
| 1107 | const symbol = elf_file.symbol(sym_index); | |
| 1102 | const symbol = elf_file.symbol(ref).?; | |
| 1108 | 1103 | symbol.flags.has_plt = true; |
| 1109 | 1104 | symbol.flags.has_got = true; |
| 1110 | try symbol.addExtra(.{ .plt_got = index }, elf_file); | |
| 1111 | try plt_got.symbols.append(gpa, sym_index); | |
| 1105 | symbol.addExtra(.{ .plt_got = index }, elf_file); | |
| 1106 | try plt_got.symbols.append(gpa, ref); | |
| 1112 | 1107 | } |
| 1113 | 1108 | |
| 1114 | 1109 | pub fn size(plt_got: PltGotSection, elf_file: *Elf) usize { |
| ... | ... | @@ -1134,15 +1129,15 @@ pub const PltGotSection = struct { |
| 1134 | 1129 | |
| 1135 | 1130 | pub fn updateSymtabSize(plt_got: *PltGotSection, elf_file: *Elf) void { |
| 1136 | 1131 | plt_got.output_symtab_ctx.nlocals = @as(u32, @intCast(plt_got.symbols.items.len)); |
| 1137 | for (plt_got.symbols.items) |sym_index| { | |
| 1138 | const name = elf_file.symbol(sym_index).name(elf_file); | |
| 1132 | for (plt_got.symbols.items) |ref| { | |
| 1133 | const name = elf_file.symbol(ref).?.name(elf_file); | |
| 1139 | 1134 | plt_got.output_symtab_ctx.strsize += @as(u32, @intCast(name.len + "$pltgot".len)) + 1; |
| 1140 | 1135 | } |
| 1141 | 1136 | } |
| 1142 | 1137 | |
| 1143 | 1138 | pub fn writeSymtab(plt_got: PltGotSection, elf_file: *Elf) void { |
| 1144 | for (plt_got.symbols.items, plt_got.output_symtab_ctx.ilocal..) |sym_index, ilocal| { | |
| 1145 | const sym = elf_file.symbol(sym_index); | |
| 1139 | for (plt_got.symbols.items, plt_got.output_symtab_ctx.ilocal..) |ref, ilocal| { | |
| 1140 | const sym = elf_file.symbol(ref).?; | |
| 1146 | 1141 | const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); |
| 1147 | 1142 | elf_file.strtab.appendSliceAssumeCapacity(sym.name(elf_file)); |
| 1148 | 1143 | elf_file.strtab.appendSliceAssumeCapacity("$pltgot"); |
| ... | ... | @@ -1160,8 +1155,8 @@ pub const PltGotSection = struct { |
| 1160 | 1155 | |
| 1161 | 1156 | const x86_64 = struct { |
| 1162 | 1157 | pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void { |
| 1163 | for (plt_got.symbols.items) |sym_index| { | |
| 1164 | const sym = elf_file.symbol(sym_index); | |
| 1158 | for (plt_got.symbols.items) |ref| { | |
| 1159 | const sym = elf_file.symbol(ref).?; | |
| 1165 | 1160 | const target_addr = sym.gotAddress(elf_file); |
| 1166 | 1161 | const source_addr = sym.pltGotAddress(elf_file); |
| 1167 | 1162 | const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 6)) - 4; |
| ... | ... | @@ -1178,8 +1173,8 @@ pub const PltGotSection = struct { |
| 1178 | 1173 | |
| 1179 | 1174 | const aarch64 = struct { |
| 1180 | 1175 | fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void { |
| 1181 | for (plt_got.symbols.items) |sym_index| { | |
| 1182 | const sym = elf_file.symbol(sym_index); | |
| 1176 | for (plt_got.symbols.items) |ref| { | |
| 1177 | const sym = elf_file.symbol(ref).?; | |
| 1183 | 1178 | const target_addr = sym.gotAddress(elf_file); |
| 1184 | 1179 | const source_addr = sym.pltGotAddress(elf_file); |
| 1185 | 1180 | const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr); |
| ... | ... | @@ -1204,56 +1199,56 @@ pub const PltGotSection = struct { |
| 1204 | 1199 | }; |
| 1205 | 1200 | |
| 1206 | 1201 | pub const CopyRelSection = struct { |
| 1207 | symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, | |
| 1202 | symbols: std.ArrayListUnmanaged(Elf.Ref) = .{}, | |
| 1208 | 1203 | |
| 1209 | 1204 | pub fn deinit(copy_rel: *CopyRelSection, allocator: Allocator) void { |
| 1210 | 1205 | copy_rel.symbols.deinit(allocator); |
| 1211 | 1206 | } |
| 1212 | 1207 | |
| 1213 | pub fn addSymbol(copy_rel: *CopyRelSection, sym_index: Symbol.Index, elf_file: *Elf) !void { | |
| 1208 | pub fn addSymbol(copy_rel: *CopyRelSection, ref: Elf.Ref, elf_file: *Elf) !void { | |
| 1214 | 1209 | const comp = elf_file.base.comp; |
| 1215 | 1210 | const gpa = comp.gpa; |
| 1216 | 1211 | const index = @as(u32, @intCast(copy_rel.symbols.items.len)); |
| 1217 | const symbol = elf_file.symbol(sym_index); | |
| 1212 | const symbol = elf_file.symbol(ref).?; | |
| 1218 | 1213 | symbol.flags.import = true; |
| 1219 | 1214 | symbol.flags.@"export" = true; |
| 1220 | 1215 | symbol.flags.has_copy_rel = true; |
| 1221 | 1216 | symbol.flags.weak = false; |
| 1222 | try symbol.addExtra(.{ .copy_rel = index }, elf_file); | |
| 1223 | try copy_rel.symbols.append(gpa, sym_index); | |
| 1217 | symbol.addExtra(.{ .copy_rel = index }, elf_file); | |
| 1218 | try copy_rel.symbols.append(gpa, ref); | |
| 1224 | 1219 | |
| 1225 | 1220 | const shared_object = symbol.file(elf_file).?.shared_object; |
| 1226 | 1221 | if (shared_object.aliases == null) { |
| 1227 | 1222 | try shared_object.initSymbolAliases(elf_file); |
| 1228 | 1223 | } |
| 1229 | 1224 | |
| 1230 | const aliases = shared_object.symbolAliases(sym_index, elf_file); | |
| 1225 | const aliases = shared_object.symbolAliases(ref.index, elf_file); | |
| 1231 | 1226 | for (aliases) |alias| { |
| 1232 | if (alias == sym_index) continue; | |
| 1233 | const alias_sym = elf_file.symbol(alias); | |
| 1227 | if (alias == ref.index) continue; | |
| 1228 | const alias_sym = &shared_object.symbols.items[alias]; | |
| 1234 | 1229 | alias_sym.flags.import = true; |
| 1235 | 1230 | alias_sym.flags.@"export" = true; |
| 1236 | 1231 | alias_sym.flags.has_copy_rel = true; |
| 1237 | 1232 | alias_sym.flags.needs_copy_rel = true; |
| 1238 | 1233 | alias_sym.flags.weak = false; |
| 1239 | try elf_file.dynsym.addSymbol(alias, elf_file); | |
| 1234 | try elf_file.dynsym.addSymbol(.{ .index = alias, .file = shared_object.index }, elf_file); | |
| 1240 | 1235 | } |
| 1241 | 1236 | } |
| 1242 | 1237 | |
| 1243 | 1238 | pub fn updateSectionSize(copy_rel: CopyRelSection, shndx: u32, elf_file: *Elf) !void { |
| 1244 | 1239 | const shdr = &elf_file.shdrs.items[shndx]; |
| 1245 | for (copy_rel.symbols.items) |sym_index| { | |
| 1246 | const symbol = elf_file.symbol(sym_index); | |
| 1240 | for (copy_rel.symbols.items) |ref| { | |
| 1241 | const symbol = elf_file.symbol(ref).?; | |
| 1247 | 1242 | const shared_object = symbol.file(elf_file).?.shared_object; |
| 1248 | 1243 | const alignment = try symbol.dsoAlignment(elf_file); |
| 1249 | 1244 | symbol.value = @intCast(mem.alignForward(u64, shdr.sh_size, alignment)); |
| 1250 | 1245 | shdr.sh_addralign = @max(shdr.sh_addralign, alignment); |
| 1251 | 1246 | shdr.sh_size = @as(u64, @intCast(symbol.value)) + symbol.elfSym(elf_file).st_size; |
| 1252 | 1247 | |
| 1253 | const aliases = shared_object.symbolAliases(sym_index, elf_file); | |
| 1248 | const aliases = shared_object.symbolAliases(ref.index, elf_file); | |
| 1254 | 1249 | for (aliases) |alias| { |
| 1255 | if (alias == sym_index) continue; | |
| 1256 | const alias_sym = elf_file.symbol(alias); | |
| 1250 | if (alias == ref.index) continue; | |
| 1251 | const alias_sym = &shared_object.symbols.items[alias]; | |
| 1257 | 1252 | alias_sym.value = symbol.value; |
| 1258 | 1253 | } |
| 1259 | 1254 | } |
| ... | ... | @@ -1264,8 +1259,8 @@ pub const CopyRelSection = struct { |
| 1264 | 1259 | const gpa = comp.gpa; |
| 1265 | 1260 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 1266 | 1261 | try elf_file.rela_dyn.ensureUnusedCapacity(gpa, copy_rel.numRela()); |
| 1267 | for (copy_rel.symbols.items) |sym_index| { | |
| 1268 | const sym = elf_file.symbol(sym_index); | |
| 1262 | for (copy_rel.symbols.items) |ref| { | |
| 1263 | const sym = elf_file.symbol(ref).?; | |
| 1269 | 1264 | assert(sym.flags.import and sym.flags.has_copy_rel); |
| 1270 | 1265 | const extra = sym.extra(elf_file); |
| 1271 | 1266 | elf_file.addRelaDynAssumeCapacity(.{ |
| ... | ... | @@ -1285,8 +1280,8 @@ pub const DynsymSection = struct { |
| 1285 | 1280 | entries: std.ArrayListUnmanaged(Entry) = .{}, |
| 1286 | 1281 | |
| 1287 | 1282 | pub const Entry = struct { |
| 1288 | /// Index of the symbol which gets privilege of getting a dynamic treatment | |
| 1289 | symbol_index: Symbol.Index, | |
| 1283 | /// Ref of the symbol which gets privilege of getting a dynamic treatment | |
| 1284 | ref: Elf.Ref, | |
| 1290 | 1285 | /// Offset into .dynstrtab |
| 1291 | 1286 | off: u32, |
| 1292 | 1287 | }; |
| ... | ... | @@ -1295,22 +1290,22 @@ pub const DynsymSection = struct { |
| 1295 | 1290 | dynsym.entries.deinit(allocator); |
| 1296 | 1291 | } |
| 1297 | 1292 | |
| 1298 | pub fn addSymbol(dynsym: *DynsymSection, sym_index: Symbol.Index, elf_file: *Elf) !void { | |
| 1293 | pub fn addSymbol(dynsym: *DynsymSection, ref: Elf.Ref, elf_file: *Elf) !void { | |
| 1299 | 1294 | const comp = elf_file.base.comp; |
| 1300 | 1295 | const gpa = comp.gpa; |
| 1301 | 1296 | const index = @as(u32, @intCast(dynsym.entries.items.len + 1)); |
| 1302 | const sym = elf_file.symbol(sym_index); | |
| 1297 | const sym = elf_file.symbol(ref).?; | |
| 1303 | 1298 | sym.flags.has_dynamic = true; |
| 1304 | try sym.addExtra(.{ .dynamic = index }, elf_file); | |
| 1299 | sym.addExtra(.{ .dynamic = index }, elf_file); | |
| 1305 | 1300 | const off = try elf_file.insertDynString(sym.name(elf_file)); |
| 1306 | try dynsym.entries.append(gpa, .{ .symbol_index = sym_index, .off = off }); | |
| 1301 | try dynsym.entries.append(gpa, .{ .ref = ref, .off = off }); | |
| 1307 | 1302 | } |
| 1308 | 1303 | |
| 1309 | 1304 | pub fn sort(dynsym: *DynsymSection, elf_file: *Elf) void { |
| 1310 | 1305 | const Sort = struct { |
| 1311 | 1306 | pub fn lessThan(ctx: *Elf, lhs: Entry, rhs: Entry) bool { |
| 1312 | const lhs_sym = ctx.symbol(lhs.symbol_index); | |
| 1313 | const rhs_sym = ctx.symbol(rhs.symbol_index); | |
| 1307 | const lhs_sym = ctx.symbol(lhs.ref).?; | |
| 1308 | const rhs_sym = ctx.symbol(rhs.ref).?; | |
| 1314 | 1309 | |
| 1315 | 1310 | if (lhs_sym.flags.@"export" != rhs_sym.flags.@"export") { |
| 1316 | 1311 | return rhs_sym.flags.@"export"; |
| ... | ... | @@ -1329,7 +1324,7 @@ pub const DynsymSection = struct { |
| 1329 | 1324 | |
| 1330 | 1325 | var num_exports: u32 = 0; |
| 1331 | 1326 | for (dynsym.entries.items) |entry| { |
| 1332 | const sym = elf_file.symbol(entry.symbol_index); | |
| 1327 | const sym = elf_file.symbol(entry.ref).?; | |
| 1333 | 1328 | if (sym.flags.@"export") num_exports += 1; |
| 1334 | 1329 | } |
| 1335 | 1330 | |
| ... | ... | @@ -1338,7 +1333,7 @@ pub const DynsymSection = struct { |
| 1338 | 1333 | std.mem.sort(Entry, dynsym.entries.items, elf_file, Sort.lessThan); |
| 1339 | 1334 | |
| 1340 | 1335 | for (dynsym.entries.items, 1..) |entry, index| { |
| 1341 | const sym = elf_file.symbol(entry.symbol_index); | |
| 1336 | const sym = elf_file.symbol(entry.ref).?; | |
| 1342 | 1337 | var extra = sym.extra(elf_file); |
| 1343 | 1338 | extra.dynamic = @as(u32, @intCast(index)); |
| 1344 | 1339 | sym.setExtra(extra, elf_file); |
| ... | ... | @@ -1356,7 +1351,7 @@ pub const DynsymSection = struct { |
| 1356 | 1351 | pub fn write(dynsym: DynsymSection, elf_file: *Elf, writer: anytype) !void { |
| 1357 | 1352 | try writer.writeStruct(Elf.null_sym); |
| 1358 | 1353 | for (dynsym.entries.items) |entry| { |
| 1359 | const sym = elf_file.symbol(entry.symbol_index); | |
| 1354 | const sym = elf_file.symbol(entry.ref).?; | |
| 1360 | 1355 | var out_sym: elf.Elf64_Sym = Elf.null_sym; |
| 1361 | 1356 | sym.setOutputSym(elf_file, &out_sym); |
| 1362 | 1357 | out_sym.st_name = entry.off; |
| ... | ... | @@ -1429,7 +1424,7 @@ pub const GnuHashSection = struct { |
| 1429 | 1424 | |
| 1430 | 1425 | fn getExports(elf_file: *Elf) []const DynsymSection.Entry { |
| 1431 | 1426 | const start = for (elf_file.dynsym.entries.items, 0..) |entry, i| { |
| 1432 | const sym = elf_file.symbol(entry.symbol_index); | |
| 1427 | const sym = elf_file.symbol(entry.ref).?; | |
| 1433 | 1428 | if (sym.flags.@"export") break i; |
| 1434 | 1429 | } else elf_file.dynsym.entries.items.len; |
| 1435 | 1430 | return elf_file.dynsym.entries.items[start..]; |
| ... | ... | @@ -1477,7 +1472,7 @@ pub const GnuHashSection = struct { |
| 1477 | 1472 | @memset(bloom, 0); |
| 1478 | 1473 | |
| 1479 | 1474 | for (exports, 0..) |entry, i| { |
| 1480 | const sym = elf_file.symbol(entry.symbol_index); | |
| 1475 | const sym = elf_file.symbol(entry.ref).?; | |
| 1481 | 1476 | const h = hasher(sym.name(elf_file)); |
| 1482 | 1477 | hashes[i] = h; |
| 1483 | 1478 | indices[i] = h % hash.num_buckets; |
| ... | ... | @@ -1574,7 +1569,7 @@ pub const VerneedSection = struct { |
| 1574 | 1569 | try verneed.ensureTotalCapacity(dynsyms.len); |
| 1575 | 1570 | |
| 1576 | 1571 | for (dynsyms, 1..) |entry, i| { |
| 1577 | const symbol = elf_file.symbol(entry.symbol_index); | |
| 1572 | const symbol = elf_file.symbol(entry.ref).?; | |
| 1578 | 1573 | if (symbol.flags.import and symbol.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) { |
| 1579 | 1574 | const shared_object = symbol.file(elf_file).?.shared_object; |
| 1580 | 1575 | verneed.appendAssumeCapacity(.{ |
| ... | ... | @@ -1677,11 +1672,11 @@ pub const ComdatGroupSection = struct { |
| 1677 | 1672 | return cg_file.object.comdatGroup(cgs.cg_ref.index); |
| 1678 | 1673 | } |
| 1679 | 1674 | |
| 1680 | pub fn symbol(cgs: ComdatGroupSection, elf_file: *Elf) Symbol.Index { | |
| 1675 | pub fn symbol(cgs: ComdatGroupSection, elf_file: *Elf) *Symbol { | |
| 1681 | 1676 | const cg = cgs.comdatGroup(elf_file); |
| 1682 | 1677 | const object = cg.file(elf_file).object; |
| 1683 | 1678 | const shdr = object.shdrs.items[cg.shndx]; |
| 1684 | return object.symbols.items[shdr.sh_info]; | |
| 1679 | return &object.symbols.items[shdr.sh_info]; | |
| 1685 | 1680 | } |
| 1686 | 1681 | |
| 1687 | 1682 | pub fn size(cgs: ComdatGroupSection, elf_file: *Elf) usize { |
src/link/Elf/thunks.zig+16-24| ... | ... | @@ -43,11 +43,7 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void { |
| 43 | 43 | else => @panic("unsupported arch"), |
| 44 | 44 | }; |
| 45 | 45 | if (is_reachable) continue; |
| 46 | const target = switch (file) { | |
| 47 | .zig_object => |x| x.symbol(rel.r_sym()), | |
| 48 | .object => |x| x.symbols.items[rel.r_sym()], | |
| 49 | else => unreachable, | |
| 50 | }; | |
| 46 | const target = file.resolveSymbol(rel.r_sym(), elf_file); | |
| 51 | 47 | try thunk.symbols.put(gpa, target, {}); |
| 52 | 48 | } |
| 53 | 49 | atom.addExtra(.{ .thunk = thunk_index }, elf_file); |
| ... | ... | @@ -80,7 +76,7 @@ fn maxAllowedDistance(cpu_arch: std.Target.Cpu.Arch) u32 { |
| 80 | 76 | pub const Thunk = struct { |
| 81 | 77 | value: i64 = 0, |
| 82 | 78 | output_section_index: u32 = 0, |
| 83 | symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{}, | |
| 79 | symbols: std.AutoArrayHashMapUnmanaged(Elf.Ref, void) = .{}, | |
| 84 | 80 | output_symtab_ctx: Elf.SymtabCtx = .{}, |
| 85 | 81 | |
| 86 | 82 | pub fn deinit(thunk: *Thunk, allocator: Allocator) void { |
| ... | ... | @@ -97,9 +93,9 @@ pub const Thunk = struct { |
| 97 | 93 | return @as(i64, @intCast(shdr.sh_addr)) + thunk.value; |
| 98 | 94 | } |
| 99 | 95 | |
| 100 | pub fn targetAddress(thunk: Thunk, sym_index: Symbol.Index, elf_file: *Elf) i64 { | |
| 96 | pub fn targetAddress(thunk: Thunk, ref: Elf.Ref, elf_file: *Elf) i64 { | |
| 101 | 97 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 102 | return thunk.address(elf_file) + @as(i64, @intCast(thunk.symbols.getIndex(sym_index).? * trampolineSize(cpu_arch))); | |
| 98 | return thunk.address(elf_file) + @as(i64, @intCast(thunk.symbols.getIndex(ref).? * trampolineSize(cpu_arch))); | |
| 103 | 99 | } |
| 104 | 100 | |
| 105 | 101 | pub fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void { |
| ... | ... | @@ -112,16 +108,16 @@ pub const Thunk = struct { |
| 112 | 108 | |
| 113 | 109 | pub fn calcSymtabSize(thunk: *Thunk, elf_file: *Elf) void { |
| 114 | 110 | thunk.output_symtab_ctx.nlocals = @as(u32, @intCast(thunk.symbols.keys().len)); |
| 115 | for (thunk.symbols.keys()) |sym_index| { | |
| 116 | const sym = elf_file.symbol(sym_index); | |
| 111 | for (thunk.symbols.keys()) |ref| { | |
| 112 | const sym = elf_file.symbol(ref).?; | |
| 117 | 113 | thunk.output_symtab_ctx.strsize += @as(u32, @intCast(sym.name(elf_file).len + "$thunk".len + 1)); |
| 118 | 114 | } |
| 119 | 115 | } |
| 120 | 116 | |
| 121 | 117 | pub fn writeSymtab(thunk: Thunk, elf_file: *Elf) void { |
| 122 | 118 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 123 | for (thunk.symbols.keys(), thunk.output_symtab_ctx.ilocal..) |sym_index, ilocal| { | |
| 124 | const sym = elf_file.symbol(sym_index); | |
| 119 | for (thunk.symbols.keys(), thunk.output_symtab_ctx.ilocal..) |ref, ilocal| { | |
| 120 | const sym = elf_file.symbol(ref).?; | |
| 125 | 121 | const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); |
| 126 | 122 | elf_file.strtab.appendSliceAssumeCapacity(sym.name(elf_file)); |
| 127 | 123 | elf_file.strtab.appendSliceAssumeCapacity("$thunk"); |
| ... | ... | @@ -131,7 +127,7 @@ pub const Thunk = struct { |
| 131 | 127 | .st_info = elf.STT_FUNC, |
| 132 | 128 | .st_other = 0, |
| 133 | 129 | .st_shndx = @intCast(thunk.output_section_index), |
| 134 | .st_value = @intCast(thunk.targetAddress(sym_index, elf_file)), | |
| 130 | .st_value = @intCast(thunk.targetAddress(ref, elf_file)), | |
| 135 | 131 | .st_size = trampolineSize(cpu_arch), |
| 136 | 132 | }; |
| 137 | 133 | } |
| ... | ... | @@ -181,9 +177,9 @@ pub const Thunk = struct { |
| 181 | 177 | const thunk = ctx.thunk; |
| 182 | 178 | const elf_file = ctx.elf_file; |
| 183 | 179 | try writer.print("@{x} : size({x})\n", .{ thunk.value, thunk.size(elf_file) }); |
| 184 | for (thunk.symbols.keys()) |index| { | |
| 185 | const sym = elf_file.symbol(index); | |
| 186 | try writer.print(" %{d} : {s} : @{x}\n", .{ index, sym.name(elf_file), sym.value }); | |
| 180 | for (thunk.symbols.keys()) |ref| { | |
| 181 | const sym = elf_file.symbol(ref).?; | |
| 182 | try writer.print(" {} : {s} : @{x}\n", .{ ref, sym.name(elf_file), sym.value }); | |
| 187 | 183 | } |
| 188 | 184 | } |
| 189 | 185 | |
| ... | ... | @@ -195,12 +191,8 @@ const aarch64 = struct { |
| 195 | 191 | const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type()); |
| 196 | 192 | if (r_type != .CALL26 and r_type != .JUMP26) return true; |
| 197 | 193 | const file = atom.file(elf_file).?; |
| 198 | const target_index = switch (file) { | |
| 199 | .zig_object => |x| x.symbol(rel.r_sym()), | |
| 200 | .object => |x| x.symbols.items[rel.r_sym()], | |
| 201 | else => unreachable, | |
| 202 | }; | |
| 203 | const target = elf_file.symbol(target_index); | |
| 194 | const target_ref = file.resolveSymbol(rel.r_sym(), elf_file); | |
| 195 | const target = elf_file.symbol(target_ref).?; | |
| 204 | 196 | if (target.flags.has_plt) return false; |
| 205 | 197 | if (atom.output_section_index != target.output_section_index) return false; |
| 206 | 198 | const target_atom = target.atom(elf_file).?; |
| ... | ... | @@ -212,8 +204,8 @@ const aarch64 = struct { |
| 212 | 204 | } |
| 213 | 205 | |
| 214 | 206 | fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void { |
| 215 | for (thunk.symbols.keys(), 0..) |sym_index, i| { | |
| 216 | const sym = elf_file.symbol(sym_index); | |
| 207 | for (thunk.symbols.keys(), 0..) |ref, i| { | |
| 208 | const sym = elf_file.symbol(ref).?; | |
| 217 | 209 | const saddr = thunk.address(elf_file) + @as(i64, @intCast(i * trampoline_size)); |
| 218 | 210 | const taddr = sym.address(.{}, elf_file); |
| 219 | 211 | const pages = try util.calcNumberOfPages(saddr, taddr); |