| author | |
| committer | |
| log | cfe6ff4301d43ccd2739b2f4495e371211252afd |
| tree | 065a3fcfb21e8d3d986be2e5779a2ef43ee7ef78 |
| parent | b8705ed6527e779a140e8beccb48d424dbbdf856 |
| parent | b058545970efb6f533f9930d23af2a6d0c6ce9c3 |
| signature |
elf: move ownership of symbols into owning objects22 files changed, 1607 insertions(+), 1229 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+10-14| ... | ... | @@ -1409,14 +1409,14 @@ 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 | 1418 | |
| 1419 | try func.genSetReg(Type.u64, data_reg, .{ .lea_symbol = .{ .sym = sym.esym_index } }); | |
| 1419 | try func.genSetReg(Type.u64, data_reg, .{ .lea_symbol = .{ .sym = sym_index } }); | |
| 1420 | 1420 | |
| 1421 | 1421 | const cmp_reg, const cmp_lock = try func.allocReg(.int); |
| 1422 | 1422 | defer func.register_manager.unlockReg(cmp_lock); |
| ... | ... | @@ -4946,13 +4946,13 @@ fn genCall( |
| 4946 | 4946 | }) { |
| 4947 | 4947 | .func => |func_val| { |
| 4948 | 4948 | 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); | |
| 4949 | const zo = elf_file.zigObjectPtr().?; | |
| 4950 | const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func_val.owner_decl); | |
| 4951 | 4951 | |
| 4952 | 4952 | if (func.mod.pic) { |
| 4953 | 4953 | return func.fail("TODO: genCall pic", .{}); |
| 4954 | 4954 | } else { |
| 4955 | try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } }); | |
| 4955 | try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym_index } }); | |
| 4956 | 4956 | _ = try func.addInst(.{ |
| 4957 | 4957 | .tag = .jalr, |
| 4958 | 4958 | .data = .{ .i_type = .{ |
| ... | ... | @@ -7822,14 +7822,14 @@ fn airTagName(func: *Func, inst: Air.Inst.Index) !void { |
| 7822 | 7822 | |
| 7823 | 7823 | const lazy_sym = link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(zcu), zcu); |
| 7824 | 7824 | 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| | |
| 7825 | const zo = elf_file.zigObjectPtr().?; | |
| 7826 | const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err| | |
| 7826 | 7827 | return func.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 7827 | const sym = elf_file.symbol(sym_index); | |
| 7828 | 7828 | |
| 7829 | 7829 | if (func.mod.pic) { |
| 7830 | 7830 | return func.fail("TODO: airTagName pic", .{}); |
| 7831 | 7831 | } else { |
| 7832 | try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } }); | |
| 7832 | try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym_index } }); | |
| 7833 | 7833 | _ = try func.addInst(.{ |
| 7834 | 7834 | .tag = .jalr, |
| 7835 | 7835 | .data = .{ .i_type = .{ |
| ... | ... | @@ -8047,11 +8047,7 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue { |
| 8047 | 8047 | return error.CodegenFail; |
| 8048 | 8048 | }; |
| 8049 | 8049 | switch (lf.tag) { |
| 8050 | .elf => { | |
| 8051 | const elf_file = lf.cast(link.File.Elf).?; | |
| 8052 | const local = elf_file.symbol(local_sym_index); | |
| 8053 | return MCValue{ .undef = local.esym_index }; | |
| 8054 | }, | |
| 8050 | .elf => return MCValue{ .undef = local_sym_index }, | |
| 8055 | 8051 | else => unreachable, |
| 8056 | 8052 | } |
| 8057 | 8053 | } |
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+9-9| ... | ... | @@ -12327,8 +12327,8 @@ 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 | 12332 | if (self.mod.pic) { |
| 12333 | 12333 | const callee_reg: Register = switch (resolved_cc) { |
| 12334 | 12334 | .SysV => callee: { |
| ... | ... | @@ -12345,14 +12345,14 @@ fn genCall(self: *Self, info: union(enum) { |
| 12345 | 12345 | try self.genSetReg( |
| 12346 | 12346 | callee_reg, |
| 12347 | 12347 | Type.usize, |
| 12348 | .{ .load_symbol = .{ .sym = sym.esym_index } }, | |
| 12348 | .{ .load_symbol = .{ .sym = sym_index } }, | |
| 12349 | 12349 | .{}, |
| 12350 | 12350 | ); |
| 12351 | 12351 | try self.asmRegister(.{ ._, .call }, callee_reg); |
| 12352 | 12352 | } else try self.asmMemory(.{ ._, .call }, .{ |
| 12353 | 12353 | .base = .{ .reloc = .{ |
| 12354 | 12354 | .atom_index = try self.owner.getSymbolIndex(self), |
| 12355 | .sym_index = sym.esym_index, | |
| 12355 | .sym_index = sym_index, | |
| 12356 | 12356 | } }, |
| 12357 | 12357 | .mod = .{ .rm = .{ .size = .qword } }, |
| 12358 | 12358 | }); |
| ... | ... | @@ -15320,16 +15320,16 @@ fn genLazySymbolRef( |
| 15320 | 15320 | ) InnerError!void { |
| 15321 | 15321 | const pt = self.pt; |
| 15322 | 15322 | 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| | |
| 15323 | const zo = elf_file.zigObjectPtr().?; | |
| 15324 | const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err| | |
| 15324 | 15325 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 15325 | const sym = elf_file.symbol(sym_index); | |
| 15326 | 15326 | if (self.mod.pic) { |
| 15327 | 15327 | switch (tag) { |
| 15328 | 15328 | .lea, .call => try self.genSetReg(reg, Type.usize, .{ |
| 15329 | .load_symbol = .{ .sym = sym.esym_index }, | |
| 15329 | .load_symbol = .{ .sym = sym_index }, | |
| 15330 | 15330 | }, .{}), |
| 15331 | 15331 | .mov => try self.genSetReg(reg, Type.usize, .{ |
| 15332 | .load_symbol = .{ .sym = sym.esym_index }, | |
| 15332 | .load_symbol = .{ .sym = sym_index }, | |
| 15333 | 15333 | }, .{}), |
| 15334 | 15334 | else => unreachable, |
| 15335 | 15335 | } |
| ... | ... | @@ -15341,7 +15341,7 @@ fn genLazySymbolRef( |
| 15341 | 15341 | } else { |
| 15342 | 15342 | const reloc = bits.Symbol{ |
| 15343 | 15343 | .atom_index = try self.owner.getSymbolIndex(self), |
| 15344 | .sym_index = sym.esym_index, | |
| 15344 | .sym_index = sym_index, | |
| 15345 | 15345 | }; |
| 15346 | 15346 | switch (tag) { |
| 15347 | 15347 | .lea, .mov => try self.asmRegisterMemory(.{ ._, .mov }, reg.to64(), .{ |
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+186-249| ... | ... | @@ -173,12 +173,7 @@ shstrtab_section_index: ?u32 = null, |
| 173 | 173 | strtab_section_index: ?u32 = null, |
| 174 | 174 | symtab_section_index: ?u32 = null, |
| 175 | 175 | |
| 176 | /// An array of symbols parsed across all input files. | |
| 177 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, | |
| 178 | symbols_extra: std.ArrayListUnmanaged(u32) = .{}, | |
| 179 | symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{}, | |
| 180 | ||
| 181 | resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{}, | |
| 176 | resolver: SymbolResolver = .{}, | |
| 182 | 177 | |
| 183 | 178 | has_text_reloc: bool = false, |
| 184 | 179 | num_ifunc_dynrelocs: usize = 0, |
| ... | ... | @@ -192,10 +187,6 @@ merge_sections: std.ArrayListUnmanaged(MergeSection) = .{}, |
| 192 | 187 | /// Table of last atom index in a section and matching atom free list if any. |
| 193 | 188 | last_atom_and_free_list_table: LastAtomAndFreeListTable = .{}, |
| 194 | 189 | |
| 195 | /// Global string table used to provide quick access to global symbol resolvers | |
| 196 | /// such as `resolver`. | |
| 197 | strings: StringTable = .{}, | |
| 198 | ||
| 199 | 190 | first_eflags: ?elf.Elf64_Word = null, |
| 200 | 191 | |
| 201 | 192 | /// When allocating, the ideal_capacity is calculated by |
| ... | ... | @@ -341,10 +332,6 @@ pub fn createEmpty( |
| 341 | 332 | |
| 342 | 333 | const gpa = comp.gpa; |
| 343 | 334 | |
| 344 | // Index 0 is always a null symbol. | |
| 345 | try self.symbols.append(gpa, .{}); | |
| 346 | // Index 0 is always a null symbol. | |
| 347 | try self.symbols_extra.append(gpa, 0); | |
| 348 | 335 | // Append null file at index 0 |
| 349 | 336 | try self.files.append(gpa, .null); |
| 350 | 337 | // Append null byte to string tables |
| ... | ... | @@ -460,9 +447,6 @@ pub fn deinit(self: *Elf) void { |
| 460 | 447 | self.shstrtab.deinit(gpa); |
| 461 | 448 | self.symtab.deinit(gpa); |
| 462 | 449 | self.strtab.deinit(gpa); |
| 463 | self.symbols.deinit(gpa); | |
| 464 | self.symbols_extra.deinit(gpa); | |
| 465 | self.symbols_free_list.deinit(gpa); | |
| 466 | 450 | self.resolver.deinit(gpa); |
| 467 | 451 | |
| 468 | 452 | for (self.thunks.items) |*th| { |
| ... | ... | @@ -478,8 +462,6 @@ pub fn deinit(self: *Elf) void { |
| 478 | 462 | } |
| 479 | 463 | self.last_atom_and_free_list_table.deinit(gpa); |
| 480 | 464 | |
| 481 | self.strings.deinit(gpa); | |
| 482 | ||
| 483 | 465 | self.got.deinit(gpa); |
| 484 | 466 | self.plt.deinit(gpa); |
| 485 | 467 | self.plt_got.deinit(gpa); |
| ... | ... | @@ -1300,6 +1282,9 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 1300 | 1282 | try self.finalizeMergeSections(); |
| 1301 | 1283 | try self.initOutputSections(); |
| 1302 | 1284 | try self.initMergeSections(); |
| 1285 | if (self.linkerDefinedPtr()) |obj| { | |
| 1286 | try obj.initStartStopSymbols(self); | |
| 1287 | } | |
| 1303 | 1288 | self.claimUnresolved(); |
| 1304 | 1289 | |
| 1305 | 1290 | // Scan and create missing synthetic entries such as GOT indirection. |
| ... | ... | @@ -1922,20 +1907,17 @@ fn accessLibPath( |
| 1922 | 1907 | /// 6. Re-run symbol resolution on pruned objects and shared objects sets. |
| 1923 | 1908 | pub fn resolveSymbols(self: *Elf) !void { |
| 1924 | 1909 | // Resolve symbols in the ZigObject. For now, we assume that it's always live. |
| 1925 | if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resolveSymbols(self); | |
| 1910 | if (self.zigObjectPtr()) |zo| try zo.asFile().resolveSymbols(self); | |
| 1926 | 1911 | // Resolve symbols on the set of all objects and shared objects (even if some are unneeded). |
| 1927 | for (self.objects.items) |index| self.file(index).?.resolveSymbols(self); | |
| 1928 | for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self); | |
| 1929 | if (self.linkerDefinedPtr()) |obj| obj.asFile().resolveSymbols(self); | |
| 1912 | for (self.objects.items) |index| try self.file(index).?.resolveSymbols(self); | |
| 1913 | for (self.shared_objects.items) |index| try self.file(index).?.resolveSymbols(self); | |
| 1914 | if (self.linkerDefinedPtr()) |obj| try obj.asFile().resolveSymbols(self); | |
| 1930 | 1915 | |
| 1931 | 1916 | // Mark live objects. |
| 1932 | 1917 | self.markLive(); |
| 1933 | 1918 | |
| 1934 | 1919 | // Reset state of all globals after marking live objects. |
| 1935 | if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resetGlobals(self); | |
| 1936 | for (self.objects.items) |index| self.file(index).?.resetGlobals(self); | |
| 1937 | for (self.shared_objects.items) |index| self.file(index).?.resetGlobals(self); | |
| 1938 | if (self.linkerDefinedPtr()) |obj| obj.asFile().resetGlobals(self); | |
| 1920 | self.resolver.reset(); | |
| 1939 | 1921 | |
| 1940 | 1922 | // Prune dead objects and shared objects. |
| 1941 | 1923 | var i: usize = 0; |
| ... | ... | @@ -1968,10 +1950,10 @@ pub fn resolveSymbols(self: *Elf) !void { |
| 1968 | 1950 | } |
| 1969 | 1951 | |
| 1970 | 1952 | // Re-resolve the symbols. |
| 1971 | if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resolveSymbols(self); | |
| 1972 | for (self.objects.items) |index| self.file(index).?.resolveSymbols(self); | |
| 1973 | for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self); | |
| 1974 | if (self.linkerDefinedPtr()) |obj| obj.asFile().resolveSymbols(self); | |
| 1953 | if (self.zigObjectPtr()) |zo| try zo.asFile().resolveSymbols(self); | |
| 1954 | for (self.objects.items) |index| try self.file(index).?.resolveSymbols(self); | |
| 1955 | for (self.shared_objects.items) |index| try self.file(index).?.resolveSymbols(self); | |
| 1956 | if (self.linkerDefinedPtr()) |obj| try obj.asFile().resolveSymbols(self); | |
| 1975 | 1957 | } |
| 1976 | 1958 | |
| 1977 | 1959 | /// Traverses all objects and shared objects marking any object referenced by |
| ... | ... | @@ -2005,46 +1987,17 @@ fn convertCommonSymbols(self: *Elf) !void { |
| 2005 | 1987 | } |
| 2006 | 1988 | |
| 2007 | 1989 | fn markImportsExports(self: *Elf) void { |
| 2008 | const mark = struct { | |
| 2009 | fn mark(elf_file: *Elf, file_index: File.Index) void { | |
| 2010 | for (elf_file.file(file_index).?.globals()) |global_index| { | |
| 2011 | const global = elf_file.symbol(global_index); | |
| 2012 | if (global.version_index == elf.VER_NDX_LOCAL) continue; | |
| 2013 | const file_ptr = global.file(elf_file) orelse continue; | |
| 2014 | const vis = @as(elf.STV, @enumFromInt(global.elfSym(elf_file).st_other)); | |
| 2015 | if (vis == .HIDDEN) continue; | |
| 2016 | if (file_ptr == .shared_object and !global.isAbs(elf_file)) { | |
| 2017 | global.flags.import = true; | |
| 2018 | continue; | |
| 2019 | } | |
| 2020 | if (file_ptr.index() == file_index) { | |
| 2021 | global.flags.@"export" = true; | |
| 2022 | if (elf_file.isEffectivelyDynLib() and vis != .PROTECTED) { | |
| 2023 | global.flags.import = true; | |
| 2024 | } | |
| 2025 | } | |
| 2026 | } | |
| 2027 | } | |
| 2028 | }.mark; | |
| 2029 | ||
| 1990 | if (self.zigObjectPtr()) |zo| { | |
| 1991 | zo.markImportsExports(self); | |
| 1992 | } | |
| 1993 | for (self.objects.items) |index| { | |
| 1994 | self.file(index).?.object.markImportsExports(self); | |
| 1995 | } | |
| 2030 | 1996 | if (!self.isEffectivelyDynLib()) { |
| 2031 | 1997 | for (self.shared_objects.items) |index| { |
| 2032 | for (self.file(index).?.globals()) |global_index| { | |
| 2033 | const global = self.symbol(global_index); | |
| 2034 | const file_ptr = global.file(self) orelse continue; | |
| 2035 | const vis = @as(elf.STV, @enumFromInt(global.elfSym(self).st_other)); | |
| 2036 | if (file_ptr != .shared_object and vis != .HIDDEN) global.flags.@"export" = true; | |
| 2037 | } | |
| 1998 | self.file(index).?.shared_object.markImportExports(self); | |
| 2038 | 1999 | } |
| 2039 | 2000 | } |
| 2040 | ||
| 2041 | if (self.zig_object_index) |index| { | |
| 2042 | mark(self, index); | |
| 2043 | } | |
| 2044 | ||
| 2045 | for (self.objects.items) |index| { | |
| 2046 | mark(self, index); | |
| 2047 | } | |
| 2048 | 2001 | } |
| 2049 | 2002 | |
| 2050 | 2003 | fn claimUnresolved(self: *Elf) void { |
| ... | ... | @@ -2063,22 +2016,27 @@ fn claimUnresolved(self: *Elf) void { |
| 2063 | 2016 | fn scanRelocs(self: *Elf) !void { |
| 2064 | 2017 | const gpa = self.base.comp.gpa; |
| 2065 | 2018 | |
| 2066 | var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Ref)).init(gpa); | |
| 2019 | var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa); | |
| 2067 | 2020 | defer { |
| 2068 | var it = undefs.iterator(); | |
| 2069 | while (it.next()) |entry| { | |
| 2070 | entry.value_ptr.deinit(); | |
| 2021 | for (undefs.values()) |*refs| { | |
| 2022 | refs.deinit(); | |
| 2071 | 2023 | } |
| 2072 | 2024 | undefs.deinit(); |
| 2073 | 2025 | } |
| 2074 | 2026 | |
| 2075 | var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1); | |
| 2076 | defer objects.deinit(); | |
| 2077 | if (self.zigObjectPtr()) |zo| objects.appendAssumeCapacity(zo.index); | |
| 2078 | objects.appendSliceAssumeCapacity(self.objects.items); | |
| 2079 | ||
| 2080 | 2027 | var has_reloc_errors = false; |
| 2081 | for (objects.items) |index| { | |
| 2028 | if (self.zigObjectPtr()) |zo| { | |
| 2029 | zo.asFile().scanRelocs(self, &undefs) catch |err| switch (err) { | |
| 2030 | error.RelaxFailure => unreachable, | |
| 2031 | error.UnsupportedCpuArch => { | |
| 2032 | try self.reportUnsupportedCpuArch(); | |
| 2033 | return error.FlushFailure; | |
| 2034 | }, | |
| 2035 | error.RelocFailure => has_reloc_errors = true, | |
| 2036 | else => |e| return e, | |
| 2037 | }; | |
| 2038 | } | |
| 2039 | for (self.objects.items) |index| { | |
| 2082 | 2040 | self.file(index).?.scanRelocs(self, &undefs) catch |err| switch (err) { |
| 2083 | 2041 | error.RelaxFailure => unreachable, |
| 2084 | 2042 | error.UnsupportedCpuArch => { |
| ... | ... | @@ -2094,47 +2052,18 @@ fn scanRelocs(self: *Elf) !void { |
| 2094 | 2052 | |
| 2095 | 2053 | if (has_reloc_errors) return error.FlushFailure; |
| 2096 | 2054 | |
| 2097 | for (self.symbols.items, 0..) |*sym, i| { | |
| 2098 | const index = @as(u32, @intCast(i)); | |
| 2099 | if (!sym.isLocal(self) and !sym.flags.has_dynamic) { | |
| 2100 | log.debug("'{s}' is non-local", .{sym.name(self)}); | |
| 2101 | try self.dynsym.addSymbol(index, self); | |
| 2102 | } | |
| 2103 | if (sym.flags.needs_got) { | |
| 2104 | log.debug("'{s}' needs GOT", .{sym.name(self)}); | |
| 2105 | _ = try self.got.addGotSymbol(index, self); | |
| 2106 | } | |
| 2107 | if (sym.flags.needs_plt) { | |
| 2108 | if (sym.flags.is_canonical) { | |
| 2109 | log.debug("'{s}' needs CPLT", .{sym.name(self)}); | |
| 2110 | sym.flags.@"export" = true; | |
| 2111 | try self.plt.addSymbol(index, self); | |
| 2112 | } else if (sym.flags.needs_got) { | |
| 2113 | log.debug("'{s}' needs PLTGOT", .{sym.name(self)}); | |
| 2114 | try self.plt_got.addSymbol(index, self); | |
| 2115 | } else { | |
| 2116 | log.debug("'{s}' needs PLT", .{sym.name(self)}); | |
| 2117 | try self.plt.addSymbol(index, self); | |
| 2118 | } | |
| 2119 | } | |
| 2120 | if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) { | |
| 2121 | log.debug("'{s}' needs COPYREL", .{sym.name(self)}); | |
| 2122 | try self.copy_rel.addSymbol(index, self); | |
| 2123 | } | |
| 2124 | if (sym.flags.needs_tlsgd) { | |
| 2125 | log.debug("'{s}' needs TLSGD", .{sym.name(self)}); | |
| 2126 | try self.got.addTlsGdSymbol(index, self); | |
| 2127 | } | |
| 2128 | if (sym.flags.needs_gottp) { | |
| 2129 | log.debug("'{s}' needs GOTTP", .{sym.name(self)}); | |
| 2130 | try self.got.addGotTpSymbol(index, self); | |
| 2131 | } | |
| 2132 | if (sym.flags.needs_tlsdesc) { | |
| 2133 | log.debug("'{s}' needs TLSDESC", .{sym.name(self)}); | |
| 2134 | try self.got.addTlsDescSymbol(index, self); | |
| 2135 | } | |
| 2055 | if (self.zigObjectPtr()) |zo| { | |
| 2056 | try zo.asFile().createSymbolIndirection(self); | |
| 2057 | } | |
| 2058 | for (self.objects.items) |index| { | |
| 2059 | try self.file(index).?.createSymbolIndirection(self); | |
| 2060 | } | |
| 2061 | for (self.shared_objects.items) |index| { | |
| 2062 | try self.file(index).?.createSymbolIndirection(self); | |
| 2063 | } | |
| 2064 | if (self.linkerDefinedPtr()) |obj| { | |
| 2065 | try obj.asFile().createSymbolIndirection(self); | |
| 2136 | 2066 | } |
| 2137 | ||
| 2138 | 2067 | if (self.got.flags.needs_tlsld) { |
| 2139 | 2068 | log.debug("program needs TLSLD", .{}); |
| 2140 | 2069 | try self.got.addTlsLdSymbol(self); |
| ... | ... | @@ -2911,8 +2840,8 @@ pub fn writeElfHeader(self: *Elf) !void { |
| 2911 | 2840 | index += 4; |
| 2912 | 2841 | |
| 2913 | 2842 | const e_entry: u64 = if (self.linkerDefinedPtr()) |obj| blk: { |
| 2914 | const entry_index = obj.entry_index orelse break :blk 0; | |
| 2915 | break :blk @intCast(self.symbol(entry_index).address(.{}, self)); | |
| 2843 | const entry_sym = obj.entrySymbol(self) orelse break :blk 0; | |
| 2844 | break :blk @intCast(entry_sym.address(.{}, self)); | |
| 2916 | 2845 | } else 0; |
| 2917 | 2846 | const phdr_table_offset = if (self.phdr_table_index) |phndx| self.phdrs.items[phndx].p_offset else 0; |
| 2918 | 2847 | switch (self.ptr_width) { |
| ... | ... | @@ -3043,7 +2972,7 @@ pub fn deleteExport( |
| 3043 | 2972 | fn checkDuplicates(self: *Elf) !void { |
| 3044 | 2973 | const gpa = self.base.comp.gpa; |
| 3045 | 2974 | |
| 3046 | var dupes = std.AutoArrayHashMap(Symbol.Index, std.ArrayListUnmanaged(File.Index)).init(gpa); | |
| 2975 | var dupes = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayListUnmanaged(File.Index)).init(gpa); | |
| 3047 | 2976 | defer { |
| 3048 | 2977 | for (dupes.values()) |*list| { |
| 3049 | 2978 | list.deinit(gpa); |
| ... | ... | @@ -3351,7 +3280,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3351 | 3280 | }); |
| 3352 | 3281 | |
| 3353 | 3282 | const needs_versions = for (self.dynsym.entries.items) |entry| { |
| 3354 | const sym = self.symbol(entry.symbol_index); | |
| 3283 | const sym = self.symbol(entry.ref).?; | |
| 3355 | 3284 | if (sym.flags.import and sym.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) break true; |
| 3356 | 3285 | } else false; |
| 3357 | 3286 | if (needs_versions) { |
| ... | ... | @@ -3565,7 +3494,7 @@ fn setVersionSymtab(self: *Elf) !void { |
| 3565 | 3494 | try self.versym.resize(gpa, self.dynsym.count()); |
| 3566 | 3495 | self.versym.items[0] = elf.VER_NDX_LOCAL; |
| 3567 | 3496 | for (self.dynsym.entries.items, 1..) |entry, i| { |
| 3568 | const sym = self.symbol(entry.symbol_index); | |
| 3497 | const sym = self.symbol(entry.ref).?; | |
| 3569 | 3498 | self.versym.items[i] = sym.version_index; |
| 3570 | 3499 | } |
| 3571 | 3500 | |
| ... | ... | @@ -4357,11 +4286,10 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 4357 | 4286 | fn writeAtoms(self: *Elf) !void { |
| 4358 | 4287 | const gpa = self.base.comp.gpa; |
| 4359 | 4288 | |
| 4360 | var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Ref)).init(gpa); | |
| 4289 | var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa); | |
| 4361 | 4290 | defer { |
| 4362 | var it = undefs.iterator(); | |
| 4363 | while (it.next()) |entry| { | |
| 4364 | entry.value_ptr.deinit(); | |
| 4291 | for (undefs.values()) |*refs| { | |
| 4292 | refs.deinit(); | |
| 4365 | 4293 | } |
| 4366 | 4294 | undefs.deinit(); |
| 4367 | 4295 | } |
| ... | ... | @@ -4507,11 +4435,13 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4507 | 4435 | strsize += ctx.strsize; |
| 4508 | 4436 | } |
| 4509 | 4437 | |
| 4510 | if (self.zig_got_section_index) |_| { | |
| 4511 | self.zig_got.output_symtab_ctx.ilocal = nlocals + 1; | |
| 4512 | self.zig_got.updateSymtabSize(self); | |
| 4513 | nlocals += self.zig_got.output_symtab_ctx.nlocals; | |
| 4514 | strsize += self.zig_got.output_symtab_ctx.strsize; | |
| 4438 | if (self.zigObjectPtr()) |_| { | |
| 4439 | if (self.zig_got_section_index) |_| { | |
| 4440 | self.zig_got.output_symtab_ctx.ilocal = nlocals + 1; | |
| 4441 | self.zig_got.updateSymtabSize(self); | |
| 4442 | nlocals += self.zig_got.output_symtab_ctx.nlocals; | |
| 4443 | strsize += self.zig_got.output_symtab_ctx.strsize; | |
| 4444 | } | |
| 4515 | 4445 | } |
| 4516 | 4446 | |
| 4517 | 4447 | if (self.got_section_index) |_| { |
| ... | ... | @@ -4650,7 +4580,9 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4650 | 4580 | const shdr = self.shdrs.items[shndx]; |
| 4651 | 4581 | try self.got.addRela(self); |
| 4652 | 4582 | try self.copy_rel.addRela(self); |
| 4653 | try self.zig_got.addRela(self); | |
| 4583 | if (self.zigObjectPtr()) |_| { | |
| 4584 | try self.zig_got.addRela(self); | |
| 4585 | } | |
| 4654 | 4586 | self.sortRelaDyn(); |
| 4655 | 4587 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_dyn.items), shdr.sh_offset); |
| 4656 | 4588 | } |
| ... | ... | @@ -5311,13 +5243,21 @@ pub fn calcNumIRelativeRelocs(self: *Elf) usize { |
| 5311 | 5243 | |
| 5312 | 5244 | for (self.got.entries.items) |entry| { |
| 5313 | 5245 | if (entry.tag != .got) continue; |
| 5314 | const sym = self.symbol(entry.symbol_index); | |
| 5246 | const sym = self.symbol(entry.ref).?; | |
| 5315 | 5247 | if (sym.isIFunc(self)) count += 1; |
| 5316 | 5248 | } |
| 5317 | 5249 | |
| 5318 | 5250 | return count; |
| 5319 | 5251 | } |
| 5320 | 5252 | |
| 5253 | pub fn getStartStopBasename(self: Elf, shdr: elf.Elf64_Shdr) ?[]const u8 { | |
| 5254 | const name = self.getShString(shdr.sh_name); | |
| 5255 | if (shdr.sh_flags & elf.SHF_ALLOC != 0 and name.len > 0) { | |
| 5256 | if (Elf.isCIdentifier(name)) return name; | |
| 5257 | } | |
| 5258 | return null; | |
| 5259 | } | |
| 5260 | ||
| 5321 | 5261 | pub fn isCIdentifier(name: []const u8) bool { |
| 5322 | 5262 | if (name.len == 0) return false; |
| 5323 | 5263 | const first_c = name[0]; |
| ... | ... | @@ -5328,14 +5268,6 @@ pub fn isCIdentifier(name: []const u8) bool { |
| 5328 | 5268 | return true; |
| 5329 | 5269 | } |
| 5330 | 5270 | |
| 5331 | pub fn getStartStopBasename(self: *Elf, shdr: elf.Elf64_Shdr) ?[]const u8 { | |
| 5332 | const name = self.getShString(shdr.sh_name); | |
| 5333 | if (shdr.sh_flags & elf.SHF_ALLOC != 0 and name.len > 0) { | |
| 5334 | if (isCIdentifier(name)) return name; | |
| 5335 | } | |
| 5336 | return null; | |
| 5337 | } | |
| 5338 | ||
| 5339 | 5271 | pub fn addThunk(self: *Elf) !Thunk.Index { |
| 5340 | 5272 | const index = @as(Thunk.Index, @intCast(self.thunks.items.len)); |
| 5341 | 5273 | const th = try self.thunks.addOne(self.base.comp.gpa); |
| ... | ... | @@ -5381,95 +5313,9 @@ pub fn comdatGroup(self: *Elf, ref: Ref) *ComdatGroup { |
| 5381 | 5313 | return self.file(ref.file).?.comdatGroup(ref.index); |
| 5382 | 5314 | } |
| 5383 | 5315 | |
| 5384 | /// Returns pointer-to-symbol described at sym_index. | |
| 5385 | pub fn symbol(self: *Elf, sym_index: Symbol.Index) *Symbol { | |
| 5386 | return &self.symbols.items[sym_index]; | |
| 5387 | } | |
| 5388 | ||
| 5389 | pub fn addSymbol(self: *Elf) !Symbol.Index { | |
| 5390 | const gpa = self.base.comp.gpa; | |
| 5391 | try self.symbols.ensureUnusedCapacity(gpa, 1); | |
| 5392 | const index = blk: { | |
| 5393 | if (self.symbols_free_list.popOrNull()) |index| { | |
| 5394 | log.debug(" (reusing symbol index {d})", .{index}); | |
| 5395 | break :blk index; | |
| 5396 | } else { | |
| 5397 | log.debug(" (allocating symbol index {d})", .{self.symbols.items.len}); | |
| 5398 | const index: Symbol.Index = @intCast(self.symbols.items.len); | |
| 5399 | _ = self.symbols.addOneAssumeCapacity(); | |
| 5400 | break :blk index; | |
| 5401 | } | |
| 5402 | }; | |
| 5403 | self.symbols.items[index] = .{}; | |
| 5404 | return index; | |
| 5405 | } | |
| 5406 | ||
| 5407 | pub fn addSymbolExtra(self: *Elf, extra: Symbol.Extra) !u32 { | |
| 5408 | const gpa = self.base.comp.gpa; | |
| 5409 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 5410 | try self.symbols_extra.ensureUnusedCapacity(gpa, fields.len); | |
| 5411 | return self.addSymbolExtraAssumeCapacity(extra); | |
| 5412 | } | |
| 5413 | ||
| 5414 | pub fn addSymbolExtraAssumeCapacity(self: *Elf, extra: Symbol.Extra) u32 { | |
| 5415 | const index = @as(u32, @intCast(self.symbols_extra.items.len)); | |
| 5416 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 5417 | inline for (fields) |field| { | |
| 5418 | self.symbols_extra.appendAssumeCapacity(switch (field.type) { | |
| 5419 | u32 => @field(extra, field.name), | |
| 5420 | else => @compileError("bad field type"), | |
| 5421 | }); | |
| 5422 | } | |
| 5423 | return index; | |
| 5424 | } | |
| 5425 | ||
| 5426 | pub fn symbolExtra(self: *Elf, index: u32) ?Symbol.Extra { | |
| 5427 | if (index == 0) return null; | |
| 5428 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 5429 | var i: usize = index; | |
| 5430 | var result: Symbol.Extra = undefined; | |
| 5431 | inline for (fields) |field| { | |
| 5432 | @field(result, field.name) = switch (field.type) { | |
| 5433 | u32 => self.symbols_extra.items[i], | |
| 5434 | else => @compileError("bad field type"), | |
| 5435 | }; | |
| 5436 | i += 1; | |
| 5437 | } | |
| 5438 | return result; | |
| 5439 | } | |
| 5440 | ||
| 5441 | pub fn setSymbolExtra(self: *Elf, index: u32, extra: Symbol.Extra) void { | |
| 5442 | assert(index > 0); | |
| 5443 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 5444 | inline for (fields, 0..) |field, i| { | |
| 5445 | self.symbols_extra.items[index + i] = switch (field.type) { | |
| 5446 | u32 => @field(extra, field.name), | |
| 5447 | else => @compileError("bad field type"), | |
| 5448 | }; | |
| 5449 | } | |
| 5450 | } | |
| 5451 | ||
| 5452 | const GetOrPutGlobalResult = struct { | |
| 5453 | found_existing: bool, | |
| 5454 | index: Symbol.Index, | |
| 5455 | }; | |
| 5456 | ||
| 5457 | pub fn getOrPutGlobal(self: *Elf, name: []const u8) !GetOrPutGlobalResult { | |
| 5458 | const gpa = self.base.comp.gpa; | |
| 5459 | const name_off = try self.strings.insert(gpa, name); | |
| 5460 | const gop = try self.resolver.getOrPut(gpa, name_off); | |
| 5461 | if (!gop.found_existing) { | |
| 5462 | const index = try self.addSymbol(); | |
| 5463 | log.debug("added symbol '{s}' at index {d}", .{ name, index }); | |
| 5464 | const global = self.symbol(index); | |
| 5465 | global.name_offset = name_off; | |
| 5466 | global.flags.global = true; | |
| 5467 | gop.value_ptr.* = index; | |
| 5468 | } | |
| 5469 | return .{ | |
| 5470 | .found_existing = gop.found_existing, | |
| 5471 | .index = gop.value_ptr.*, | |
| 5472 | }; | |
| 5316 | pub fn symbol(self: *Elf, ref: Ref) ?*Symbol { | |
| 5317 | const file_ptr = self.file(ref.file) orelse return null; | |
| 5318 | return file_ptr.symbol(ref.index); | |
| 5473 | 5319 | } |
| 5474 | 5320 | |
| 5475 | 5321 | pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 { |
| ... | ... | @@ -5579,36 +5425,34 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { |
| 5579 | 5425 | |
| 5580 | 5426 | try self.base.comp.link_errors.ensureUnusedCapacity(gpa, undefs.count()); |
| 5581 | 5427 | |
| 5582 | var it = undefs.iterator(); | |
| 5583 | while (it.next()) |entry| { | |
| 5584 | const undef_index = entry.key_ptr.*; | |
| 5585 | const atoms = entry.value_ptr.*.items; | |
| 5586 | const natoms = @min(atoms.len, max_notes); | |
| 5587 | const nnotes = natoms + @intFromBool(atoms.len > max_notes); | |
| 5428 | for (undefs.keys(), undefs.values()) |key, refs| { | |
| 5429 | const undef_sym = self.resolver.keys.items[key - 1]; | |
| 5430 | const nrefs = @min(refs.items.len, max_notes); | |
| 5431 | const nnotes = nrefs + @intFromBool(refs.items.len > max_notes); | |
| 5588 | 5432 | |
| 5589 | 5433 | var err = try self.base.addErrorWithNotesAssumeCapacity(nnotes); |
| 5590 | try err.addMsg("undefined symbol: {s}", .{self.symbol(undef_index).name(self)}); | |
| 5434 | try err.addMsg("undefined symbol: {s}", .{undef_sym.name(self)}); | |
| 5591 | 5435 | |
| 5592 | for (atoms[0..natoms]) |ref| { | |
| 5436 | for (refs.items[0..nrefs]) |ref| { | |
| 5593 | 5437 | const atom_ptr = self.atom(ref).?; |
| 5594 | const file_ptr = self.file(ref.file).?; | |
| 5438 | const file_ptr = atom_ptr.file(self).?; | |
| 5595 | 5439 | try err.addNote("referenced by {s}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) }); |
| 5596 | 5440 | } |
| 5597 | 5441 | |
| 5598 | if (atoms.len > max_notes) { | |
| 5599 | const remaining = atoms.len - max_notes; | |
| 5442 | if (refs.items.len > max_notes) { | |
| 5443 | const remaining = refs.items.len - max_notes; | |
| 5600 | 5444 | try err.addNote("referenced {d} more times", .{remaining}); |
| 5601 | 5445 | } |
| 5602 | 5446 | } |
| 5603 | 5447 | } |
| 5604 | 5448 | |
| 5605 | 5449 | fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemory }!void { |
| 5450 | if (dupes.keys().len == 0) return; // Nothing to do | |
| 5451 | ||
| 5606 | 5452 | const max_notes = 3; |
| 5607 | var has_dupes = false; | |
| 5608 | var it = dupes.iterator(); | |
| 5609 | while (it.next()) |entry| { | |
| 5610 | const sym = self.symbol(entry.key_ptr.*); | |
| 5611 | const notes = entry.value_ptr.*; | |
| 5453 | ||
| 5454 | for (dupes.keys(), dupes.values()) |key, notes| { | |
| 5455 | const sym = self.resolver.keys.items[key - 1]; | |
| 5612 | 5456 | const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes); |
| 5613 | 5457 | |
| 5614 | 5458 | var err = try self.base.addErrorWithNotes(nnotes + 1); |
| ... | ... | @@ -5625,11 +5469,9 @@ fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemor |
| 5625 | 5469 | const remaining = notes.items.len - max_notes; |
| 5626 | 5470 | try err.addNote("defined {d} more times", .{remaining}); |
| 5627 | 5471 | } |
| 5628 | ||
| 5629 | has_dupes = true; | |
| 5630 | 5472 | } |
| 5631 | 5473 | |
| 5632 | if (has_dupes) return error.HasDuplicates; | |
| 5474 | return error.HasDuplicates; | |
| 5633 | 5475 | } |
| 5634 | 5476 | |
| 5635 | 5477 | fn reportMissingLibraryError( |
| ... | ... | @@ -6018,6 +5860,10 @@ pub const Ref = struct { |
| 6018 | 5860 | index: u32, |
| 6019 | 5861 | file: u32, |
| 6020 | 5862 | |
| 5863 | pub fn eql(ref: Ref, other: Ref) bool { | |
| 5864 | return ref.index == other.index and ref.file == other.file; | |
| 5865 | } | |
| 5866 | ||
| 6021 | 5867 | pub fn format( |
| 6022 | 5868 | ref: Ref, |
| 6023 | 5869 | comptime unused_fmt_string: []const u8, |
| ... | ... | @@ -6030,6 +5876,96 @@ pub const Ref = struct { |
| 6030 | 5876 | } |
| 6031 | 5877 | }; |
| 6032 | 5878 | |
| 5879 | pub const SymbolResolver = struct { | |
| 5880 | keys: std.ArrayListUnmanaged(Key) = .{}, | |
| 5881 | values: std.ArrayListUnmanaged(Ref) = .{}, | |
| 5882 | table: std.AutoArrayHashMapUnmanaged(void, void) = .{}, | |
| 5883 | ||
| 5884 | const Result = struct { | |
| 5885 | found_existing: bool, | |
| 5886 | index: Index, | |
| 5887 | ref: *Ref, | |
| 5888 | }; | |
| 5889 | ||
| 5890 | pub fn deinit(resolver: *SymbolResolver, allocator: Allocator) void { | |
| 5891 | resolver.keys.deinit(allocator); | |
| 5892 | resolver.values.deinit(allocator); | |
| 5893 | resolver.table.deinit(allocator); | |
| 5894 | } | |
| 5895 | ||
| 5896 | pub fn getOrPut( | |
| 5897 | resolver: *SymbolResolver, | |
| 5898 | allocator: Allocator, | |
| 5899 | ref: Ref, | |
| 5900 | elf_file: *Elf, | |
| 5901 | ) !Result { | |
| 5902 | const adapter = Adapter{ .keys = resolver.keys.items, .elf_file = elf_file }; | |
| 5903 | const key = Key{ .index = ref.index, .file_index = ref.file }; | |
| 5904 | const gop = try resolver.table.getOrPutAdapted(allocator, key, adapter); | |
| 5905 | if (!gop.found_existing) { | |
| 5906 | try resolver.keys.append(allocator, key); | |
| 5907 | _ = try resolver.values.addOne(allocator); | |
| 5908 | } | |
| 5909 | return .{ | |
| 5910 | .found_existing = gop.found_existing, | |
| 5911 | .index = @intCast(gop.index + 1), | |
| 5912 | .ref = &resolver.values.items[gop.index], | |
| 5913 | }; | |
| 5914 | } | |
| 5915 | ||
| 5916 | pub fn get(resolver: SymbolResolver, index: Index) ?Ref { | |
| 5917 | if (index == 0) return null; | |
| 5918 | return resolver.values.items[index - 1]; | |
| 5919 | } | |
| 5920 | ||
| 5921 | pub fn reset(resolver: *SymbolResolver) void { | |
| 5922 | resolver.keys.clearRetainingCapacity(); | |
| 5923 | resolver.values.clearRetainingCapacity(); | |
| 5924 | resolver.table.clearRetainingCapacity(); | |
| 5925 | } | |
| 5926 | ||
| 5927 | const Key = struct { | |
| 5928 | index: Symbol.Index, | |
| 5929 | file_index: File.Index, | |
| 5930 | ||
| 5931 | fn name(key: Key, elf_file: *Elf) [:0]const u8 { | |
| 5932 | const ref = Ref{ .index = key.index, .file = key.file_index }; | |
| 5933 | return elf_file.symbol(ref).?.name(elf_file); | |
| 5934 | } | |
| 5935 | ||
| 5936 | fn file(key: Key, elf_file: *Elf) ?File { | |
| 5937 | return elf_file.file(key.file_index); | |
| 5938 | } | |
| 5939 | ||
| 5940 | fn eql(key: Key, other: Key, elf_file: *Elf) bool { | |
| 5941 | const key_name = key.name(elf_file); | |
| 5942 | const other_name = other.name(elf_file); | |
| 5943 | return mem.eql(u8, key_name, other_name); | |
| 5944 | } | |
| 5945 | ||
| 5946 | fn hash(key: Key, elf_file: *Elf) u32 { | |
| 5947 | return @truncate(Hash.hash(0, key.name(elf_file))); | |
| 5948 | } | |
| 5949 | }; | |
| 5950 | ||
| 5951 | const Adapter = struct { | |
| 5952 | keys: []const Key, | |
| 5953 | elf_file: *Elf, | |
| 5954 | ||
| 5955 | pub fn eql(ctx: @This(), key: Key, b_void: void, b_map_index: usize) bool { | |
| 5956 | _ = b_void; | |
| 5957 | const other = ctx.keys[b_map_index]; | |
| 5958 | return key.eql(other, ctx.elf_file); | |
| 5959 | } | |
| 5960 | ||
| 5961 | pub fn hash(ctx: @This(), key: Key) u32 { | |
| 5962 | return key.hash(ctx.elf_file); | |
| 5963 | } | |
| 5964 | }; | |
| 5965 | ||
| 5966 | pub const Index = u32; | |
| 5967 | }; | |
| 5968 | ||
| 6033 | 5969 | const LastAtomAndFreeList = struct { |
| 6034 | 5970 | /// Index of the last allocated atom in this section. |
| 6035 | 5971 | last_atom_index: Atom.Index = 0, |
| ... | ... | @@ -6143,6 +6079,7 @@ const File = @import("Elf/file.zig").File; |
| 6143 | 6079 | const GnuHashSection = synthetic_sections.GnuHashSection; |
| 6144 | 6080 | const GotSection = synthetic_sections.GotSection; |
| 6145 | 6081 | const GotPltSection = synthetic_sections.GotPltSection; |
| 6082 | const Hash = std.hash.Wyhash; | |
| 6146 | 6083 | const HashSection = synthetic_sections.HashSection; |
| 6147 | 6084 | const InputMergeSection = merge_section.InputMergeSection; |
| 6148 | 6085 | const LdScript = @import("Elf/LdScript.zig"); |
src/link/Elf/Atom.zig+51-64| ... | ... | @@ -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: |
| ... | ... | @@ -845,7 +840,7 @@ fn resolveDynAbsReloc( |
| 845 | 840 | if (is_writeable or elf_file.z_nocopyreloc) { |
| 846 | 841 | elf_file.addRelaDynAssumeCapacity(.{ |
| 847 | 842 | .offset = P, |
| 848 | .sym = target.extra(elf_file).?.dynamic, | |
| 843 | .sym = target.extra(elf_file).dynamic, | |
| 849 | 844 | .type = relocation.encode(.abs, cpu_arch), |
| 850 | 845 | .addend = A, |
| 851 | 846 | }); |
| ... | ... | @@ -859,7 +854,7 @@ fn resolveDynAbsReloc( |
| 859 | 854 | if (is_writeable) { |
| 860 | 855 | elf_file.addRelaDynAssumeCapacity(.{ |
| 861 | 856 | .offset = P, |
| 862 | .sym = target.extra(elf_file).?.dynamic, | |
| 857 | .sym = target.extra(elf_file).dynamic, | |
| 863 | 858 | .type = relocation.encode(.abs, cpu_arch), |
| 864 | 859 | .addend = A, |
| 865 | 860 | }); |
| ... | ... | @@ -872,7 +867,7 @@ fn resolveDynAbsReloc( |
| 872 | 867 | .dynrel => { |
| 873 | 868 | elf_file.addRelaDynAssumeCapacity(.{ |
| 874 | 869 | .offset = P, |
| 875 | .sym = target.extra(elf_file).?.dynamic, | |
| 870 | .sym = target.extra(elf_file).dynamic, | |
| 876 | 871 | .type = relocation.encode(.abs, cpu_arch), |
| 877 | 872 | .addend = A, |
| 878 | 873 | }); |
| ... | ... | @@ -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+268-143| ... | ... | @@ -2,7 +2,10 @@ index: File.Index, |
| 2 | 2 | |
| 3 | 3 | symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, |
| 4 | 4 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 5 | symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, | |
| 5 | ||
| 6 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, | |
| 7 | symbols_extra: std.ArrayListUnmanaged(u32) = .{}, | |
| 8 | symbols_resolver: std.ArrayListUnmanaged(Elf.SymbolResolver.Index) = .{}, | |
| 6 | 9 | |
| 7 | 10 | entry_index: ?Symbol.Index = null, |
| 8 | 11 | dynamic_index: ?Symbol.Index = null, |
| ... | ... | @@ -29,6 +32,8 @@ pub fn deinit(self: *LinkerDefined, allocator: Allocator) void { |
| 29 | 32 | self.symtab.deinit(allocator); |
| 30 | 33 | self.strtab.deinit(allocator); |
| 31 | 34 | self.symbols.deinit(allocator); |
| 35 | self.symbols_extra.deinit(allocator); | |
| 36 | self.symbols_resolver.deinit(allocator); | |
| 32 | 37 | self.start_stop_indexes.deinit(allocator); |
| 33 | 38 | } |
| 34 | 39 | |
| ... | ... | @@ -37,86 +42,150 @@ pub fn init(self: *LinkerDefined, allocator: Allocator) !void { |
| 37 | 42 | try self.strtab.append(allocator, 0); |
| 38 | 43 | } |
| 39 | 44 | |
| 45 | fn newSymbolAssumeCapacity(self: *LinkerDefined, name_off: u32, elf_file: *Elf) Symbol.Index { | |
| 46 | const esym_index: u32 = @intCast(self.symtab.items.len); | |
| 47 | const esym = self.symtab.addOneAssumeCapacity(); | |
| 48 | esym.* = .{ | |
| 49 | .st_name = name_off, | |
| 50 | .st_info = elf.STB_GLOBAL << 4, | |
| 51 | .st_other = @intFromEnum(elf.STV.HIDDEN), | |
| 52 | .st_shndx = elf.SHN_ABS, | |
| 53 | .st_value = 0, | |
| 54 | .st_size = 0, | |
| 55 | }; | |
| 56 | const index = self.addSymbolAssumeCapacity(); | |
| 57 | const symbol = &self.symbols.items[index]; | |
| 58 | symbol.name_offset = name_off; | |
| 59 | symbol.extra_index = self.addSymbolExtraAssumeCapacity(.{}); | |
| 60 | symbol.ref = .{ .index = 0, .file = 0 }; | |
| 61 | symbol.esym_index = esym_index; | |
| 62 | symbol.version_index = elf_file.default_sym_version; | |
| 63 | return index; | |
| 64 | } | |
| 65 | ||
| 40 | 66 | pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void { |
| 41 | 67 | const gpa = elf_file.base.comp.gpa; |
| 42 | 68 | |
| 69 | var nsyms: usize = 0; | |
| 70 | if (elf_file.entry_name) |_| { | |
| 71 | nsyms += 1; // entry | |
| 72 | } | |
| 73 | nsyms += 1; // _DYNAMIC | |
| 74 | nsyms += 1; // __ehdr_start | |
| 75 | nsyms += 1; // __init_array_start | |
| 76 | nsyms += 1; // __init_array_end | |
| 77 | nsyms += 1; // __fini_array_start | |
| 78 | nsyms += 1; // __fini_array_end | |
| 79 | nsyms += 1; // __preinit_array_start | |
| 80 | nsyms += 1; // __preinit_array_end | |
| 81 | nsyms += 1; // _GLOBAL_OFFSET_TABLE_ | |
| 82 | nsyms += 1; // _PROCEDURE_LINKAGE_TABLE_ | |
| 83 | nsyms += 1; // _end | |
| 84 | if (elf_file.base.comp.link_eh_frame_hdr) { | |
| 85 | nsyms += 1; // __GNU_EH_FRAME_HDR | |
| 86 | } | |
| 87 | nsyms += 1; // __dso_handle | |
| 88 | nsyms += 1; // __rela_iplt_start | |
| 89 | nsyms += 1; // __rela_iplt_end | |
| 90 | if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) { | |
| 91 | nsyms += 1; // __global_pointer$ | |
| 92 | } | |
| 93 | ||
| 94 | try self.symtab.ensureTotalCapacityPrecise(gpa, nsyms); | |
| 95 | try self.symbols.ensureTotalCapacityPrecise(gpa, nsyms); | |
| 96 | try self.symbols_extra.ensureTotalCapacityPrecise(gpa, nsyms * @sizeOf(Symbol.Extra)); | |
| 97 | try self.symbols_resolver.ensureTotalCapacityPrecise(gpa, nsyms); | |
| 98 | self.symbols_resolver.resize(gpa, nsyms) catch unreachable; | |
| 99 | @memset(self.symbols_resolver.items, 0); | |
| 100 | ||
| 43 | 101 | if (elf_file.entry_name) |name| { |
| 44 | self.entry_index = try self.addGlobal(name, elf_file); | |
| 102 | self.entry_index = self.newSymbolAssumeCapacity(try self.addString(gpa, name), elf_file); | |
| 45 | 103 | } |
| 46 | 104 | |
| 47 | self.dynamic_index = try self.addGlobal("_DYNAMIC", elf_file); | |
| 48 | self.ehdr_start_index = try self.addGlobal("__ehdr_start", elf_file); | |
| 49 | self.init_array_start_index = try self.addGlobal("__init_array_start", elf_file); | |
| 50 | self.init_array_end_index = try self.addGlobal("__init_array_end", elf_file); | |
| 51 | self.fini_array_start_index = try self.addGlobal("__fini_array_start", elf_file); | |
| 52 | self.fini_array_end_index = try self.addGlobal("__fini_array_end", elf_file); | |
| 53 | self.preinit_array_start_index = try self.addGlobal("__preinit_array_start", elf_file); | |
| 54 | self.preinit_array_end_index = try self.addGlobal("__preinit_array_end", elf_file); | |
| 55 | self.got_index = try self.addGlobal("_GLOBAL_OFFSET_TABLE_", elf_file); | |
| 56 | self.plt_index = try self.addGlobal("_PROCEDURE_LINKAGE_TABLE_", elf_file); | |
| 57 | self.end_index = try self.addGlobal("_end", elf_file); | |
| 105 | self.dynamic_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_DYNAMIC"), elf_file); | |
| 106 | self.ehdr_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__ehdr_start"), elf_file); | |
| 107 | self.init_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__init_array_start"), elf_file); | |
| 108 | self.init_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__init_array_end"), elf_file); | |
| 109 | self.fini_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__fini_array_start"), elf_file); | |
| 110 | self.fini_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__fini_array_end"), elf_file); | |
| 111 | self.preinit_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__preinit_array_start"), elf_file); | |
| 112 | self.preinit_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__preinit_array_end"), elf_file); | |
| 113 | self.got_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_GLOBAL_OFFSET_TABLE_"), elf_file); | |
| 114 | self.plt_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_PROCEDURE_LINKAGE_TABLE_"), elf_file); | |
| 115 | self.end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_end"), elf_file); | |
| 58 | 116 | |
| 59 | 117 | if (elf_file.base.comp.link_eh_frame_hdr) { |
| 60 | self.gnu_eh_frame_hdr_index = try self.addGlobal("__GNU_EH_FRAME_HDR", elf_file); | |
| 118 | self.gnu_eh_frame_hdr_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__GNU_EH_FRAME_HDR"), elf_file); | |
| 61 | 119 | } |
| 62 | 120 | |
| 63 | self.dso_handle_index = try self.addGlobal("__dso_handle", elf_file); | |
| 64 | self.rela_iplt_start_index = try self.addGlobal("__rela_iplt_start", elf_file); | |
| 65 | self.rela_iplt_end_index = try self.addGlobal("__rela_iplt_end", elf_file); | |
| 121 | self.dso_handle_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__dso_handle"), elf_file); | |
| 122 | self.rela_iplt_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__rela_iplt_start"), elf_file); | |
| 123 | self.rela_iplt_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__rela_iplt_end"), elf_file); | |
| 66 | 124 | |
| 67 | for (elf_file.shdrs.items) |shdr| { | |
| 68 | if (elf_file.getStartStopBasename(shdr)) |name| { | |
| 69 | try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2); | |
| 125 | if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) { | |
| 126 | self.global_pointer_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__global_pointer$"), elf_file); | |
| 127 | } | |
| 128 | } | |
| 70 | 129 | |
| 71 | const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); | |
| 72 | defer gpa.free(start); | |
| 73 | const stop = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name}); | |
| 74 | defer gpa.free(stop); | |
| 130 | pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void { | |
| 131 | const gpa = elf_file.base.comp.gpa; | |
| 75 | 132 | |
| 76 | self.start_stop_indexes.appendAssumeCapacity(try self.addGlobal(start, elf_file)); | |
| 77 | self.start_stop_indexes.appendAssumeCapacity(try self.addGlobal(stop, elf_file)); | |
| 133 | var nsyms: usize = 0; | |
| 134 | for (elf_file.shdrs.items) |shdr| { | |
| 135 | if (elf_file.getStartStopBasename(shdr)) |_| { | |
| 136 | nsyms += 2; // __start_, __stop_ | |
| 78 | 137 | } |
| 79 | 138 | } |
| 80 | 139 | |
| 81 | if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) { | |
| 82 | self.global_pointer_index = try self.addGlobal("__global_pointer$", elf_file); | |
| 140 | try self.start_stop_indexes.ensureTotalCapacityPrecise(gpa, nsyms); | |
| 141 | try self.symtab.ensureUnusedCapacity(gpa, nsyms); | |
| 142 | try self.symbols.ensureUnusedCapacity(gpa, nsyms); | |
| 143 | try self.symbols_extra.ensureUnusedCapacity(gpa, nsyms * @sizeOf(Symbol.Extra)); | |
| 144 | try self.symbols_resolver.ensureUnusedCapacity(gpa, nsyms); | |
| 145 | ||
| 146 | for (elf_file.shdrs.items) |shdr| { | |
| 147 | if (elf_file.getStartStopBasename(shdr)) |name| { | |
| 148 | const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); | |
| 149 | defer gpa.free(start_name); | |
| 150 | const stop_name = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name}); | |
| 151 | defer gpa.free(stop_name); | |
| 152 | ||
| 153 | for (&[_][]const u8{ start_name, stop_name }) |nn| { | |
| 154 | const index = self.newSymbolAssumeCapacity(try self.addString(gpa, nn), elf_file); | |
| 155 | self.start_stop_indexes.appendAssumeCapacity(index); | |
| 156 | const gop = try elf_file.resolver.getOrPut(gpa, .{ | |
| 157 | .index = index, | |
| 158 | .file = self.index, | |
| 159 | }, elf_file); | |
| 160 | assert(!gop.found_existing); | |
| 161 | gop.ref.* = .{ .index = index, .file = self.index }; | |
| 162 | self.symbols_resolver.appendAssumeCapacity(gop.index); | |
| 163 | } | |
| 164 | } | |
| 83 | 165 | } |
| 84 | 166 | } |
| 85 | 167 | |
| 86 | fn addGlobal(self: *LinkerDefined, name: []const u8, elf_file: *Elf) !u32 { | |
| 87 | const comp = elf_file.base.comp; | |
| 88 | const gpa = comp.gpa; | |
| 89 | try self.symtab.ensureUnusedCapacity(gpa, 1); | |
| 90 | try self.symbols.ensureUnusedCapacity(gpa, 1); | |
| 91 | const name_off = @as(u32, @intCast(self.strtab.items.len)); | |
| 92 | try self.strtab.writer(gpa).print("{s}\x00", .{name}); | |
| 93 | self.symtab.appendAssumeCapacity(.{ | |
| 94 | .st_name = name_off, | |
| 95 | .st_info = elf.STB_GLOBAL << 4, | |
| 96 | .st_other = @intFromEnum(elf.STV.HIDDEN), | |
| 97 | .st_shndx = elf.SHN_ABS, | |
| 98 | .st_value = 0, | |
| 99 | .st_size = 0, | |
| 100 | }); | |
| 101 | const gop = try elf_file.getOrPutGlobal(name); | |
| 102 | self.symbols.addOneAssumeCapacity().* = gop.index; | |
| 103 | return gop.index; | |
| 104 | } | |
| 168 | pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) !void { | |
| 169 | const gpa = elf_file.base.comp.gpa; | |
| 105 | 170 | |
| 106 | pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void { | |
| 107 | for (self.symbols.items, 0..) |index, i| { | |
| 108 | const sym_idx = @as(Symbol.Index, @intCast(i)); | |
| 109 | const this_sym = self.symtab.items[sym_idx]; | |
| 171 | for (self.symtab.items, self.symbols_resolver.items, 0..) |esym, *resolv, i| { | |
| 172 | const gop = try elf_file.resolver.getOrPut(gpa, .{ | |
| 173 | .index = @intCast(i), | |
| 174 | .file = self.index, | |
| 175 | }, elf_file); | |
| 176 | if (!gop.found_existing) { | |
| 177 | gop.ref.* = .{ .index = 0, .file = 0 }; | |
| 178 | } | |
| 179 | resolv.* = gop.index; | |
| 110 | 180 | |
| 111 | if (this_sym.st_shndx == elf.SHN_UNDEF) continue; | |
| 181 | if (esym.st_shndx == elf.SHN_UNDEF) continue; | |
| 182 | if (elf_file.symbol(gop.ref.*) == null) { | |
| 183 | gop.ref.* = .{ .index = @intCast(i), .file = self.index }; | |
| 184 | continue; | |
| 185 | } | |
| 112 | 186 | |
| 113 | const global = elf_file.symbol(index); | |
| 114 | if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) { | |
| 115 | global.value = 0; | |
| 116 | global.ref = .{ .index = 0, .file = 0 }; | |
| 117 | global.file_index = self.index; | |
| 118 | global.esym_index = sym_idx; | |
| 119 | global.version_index = elf_file.default_sym_version; | |
| 187 | if (self.asFile().symbolRank(esym, false) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) { | |
| 188 | gop.ref.* = .{ .index = @intCast(i), .file = self.index }; | |
| 120 | 189 | } |
| 121 | 190 | } |
| 122 | 191 | } |
| ... | ... | @@ -125,93 +194,73 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { |
| 125 | 194 | const comp = elf_file.base.comp; |
| 126 | 195 | const link_mode = comp.config.link_mode; |
| 127 | 196 | |
| 197 | const allocSymbol = struct { | |
| 198 | fn allocSymbol(ld: *LinkerDefined, index: Symbol.Index, value: u64, osec: u32, ef: *Elf) void { | |
| 199 | const sym = ef.symbol(ld.resolveSymbol(index, ef)).?; | |
| 200 | sym.value = @intCast(value); | |
| 201 | sym.output_section_index = osec; | |
| 202 | } | |
| 203 | }.allocSymbol; | |
| 204 | ||
| 128 | 205 | // _DYNAMIC |
| 129 | 206 | if (elf_file.dynamic_section_index) |shndx| { |
| 130 | 207 | const shdr = &elf_file.shdrs.items[shndx]; |
| 131 | const symbol_ptr = elf_file.symbol(self.dynamic_index.?); | |
| 132 | symbol_ptr.value = @intCast(shdr.sh_addr); | |
| 133 | symbol_ptr.output_section_index = shndx; | |
| 208 | allocSymbol(self, self.dynamic_index.?, shdr.sh_addr, shndx, elf_file); | |
| 134 | 209 | } |
| 135 | 210 | |
| 136 | 211 | // __ehdr_start |
| 137 | { | |
| 138 | const symbol_ptr = elf_file.symbol(self.ehdr_start_index.?); | |
| 139 | symbol_ptr.value = @intCast(elf_file.image_base); | |
| 140 | symbol_ptr.output_section_index = 1; | |
| 141 | } | |
| 212 | allocSymbol(self, self.ehdr_start_index.?, elf_file.image_base, 1, elf_file); | |
| 142 | 213 | |
| 143 | 214 | // __init_array_start, __init_array_end |
| 144 | 215 | if (elf_file.sectionByName(".init_array")) |shndx| { |
| 145 | const start_sym = elf_file.symbol(self.init_array_start_index.?); | |
| 146 | const end_sym = elf_file.symbol(self.init_array_end_index.?); | |
| 147 | 216 | const shdr = &elf_file.shdrs.items[shndx]; |
| 148 | start_sym.output_section_index = shndx; | |
| 149 | start_sym.value = @intCast(shdr.sh_addr); | |
| 150 | end_sym.output_section_index = shndx; | |
| 151 | end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); | |
| 217 | allocSymbol(self, self.init_array_start_index.?, shdr.sh_addr, shndx, elf_file); | |
| 218 | allocSymbol(self, self.init_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file); | |
| 152 | 219 | } |
| 153 | 220 | |
| 154 | 221 | // __fini_array_start, __fini_array_end |
| 155 | 222 | if (elf_file.sectionByName(".fini_array")) |shndx| { |
| 156 | const start_sym = elf_file.symbol(self.fini_array_start_index.?); | |
| 157 | const end_sym = elf_file.symbol(self.fini_array_end_index.?); | |
| 158 | 223 | const shdr = &elf_file.shdrs.items[shndx]; |
| 159 | start_sym.output_section_index = shndx; | |
| 160 | start_sym.value = @intCast(shdr.sh_addr); | |
| 161 | end_sym.output_section_index = shndx; | |
| 162 | end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); | |
| 224 | allocSymbol(self, self.fini_array_start_index.?, shdr.sh_addr, shndx, elf_file); | |
| 225 | allocSymbol(self, self.fini_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file); | |
| 163 | 226 | } |
| 164 | 227 | |
| 165 | 228 | // __preinit_array_start, __preinit_array_end |
| 166 | 229 | if (elf_file.sectionByName(".preinit_array")) |shndx| { |
| 167 | const start_sym = elf_file.symbol(self.preinit_array_start_index.?); | |
| 168 | const end_sym = elf_file.symbol(self.preinit_array_end_index.?); | |
| 169 | 230 | const shdr = &elf_file.shdrs.items[shndx]; |
| 170 | start_sym.output_section_index = shndx; | |
| 171 | start_sym.value = @intCast(shdr.sh_addr); | |
| 172 | end_sym.output_section_index = shndx; | |
| 173 | end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); | |
| 231 | allocSymbol(self, self.preinit_array_start_index.?, shdr.sh_addr, shndx, elf_file); | |
| 232 | allocSymbol(self, self.preinit_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file); | |
| 174 | 233 | } |
| 175 | 234 | |
| 176 | 235 | // _GLOBAL_OFFSET_TABLE_ |
| 177 | 236 | if (elf_file.getTarget().cpu.arch == .x86_64) { |
| 178 | 237 | if (elf_file.got_plt_section_index) |shndx| { |
| 179 | 238 | const shdr = elf_file.shdrs.items[shndx]; |
| 180 | const sym = elf_file.symbol(self.got_index.?); | |
| 181 | sym.value = @intCast(shdr.sh_addr); | |
| 182 | sym.output_section_index = shndx; | |
| 239 | allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file); | |
| 183 | 240 | } |
| 184 | 241 | } else { |
| 185 | 242 | if (elf_file.got_section_index) |shndx| { |
| 186 | 243 | const shdr = elf_file.shdrs.items[shndx]; |
| 187 | const sym = elf_file.symbol(self.got_index.?); | |
| 188 | sym.value = @intCast(shdr.sh_addr); | |
| 189 | sym.output_section_index = shndx; | |
| 244 | allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file); | |
| 190 | 245 | } |
| 191 | 246 | } |
| 192 | 247 | |
| 193 | 248 | // _PROCEDURE_LINKAGE_TABLE_ |
| 194 | 249 | if (elf_file.plt_section_index) |shndx| { |
| 195 | 250 | const shdr = &elf_file.shdrs.items[shndx]; |
| 196 | const symbol_ptr = elf_file.symbol(self.plt_index.?); | |
| 197 | symbol_ptr.value = @intCast(shdr.sh_addr); | |
| 198 | symbol_ptr.output_section_index = shndx; | |
| 251 | allocSymbol(self, self.plt_index.?, shdr.sh_addr, shndx, elf_file); | |
| 199 | 252 | } |
| 200 | 253 | |
| 201 | 254 | // __dso_handle |
| 202 | 255 | if (self.dso_handle_index) |index| { |
| 203 | 256 | const shdr = &elf_file.shdrs.items[1]; |
| 204 | const symbol_ptr = elf_file.symbol(index); | |
| 205 | symbol_ptr.value = @intCast(shdr.sh_addr); | |
| 206 | symbol_ptr.output_section_index = 0; | |
| 257 | allocSymbol(self, index, shdr.sh_addr, 0, elf_file); | |
| 207 | 258 | } |
| 208 | 259 | |
| 209 | 260 | // __GNU_EH_FRAME_HDR |
| 210 | 261 | if (elf_file.eh_frame_hdr_section_index) |shndx| { |
| 211 | 262 | const shdr = &elf_file.shdrs.items[shndx]; |
| 212 | const symbol_ptr = elf_file.symbol(self.gnu_eh_frame_hdr_index.?); | |
| 213 | symbol_ptr.value = @intCast(shdr.sh_addr); | |
| 214 | symbol_ptr.output_section_index = shndx; | |
| 263 | allocSymbol(self, self.gnu_eh_frame_hdr_index.?, shdr.sh_addr, shndx, elf_file); | |
| 215 | 264 | } |
| 216 | 265 | |
| 217 | 266 | // __rela_iplt_start, __rela_iplt_end |
| ... | ... | @@ -220,32 +269,41 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { |
| 220 | 269 | const shdr = &elf_file.shdrs.items[shndx]; |
| 221 | 270 | const end_addr = shdr.sh_addr + shdr.sh_size; |
| 222 | 271 | const start_addr = end_addr - elf_file.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela); |
| 223 | const start_sym = elf_file.symbol(self.rela_iplt_start_index.?); | |
| 224 | const end_sym = elf_file.symbol(self.rela_iplt_end_index.?); | |
| 225 | start_sym.value = @intCast(start_addr); | |
| 226 | start_sym.output_section_index = shndx; | |
| 227 | end_sym.value = @intCast(end_addr); | |
| 228 | end_sym.output_section_index = shndx; | |
| 272 | allocSymbol(self, self.rela_iplt_start_index.?, start_addr, shndx, elf_file); | |
| 273 | allocSymbol(self, self.rela_iplt_end_index.?, end_addr, shndx, elf_file); | |
| 229 | 274 | } |
| 230 | 275 | |
| 231 | 276 | // _end |
| 232 | 277 | { |
| 233 | const end_symbol = elf_file.symbol(self.end_index.?); | |
| 278 | var value: u64 = 0; | |
| 279 | var osec: u32 = 0; | |
| 234 | 280 | for (elf_file.shdrs.items, 0..) |shdr, shndx| { |
| 235 | 281 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) { |
| 236 | end_symbol.value = @intCast(shdr.sh_addr + shdr.sh_size); | |
| 237 | end_symbol.output_section_index = @intCast(shndx); | |
| 282 | value = shdr.sh_addr + shdr.sh_size; | |
| 283 | osec = @intCast(shndx); | |
| 238 | 284 | } |
| 239 | 285 | } |
| 286 | allocSymbol(self, self.end_index.?, value, osec, elf_file); | |
| 287 | } | |
| 288 | ||
| 289 | // __global_pointer$ | |
| 290 | if (self.global_pointer_index) |index| { | |
| 291 | const value, const osec = if (elf_file.sectionByName(".sdata")) |shndx| .{ | |
| 292 | elf_file.shdrs.items[shndx].sh_addr + 0x800, | |
| 293 | shndx, | |
| 294 | } else .{ 0, 0 }; | |
| 295 | allocSymbol(self, index, value, osec, elf_file); | |
| 240 | 296 | } |
| 241 | 297 | |
| 242 | 298 | // __start_*, __stop_* |
| 243 | 299 | { |
| 244 | 300 | var index: usize = 0; |
| 245 | 301 | while (index < self.start_stop_indexes.items.len) : (index += 2) { |
| 246 | const start = elf_file.symbol(self.start_stop_indexes.items[index]); | |
| 302 | const start_ref = self.resolveSymbol(self.start_stop_indexes.items[index], elf_file); | |
| 303 | const start = elf_file.symbol(start_ref).?; | |
| 247 | 304 | const name = start.name(elf_file); |
| 248 | const stop = elf_file.symbol(self.start_stop_indexes.items[index + 1]); | |
| 305 | const stop_ref = self.resolveSymbol(self.start_stop_indexes.items[index + 1], elf_file); | |
| 306 | const stop = elf_file.symbol(stop_ref).?; | |
| 249 | 307 | const shndx = elf_file.sectionByName(name["__start_".len..]).?; |
| 250 | 308 | const shdr = &elf_file.shdrs.items[shndx]; |
| 251 | 309 | start.value = @intCast(shdr.sh_addr); |
| ... | ... | @@ -254,47 +312,30 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { |
| 254 | 312 | stop.output_section_index = shndx; |
| 255 | 313 | } |
| 256 | 314 | } |
| 257 | ||
| 258 | // __global_pointer$ | |
| 259 | if (self.global_pointer_index) |index| { | |
| 260 | const sym = elf_file.symbol(index); | |
| 261 | if (elf_file.sectionByName(".sdata")) |shndx| { | |
| 262 | const shdr = elf_file.shdrs.items[shndx]; | |
| 263 | sym.value = @intCast(shdr.sh_addr + 0x800); | |
| 264 | sym.output_section_index = shndx; | |
| 265 | } else { | |
| 266 | sym.value = 0; | |
| 267 | sym.output_section_index = 0; | |
| 268 | } | |
| 269 | } | |
| 270 | } | |
| 271 | ||
| 272 | pub fn globals(self: LinkerDefined) []const Symbol.Index { | |
| 273 | return self.symbols.items; | |
| 274 | 315 | } |
| 275 | 316 | |
| 276 | pub fn updateSymtabSize(self: *LinkerDefined, elf_file: *Elf) !void { | |
| 277 | for (self.globals()) |global_index| { | |
| 278 | const global = elf_file.symbol(global_index); | |
| 279 | const file_ptr = global.file(elf_file) orelse continue; | |
| 280 | if (file_ptr.index() != self.index) continue; | |
| 317 | pub fn updateSymtabSize(self: *LinkerDefined, elf_file: *Elf) void { | |
| 318 | for (self.symbols.items, self.symbols_resolver.items) |*global, resolv| { | |
| 319 | const ref = elf_file.resolver.get(resolv).?; | |
| 320 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 321 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 281 | 322 | global.flags.output_symtab = true; |
| 282 | 323 | if (global.isLocal(elf_file)) { |
| 283 | try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); | |
| 324 | global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); | |
| 284 | 325 | self.output_symtab_ctx.nlocals += 1; |
| 285 | 326 | } else { |
| 286 | try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file); | |
| 327 | global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file); | |
| 287 | 328 | self.output_symtab_ctx.nglobals += 1; |
| 288 | 329 | } |
| 289 | 330 | self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1; |
| 290 | 331 | } |
| 291 | 332 | } |
| 292 | 333 | |
| 293 | pub fn writeSymtab(self: LinkerDefined, elf_file: *Elf) void { | |
| 294 | for (self.globals()) |global_index| { | |
| 295 | const global = elf_file.symbol(global_index); | |
| 296 | const file_ptr = global.file(elf_file) orelse continue; | |
| 297 | if (file_ptr.index() != self.index) continue; | |
| 334 | pub fn writeSymtab(self: *LinkerDefined, elf_file: *Elf) void { | |
| 335 | for (self.symbols.items, self.symbols_resolver.items) |global, resolv| { | |
| 336 | const ref = elf_file.resolver.get(resolv).?; | |
| 337 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 338 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 298 | 339 | const idx = global.outputSymtabIndex(elf_file) orelse continue; |
| 299 | 340 | const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); |
| 300 | 341 | elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file)); |
| ... | ... | @@ -305,15 +346,93 @@ pub fn writeSymtab(self: LinkerDefined, elf_file: *Elf) void { |
| 305 | 346 | } |
| 306 | 347 | } |
| 307 | 348 | |
| 349 | pub fn dynamicSymbol(self: LinkerDefined, elf_file: *Elf) ?*Symbol { | |
| 350 | const index = self.dynamic_index orelse return null; | |
| 351 | const resolv = self.resolveSymbol(index, elf_file); | |
| 352 | return elf_file.symbol(resolv); | |
| 353 | } | |
| 354 | ||
| 355 | pub fn entrySymbol(self: LinkerDefined, elf_file: *Elf) ?*Symbol { | |
| 356 | const index = self.entry_index orelse return null; | |
| 357 | const resolv = self.resolveSymbol(index, elf_file); | |
| 358 | return elf_file.symbol(resolv); | |
| 359 | } | |
| 360 | ||
| 308 | 361 | pub fn asFile(self: *LinkerDefined) File { |
| 309 | 362 | return .{ .linker_defined = self }; |
| 310 | 363 | } |
| 311 | 364 | |
| 365 | fn addString(self: *LinkerDefined, allocator: Allocator, str: []const u8) !u32 { | |
| 366 | const off: u32 = @intCast(self.strtab.items.len); | |
| 367 | try self.strtab.ensureUnusedCapacity(allocator, str.len + 1); | |
| 368 | self.strtab.appendSliceAssumeCapacity(str); | |
| 369 | self.strtab.appendAssumeCapacity(0); | |
| 370 | return off; | |
| 371 | } | |
| 372 | ||
| 312 | 373 | pub fn getString(self: LinkerDefined, off: u32) [:0]const u8 { |
| 313 | 374 | assert(off < self.strtab.items.len); |
| 314 | 375 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0); |
| 315 | 376 | } |
| 316 | 377 | |
| 378 | pub fn resolveSymbol(self: LinkerDefined, index: Symbol.Index, elf_file: *Elf) Elf.Ref { | |
| 379 | const resolv = self.symbols_resolver.items[index]; | |
| 380 | return elf_file.resolver.get(resolv).?; | |
| 381 | } | |
| 382 | ||
| 383 | fn addSymbol(self: *LinkerDefined, allocator: Allocator) !Symbol.Index { | |
| 384 | try self.symbols.ensureUnusedCapacity(allocator, 1); | |
| 385 | return self.addSymbolAssumeCapacity(); | |
| 386 | } | |
| 387 | ||
| 388 | fn addSymbolAssumeCapacity(self: *LinkerDefined) Symbol.Index { | |
| 389 | const index: Symbol.Index = @intCast(self.symbols.items.len); | |
| 390 | self.symbols.appendAssumeCapacity(.{ .file_index = self.index }); | |
| 391 | return index; | |
| 392 | } | |
| 393 | ||
| 394 | pub fn addSymbolExtra(self: *LinkerDefined, allocator: Allocator, extra: Symbol.Extra) !u32 { | |
| 395 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 396 | try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len); | |
| 397 | return self.addSymbolExtraAssumeCapacity(extra); | |
| 398 | } | |
| 399 | ||
| 400 | pub fn addSymbolExtraAssumeCapacity(self: *LinkerDefined, extra: Symbol.Extra) u32 { | |
| 401 | const index = @as(u32, @intCast(self.symbols_extra.items.len)); | |
| 402 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 403 | inline for (fields) |field| { | |
| 404 | self.symbols_extra.appendAssumeCapacity(switch (field.type) { | |
| 405 | u32 => @field(extra, field.name), | |
| 406 | else => @compileError("bad field type"), | |
| 407 | }); | |
| 408 | } | |
| 409 | return index; | |
| 410 | } | |
| 411 | ||
| 412 | pub fn symbolExtra(self: *LinkerDefined, index: u32) Symbol.Extra { | |
| 413 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 414 | var i: usize = index; | |
| 415 | var result: Symbol.Extra = undefined; | |
| 416 | inline for (fields) |field| { | |
| 417 | @field(result, field.name) = switch (field.type) { | |
| 418 | u32 => self.symbols_extra.items[i], | |
| 419 | else => @compileError("bad field type"), | |
| 420 | }; | |
| 421 | i += 1; | |
| 422 | } | |
| 423 | return result; | |
| 424 | } | |
| 425 | ||
| 426 | pub fn setSymbolExtra(self: *LinkerDefined, index: u32, extra: Symbol.Extra) void { | |
| 427 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 428 | inline for (fields, 0..) |field, i| { | |
| 429 | self.symbols_extra.items[index + i] = switch (field.type) { | |
| 430 | u32 => @field(extra, field.name), | |
| 431 | else => @compileError("bad field type"), | |
| 432 | }; | |
| 433 | } | |
| 434 | } | |
| 435 | ||
| 317 | 436 | pub fn fmtSymtab(self: *LinkerDefined, elf_file: *Elf) std.fmt.Formatter(formatSymtab) { |
| 318 | 437 | return .{ .data = .{ |
| 319 | 438 | .self = self, |
| ... | ... | @@ -334,10 +453,16 @@ fn formatSymtab( |
| 334 | 453 | ) !void { |
| 335 | 454 | _ = unused_fmt_string; |
| 336 | 455 | _ = options; |
| 456 | const self = ctx.self; | |
| 457 | const elf_file = ctx.elf_file; | |
| 337 | 458 | try writer.writeAll(" globals\n"); |
| 338 | for (ctx.self.globals()) |index| { | |
| 339 | const global = ctx.elf_file.symbol(index); | |
| 340 | try writer.print(" {}\n", .{global.fmt(ctx.elf_file)}); | |
| 459 | for (self.symbols.items, 0..) |sym, i| { | |
| 460 | const ref = self.resolveSymbol(@intCast(i), elf_file); | |
| 461 | if (elf_file.symbol(ref)) |ref_sym| { | |
| 462 | try writer.print(" {}\n", .{ref_sym.fmt(elf_file)}); | |
| 463 | } else { | |
| 464 | try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)}); | |
| 465 | } | |
| 341 | 466 | } |
| 342 | 467 | } |
| 343 | 468 |
src/link/Elf/Object.zig+232-154| ... | ... | @@ -9,7 +9,9 @@ shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{}, |
| 9 | 9 | symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, |
| 10 | 10 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 11 | 11 | first_global: ?Symbol.Index = null, |
| 12 | symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, | |
| 12 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, | |
| 13 | symbols_extra: std.ArrayListUnmanaged(u32) = .{}, | |
| 14 | symbols_resolver: std.ArrayListUnmanaged(Elf.SymbolResolver.Index) = .{}, | |
| 13 | 15 | relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{}, |
| 14 | 16 | |
| 15 | 17 | atoms: std.ArrayListUnmanaged(Atom) = .{}, |
| ... | ... | @@ -51,6 +53,8 @@ pub fn deinit(self: *Object, allocator: Allocator) void { |
| 51 | 53 | self.symtab.deinit(allocator); |
| 52 | 54 | self.strtab.deinit(allocator); |
| 53 | 55 | self.symbols.deinit(allocator); |
| 56 | self.symbols_extra.deinit(allocator); | |
| 57 | self.symbols_resolver.deinit(allocator); | |
| 54 | 58 | self.atoms.deinit(allocator); |
| 55 | 59 | self.atoms_indexes.deinit(allocator); |
| 56 | 60 | self.atoms_extra.deinit(allocator); |
| ... | ... | @@ -80,7 +84,7 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { |
| 80 | 84 | try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); |
| 81 | 85 | |
| 82 | 86 | try self.initAtoms(gpa, handle, elf_file); |
| 83 | try self.initSymtab(gpa, elf_file); | |
| 87 | try self.initSymbols(gpa, elf_file); | |
| 84 | 88 | |
| 85 | 89 | for (self.shdrs.items, 0..) |shdr, i| { |
| 86 | 90 | const atom_ptr = self.atom(self.atoms_indexes.items[i]) orelse continue; |
| ... | ... | @@ -374,29 +378,29 @@ fn skipShdr(self: *Object, index: u32, elf_file: *Elf) bool { |
| 374 | 378 | return ignore; |
| 375 | 379 | } |
| 376 | 380 | |
| 377 | fn initSymtab(self: *Object, allocator: Allocator, elf_file: *Elf) !void { | |
| 381 | fn initSymbols(self: *Object, allocator: Allocator, elf_file: *Elf) !void { | |
| 378 | 382 | const first_global = self.first_global orelse self.symtab.items.len; |
| 383 | const nglobals = self.symtab.items.len - first_global; | |
| 379 | 384 | |
| 380 | 385 | try self.symbols.ensureTotalCapacityPrecise(allocator, self.symtab.items.len); |
| 381 | ||
| 382 | for (self.symtab.items[0..first_global], 0..) |sym, i| { | |
| 383 | const index = try elf_file.addSymbol(); | |
| 384 | self.symbols.appendAssumeCapacity(index); | |
| 385 | const sym_ptr = elf_file.symbol(index); | |
| 386 | try self.symbols_extra.ensureTotalCapacityPrecise(allocator, self.symtab.items.len * @sizeOf(Symbol.Extra)); | |
| 387 | try self.symbols_resolver.ensureTotalCapacityPrecise(allocator, nglobals); | |
| 388 | self.symbols_resolver.resize(allocator, nglobals) catch unreachable; | |
| 389 | @memset(self.symbols_resolver.items, 0); | |
| 390 | ||
| 391 | for (self.symtab.items, 0..) |sym, i| { | |
| 392 | const index = self.addSymbolAssumeCapacity(); | |
| 393 | const sym_ptr = &self.symbols.items[index]; | |
| 386 | 394 | sym_ptr.value = @intCast(sym.st_value); |
| 387 | 395 | sym_ptr.name_offset = sym.st_name; |
| 388 | sym_ptr.esym_index = @as(u32, @intCast(i)); | |
| 389 | sym_ptr.file_index = self.index; | |
| 390 | if (sym.st_shndx != elf.SHN_ABS) { | |
| 396 | sym_ptr.esym_index = @intCast(i); | |
| 397 | sym_ptr.extra_index = self.addSymbolExtraAssumeCapacity(.{}); | |
| 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; | |
| 400 | if (sym.st_shndx != elf.SHN_ABS and sym.st_shndx != elf.SHN_COMMON) { | |
| 391 | 401 | sym_ptr.ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index }; |
| 392 | 402 | } |
| 393 | 403 | } |
| 394 | ||
| 395 | for (self.symtab.items[first_global..]) |sym| { | |
| 396 | const name = self.getString(sym.st_name); | |
| 397 | const gop = try elf_file.getOrPutGlobal(name); | |
| 398 | self.symbols.addOneAssumeCapacity().* = gop.index; | |
| 399 | } | |
| 400 | 404 | } |
| 401 | 405 | |
| 402 | 406 | fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx: u32, elf_file: *Elf) !void { |
| ... | ... | @@ -543,7 +547,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { |
| 543 | 547 | |
| 544 | 548 | for (self.cies.items) |cie| { |
| 545 | 549 | for (cie.relocs(elf_file)) |rel| { |
| 546 | const sym = elf_file.symbol(self.symbols.items[rel.r_sym()]); | |
| 550 | const sym = elf_file.symbol(self.resolveSymbol(rel.r_sym(), elf_file)).?; | |
| 547 | 551 | if (sym.flags.import) { |
| 548 | 552 | if (sym.type(elf_file) != elf.STT_FUNC) |
| 549 | 553 | // TODO convert into an error |
| ... | ... | @@ -557,49 +561,47 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { |
| 557 | 561 | } |
| 558 | 562 | } |
| 559 | 563 | |
| 560 | pub fn resolveSymbols(self: *Object, elf_file: *Elf) void { | |
| 561 | const first_global = self.first_global orelse return; | |
| 562 | for (self.globals(), 0..) |index, i| { | |
| 563 | const esym_index = @as(Symbol.Index, @intCast(first_global + i)); | |
| 564 | const esym = self.symtab.items[esym_index]; | |
| 565 | ||
| 566 | if (esym.st_shndx == elf.SHN_UNDEF) continue; | |
| 564 | pub fn resolveSymbols(self: *Object, elf_file: *Elf) !void { | |
| 565 | const gpa = elf_file.base.comp.gpa; | |
| 567 | 566 | |
| 568 | if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) { | |
| 567 | const first_global = self.first_global orelse return; | |
| 568 | for (self.globals(), first_global..) |_, i| { | |
| 569 | const esym = self.symtab.items[i]; | |
| 570 | if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON and esym.st_shndx != elf.SHN_UNDEF) { | |
| 569 | 571 | const atom_index = self.atoms_indexes.items[esym.st_shndx]; |
| 570 | 572 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 571 | 573 | if (!atom_ptr.alive) continue; |
| 572 | 574 | } |
| 573 | 575 | |
| 574 | const global = elf_file.symbol(index); | |
| 575 | if (self.asFile().symbolRank(esym, !self.alive) < global.symbolRank(elf_file)) { | |
| 576 | switch (esym.st_shndx) { | |
| 577 | elf.SHN_ABS, elf.SHN_COMMON => {}, | |
| 578 | else => global.ref = .{ | |
| 579 | .index = self.atoms_indexes.items[esym.st_shndx], | |
| 580 | .file = self.index, | |
| 581 | }, | |
| 582 | } | |
| 583 | global.value = @intCast(esym.st_value); | |
| 584 | global.esym_index = esym_index; | |
| 585 | global.file_index = self.index; | |
| 586 | global.version_index = elf_file.default_sym_version; | |
| 587 | if (esym.st_bind() == elf.STB_WEAK) global.flags.weak = true; | |
| 576 | const resolv = &self.symbols_resolver.items[i - first_global]; | |
| 577 | const gop = try elf_file.resolver.getOrPut(gpa, .{ | |
| 578 | .index = @intCast(i), | |
| 579 | .file = self.index, | |
| 580 | }, elf_file); | |
| 581 | if (!gop.found_existing) { | |
| 582 | gop.ref.* = .{ .index = 0, .file = 0 }; | |
| 583 | } | |
| 584 | resolv.* = gop.index; | |
| 585 | ||
| 586 | if (esym.st_shndx == elf.SHN_UNDEF) continue; | |
| 587 | if (elf_file.symbol(gop.ref.*) == null) { | |
| 588 | gop.ref.* = .{ .index = @intCast(i), .file = self.index }; | |
| 589 | continue; | |
| 590 | } | |
| 591 | ||
| 592 | if (self.asFile().symbolRank(esym, !self.alive) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) { | |
| 593 | gop.ref.* = .{ .index = @intCast(i), .file = self.index }; | |
| 588 | 594 | } |
| 589 | 595 | } |
| 590 | 596 | } |
| 591 | 597 | |
| 592 | 598 | pub fn claimUnresolved(self: *Object, elf_file: *Elf) void { |
| 593 | 599 | const first_global = self.first_global orelse return; |
| 594 | for (self.globals(), 0..) |index, i| { | |
| 600 | for (self.globals(), 0..) |*sym, i| { | |
| 595 | 601 | const esym_index = @as(u32, @intCast(first_global + i)); |
| 596 | 602 | const esym = self.symtab.items[esym_index]; |
| 597 | 603 | if (esym.st_shndx != elf.SHN_UNDEF) continue; |
| 598 | ||
| 599 | const global = elf_file.symbol(index); | |
| 600 | if (global.file(elf_file)) |_| { | |
| 601 | if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF) continue; | |
| 602 | } | |
| 604 | if (elf_file.symbol(self.resolveSymbol(esym_index, elf_file)) != null) continue; | |
| 603 | 605 | |
| 604 | 606 | const is_import = blk: { |
| 605 | 607 | if (!elf_file.isEffectivelyDynLib()) break :blk false; |
| ... | ... | @@ -608,45 +610,48 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void { |
| 608 | 610 | break :blk true; |
| 609 | 611 | }; |
| 610 | 612 | |
| 611 | global.value = 0; | |
| 612 | global.ref = .{ .index = 0, .file = 0 }; | |
| 613 | global.esym_index = esym_index; | |
| 614 | global.file_index = self.index; | |
| 615 | global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version; | |
| 616 | global.flags.import = is_import; | |
| 613 | sym.value = 0; | |
| 614 | sym.ref = .{ .index = 0, .file = 0 }; | |
| 615 | sym.esym_index = esym_index; | |
| 616 | sym.file_index = self.index; | |
| 617 | sym.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version; | |
| 618 | sym.flags.import = is_import; | |
| 619 | ||
| 620 | const idx = self.symbols_resolver.items[i]; | |
| 621 | elf_file.resolver.values.items[idx - 1] = .{ .index = esym_index, .file = self.index }; | |
| 617 | 622 | } |
| 618 | 623 | } |
| 619 | 624 | |
| 620 | 625 | pub fn claimUnresolvedObject(self: *Object, elf_file: *Elf) void { |
| 621 | 626 | const first_global = self.first_global orelse return; |
| 622 | for (self.globals(), 0..) |index, i| { | |
| 627 | for (self.globals(), 0..) |*sym, i| { | |
| 623 | 628 | const esym_index = @as(u32, @intCast(first_global + i)); |
| 624 | 629 | const esym = self.symtab.items[esym_index]; |
| 625 | 630 | if (esym.st_shndx != elf.SHN_UNDEF) continue; |
| 631 | if (elf_file.symbol(self.resolveSymbol(esym_index, elf_file)) != null) continue; | |
| 626 | 632 | |
| 627 | const global = elf_file.symbol(index); | |
| 628 | if (global.file(elf_file)) |file| { | |
| 629 | if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or file.index() <= self.index) continue; | |
| 630 | } | |
| 633 | sym.value = 0; | |
| 634 | sym.ref = .{ .index = 0, .file = 0 }; | |
| 635 | sym.esym_index = esym_index; | |
| 636 | sym.file_index = self.index; | |
| 631 | 637 | |
| 632 | global.value = 0; | |
| 633 | global.ref = .{ .index = 0, .file = 0 }; | |
| 634 | global.esym_index = esym_index; | |
| 635 | global.file_index = self.index; | |
| 638 | const idx = self.symbols_resolver.items[i]; | |
| 639 | elf_file.resolver.values.items[idx - 1] = .{ .index = esym_index, .file = self.index }; | |
| 636 | 640 | } |
| 637 | 641 | } |
| 638 | 642 | |
| 639 | 643 | pub fn markLive(self: *Object, elf_file: *Elf) void { |
| 640 | 644 | const first_global = self.first_global orelse return; |
| 641 | for (self.globals(), 0..) |index, i| { | |
| 642 | const sym_idx = first_global + i; | |
| 643 | const sym = self.symtab.items[sym_idx]; | |
| 644 | if (sym.st_bind() == elf.STB_WEAK) continue; | |
| 645 | ||
| 646 | const global = elf_file.symbol(index); | |
| 647 | const file = global.file(elf_file) orelse continue; | |
| 648 | const should_keep = sym.st_shndx == elf.SHN_UNDEF or | |
| 649 | (sym.st_shndx == elf.SHN_COMMON and global.elfSym(elf_file).st_shndx != elf.SHN_COMMON); | |
| 645 | for (0..self.globals().len) |i| { | |
| 646 | const esym_idx = first_global + i; | |
| 647 | const esym = self.symtab.items[esym_idx]; | |
| 648 | if (esym.st_bind() == elf.STB_WEAK) continue; | |
| 649 | ||
| 650 | const ref = self.resolveSymbol(@intCast(esym_idx), elf_file); | |
| 651 | const sym = elf_file.symbol(ref) orelse continue; | |
| 652 | const file = sym.file(elf_file).?; | |
| 653 | const should_keep = esym.st_shndx == elf.SHN_UNDEF or | |
| 654 | (esym.st_shndx == elf.SHN_COMMON and sym.elfSym(elf_file).st_shndx != elf.SHN_COMMON); | |
| 650 | 655 | if (should_keep and !file.isAlive()) { |
| 651 | 656 | file.setAlive(); |
| 652 | 657 | file.markLive(elf_file); |
| ... | ... | @@ -664,26 +669,50 @@ pub fn markEhFrameAtomsDead(self: *Object, elf_file: *Elf) void { |
| 664 | 669 | } |
| 665 | 670 | } |
| 666 | 671 | |
| 672 | pub fn markImportsExports(self: *Object, elf_file: *Elf) void { | |
| 673 | const first_global = self.first_global orelse return; | |
| 674 | for (0..self.globals().len) |i| { | |
| 675 | const idx = first_global + i; | |
| 676 | const ref = self.resolveSymbol(@intCast(idx), elf_file); | |
| 677 | const sym = elf_file.symbol(ref) orelse continue; | |
| 678 | const file = sym.file(elf_file).?; | |
| 679 | if (sym.version_index == elf.VER_NDX_LOCAL) continue; | |
| 680 | const vis = @as(elf.STV, @enumFromInt(sym.elfSym(elf_file).st_other)); | |
| 681 | if (vis == .HIDDEN) continue; | |
| 682 | if (file == .shared_object and !sym.isAbs(elf_file)) { | |
| 683 | sym.flags.import = true; | |
| 684 | continue; | |
| 685 | } | |
| 686 | if (file.index() == self.index) { | |
| 687 | sym.flags.@"export" = true; | |
| 688 | if (elf_file.isEffectivelyDynLib() and vis != .PROTECTED) { | |
| 689 | sym.flags.import = true; | |
| 690 | } | |
| 691 | } | |
| 692 | } | |
| 693 | } | |
| 694 | ||
| 667 | 695 | pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void { |
| 668 | 696 | const first_global = self.first_global orelse return; |
| 669 | for (self.globals(), 0..) |index, i| { | |
| 670 | const sym_idx = first_global + i; | |
| 671 | const sym = self.symtab.items[sym_idx]; | |
| 672 | const global = elf_file.symbol(index); | |
| 673 | const global_file = global.file(elf_file) orelse continue; | |
| 674 | ||
| 675 | if (self.index == global_file.index() or | |
| 676 | sym.st_shndx == elf.SHN_UNDEF or | |
| 677 | sym.st_bind() == elf.STB_WEAK or | |
| 678 | sym.st_shndx == elf.SHN_COMMON) continue; | |
| 679 | ||
| 680 | if (sym.st_shndx != elf.SHN_ABS) { | |
| 681 | const atom_index = self.atoms_indexes.items[sym.st_shndx]; | |
| 697 | for (0..self.globals().len) |i| { | |
| 698 | const esym_idx = first_global + i; | |
| 699 | const esym = self.symtab.items[esym_idx]; | |
| 700 | const ref = self.resolveSymbol(@intCast(esym_idx), elf_file); | |
| 701 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 702 | const ref_file = ref_sym.file(elf_file).?; | |
| 703 | ||
| 704 | if (self.index == ref_file.index() or | |
| 705 | esym.st_shndx == elf.SHN_UNDEF or | |
| 706 | esym.st_bind() == elf.STB_WEAK or | |
| 707 | esym.st_shndx == elf.SHN_COMMON) continue; | |
| 708 | ||
| 709 | if (esym.st_shndx != elf.SHN_ABS) { | |
| 710 | const atom_index = self.atoms_indexes.items[esym.st_shndx]; | |
| 682 | 711 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 683 | 712 | if (!atom_ptr.alive) continue; |
| 684 | 713 | } |
| 685 | 714 | |
| 686 | const gop = try dupes.getOrPut(index); | |
| 715 | const gop = try dupes.getOrPut(self.symbols_resolver.items[i]); | |
| 687 | 716 | if (!gop.found_existing) { |
| 688 | 717 | gop.value_ptr.* = .{}; |
| 689 | 718 | } |
| ... | ... | @@ -813,9 +842,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 813 | 842 | } |
| 814 | 843 | |
| 815 | 844 | for (self.symtab.items, 0..) |*esym, idx| { |
| 816 | const sym_index = self.symbols.items[idx]; | |
| 817 | const sym = elf_file.symbol(sym_index); | |
| 818 | ||
| 845 | const sym = &self.symbols.items[idx]; | |
| 819 | 846 | if (esym.st_shndx == elf.SHN_COMMON or esym.st_shndx == elf.SHN_UNDEF or esym.st_shndx == elf.SHN_ABS) continue; |
| 820 | 847 | |
| 821 | 848 | const imsec_index = self.input_merge_sections_indexes.items[esym.st_shndx]; |
| ... | ... | @@ -854,22 +881,20 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 854 | 881 | return error.MalformedObject; |
| 855 | 882 | }; |
| 856 | 883 | |
| 857 | const out_sym_idx: u64 = @intCast(self.symbols.items.len); | |
| 858 | try self.symbols.ensureUnusedCapacity(gpa, 1); | |
| 884 | const sym_index = try self.addSymbol(gpa); | |
| 885 | const sym = &self.symbols.items[sym_index]; | |
| 859 | 886 | const name = try std.fmt.allocPrint(gpa, "{s}$subsection{d}", .{ msec.name(elf_file), res.msub_index }); |
| 860 | 887 | defer gpa.free(name); |
| 861 | const sym_index = try elf_file.addSymbol(); | |
| 862 | const sym = elf_file.symbol(sym_index); | |
| 863 | 888 | sym.* = .{ |
| 864 | 889 | .value = @bitCast(@as(i64, @intCast(res.offset)) - rel.r_addend), |
| 865 | 890 | .name_offset = try self.addString(gpa, name), |
| 866 | 891 | .esym_index = rel.r_sym(), |
| 867 | 892 | .file_index = self.index, |
| 893 | .extra_index = try self.addSymbolExtra(gpa, .{}), | |
| 868 | 894 | }; |
| 869 | 895 | sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index }; |
| 870 | 896 | sym.flags.merge_subsection = true; |
| 871 | self.symbols.addOneAssumeCapacity().* = sym_index; | |
| 872 | rel.r_info = (out_sym_idx << 32) | rel.r_type(); | |
| 897 | rel.r_info = (@as(u64, @intCast(sym_index)) << 32) | rel.r_type(); | |
| 873 | 898 | } |
| 874 | 899 | } |
| 875 | 900 | } |
| ... | ... | @@ -878,27 +903,16 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 878 | 903 | /// play nicely with the rest of the system. |
| 879 | 904 | pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { |
| 880 | 905 | const first_global = self.first_global orelse return; |
| 881 | for (self.globals(), 0..) |index, i| { | |
| 882 | const sym_idx = @as(u32, @intCast(first_global + i)); | |
| 883 | const this_sym = self.symtab.items[sym_idx]; | |
| 884 | if (this_sym.st_shndx != elf.SHN_COMMON) continue; | |
| 885 | ||
| 886 | const global = elf_file.symbol(index); | |
| 887 | const global_file = global.file(elf_file).?; | |
| 888 | if (global_file.index() != self.index) { | |
| 889 | // if (elf_file.options.warn_common) { | |
| 890 | // elf_file.base.warn("{}: multiple common symbols: {s}", .{ | |
| 891 | // self.fmtPath(), | |
| 892 | // global.getName(elf_file), | |
| 893 | // }); | |
| 894 | // } | |
| 895 | continue; | |
| 896 | } | |
| 906 | for (self.globals(), self.symbols_resolver.items, 0..) |*sym, resolv, i| { | |
| 907 | const esym_idx = @as(u32, @intCast(first_global + i)); | |
| 908 | const esym = self.symtab.items[esym_idx]; | |
| 909 | if (esym.st_shndx != elf.SHN_COMMON) continue; | |
| 910 | if (elf_file.resolver.get(resolv).?.file != self.index) continue; | |
| 897 | 911 | |
| 898 | 912 | const comp = elf_file.base.comp; |
| 899 | 913 | const gpa = comp.gpa; |
| 900 | 914 | |
| 901 | const is_tls = global.type(elf_file) == elf.STT_TLS; | |
| 915 | const is_tls = sym.type(elf_file) == elf.STT_TLS; | |
| 902 | 916 | const name = if (is_tls) ".tls_common" else ".common"; |
| 903 | 917 | const name_offset = @as(u32, @intCast(self.strtab.items.len)); |
| 904 | 918 | try self.strtab.writer(gpa).print("{s}\x00", .{name}); |
| ... | ... | @@ -907,7 +921,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { |
| 907 | 921 | if (is_tls) sh_flags |= elf.SHF_TLS; |
| 908 | 922 | const shndx = @as(u32, @intCast(self.shdrs.items.len)); |
| 909 | 923 | const shdr = try self.shdrs.addOne(gpa); |
| 910 | const sh_size = math.cast(usize, this_sym.st_size) orelse return error.Overflow; | |
| 924 | const sh_size = math.cast(usize, esym.st_size) orelse return error.Overflow; | |
| 911 | 925 | shdr.* = .{ |
| 912 | 926 | .sh_name = name_offset, |
| 913 | 927 | .sh_type = elf.SHT_NOBITS, |
| ... | ... | @@ -917,21 +931,21 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { |
| 917 | 931 | .sh_size = sh_size, |
| 918 | 932 | .sh_link = 0, |
| 919 | 933 | .sh_info = 0, |
| 920 | .sh_addralign = this_sym.st_value, | |
| 934 | .sh_addralign = esym.st_value, | |
| 921 | 935 | .sh_entsize = 0, |
| 922 | 936 | }; |
| 923 | 937 | |
| 924 | 938 | const atom_index = try self.addAtom(gpa, .{ |
| 925 | 939 | .name = name_offset, |
| 926 | 940 | .shndx = shndx, |
| 927 | .size = this_sym.st_size, | |
| 928 | .alignment = Alignment.fromNonzeroByteUnits(this_sym.st_value), | |
| 941 | .size = esym.st_size, | |
| 942 | .alignment = Alignment.fromNonzeroByteUnits(esym.st_value), | |
| 929 | 943 | }); |
| 930 | 944 | try self.atoms_indexes.append(gpa, atom_index); |
| 931 | 945 | |
| 932 | global.value = 0; | |
| 933 | global.ref = .{ .index = atom_index, .file = self.index }; | |
| 934 | global.flags.weak = false; | |
| 946 | sym.value = 0; | |
| 947 | sym.ref = .{ .index = atom_index, .file = self.index }; | |
| 948 | sym.flags.weak = false; | |
| 935 | 949 | } |
| 936 | 950 | } |
| 937 | 951 | |
| ... | ... | @@ -1073,7 +1087,7 @@ pub fn writeAr(self: Object, elf_file: *Elf, writer: anytype) !void { |
| 1073 | 1087 | try writer.writeAll(data); |
| 1074 | 1088 | } |
| 1075 | 1089 | |
| 1076 | pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void { | |
| 1090 | pub fn updateSymtabSize(self: *Object, elf_file: *Elf) void { | |
| 1077 | 1091 | const isAlive = struct { |
| 1078 | 1092 | fn isAlive(sym: *const Symbol, ctx: *Elf) bool { |
| 1079 | 1093 | if (sym.mergeSubsection(ctx)) |msub| return msub.alive; |
| ... | ... | @@ -1082,8 +1096,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void { |
| 1082 | 1096 | } |
| 1083 | 1097 | }.isAlive; |
| 1084 | 1098 | |
| 1085 | for (self.locals()) |local_index| { | |
| 1086 | const local = elf_file.symbol(local_index); | |
| 1099 | for (self.locals()) |*local| { | |
| 1087 | 1100 | if (!isAlive(local, elf_file)) continue; |
| 1088 | 1101 | const esym = local.elfSym(elf_file); |
| 1089 | 1102 | switch (esym.st_type()) { |
| ... | ... | @@ -1092,31 +1105,30 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void { |
| 1092 | 1105 | else => {}, |
| 1093 | 1106 | } |
| 1094 | 1107 | local.flags.output_symtab = true; |
| 1095 | try local.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); | |
| 1108 | local.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); | |
| 1096 | 1109 | self.output_symtab_ctx.nlocals += 1; |
| 1097 | 1110 | self.output_symtab_ctx.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1; |
| 1098 | 1111 | } |
| 1099 | 1112 | |
| 1100 | for (self.globals()) |global_index| { | |
| 1101 | const global = elf_file.symbol(global_index); | |
| 1102 | const file_ptr = global.file(elf_file) orelse continue; | |
| 1103 | if (file_ptr.index() != self.index) continue; | |
| 1113 | for (self.globals(), self.symbols_resolver.items) |*global, resolv| { | |
| 1114 | const ref = elf_file.resolver.values.items[resolv - 1]; | |
| 1115 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 1116 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 1104 | 1117 | if (!isAlive(global, elf_file)) continue; |
| 1105 | 1118 | global.flags.output_symtab = true; |
| 1106 | 1119 | if (global.isLocal(elf_file)) { |
| 1107 | try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); | |
| 1120 | global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); | |
| 1108 | 1121 | self.output_symtab_ctx.nlocals += 1; |
| 1109 | 1122 | } else { |
| 1110 | try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file); | |
| 1123 | global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file); | |
| 1111 | 1124 | self.output_symtab_ctx.nglobals += 1; |
| 1112 | 1125 | } |
| 1113 | 1126 | self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1; |
| 1114 | 1127 | } |
| 1115 | 1128 | } |
| 1116 | 1129 | |
| 1117 | pub fn writeSymtab(self: Object, elf_file: *Elf) void { | |
| 1118 | for (self.locals()) |local_index| { | |
| 1119 | const local = elf_file.symbol(local_index); | |
| 1130 | pub fn writeSymtab(self: *Object, elf_file: *Elf) void { | |
| 1131 | for (self.locals()) |local| { | |
| 1120 | 1132 | const idx = local.outputSymtabIndex(elf_file) orelse continue; |
| 1121 | 1133 | const out_sym = &elf_file.symtab.items[idx]; |
| 1122 | 1134 | out_sym.st_name = @intCast(elf_file.strtab.items.len); |
| ... | ... | @@ -1125,10 +1137,10 @@ pub fn writeSymtab(self: Object, elf_file: *Elf) void { |
| 1125 | 1137 | local.setOutputSym(elf_file, out_sym); |
| 1126 | 1138 | } |
| 1127 | 1139 | |
| 1128 | for (self.globals()) |global_index| { | |
| 1129 | const global = elf_file.symbol(global_index); | |
| 1130 | const file_ptr = global.file(elf_file) orelse continue; | |
| 1131 | if (file_ptr.index() != self.index) continue; | |
| 1140 | for (self.globals(), self.symbols_resolver.items) |global, resolv| { | |
| 1141 | const ref = elf_file.resolver.values.items[resolv - 1]; | |
| 1142 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 1143 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 1132 | 1144 | const idx = global.outputSymtabIndex(elf_file) orelse continue; |
| 1133 | 1145 | const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); |
| 1134 | 1146 | elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file)); |
| ... | ... | @@ -1139,20 +1151,6 @@ pub fn writeSymtab(self: Object, elf_file: *Elf) void { |
| 1139 | 1151 | } |
| 1140 | 1152 | } |
| 1141 | 1153 | |
| 1142 | pub fn locals(self: Object) []const Symbol.Index { | |
| 1143 | if (self.symbols.items.len == 0) return &[0]Symbol.Index{}; | |
| 1144 | assert(self.symbols.items.len >= self.symtab.items.len); | |
| 1145 | const end = self.first_global orelse self.symtab.items.len; | |
| 1146 | return self.symbols.items[0..end]; | |
| 1147 | } | |
| 1148 | ||
| 1149 | pub fn globals(self: Object) []const Symbol.Index { | |
| 1150 | if (self.symbols.items.len == 0) return &[0]Symbol.Index{}; | |
| 1151 | assert(self.symbols.items.len >= self.symtab.items.len); | |
| 1152 | const start = self.first_global orelse self.symtab.items.len; | |
| 1153 | return self.symbols.items[start..self.symtab.items.len]; | |
| 1154 | } | |
| 1155 | ||
| 1156 | 1154 | /// Returns atom's code and optionally uncompresses data if required (for compressed sections). |
| 1157 | 1155 | /// Caller owns the memory. |
| 1158 | 1156 | pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { |
| ... | ... | @@ -1185,6 +1183,81 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index |
| 1185 | 1183 | return data; |
| 1186 | 1184 | } |
| 1187 | 1185 | |
| 1186 | fn locals(self: *Object) []Symbol { | |
| 1187 | if (self.symbols.items.len == 0) return &[0]Symbol{}; | |
| 1188 | assert(self.symbols.items.len >= self.symtab.items.len); | |
| 1189 | const end = self.first_global orelse self.symtab.items.len; | |
| 1190 | return self.symbols.items[0..end]; | |
| 1191 | } | |
| 1192 | ||
| 1193 | pub fn globals(self: *Object) []Symbol { | |
| 1194 | if (self.symbols.items.len == 0) return &[0]Symbol{}; | |
| 1195 | assert(self.symbols.items.len >= self.symtab.items.len); | |
| 1196 | const start = self.first_global orelse self.symtab.items.len; | |
| 1197 | return self.symbols.items[start..self.symtab.items.len]; | |
| 1198 | } | |
| 1199 | ||
| 1200 | pub fn resolveSymbol(self: Object, index: Symbol.Index, elf_file: *Elf) Elf.Ref { | |
| 1201 | const start = self.first_global orelse self.symtab.items.len; | |
| 1202 | const end = self.symtab.items.len; | |
| 1203 | if (index < start or index >= end) return .{ .index = index, .file = self.index }; | |
| 1204 | const resolv = self.symbols_resolver.items[index - start]; | |
| 1205 | return elf_file.resolver.get(resolv).?; | |
| 1206 | } | |
| 1207 | ||
| 1208 | fn addSymbol(self: *Object, allocator: Allocator) !Symbol.Index { | |
| 1209 | try self.symbols.ensureUnusedCapacity(allocator, 1); | |
| 1210 | return self.addSymbolAssumeCapacity(); | |
| 1211 | } | |
| 1212 | ||
| 1213 | fn addSymbolAssumeCapacity(self: *Object) Symbol.Index { | |
| 1214 | const index: Symbol.Index = @intCast(self.symbols.items.len); | |
| 1215 | self.symbols.appendAssumeCapacity(.{ .file_index = self.index }); | |
| 1216 | return index; | |
| 1217 | } | |
| 1218 | ||
| 1219 | pub fn addSymbolExtra(self: *Object, allocator: Allocator, extra: Symbol.Extra) !u32 { | |
| 1220 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 1221 | try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len); | |
| 1222 | return self.addSymbolExtraAssumeCapacity(extra); | |
| 1223 | } | |
| 1224 | ||
| 1225 | pub fn addSymbolExtraAssumeCapacity(self: *Object, extra: Symbol.Extra) u32 { | |
| 1226 | const index = @as(u32, @intCast(self.symbols_extra.items.len)); | |
| 1227 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 1228 | inline for (fields) |field| { | |
| 1229 | self.symbols_extra.appendAssumeCapacity(switch (field.type) { | |
| 1230 | u32 => @field(extra, field.name), | |
| 1231 | else => @compileError("bad field type"), | |
| 1232 | }); | |
| 1233 | } | |
| 1234 | return index; | |
| 1235 | } | |
| 1236 | ||
| 1237 | pub fn symbolExtra(self: *Object, index: u32) Symbol.Extra { | |
| 1238 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 1239 | var i: usize = index; | |
| 1240 | var result: Symbol.Extra = undefined; | |
| 1241 | inline for (fields) |field| { | |
| 1242 | @field(result, field.name) = switch (field.type) { | |
| 1243 | u32 => self.symbols_extra.items[i], | |
| 1244 | else => @compileError("bad field type"), | |
| 1245 | }; | |
| 1246 | i += 1; | |
| 1247 | } | |
| 1248 | return result; | |
| 1249 | } | |
| 1250 | ||
| 1251 | pub fn setSymbolExtra(self: *Object, index: u32, extra: Symbol.Extra) void { | |
| 1252 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 1253 | inline for (fields, 0..) |field, i| { | |
| 1254 | self.symbols_extra.items[index + i] = switch (field.type) { | |
| 1255 | u32 => @field(extra, field.name), | |
| 1256 | else => @compileError("bad field type"), | |
| 1257 | }; | |
| 1258 | } | |
| 1259 | } | |
| 1260 | ||
| 1188 | 1261 | pub fn asFile(self: *Object) File { |
| 1189 | 1262 | return .{ .object = self }; |
| 1190 | 1263 | } |
| ... | ... | @@ -1352,15 +1425,20 @@ fn formatSymtab( |
| 1352 | 1425 | _ = unused_fmt_string; |
| 1353 | 1426 | _ = options; |
| 1354 | 1427 | const object = ctx.object; |
| 1428 | const elf_file = ctx.elf_file; | |
| 1355 | 1429 | try writer.writeAll(" locals\n"); |
| 1356 | for (object.locals()) |index| { | |
| 1357 | const local = ctx.elf_file.symbol(index); | |
| 1358 | try writer.print(" {}\n", .{local.fmt(ctx.elf_file)}); | |
| 1430 | for (object.locals()) |sym| { | |
| 1431 | try writer.print(" {}\n", .{sym.fmt(elf_file)}); | |
| 1359 | 1432 | } |
| 1360 | 1433 | try writer.writeAll(" globals\n"); |
| 1361 | for (object.globals()) |index| { | |
| 1362 | const global = ctx.elf_file.symbol(index); | |
| 1363 | try writer.print(" {}\n", .{global.fmt(ctx.elf_file)}); | |
| 1434 | for (object.globals(), 0..) |sym, i| { | |
| 1435 | const first_global = object.first_global.?; | |
| 1436 | const ref = object.resolveSymbol(@intCast(i + first_global), elf_file); | |
| 1437 | if (elf_file.symbol(ref)) |ref_sym| { | |
| 1438 | try writer.print(" {}\n", .{ref_sym.fmt(elf_file)}); | |
| 1439 | } else { | |
| 1440 | try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)}); | |
| 1441 | } | |
| 1364 | 1442 | } |
| 1365 | 1443 | } |
| 1366 | 1444 |
src/link/Elf/SharedObject.zig+163-62| ... | ... | @@ -10,7 +10,10 @@ strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 10 | 10 | versyms: std.ArrayListUnmanaged(elf.Elf64_Versym) = .{}, |
| 11 | 11 | verstrings: std.ArrayListUnmanaged(u32) = .{}, |
| 12 | 12 | |
| 13 | symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, | |
| 13 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, | |
| 14 | symbols_extra: std.ArrayListUnmanaged(u32) = .{}, | |
| 15 | symbols_resolver: std.ArrayListUnmanaged(Elf.SymbolResolver.Index) = .{}, | |
| 16 | ||
| 14 | 17 | aliases: ?std.ArrayListUnmanaged(u32) = null, |
| 15 | 18 | dynamic_table: std.ArrayListUnmanaged(elf.Elf64_Dyn) = .{}, |
| 16 | 19 | |
| ... | ... | @@ -38,6 +41,8 @@ pub fn deinit(self: *SharedObject, allocator: Allocator) void { |
| 38 | 41 | self.versyms.deinit(allocator); |
| 39 | 42 | self.verstrings.deinit(allocator); |
| 40 | 43 | self.symbols.deinit(allocator); |
| 44 | self.symbols_extra.deinit(allocator); | |
| 45 | self.symbols_resolver.deinit(allocator); | |
| 41 | 46 | if (self.aliases) |*aliases| aliases.deinit(allocator); |
| 42 | 47 | self.dynamic_table.deinit(allocator); |
| 43 | 48 | } |
| ... | ... | @@ -129,7 +134,7 @@ pub fn parse(self: *SharedObject, elf_file: *Elf, handle: std.fs.File) !void { |
| 129 | 134 | .versym_sect_index = versym_sect_index, |
| 130 | 135 | }); |
| 131 | 136 | |
| 132 | try self.initSymtab(elf_file, .{ | |
| 137 | try self.initSymbols(elf_file, .{ | |
| 133 | 138 | .symtab = symtab, |
| 134 | 139 | .strtab = strtab, |
| 135 | 140 | }); |
| ... | ... | @@ -188,16 +193,20 @@ fn parseVersions(self: *SharedObject, elf_file: *Elf, handle: std.fs.File, opts: |
| 188 | 193 | } |
| 189 | 194 | } |
| 190 | 195 | |
| 191 | fn initSymtab(self: *SharedObject, elf_file: *Elf, opts: struct { | |
| 196 | fn initSymbols(self: *SharedObject, elf_file: *Elf, opts: struct { | |
| 192 | 197 | symtab: []align(1) const elf.Elf64_Sym, |
| 193 | 198 | strtab: []const u8, |
| 194 | 199 | }) !void { |
| 195 | const comp = elf_file.base.comp; | |
| 196 | const gpa = comp.gpa; | |
| 200 | const gpa = elf_file.base.comp.gpa; | |
| 201 | const nsyms = opts.symtab.len; | |
| 197 | 202 | |
| 198 | 203 | try self.strtab.appendSlice(gpa, opts.strtab); |
| 199 | try self.symtab.ensureTotalCapacityPrecise(gpa, opts.symtab.len); | |
| 200 | try self.symbols.ensureTotalCapacityPrecise(gpa, opts.symtab.len); | |
| 204 | try self.symtab.ensureTotalCapacityPrecise(gpa, nsyms); | |
| 205 | try self.symbols.ensureTotalCapacityPrecise(gpa, nsyms); | |
| 206 | try self.symbols_extra.ensureTotalCapacityPrecise(gpa, nsyms * @sizeOf(Symbol.Extra)); | |
| 207 | try self.symbols_resolver.ensureTotalCapacityPrecise(gpa, nsyms); | |
| 208 | self.symbols_resolver.resize(gpa, nsyms) catch unreachable; | |
| 209 | @memset(self.symbols_resolver.items, 0); | |
| 201 | 210 | |
| 202 | 211 | for (opts.symtab, 0..) |sym, i| { |
| 203 | 212 | const hidden = self.versyms.items[i] & elf.VERSYM_HIDDEN != 0; |
| ... | ... | @@ -210,45 +219,57 @@ fn initSymtab(self: *SharedObject, elf_file: *Elf, opts: struct { |
| 210 | 219 | self.versionString(self.versyms.items[i]), |
| 211 | 220 | }); |
| 212 | 221 | defer gpa.free(mangled); |
| 213 | const name_off = @as(u32, @intCast(self.strtab.items.len)); | |
| 214 | try self.strtab.writer(gpa).print("{s}\x00", .{mangled}); | |
| 215 | break :blk name_off; | |
| 222 | break :blk try self.addString(gpa, mangled); | |
| 216 | 223 | } else sym.st_name; |
| 217 | const out_sym = self.symtab.addOneAssumeCapacity(); | |
| 218 | out_sym.* = sym; | |
| 219 | out_sym.st_name = name_off; | |
| 220 | const gop = try elf_file.getOrPutGlobal(self.getString(name_off)); | |
| 221 | self.symbols.addOneAssumeCapacity().* = gop.index; | |
| 224 | const out_esym_index: u32 = @intCast(self.symtab.items.len); | |
| 225 | const out_esym = self.symtab.addOneAssumeCapacity(); | |
| 226 | out_esym.* = sym; | |
| 227 | out_esym.st_name = name_off; | |
| 228 | const out_sym_index = self.addSymbolAssumeCapacity(); | |
| 229 | const out_sym = &self.symbols.items[out_sym_index]; | |
| 230 | out_sym.value = @intCast(out_esym.st_value); | |
| 231 | out_sym.name_offset = name_off; | |
| 232 | out_sym.ref = .{ .index = 0, .file = 0 }; | |
| 233 | out_sym.esym_index = out_esym_index; | |
| 234 | out_sym.version_index = self.versyms.items[out_esym_index]; | |
| 235 | out_sym.extra_index = self.addSymbolExtraAssumeCapacity(.{}); | |
| 222 | 236 | } |
| 223 | 237 | } |
| 224 | 238 | |
| 225 | pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) void { | |
| 226 | for (self.globals(), 0..) |index, i| { | |
| 227 | const esym_index = @as(u32, @intCast(i)); | |
| 228 | const this_sym = self.symtab.items[esym_index]; | |
| 239 | pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) !void { | |
| 240 | const gpa = elf_file.base.comp.gpa; | |
| 241 | ||
| 242 | for (self.symtab.items, self.symbols_resolver.items, 0..) |esym, *resolv, i| { | |
| 243 | const gop = try elf_file.resolver.getOrPut(gpa, .{ | |
| 244 | .index = @intCast(i), | |
| 245 | .file = self.index, | |
| 246 | }, elf_file); | |
| 247 | if (!gop.found_existing) { | |
| 248 | gop.ref.* = .{ .index = 0, .file = 0 }; | |
| 249 | } | |
| 250 | resolv.* = gop.index; | |
| 229 | 251 | |
| 230 | if (this_sym.st_shndx == elf.SHN_UNDEF) continue; | |
| 252 | if (esym.st_shndx == elf.SHN_UNDEF) continue; | |
| 253 | if (elf_file.symbol(gop.ref.*) == null) { | |
| 254 | gop.ref.* = .{ .index = @intCast(i), .file = self.index }; | |
| 255 | continue; | |
| 256 | } | |
| 231 | 257 | |
| 232 | const global = elf_file.symbol(index); | |
| 233 | if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) { | |
| 234 | global.value = @intCast(this_sym.st_value); | |
| 235 | global.ref = .{ .index = 0, .file = 0 }; | |
| 236 | global.esym_index = esym_index; | |
| 237 | global.version_index = self.versyms.items[esym_index]; | |
| 238 | global.file_index = self.index; | |
| 258 | if (self.asFile().symbolRank(esym, false) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) { | |
| 259 | gop.ref.* = .{ .index = @intCast(i), .file = self.index }; | |
| 239 | 260 | } |
| 240 | 261 | } |
| 241 | 262 | } |
| 242 | 263 | |
| 243 | 264 | pub fn markLive(self: *SharedObject, elf_file: *Elf) void { |
| 244 | for (self.globals(), 0..) |index, i| { | |
| 245 | const sym = self.symtab.items[i]; | |
| 246 | if (sym.st_shndx != elf.SHN_UNDEF) continue; | |
| 265 | for (self.symtab.items, 0..) |esym, i| { | |
| 266 | if (esym.st_shndx != elf.SHN_UNDEF) continue; | |
| 247 | 267 | |
| 248 | const global = elf_file.symbol(index); | |
| 249 | const file = global.file(elf_file) orelse continue; | |
| 268 | const ref = self.resolveSymbol(@intCast(i), elf_file); | |
| 269 | const sym = elf_file.symbol(ref) orelse continue; | |
| 270 | const file = sym.file(elf_file).?; | |
| 250 | 271 | const should_drop = switch (file) { |
| 251 | .shared_object => |sh| !sh.needed and sym.st_bind() == elf.STB_WEAK, | |
| 272 | .shared_object => |sh| !sh.needed and esym.st_bind() == elf.STB_WEAK, | |
| 252 | 273 | else => false, |
| 253 | 274 | }; |
| 254 | 275 | if (!should_drop and !file.isAlive()) { |
| ... | ... | @@ -258,28 +279,34 @@ pub fn markLive(self: *SharedObject, elf_file: *Elf) void { |
| 258 | 279 | } |
| 259 | 280 | } |
| 260 | 281 | |
| 261 | pub fn globals(self: SharedObject) []const Symbol.Index { | |
| 262 | return self.symbols.items; | |
| 282 | pub fn markImportExports(self: *SharedObject, elf_file: *Elf) void { | |
| 283 | for (0..self.symbols.items.len) |i| { | |
| 284 | const ref = self.resolveSymbol(@intCast(i), elf_file); | |
| 285 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 286 | const ref_file = ref_sym.file(elf_file).?; | |
| 287 | const vis = @as(elf.STV, @enumFromInt(ref_sym.elfSym(elf_file).st_other)); | |
| 288 | if (ref_file != .shared_object and vis != .HIDDEN) ref_sym.flags.@"export" = true; | |
| 289 | } | |
| 263 | 290 | } |
| 264 | 291 | |
| 265 | pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) !void { | |
| 266 | for (self.globals()) |global_index| { | |
| 267 | const global = elf_file.symbol(global_index); | |
| 268 | const file_ptr = global.file(elf_file) orelse continue; | |
| 269 | if (file_ptr.index() != self.index) continue; | |
| 292 | pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) void { | |
| 293 | for (self.symbols.items, self.symbols_resolver.items) |*global, resolv| { | |
| 294 | const ref = elf_file.resolver.get(resolv).?; | |
| 295 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 296 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 270 | 297 | if (global.isLocal(elf_file)) continue; |
| 271 | 298 | global.flags.output_symtab = true; |
| 272 | try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file); | |
| 299 | global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file); | |
| 273 | 300 | self.output_symtab_ctx.nglobals += 1; |
| 274 | 301 | self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1; |
| 275 | 302 | } |
| 276 | 303 | } |
| 277 | 304 | |
| 278 | pub fn writeSymtab(self: SharedObject, elf_file: *Elf) void { | |
| 279 | for (self.globals()) |global_index| { | |
| 280 | const global = elf_file.symbol(global_index); | |
| 281 | const file_ptr = global.file(elf_file) orelse continue; | |
| 282 | if (file_ptr.index() != self.index) continue; | |
| 305 | pub fn writeSymtab(self: *SharedObject, elf_file: *Elf) void { | |
| 306 | for (self.symbols.items, self.symbols_resolver.items) |global, resolv| { | |
| 307 | const ref = elf_file.resolver.get(resolv).?; | |
| 308 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 309 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 283 | 310 | const idx = global.outputSymtabIndex(elf_file) orelse continue; |
| 284 | 311 | const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); |
| 285 | 312 | elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file)); |
| ... | ... | @@ -319,9 +346,12 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void { |
| 319 | 346 | assert(self.aliases == null); |
| 320 | 347 | |
| 321 | 348 | const SortAlias = struct { |
| 322 | pub fn lessThan(ctx: *Elf, lhs: Symbol.Index, rhs: Symbol.Index) bool { | |
| 323 | const lhs_sym = ctx.symbol(lhs).elfSym(ctx); | |
| 324 | const rhs_sym = ctx.symbol(rhs).elfSym(ctx); | |
| 349 | so: *SharedObject, | |
| 350 | ef: *Elf, | |
| 351 | ||
| 352 | pub fn lessThan(ctx: @This(), lhs: Symbol.Index, rhs: Symbol.Index) bool { | |
| 353 | const lhs_sym = ctx.so.symbols.items[lhs].elfSym(ctx.ef); | |
| 354 | const rhs_sym = ctx.so.symbols.items[rhs].elfSym(ctx.ef); | |
| 325 | 355 | return lhs_sym.st_value < rhs_sym.st_value; |
| 326 | 356 | } |
| 327 | 357 | }; |
| ... | ... | @@ -330,16 +360,16 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void { |
| 330 | 360 | const gpa = comp.gpa; |
| 331 | 361 | var aliases = std.ArrayList(Symbol.Index).init(gpa); |
| 332 | 362 | defer aliases.deinit(); |
| 333 | try aliases.ensureTotalCapacityPrecise(self.globals().len); | |
| 363 | try aliases.ensureTotalCapacityPrecise(self.symbols.items.len); | |
| 334 | 364 | |
| 335 | for (self.globals()) |index| { | |
| 336 | const global = elf_file.symbol(index); | |
| 337 | const global_file = global.file(elf_file) orelse continue; | |
| 338 | if (global_file.index() != self.index) continue; | |
| 339 | aliases.appendAssumeCapacity(index); | |
| 365 | for (self.symbols_resolver.items, 0..) |resolv, index| { | |
| 366 | const ref = elf_file.resolver.get(resolv).?; | |
| 367 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 368 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 369 | aliases.appendAssumeCapacity(@intCast(index)); | |
| 340 | 370 | } |
| 341 | 371 | |
| 342 | std.mem.sort(u32, aliases.items, elf_file, SortAlias.lessThan); | |
| 372 | std.mem.sort(u32, aliases.items, SortAlias{ .so = self, .ef = elf_file }, SortAlias.lessThan); | |
| 343 | 373 | |
| 344 | 374 | self.aliases = aliases.moveToUnmanaged(); |
| 345 | 375 | } |
| ... | ... | @@ -347,27 +377,93 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void { |
| 347 | 377 | pub fn symbolAliases(self: *SharedObject, index: u32, elf_file: *Elf) []const u32 { |
| 348 | 378 | assert(self.aliases != null); |
| 349 | 379 | |
| 350 | const symbol = elf_file.symbol(index).elfSym(elf_file); | |
| 380 | const symbol = self.symbols.items[index].elfSym(elf_file); | |
| 351 | 381 | const aliases = self.aliases.?; |
| 352 | 382 | |
| 353 | 383 | const start = for (aliases.items, 0..) |alias, i| { |
| 354 | const alias_sym = elf_file.symbol(alias).elfSym(elf_file); | |
| 384 | const alias_sym = self.symbols.items[alias].elfSym(elf_file); | |
| 355 | 385 | if (symbol.st_value == alias_sym.st_value) break i; |
| 356 | 386 | } else aliases.items.len; |
| 357 | 387 | |
| 358 | 388 | const end = for (aliases.items[start..], 0..) |alias, i| { |
| 359 | const alias_sym = elf_file.symbol(alias).elfSym(elf_file); | |
| 389 | const alias_sym = self.symbols.items[alias].elfSym(elf_file); | |
| 360 | 390 | if (symbol.st_value < alias_sym.st_value) break i + start; |
| 361 | 391 | } else aliases.items.len; |
| 362 | 392 | |
| 363 | 393 | return aliases.items[start..end]; |
| 364 | 394 | } |
| 365 | 395 | |
| 396 | fn addString(self: *SharedObject, allocator: Allocator, str: []const u8) !u32 { | |
| 397 | const off: u32 = @intCast(self.strtab.items.len); | |
| 398 | try self.strtab.ensureUnusedCapacity(allocator, str.len + 1); | |
| 399 | self.strtab.appendSliceAssumeCapacity(str); | |
| 400 | self.strtab.appendAssumeCapacity(0); | |
| 401 | return off; | |
| 402 | } | |
| 403 | ||
| 366 | 404 | pub fn getString(self: SharedObject, off: u32) [:0]const u8 { |
| 367 | 405 | assert(off < self.strtab.items.len); |
| 368 | 406 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0); |
| 369 | 407 | } |
| 370 | 408 | |
| 409 | pub fn resolveSymbol(self: SharedObject, index: Symbol.Index, elf_file: *Elf) Elf.Ref { | |
| 410 | const resolv = self.symbols_resolver.items[index]; | |
| 411 | return elf_file.resolver.get(resolv).?; | |
| 412 | } | |
| 413 | ||
| 414 | fn addSymbol(self: *SharedObject, allocator: Allocator) !Symbol.Index { | |
| 415 | try self.symbols.ensureUnusedCapacity(allocator, 1); | |
| 416 | return self.addSymbolAssumeCapacity(); | |
| 417 | } | |
| 418 | ||
| 419 | fn addSymbolAssumeCapacity(self: *SharedObject) Symbol.Index { | |
| 420 | const index: Symbol.Index = @intCast(self.symbols.items.len); | |
| 421 | self.symbols.appendAssumeCapacity(.{ .file_index = self.index }); | |
| 422 | return index; | |
| 423 | } | |
| 424 | ||
| 425 | pub fn addSymbolExtra(self: *SharedObject, allocator: Allocator, extra: Symbol.Extra) !u32 { | |
| 426 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 427 | try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len); | |
| 428 | return self.addSymbolExtraAssumeCapacity(extra); | |
| 429 | } | |
| 430 | ||
| 431 | pub fn addSymbolExtraAssumeCapacity(self: *SharedObject, extra: Symbol.Extra) u32 { | |
| 432 | const index = @as(u32, @intCast(self.symbols_extra.items.len)); | |
| 433 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 434 | inline for (fields) |field| { | |
| 435 | self.symbols_extra.appendAssumeCapacity(switch (field.type) { | |
| 436 | u32 => @field(extra, field.name), | |
| 437 | else => @compileError("bad field type"), | |
| 438 | }); | |
| 439 | } | |
| 440 | return index; | |
| 441 | } | |
| 442 | ||
| 443 | pub fn symbolExtra(self: *SharedObject, index: u32) Symbol.Extra { | |
| 444 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 445 | var i: usize = index; | |
| 446 | var result: Symbol.Extra = undefined; | |
| 447 | inline for (fields) |field| { | |
| 448 | @field(result, field.name) = switch (field.type) { | |
| 449 | u32 => self.symbols_extra.items[i], | |
| 450 | else => @compileError("bad field type"), | |
| 451 | }; | |
| 452 | i += 1; | |
| 453 | } | |
| 454 | return result; | |
| 455 | } | |
| 456 | ||
| 457 | pub fn setSymbolExtra(self: *SharedObject, index: u32, extra: Symbol.Extra) void { | |
| 458 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 459 | inline for (fields, 0..) |field, i| { | |
| 460 | self.symbols_extra.items[index + i] = switch (field.type) { | |
| 461 | u32 => @field(extra, field.name), | |
| 462 | else => @compileError("bad field type"), | |
| 463 | }; | |
| 464 | } | |
| 465 | } | |
| 466 | ||
| 371 | 467 | pub fn format( |
| 372 | 468 | self: SharedObject, |
| 373 | 469 | comptime unused_fmt_string: []const u8, |
| ... | ... | @@ -402,10 +498,15 @@ fn formatSymtab( |
| 402 | 498 | _ = unused_fmt_string; |
| 403 | 499 | _ = options; |
| 404 | 500 | const shared = ctx.shared; |
| 501 | const elf_file = ctx.elf_file; | |
| 405 | 502 | try writer.writeAll(" globals\n"); |
| 406 | for (shared.symbols.items) |index| { | |
| 407 | const global = ctx.elf_file.symbol(index); | |
| 408 | try writer.print(" {}\n", .{global.fmt(ctx.elf_file)}); | |
| 503 | for (shared.symbols.items, 0..) |sym, i| { | |
| 504 | const ref = shared.resolveSymbol(@intCast(i), elf_file); | |
| 505 | if (elf_file.symbol(ref)) |ref_sym| { | |
| 506 | try writer.print(" {}\n", .{ref_sym.fmt(elf_file)}); | |
| 507 | } else { | |
| 508 | try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)}); | |
| 509 | } | |
| 409 | 510 | } |
| 410 | 511 | } |
| 411 | 512 |
src/link/Elf/Symbol.zig+22-30| ... | ... | @@ -63,9 +63,7 @@ pub fn @"type"(symbol: Symbol, elf_file: *Elf) u4 { |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | 65 | pub fn name(symbol: Symbol, elf_file: *Elf) [:0]const u8 { |
| 66 | if (symbol.flags.global) return elf_file.strings.getAssumeExists(symbol.name_offset); | |
| 67 | const file_ptr = symbol.file(elf_file).?; | |
| 68 | return switch (file_ptr) { | |
| 66 | return switch (symbol.file(elf_file).?) { | |
| 69 | 67 | inline else => |x| x.getString(symbol.name_offset), |
| 70 | 68 | }; |
| 71 | 69 | } |
| ... | ... | @@ -87,9 +85,8 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File { |
| 87 | 85 | } |
| 88 | 86 | |
| 89 | 87 | pub fn elfSym(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym { |
| 90 | const file_ptr = symbol.file(elf_file).?; | |
| 91 | return switch (file_ptr) { | |
| 92 | .zig_object => |x| x.elfSym(symbol.esym_index).*, | |
| 88 | return switch (symbol.file(elf_file).?) { | |
| 89 | .zig_object => |x| x.symtab.items(.elf_sym)[symbol.esym_index], | |
| 93 | 90 | inline else => |x| x.symtab.items[symbol.esym_index], |
| 94 | 91 | }; |
| 95 | 92 | } |
| ... | ... | @@ -159,20 +156,20 @@ pub fn outputSymtabIndex(symbol: Symbol, elf_file: *Elf) ?u32 { |
| 159 | 156 | const symtab_ctx = switch (file_ptr) { |
| 160 | 157 | inline else => |x| x.output_symtab_ctx, |
| 161 | 158 | }; |
| 162 | const idx = symbol.extra(elf_file).?.symtab; | |
| 159 | const idx = symbol.extra(elf_file).symtab; | |
| 163 | 160 | return if (symbol.isLocal(elf_file)) idx + symtab_ctx.ilocal else idx + symtab_ctx.iglobal; |
| 164 | 161 | } |
| 165 | 162 | |
| 166 | 163 | pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 167 | 164 | if (!symbol.flags.has_got) return 0; |
| 168 | const extras = symbol.extra(elf_file).?; | |
| 165 | const extras = symbol.extra(elf_file); | |
| 169 | 166 | const entry = elf_file.got.entries.items[extras.got]; |
| 170 | 167 | return entry.address(elf_file); |
| 171 | 168 | } |
| 172 | 169 | |
| 173 | 170 | pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 174 | 171 | if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0; |
| 175 | const extras = symbol.extra(elf_file).?; | |
| 172 | const extras = symbol.extra(elf_file); | |
| 176 | 173 | const shdr = elf_file.shdrs.items[elf_file.plt_got_section_index.?]; |
| 177 | 174 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 178 | 175 | return @intCast(shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch)); |
| ... | ... | @@ -180,7 +177,7 @@ pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 180 | 177 | |
| 181 | 178 | pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 182 | 179 | if (!symbol.flags.has_plt) return 0; |
| 183 | const extras = symbol.extra(elf_file).?; | |
| 180 | const extras = symbol.extra(elf_file); | |
| 184 | 181 | const shdr = elf_file.shdrs.items[elf_file.plt_section_index.?]; |
| 185 | 182 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 186 | 183 | return @intCast(shdr.sh_addr + extras.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch)); |
| ... | ... | @@ -188,7 +185,7 @@ pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 188 | 185 | |
| 189 | 186 | pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 190 | 187 | if (!symbol.flags.has_plt) return 0; |
| 191 | const extras = symbol.extra(elf_file).?; | |
| 188 | const extras = symbol.extra(elf_file); | |
| 192 | 189 | const shdr = elf_file.shdrs.items[elf_file.got_plt_section_index.?]; |
| 193 | 190 | return @intCast(shdr.sh_addr + extras.plt * 8 + GotPltSection.preamble_size); |
| 194 | 191 | } |
| ... | ... | @@ -201,21 +198,21 @@ pub fn copyRelAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 201 | 198 | |
| 202 | 199 | pub fn tlsGdAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 203 | 200 | if (!symbol.flags.has_tlsgd) return 0; |
| 204 | const extras = symbol.extra(elf_file).?; | |
| 201 | const extras = symbol.extra(elf_file); | |
| 205 | 202 | const entry = elf_file.got.entries.items[extras.tlsgd]; |
| 206 | 203 | return entry.address(elf_file); |
| 207 | 204 | } |
| 208 | 205 | |
| 209 | 206 | pub fn gotTpAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 210 | 207 | if (!symbol.flags.has_gottp) return 0; |
| 211 | const extras = symbol.extra(elf_file).?; | |
| 208 | const extras = symbol.extra(elf_file); | |
| 212 | 209 | const entry = elf_file.got.entries.items[extras.gottp]; |
| 213 | 210 | return entry.address(elf_file); |
| 214 | 211 | } |
| 215 | 212 | |
| 216 | 213 | pub fn tlsDescAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 217 | 214 | if (!symbol.flags.has_tlsdesc) return 0; |
| 218 | const extras = symbol.extra(elf_file).?; | |
| 215 | const extras = symbol.extra(elf_file); | |
| 219 | 216 | const entry = elf_file.got.entries.items[extras.tlsdesc]; |
| 220 | 217 | return entry.address(elf_file); |
| 221 | 218 | } |
| ... | ... | @@ -228,14 +225,14 @@ const GetOrCreateZigGotEntryResult = struct { |
| 228 | 225 | pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, elf_file: *Elf) !GetOrCreateZigGotEntryResult { |
| 229 | 226 | assert(!elf_file.base.isRelocatable()); |
| 230 | 227 | assert(symbol.flags.needs_zig_got); |
| 231 | if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.extra(elf_file).?.zig_got }; | |
| 228 | if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.extra(elf_file).zig_got }; | |
| 232 | 229 | const index = try elf_file.zig_got.addSymbol(symbol_index, elf_file); |
| 233 | 230 | return .{ .found_existing = false, .index = index }; |
| 234 | 231 | } |
| 235 | 232 | |
| 236 | 233 | pub fn zigGotAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 237 | 234 | if (!symbol.flags.has_zig_got) return 0; |
| 238 | const extras = symbol.extra(elf_file).?; | |
| 235 | const extras = symbol.extra(elf_file); | |
| 239 | 236 | return elf_file.zig_got.entryAddress(extras.zig_got, elf_file); |
| 240 | 237 | } |
| 241 | 238 | |
| ... | ... | @@ -265,11 +262,8 @@ const AddExtraOpts = struct { |
| 265 | 262 | zig_got: ?u32 = null, |
| 266 | 263 | }; |
| 267 | 264 | |
| 268 | pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void { | |
| 269 | if (symbol.extra(elf_file) == null) { | |
| 270 | symbol.extra_index = try elf_file.addSymbolExtra(.{}); | |
| 271 | } | |
| 272 | var extras = symbol.extra(elf_file).?; | |
| 265 | pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) void { | |
| 266 | var extras = symbol.extra(elf_file); | |
| 273 | 267 | inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| { |
| 274 | 268 | if (@field(opts, field.name)) |x| { |
| 275 | 269 | @field(extras, field.name) = x; |
| ... | ... | @@ -278,12 +272,16 @@ pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void { |
| 278 | 272 | symbol.setExtra(extras, elf_file); |
| 279 | 273 | } |
| 280 | 274 | |
| 281 | pub fn extra(symbol: Symbol, elf_file: *Elf) ?Extra { | |
| 282 | return elf_file.symbolExtra(symbol.extra_index); | |
| 275 | pub fn extra(symbol: Symbol, elf_file: *Elf) Extra { | |
| 276 | return switch (symbol.file(elf_file).?) { | |
| 277 | inline else => |x| x.symbolExtra(symbol.extra_index), | |
| 278 | }; | |
| 283 | 279 | } |
| 284 | 280 | |
| 285 | 281 | pub fn setExtra(symbol: Symbol, extras: Extra, elf_file: *Elf) void { |
| 286 | 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 | }; | |
| 287 | 285 | } |
| 288 | 286 | |
| 289 | 287 | pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { |
| ... | ... | @@ -426,12 +424,6 @@ pub const Flags = packed struct { |
| 426 | 424 | /// Whether this symbol is weak. |
| 427 | 425 | weak: bool = false, |
| 428 | 426 | |
| 429 | /// Whether the symbol has its name interned in global symbol | |
| 430 | /// resolver table. | |
| 431 | /// This happens for any symbol that is considered a global | |
| 432 | /// symbol, but is not necessarily an import or export. | |
| 433 | global: bool = false, | |
| 434 | ||
| 435 | 427 | /// Whether the symbol makes into the output symtab. |
| 436 | 428 | output_symtab: bool = false, |
| 437 | 429 |
src/link/Elf/ZigObject.zig+309-223| ... | ... | @@ -8,9 +8,11 @@ data: std.ArrayListUnmanaged(u8) = .{}, |
| 8 | 8 | path: []const u8, |
| 9 | 9 | index: File.Index, |
| 10 | 10 | |
| 11 | local_esyms: std.MultiArrayList(ElfSym) = .{}, | |
| 12 | global_esyms: std.MultiArrayList(ElfSym) = .{}, | |
| 11 | symtab: std.MultiArrayList(ElfSym) = .{}, | |
| 13 | 12 | strtab: StringTable = .{}, |
| 13 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, | |
| 14 | symbols_extra: std.ArrayListUnmanaged(u32) = .{}, | |
| 15 | symbols_resolver: std.ArrayListUnmanaged(Elf.SymbolResolver.Index) = .{}, | |
| 14 | 16 | local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 15 | 17 | global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 16 | 18 | globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{}, |
| ... | ... | @@ -87,18 +89,11 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void { |
| 87 | 89 | try self.strtab.buffer.append(gpa, 0); |
| 88 | 90 | |
| 89 | 91 | const name_off = try self.strtab.insert(gpa, self.path); |
| 90 | const symbol_index = try elf_file.addSymbol(); | |
| 91 | try self.local_symbols.append(gpa, symbol_index); | |
| 92 | const symbol_ptr = elf_file.symbol(symbol_index); | |
| 93 | symbol_ptr.file_index = self.index; | |
| 94 | symbol_ptr.name_offset = name_off; | |
| 95 | ||
| 96 | const esym_index = try self.addLocalEsym(gpa); | |
| 97 | const esym = &self.local_esyms.items(.elf_sym)[esym_index]; | |
| 98 | 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]; | |
| 99 | 95 | esym.st_info = elf.STT_FILE; |
| 100 | 96 | esym.st_shndx = elf.SHN_ABS; |
| 101 | symbol_ptr.esym_index = esym_index; | |
| 102 | 97 | |
| 103 | 98 | switch (comp.config.debug_format) { |
| 104 | 99 | .strip => {}, |
| ... | ... | @@ -112,9 +107,11 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void { |
| 112 | 107 | |
| 113 | 108 | pub fn deinit(self: *ZigObject, allocator: Allocator) void { |
| 114 | 109 | self.data.deinit(allocator); |
| 115 | self.local_esyms.deinit(allocator); | |
| 116 | self.global_esyms.deinit(allocator); | |
| 110 | self.symtab.deinit(allocator); | |
| 117 | 111 | self.strtab.deinit(allocator); |
| 112 | self.symbols.deinit(allocator); | |
| 113 | self.symbols_extra.deinit(allocator); | |
| 114 | self.symbols_resolver.deinit(allocator); | |
| 118 | 115 | self.local_symbols.deinit(allocator); |
| 119 | 116 | self.global_symbols.deinit(allocator); |
| 120 | 117 | self.globals_lookup.deinit(allocator); |
| ... | ... | @@ -262,50 +259,75 @@ fn saveDebugSectionsSizes(self: *ZigObject, elf_file: *Elf) void { |
| 262 | 259 | } |
| 263 | 260 | } |
| 264 | 261 | |
| 265 | pub fn addLocalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index { | |
| 266 | try self.local_esyms.ensureUnusedCapacity(allocator, 1); | |
| 267 | const index = @as(Symbol.Index, @intCast(self.local_esyms.addOneAssumeCapacity())); | |
| 268 | var esym = ElfSym{ .elf_sym = Elf.null_sym }; | |
| 269 | esym.elf_sym.st_info = elf.STB_LOCAL << 4; | |
| 270 | self.local_esyms.set(index, esym); | |
| 262 | fn newSymbol(self: *ZigObject, allocator: Allocator, name_off: u32, st_bind: u4) !Symbol.Index { | |
| 263 | try self.symtab.ensureUnusedCapacity(allocator, 1); | |
| 264 | try self.symbols.ensureUnusedCapacity(allocator, 1); | |
| 265 | try self.symbols_extra.ensureUnusedCapacity(allocator, @sizeOf(Symbol.Extra)); | |
| 266 | ||
| 267 | const index = self.addSymbolAssumeCapacity(); | |
| 268 | const sym = &self.symbols.items[index]; | |
| 269 | sym.name_offset = name_off; | |
| 270 | sym.extra_index = self.addSymbolExtraAssumeCapacity(.{}); | |
| 271 | ||
| 272 | const esym_idx: u32 = @intCast(self.symtab.addOneAssumeCapacity()); | |
| 273 | const esym = ElfSym{ .elf_sym = .{ | |
| 274 | .st_value = 0, | |
| 275 | .st_name = name_off, | |
| 276 | .st_info = @as(u8, @intCast(st_bind)) << 4, | |
| 277 | .st_other = 0, | |
| 278 | .st_size = 0, | |
| 279 | .st_shndx = 0, | |
| 280 | } }; | |
| 281 | self.symtab.set(index, esym); | |
| 282 | sym.esym_index = esym_idx; | |
| 283 | ||
| 271 | 284 | return index; |
| 272 | 285 | } |
| 273 | 286 | |
| 274 | pub fn addGlobalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index { | |
| 275 | try self.global_esyms.ensureUnusedCapacity(allocator, 1); | |
| 276 | const index = @as(Symbol.Index, @intCast(self.global_esyms.addOneAssumeCapacity())); | |
| 277 | var esym = ElfSym{ .elf_sym = Elf.null_sym }; | |
| 278 | esym.elf_sym.st_info = elf.STB_GLOBAL << 4; | |
| 279 | self.global_esyms.set(index, esym); | |
| 280 | return index | global_symbol_bit; | |
| 287 | fn newLocalSymbol(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index { | |
| 288 | try self.local_symbols.ensureUnusedCapacity(allocator, 1); | |
| 289 | const fake_index: Symbol.Index = @intCast(self.local_symbols.items.len); | |
| 290 | const index = try self.newSymbol(allocator, name_off, elf.STB_LOCAL); | |
| 291 | self.local_symbols.appendAssumeCapacity(index); | |
| 292 | return fake_index; | |
| 281 | 293 | } |
| 282 | 294 | |
| 283 | pub fn newAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index { | |
| 284 | const gpa = elf_file.base.comp.gpa; | |
| 285 | const atom_index = try self.addAtom(gpa); | |
| 286 | const symbol_index = try elf_file.addSymbol(); | |
| 287 | const esym_index = try self.addLocalEsym(gpa); | |
| 288 | ||
| 289 | try self.atoms_indexes.append(gpa, atom_index); | |
| 290 | try self.local_symbols.append(gpa, symbol_index); | |
| 291 | ||
| 292 | const symbol_ptr = elf_file.symbol(symbol_index); | |
| 293 | symbol_ptr.file_index = self.index; | |
| 294 | symbol_ptr.ref = .{ .index = atom_index, .file = self.index }; | |
| 295 | fn newGlobalSymbol(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index { | |
| 296 | try self.global_symbols.ensureUnusedCapacity(allocator, 1); | |
| 297 | try self.symbols_resolver.ensureUnusedCapacity(allocator, 1); | |
| 298 | const fake_index: Symbol.Index = @intCast(self.global_symbols.items.len); | |
| 299 | const index = try self.newSymbol(allocator, name_off, elf.STB_GLOBAL); | |
| 300 | self.global_symbols.appendAssumeCapacity(index); | |
| 301 | self.symbols_resolver.addOneAssumeCapacity().* = 0; | |
| 302 | return fake_index | global_symbol_bit; | |
| 303 | } | |
| 295 | 304 | |
| 296 | self.local_esyms.items(.shndx)[esym_index] = atom_index; | |
| 297 | self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM; | |
| 298 | symbol_ptr.esym_index = esym_index; | |
| 305 | fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index { | |
| 306 | try self.atoms.ensureUnusedCapacity(allocator, 1); | |
| 307 | try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra)); | |
| 308 | try self.atoms_indexes.ensureUnusedCapacity(allocator, 1); | |
| 309 | try self.relocs.ensureUnusedCapacity(allocator, 1); | |
| 299 | 310 | |
| 300 | // TODO I'm thinking that maybe we shouldn' set this value unless it's actually needed? | |
| 301 | const relocs_index = @as(u32, @intCast(self.relocs.items.len)); | |
| 302 | const relocs = try self.relocs.addOne(gpa); | |
| 303 | relocs.* = .{}; | |
| 311 | const index = self.addAtomAssumeCapacity(); | |
| 312 | self.atoms_indexes.appendAssumeCapacity(index); | |
| 313 | const atom_ptr = self.atom(index).?; | |
| 314 | atom_ptr.name_offset = name_off; | |
| 304 | 315 | |
| 305 | const atom_ptr = self.atom(atom_index).?; | |
| 316 | const relocs_index: u32 = @intCast(self.relocs.items.len); | |
| 317 | self.relocs.addOneAssumeCapacity().* = .{}; | |
| 306 | 318 | atom_ptr.relocs_section_index = relocs_index; |
| 307 | 319 | |
| 308 | return symbol_index; | |
| 320 | return index; | |
| 321 | } | |
| 322 | ||
| 323 | fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index { | |
| 324 | const atom_index = try self.newAtom(allocator, name_off); | |
| 325 | const sym_index = try self.newLocalSymbol(allocator, name_off); | |
| 326 | const sym = self.symbol(sym_index); | |
| 327 | sym.ref = .{ .index = atom_index, .file = self.index }; | |
| 328 | self.symtab.items(.shndx)[sym.esym_index] = atom_index; | |
| 329 | self.symtab.items(.elf_sym)[sym.esym_index].st_shndx = SHN_ATOM; | |
| 330 | return sym_index; | |
| 309 | 331 | } |
| 310 | 332 | |
| 311 | 333 | /// TODO actually create fake input shdrs and return that instead. |
| ... | ... | @@ -320,48 +342,47 @@ pub fn inputShdr(self: *ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.E |
| 320 | 342 | return shdr; |
| 321 | 343 | } |
| 322 | 344 | |
| 323 | pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void { | |
| 324 | for (self.globals(), 0..) |index, i| { | |
| 325 | const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit; | |
| 326 | const esym = self.global_esyms.items(.elf_sym)[i]; | |
| 327 | const shndx = self.global_esyms.items(.shndx)[i]; | |
| 328 | ||
| 329 | if (esym.st_shndx == elf.SHN_UNDEF) continue; | |
| 345 | pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) !void { | |
| 346 | const gpa = elf_file.base.comp.gpa; | |
| 330 | 347 | |
| 331 | if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) { | |
| 348 | for (self.global_symbols.items, 0..) |index, i| { | |
| 349 | const global = &self.symbols.items[index]; | |
| 350 | const esym = global.elfSym(elf_file); | |
| 351 | const shndx = self.symtab.items(.shndx)[global.esym_index]; | |
| 352 | if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON and esym.st_shndx != elf.SHN_UNDEF) { | |
| 332 | 353 | assert(esym.st_shndx == SHN_ATOM); |
| 333 | 354 | const atom_ptr = self.atom(shndx) orelse continue; |
| 334 | 355 | if (!atom_ptr.alive) continue; |
| 335 | 356 | } |
| 336 | 357 | |
| 337 | const global = elf_file.symbol(index); | |
| 338 | if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) { | |
| 339 | const atom_index = switch (esym.st_shndx) { | |
| 340 | elf.SHN_ABS, elf.SHN_COMMON => 0, | |
| 341 | SHN_ATOM => shndx, | |
| 342 | else => unreachable, | |
| 343 | }; | |
| 344 | global.value = @intCast(esym.st_value); | |
| 345 | global.ref = .{ .index = atom_index, .file = self.index }; | |
| 346 | global.esym_index = esym_index; | |
| 347 | global.file_index = self.index; | |
| 348 | global.version_index = elf_file.default_sym_version; | |
| 349 | if (esym.st_bind() == elf.STB_WEAK) global.flags.weak = true; | |
| 358 | const resolv = &self.symbols_resolver.items[i]; | |
| 359 | const gop = try elf_file.resolver.getOrPut(gpa, .{ | |
| 360 | .index = @intCast(i | global_symbol_bit), | |
| 361 | .file = self.index, | |
| 362 | }, elf_file); | |
| 363 | if (!gop.found_existing) { | |
| 364 | gop.ref.* = .{ .index = 0, .file = 0 }; | |
| 365 | } | |
| 366 | resolv.* = gop.index; | |
| 367 | ||
| 368 | if (esym.st_shndx == elf.SHN_UNDEF) continue; | |
| 369 | if (elf_file.symbol(gop.ref.*) == null) { | |
| 370 | gop.ref.* = .{ .index = @intCast(i | global_symbol_bit), .file = self.index }; | |
| 371 | continue; | |
| 372 | } | |
| 373 | ||
| 374 | if (self.asFile().symbolRank(esym, false) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) { | |
| 375 | gop.ref.* = .{ .index = @intCast(i | global_symbol_bit), .file = self.index }; | |
| 350 | 376 | } |
| 351 | 377 | } |
| 352 | 378 | } |
| 353 | 379 | |
| 354 | pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void { | |
| 355 | for (self.globals(), 0..) |index, i| { | |
| 356 | const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit; | |
| 357 | const esym = self.global_esyms.items(.elf_sym)[i]; | |
| 358 | ||
| 380 | pub fn claimUnresolved(self: *ZigObject, elf_file: *Elf) void { | |
| 381 | for (self.global_symbols.items, 0..) |index, i| { | |
| 382 | const global = &self.symbols.items[index]; | |
| 383 | const esym = self.symtab.items(.elf_sym)[index]; | |
| 359 | 384 | if (esym.st_shndx != elf.SHN_UNDEF) continue; |
| 360 | ||
| 361 | const global = elf_file.symbol(index); | |
| 362 | if (global.file(elf_file)) |_| { | |
| 363 | if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF) continue; | |
| 364 | } | |
| 385 | if (elf_file.symbol(self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file)) != null) continue; | |
| 365 | 386 | |
| 366 | 387 | const is_import = blk: { |
| 367 | 388 | if (!elf_file.isEffectivelyDynLib()) break :blk false; |
| ... | ... | @@ -372,29 +393,30 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void { |
| 372 | 393 | |
| 373 | 394 | global.value = 0; |
| 374 | 395 | global.ref = .{ .index = 0, .file = 0 }; |
| 375 | global.esym_index = esym_index; | |
| 396 | global.esym_index = @intCast(index); | |
| 376 | 397 | global.file_index = self.index; |
| 377 | 398 | global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version; |
| 378 | 399 | global.flags.import = is_import; |
| 400 | ||
| 401 | const idx = self.symbols_resolver.items[i]; | |
| 402 | elf_file.resolver.values.items[idx - 1] = .{ .index = @intCast(i | global_symbol_bit), .file = self.index }; | |
| 379 | 403 | } |
| 380 | 404 | } |
| 381 | 405 | |
| 382 | 406 | pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void { |
| 383 | for (self.globals(), 0..) |index, i| { | |
| 384 | const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit; | |
| 385 | const esym = self.global_esyms.items(.elf_sym)[i]; | |
| 386 | ||
| 407 | for (self.global_symbols.items, 0..) |index, i| { | |
| 408 | const global = &self.symbols.items[index]; | |
| 409 | const esym = self.symtab.items(.elf_sym)[index]; | |
| 387 | 410 | if (esym.st_shndx != elf.SHN_UNDEF) continue; |
| 388 | ||
| 389 | const global = elf_file.symbol(index); | |
| 390 | if (global.file(elf_file)) |file| { | |
| 391 | if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or file.index() <= self.index) continue; | |
| 392 | } | |
| 411 | if (elf_file.symbol(self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file)) != null) continue; | |
| 393 | 412 | |
| 394 | 413 | global.value = 0; |
| 395 | 414 | global.ref = .{ .index = 0, .file = 0 }; |
| 396 | global.esym_index = esym_index; | |
| 415 | global.esym_index = @intCast(index); | |
| 397 | 416 | global.file_index = self.index; |
| 417 | ||
| 418 | const idx = self.symbols_resolver.items[i]; | |
| 419 | elf_file.resolver.values.items[idx - 1] = .{ .index = @intCast(i | global_symbol_bit), .file = self.index }; | |
| 398 | 420 | } |
| 399 | 421 | } |
| 400 | 422 | |
| ... | ... | @@ -417,12 +439,14 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void { |
| 417 | 439 | } |
| 418 | 440 | |
| 419 | 441 | pub fn markLive(self: *ZigObject, elf_file: *Elf) void { |
| 420 | for (self.globals(), 0..) |index, i| { | |
| 421 | const esym = self.global_esyms.items(.elf_sym)[i]; | |
| 442 | for (self.global_symbols.items, 0..) |index, i| { | |
| 443 | const global = self.symbols.items[index]; | |
| 444 | const esym = self.symtab.items(.elf_sym)[index]; | |
| 422 | 445 | if (esym.st_bind() == elf.STB_WEAK) continue; |
| 423 | 446 | |
| 424 | const global = elf_file.symbol(index); | |
| 425 | const file = global.file(elf_file) orelse continue; | |
| 447 | const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file); | |
| 448 | const sym = elf_file.symbol(ref) orelse continue; | |
| 449 | const file = sym.file(elf_file).?; | |
| 426 | 450 | const should_keep = esym.st_shndx == elf.SHN_UNDEF or |
| 427 | 451 | (esym.st_shndx == elf.SHN_COMMON and global.elfSym(elf_file).st_shndx != elf.SHN_COMMON); |
| 428 | 452 | if (should_keep and !file.isAlive()) { |
| ... | ... | @@ -432,14 +456,36 @@ pub fn markLive(self: *ZigObject, elf_file: *Elf) void { |
| 432 | 456 | } |
| 433 | 457 | } |
| 434 | 458 | |
| 435 | pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void { | |
| 436 | for (self.globals(), 0..) |index, i| { | |
| 437 | const esym = self.global_esyms.items(.elf_sym)[i]; | |
| 438 | const shndx = self.global_esyms.items(.shndx)[i]; | |
| 439 | const global = elf_file.symbol(index); | |
| 440 | const global_file = global.file(elf_file) orelse continue; | |
| 459 | pub fn markImportsExports(self: *ZigObject, elf_file: *Elf) void { | |
| 460 | for (0..self.global_symbols.items.len) |i| { | |
| 461 | const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file); | |
| 462 | const sym = elf_file.symbol(ref) orelse continue; | |
| 463 | const file = sym.file(elf_file).?; | |
| 464 | if (sym.version_index == elf.VER_NDX_LOCAL) continue; | |
| 465 | const vis = @as(elf.STV, @enumFromInt(sym.elfSym(elf_file).st_other)); | |
| 466 | if (vis == .HIDDEN) continue; | |
| 467 | if (file == .shared_object and !sym.isAbs(elf_file)) { | |
| 468 | sym.flags.import = true; | |
| 469 | continue; | |
| 470 | } | |
| 471 | if (file.index() == self.index) { | |
| 472 | sym.flags.@"export" = true; | |
| 473 | if (elf_file.isEffectivelyDynLib() and vis != .PROTECTED) { | |
| 474 | sym.flags.import = true; | |
| 475 | } | |
| 476 | } | |
| 477 | } | |
| 478 | } | |
| 441 | 479 | |
| 442 | if (self.index == global_file.index() or | |
| 480 | pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void { | |
| 481 | for (self.global_symbols.items, 0..) |index, i| { | |
| 482 | const esym = self.symtab.items(.elf_sym)[index]; | |
| 483 | const shndx = self.symtab.items(.shndx)[index]; | |
| 484 | const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file); | |
| 485 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 486 | const ref_file = ref_sym.file(elf_file).?; | |
| 487 | ||
| 488 | if (self.index == ref_file.index() or | |
| 443 | 489 | esym.st_shndx == elf.SHN_UNDEF or |
| 444 | 490 | esym.st_bind() == elf.STB_WEAK or |
| 445 | 491 | esym.st_shndx == elf.SHN_COMMON) continue; |
| ... | ... | @@ -449,7 +495,7 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O |
| 449 | 495 | if (!atom_ptr.alive) continue; |
| 450 | 496 | } |
| 451 | 497 | |
| 452 | const gop = try dupes.getOrPut(index); | |
| 498 | const gop = try dupes.getOrPut(self.symbols_resolver.items[i]); | |
| 453 | 499 | if (!gop.found_existing) { |
| 454 | 500 | gop.value_ptr.* = .{}; |
| 455 | 501 | } |
| ... | ... | @@ -481,12 +527,13 @@ pub fn readFileContents(self: *ZigObject, elf_file: *Elf) !void { |
| 481 | 527 | pub fn updateArSymtab(self: ZigObject, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) error{OutOfMemory}!void { |
| 482 | 528 | const gpa = elf_file.base.comp.gpa; |
| 483 | 529 | |
| 484 | try ar_symtab.symtab.ensureUnusedCapacity(gpa, self.globals().len); | |
| 530 | try ar_symtab.symtab.ensureUnusedCapacity(gpa, self.global_symbols.items.len); | |
| 485 | 531 | |
| 486 | for (self.globals()) |global_index| { | |
| 487 | const global = elf_file.symbol(global_index); | |
| 488 | const file_ptr = global.file(elf_file).?; | |
| 489 | assert(file_ptr.index() == self.index); | |
| 532 | for (self.global_symbols.items, 0..) |index, i| { | |
| 533 | const global = self.symbols.items[index]; | |
| 534 | const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file); | |
| 535 | const sym = elf_file.symbol(ref).?; | |
| 536 | assert(sym.file(elf_file).?.index() == self.index); | |
| 490 | 537 | if (global.outputShndx(elf_file) == null) continue; |
| 491 | 538 | |
| 492 | 539 | const off = try ar_symtab.strtab.insert(gpa, global.name(elf_file)); |
| ... | ... | @@ -528,33 +575,9 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void { |
| 528 | 575 | } |
| 529 | 576 | } |
| 530 | 577 | |
| 531 | inline fn isGlobal(index: Symbol.Index) bool { | |
| 532 | return index & global_symbol_bit != 0; | |
| 533 | } | |
| 534 | ||
| 535 | pub fn symbol(self: ZigObject, index: Symbol.Index) Symbol.Index { | |
| 536 | const actual_index = index & symbol_mask; | |
| 537 | if (isGlobal(index)) return self.globals()[actual_index]; | |
| 538 | return self.locals()[actual_index]; | |
| 539 | } | |
| 540 | ||
| 541 | pub fn elfSym(self: *ZigObject, index: Symbol.Index) *elf.Elf64_Sym { | |
| 542 | const actual_index = index & symbol_mask; | |
| 543 | if (isGlobal(index)) return &self.global_esyms.items(.elf_sym)[actual_index]; | |
| 544 | return &self.local_esyms.items(.elf_sym)[actual_index]; | |
| 545 | } | |
| 546 | ||
| 547 | pub fn locals(self: ZigObject) []const Symbol.Index { | |
| 548 | return self.local_symbols.items; | |
| 549 | } | |
| 550 | ||
| 551 | pub fn globals(self: ZigObject) []const Symbol.Index { | |
| 552 | return self.global_symbols.items; | |
| 553 | } | |
| 554 | ||
| 555 | 578 | pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void { |
| 556 | for (self.locals()) |local_index| { | |
| 557 | const local = elf_file.symbol(local_index); | |
| 579 | for (self.local_symbols.items) |index| { | |
| 580 | const local = &self.symbols.items[index]; | |
| 558 | 581 | if (local.atom(elf_file)) |atom_ptr| if (!atom_ptr.alive) continue; |
| 559 | 582 | const esym = local.elfSym(elf_file); |
| 560 | 583 | switch (esym.st_type()) { |
| ... | ... | @@ -562,22 +585,23 @@ pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void { |
| 562 | 585 | else => {}, |
| 563 | 586 | } |
| 564 | 587 | local.flags.output_symtab = true; |
| 565 | try local.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); | |
| 588 | local.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); | |
| 566 | 589 | self.output_symtab_ctx.nlocals += 1; |
| 567 | 590 | self.output_symtab_ctx.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1; |
| 568 | 591 | } |
| 569 | 592 | |
| 570 | for (self.globals()) |global_index| { | |
| 571 | const global = elf_file.symbol(global_index); | |
| 572 | const file_ptr = global.file(elf_file) orelse continue; | |
| 573 | if (file_ptr.index() != self.index) continue; | |
| 593 | for (self.global_symbols.items, self.symbols_resolver.items) |index, resolv| { | |
| 594 | const global = &self.symbols.items[index]; | |
| 595 | const ref = elf_file.resolver.values.items[resolv - 1]; | |
| 596 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 597 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 574 | 598 | if (global.atom(elf_file)) |atom_ptr| if (!atom_ptr.alive) continue; |
| 575 | 599 | global.flags.output_symtab = true; |
| 576 | 600 | if (global.isLocal(elf_file)) { |
| 577 | try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); | |
| 601 | global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); | |
| 578 | 602 | self.output_symtab_ctx.nlocals += 1; |
| 579 | 603 | } else { |
| 580 | try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file); | |
| 604 | global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file); | |
| 581 | 605 | self.output_symtab_ctx.nglobals += 1; |
| 582 | 606 | } |
| 583 | 607 | self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1; |
| ... | ... | @@ -585,8 +609,8 @@ pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void { |
| 585 | 609 | } |
| 586 | 610 | |
| 587 | 611 | pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void { |
| 588 | for (self.locals()) |local_index| { | |
| 589 | const local = elf_file.symbol(local_index); | |
| 612 | for (self.local_symbols.items) |index| { | |
| 613 | const local = &self.symbols.items[index]; | |
| 590 | 614 | const idx = local.outputSymtabIndex(elf_file) orelse continue; |
| 591 | 615 | const out_sym = &elf_file.symtab.items[idx]; |
| 592 | 616 | out_sym.st_name = @intCast(elf_file.strtab.items.len); |
| ... | ... | @@ -595,10 +619,11 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void { |
| 595 | 619 | local.setOutputSym(elf_file, out_sym); |
| 596 | 620 | } |
| 597 | 621 | |
| 598 | for (self.globals()) |global_index| { | |
| 599 | const global = elf_file.symbol(global_index); | |
| 600 | const file_ptr = global.file(elf_file) orelse continue; | |
| 601 | if (file_ptr.index() != self.index) continue; | |
| 622 | for (self.global_symbols.items, self.symbols_resolver.items) |index, resolv| { | |
| 623 | const global = self.symbols.items[index]; | |
| 624 | const ref = elf_file.resolver.values.items[resolv - 1]; | |
| 625 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 626 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 602 | 627 | const idx = global.outputSymtabIndex(elf_file) orelse continue; |
| 603 | 628 | const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); |
| 604 | 629 | elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file)); |
| ... | ... | @@ -609,10 +634,6 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void { |
| 609 | 634 | } |
| 610 | 635 | } |
| 611 | 636 | |
| 612 | pub fn asFile(self: *ZigObject) File { | |
| 613 | return .{ .zig_object = self }; | |
| 614 | } | |
| 615 | ||
| 616 | 637 | /// Returns atom's code. |
| 617 | 638 | /// Caller owns the memory. |
| 618 | 639 | pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { |
| ... | ... | @@ -645,13 +666,13 @@ pub fn getDeclVAddr( |
| 645 | 666 | reloc_info: link.File.RelocInfo, |
| 646 | 667 | ) !u64 { |
| 647 | 668 | const this_sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index); |
| 648 | const this_sym = elf_file.symbol(this_sym_index); | |
| 669 | const this_sym = self.symbol(this_sym_index); | |
| 649 | 670 | const vaddr = this_sym.address(.{}, elf_file); |
| 650 | const parent_atom = elf_file.symbol(reloc_info.parent_atom_index).atom(elf_file).?; | |
| 671 | const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?; | |
| 651 | 672 | const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch); |
| 652 | 673 | try parent_atom.addReloc(elf_file, .{ |
| 653 | 674 | .r_offset = reloc_info.offset, |
| 654 | .r_info = (@as(u64, @intCast(this_sym.esym_index)) << 32) | r_type, | |
| 675 | .r_info = (@as(u64, @intCast(this_sym_index)) << 32) | r_type, | |
| 655 | 676 | .r_addend = reloc_info.addend, |
| 656 | 677 | }); |
| 657 | 678 | return @intCast(vaddr); |
| ... | ... | @@ -664,13 +685,13 @@ pub fn getAnonDeclVAddr( |
| 664 | 685 | reloc_info: link.File.RelocInfo, |
| 665 | 686 | ) !u64 { |
| 666 | 687 | const sym_index = self.anon_decls.get(decl_val).?.symbol_index; |
| 667 | const sym = elf_file.symbol(sym_index); | |
| 688 | const sym = self.symbol(sym_index); | |
| 668 | 689 | const vaddr = sym.address(.{}, elf_file); |
| 669 | const parent_atom = elf_file.symbol(reloc_info.parent_atom_index).atom(elf_file).?; | |
| 690 | const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?; | |
| 670 | 691 | const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch); |
| 671 | 692 | try parent_atom.addReloc(elf_file, .{ |
| 672 | 693 | .r_offset = reloc_info.offset, |
| 673 | .r_info = (@as(u64, @intCast(sym.esym_index)) << 32) | r_type, | |
| 694 | .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type, | |
| 674 | 695 | .r_addend = reloc_info.addend, |
| 675 | 696 | }); |
| 676 | 697 | return @intCast(vaddr); |
| ... | ... | @@ -692,7 +713,7 @@ pub fn lowerAnonDecl( |
| 692 | 713 | else => explicit_alignment, |
| 693 | 714 | }; |
| 694 | 715 | if (self.anon_decls.get(decl_val)) |metadata| { |
| 695 | const existing_alignment = elf_file.symbol(metadata.symbol_index).atom(elf_file).?.alignment; | |
| 716 | const existing_alignment = self.symbol(metadata.symbol_index).atom(elf_file).?.alignment; | |
| 696 | 717 | if (decl_alignment.order(existing_alignment).compare(.lte)) |
| 697 | 718 | return .ok; |
| 698 | 719 | } |
| ... | ... | @@ -753,8 +774,8 @@ pub fn getOrCreateMetadataForLazySymbol( |
| 753 | 774 | }; |
| 754 | 775 | switch (metadata.state.*) { |
| 755 | 776 | .unused => { |
| 756 | const symbol_index = try self.newAtom(elf_file); | |
| 757 | const sym = elf_file.symbol(symbol_index); | |
| 777 | const symbol_index = try self.newSymbolWithAtom(gpa, 0); | |
| 778 | const sym = self.symbol(symbol_index); | |
| 758 | 779 | sym.flags.needs_zig_got = true; |
| 759 | 780 | metadata.symbol_index.* = symbol_index; |
| 760 | 781 | }, |
| ... | ... | @@ -778,13 +799,10 @@ fn freeUnnamedConsts(self: *ZigObject, elf_file: *Elf, decl_index: InternPool.De |
| 778 | 799 | } |
| 779 | 800 | |
| 780 | 801 | fn freeDeclMetadata(self: *ZigObject, elf_file: *Elf, sym_index: Symbol.Index) void { |
| 781 | _ = self; | |
| 782 | const gpa = elf_file.base.comp.gpa; | |
| 783 | const sym = elf_file.symbol(sym_index); | |
| 802 | const sym = self.symbol(sym_index); | |
| 784 | 803 | sym.atom(elf_file).?.free(elf_file); |
| 785 | 804 | log.debug("adding %{d} to local symbols free list", .{sym_index}); |
| 786 | elf_file.symbols_free_list.append(gpa, sym_index) catch {}; | |
| 787 | elf_file.symbols.items[sym_index] = .{}; | |
| 805 | self.symbols.items[sym_index] = .{}; | |
| 788 | 806 | // TODO free GOT entry here |
| 789 | 807 | } |
| 790 | 808 | |
| ... | ... | @@ -817,10 +835,10 @@ pub fn getOrCreateMetadataForDecl( |
| 817 | 835 | const gop = try self.decls.getOrPut(gpa, decl_index); |
| 818 | 836 | if (!gop.found_existing) { |
| 819 | 837 | const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded; |
| 820 | const symbol_index = try self.newAtom(elf_file); | |
| 838 | const symbol_index = try self.newSymbolWithAtom(gpa, 0); | |
| 821 | 839 | const mod = elf_file.base.comp.module.?; |
| 822 | 840 | const decl = mod.declPtr(decl_index); |
| 823 | const sym = elf_file.symbol(symbol_index); | |
| 841 | const sym = self.symbol(symbol_index); | |
| 824 | 842 | if (decl.getOwnedVariable(mod)) |variable| { |
| 825 | 843 | if (variable.is_threadlocal and any_non_single_threaded) { |
| 826 | 844 | sym.flags.is_tls = true; |
| ... | ... | @@ -909,8 +927,8 @@ fn updateDeclCode( |
| 909 | 927 | target_util.minFunctionAlignment(mod.getTarget()), |
| 910 | 928 | ); |
| 911 | 929 | |
| 912 | const sym = elf_file.symbol(sym_index); | |
| 913 | const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index]; | |
| 930 | const sym = self.symbol(sym_index); | |
| 931 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; | |
| 914 | 932 | const atom_ptr = sym.atom(elf_file).?; |
| 915 | 933 | const name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip)); |
| 916 | 934 | |
| ... | ... | @@ -940,7 +958,7 @@ fn updateDeclCode( |
| 940 | 958 | if (!elf_file.base.isRelocatable()) { |
| 941 | 959 | log.debug(" (writing new offset table entry)", .{}); |
| 942 | 960 | assert(sym.flags.has_zig_got); |
| 943 | const extra = sym.extra(elf_file).?; | |
| 961 | const extra = sym.extra(elf_file); | |
| 944 | 962 | try elf_file.zig_got.writeOne(elf_file, extra.zig_got); |
| 945 | 963 | } |
| 946 | 964 | } |
| ... | ... | @@ -1007,8 +1025,8 @@ fn updateTlv( |
| 1007 | 1025 | |
| 1008 | 1026 | const required_alignment = decl.getAlignment(pt); |
| 1009 | 1027 | |
| 1010 | const sym = elf_file.symbol(sym_index); | |
| 1011 | const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index]; | |
| 1028 | const sym = self.symbol(sym_index); | |
| 1029 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; | |
| 1012 | 1030 | const atom_ptr = sym.atom(elf_file).?; |
| 1013 | 1031 | const name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip)); |
| 1014 | 1032 | |
| ... | ... | @@ -1064,7 +1082,7 @@ pub fn updateFunc( |
| 1064 | 1082 | |
| 1065 | 1083 | const sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index); |
| 1066 | 1084 | self.freeUnnamedConsts(elf_file, decl_index); |
| 1067 | elf_file.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); | |
| 1085 | self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); | |
| 1068 | 1086 | |
| 1069 | 1087 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1070 | 1088 | defer code_buffer.deinit(); |
| ... | ... | @@ -1096,7 +1114,7 @@ pub fn updateFunc( |
| 1096 | 1114 | try self.updateDeclCode(elf_file, pt, decl_index, sym_index, shndx, code, elf.STT_FUNC); |
| 1097 | 1115 | |
| 1098 | 1116 | if (decl_state) |*ds| { |
| 1099 | const sym = elf_file.symbol(sym_index); | |
| 1117 | const sym = self.symbol(sym_index); | |
| 1100 | 1118 | try self.dwarf.?.commitDeclState( |
| 1101 | 1119 | pt, |
| 1102 | 1120 | decl_index, |
| ... | ... | @@ -1130,13 +1148,13 @@ pub fn updateDecl( |
| 1130 | 1148 | const variable = decl.getOwnedVariable(mod).?; |
| 1131 | 1149 | const name = decl.name.toSlice(&mod.intern_pool); |
| 1132 | 1150 | const lib_name = variable.lib_name.toSlice(&mod.intern_pool); |
| 1133 | const esym_index = try self.getGlobalSymbol(elf_file, name, lib_name); | |
| 1134 | elf_file.symbol(self.symbol(esym_index)).flags.needs_got = true; | |
| 1151 | const sym_index = try self.getGlobalSymbol(elf_file, name, lib_name); | |
| 1152 | self.symbol(sym_index).flags.needs_got = true; | |
| 1135 | 1153 | return; |
| 1136 | 1154 | } |
| 1137 | 1155 | |
| 1138 | 1156 | const sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index); |
| 1139 | elf_file.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); | |
| 1157 | self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); | |
| 1140 | 1158 | |
| 1141 | 1159 | const gpa = elf_file.base.comp.gpa; |
| 1142 | 1160 | var code_buffer = std.ArrayList(u8).init(gpa); |
| ... | ... | @@ -1174,7 +1192,7 @@ pub fn updateDecl( |
| 1174 | 1192 | try self.updateDeclCode(elf_file, pt, decl_index, sym_index, shndx, code, elf.STT_OBJECT); |
| 1175 | 1193 | |
| 1176 | 1194 | if (decl_state) |*ds| { |
| 1177 | const sym = elf_file.symbol(sym_index); | |
| 1195 | const sym = self.symbol(sym_index); | |
| 1178 | 1196 | try self.dwarf.?.commitDeclState( |
| 1179 | 1197 | pt, |
| 1180 | 1198 | decl_index, |
| ... | ... | @@ -1233,9 +1251,9 @@ fn updateLazySymbol( |
| 1233 | 1251 | .code => elf_file.zig_text_section_index.?, |
| 1234 | 1252 | .const_data => elf_file.zig_data_rel_ro_section_index.?, |
| 1235 | 1253 | }; |
| 1236 | const local_sym = elf_file.symbol(symbol_index); | |
| 1254 | const local_sym = self.symbol(symbol_index); | |
| 1237 | 1255 | local_sym.name_offset = name_str_index; |
| 1238 | const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index]; | |
| 1256 | const local_esym = &self.symtab.items(.elf_sym)[local_sym.esym_index]; | |
| 1239 | 1257 | local_esym.st_name = name_str_index; |
| 1240 | 1258 | local_esym.st_info |= elf.STT_OBJECT; |
| 1241 | 1259 | local_esym.st_size = code.len; |
| ... | ... | @@ -1323,7 +1341,8 @@ fn lowerConst( |
| 1323 | 1341 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1324 | 1342 | defer code_buffer.deinit(); |
| 1325 | 1343 | |
| 1326 | const sym_index = try self.newAtom(elf_file); | |
| 1344 | const name_off = try self.addString(gpa, name); | |
| 1345 | const sym_index = try self.newSymbolWithAtom(gpa, name_off); | |
| 1327 | 1346 | |
| 1328 | 1347 | const res = try codegen.generateSymbol( |
| 1329 | 1348 | &elf_file.base, |
| ... | ... | @@ -1339,27 +1358,19 @@ fn lowerConst( |
| 1339 | 1358 | .fail => |em| return .{ .fail = em }, |
| 1340 | 1359 | }; |
| 1341 | 1360 | |
| 1342 | const local_sym = elf_file.symbol(sym_index); | |
| 1343 | const name_str_index = try self.strtab.insert(gpa, name); | |
| 1344 | local_sym.name_offset = name_str_index; | |
| 1345 | const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index]; | |
| 1346 | local_esym.st_name = name_str_index; | |
| 1361 | const local_sym = self.symbol(sym_index); | |
| 1362 | const local_esym = &self.symtab.items(.elf_sym)[local_sym.esym_index]; | |
| 1347 | 1363 | local_esym.st_info |= elf.STT_OBJECT; |
| 1348 | 1364 | local_esym.st_size = code.len; |
| 1349 | 1365 | const atom_ptr = local_sym.atom(elf_file).?; |
| 1350 | 1366 | atom_ptr.alive = true; |
| 1351 | atom_ptr.name_offset = name_str_index; | |
| 1352 | 1367 | atom_ptr.alignment = required_alignment; |
| 1353 | 1368 | atom_ptr.size = code.len; |
| 1354 | 1369 | atom_ptr.output_section_index = output_section_index; |
| 1355 | 1370 | |
| 1356 | 1371 | try atom_ptr.allocate(elf_file); |
| 1357 | // TODO rename and re-audit this method | |
| 1358 | 1372 | errdefer self.freeDeclMetadata(elf_file, sym_index); |
| 1359 | 1373 | |
| 1360 | local_sym.value = 0; | |
| 1361 | local_esym.st_value = 0; | |
| 1362 | ||
| 1363 | 1374 | const shdr = elf_file.shdrs.items[output_section_index]; |
| 1364 | 1375 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); |
| 1365 | 1376 | try elf_file.base.file.?.pwriteAll(code, file_offset); |
| ... | ... | @@ -1401,9 +1412,9 @@ pub fn updateExports( |
| 1401 | 1412 | }, |
| 1402 | 1413 | }; |
| 1403 | 1414 | const sym_index = metadata.symbol_index; |
| 1404 | const esym_index = elf_file.symbol(sym_index).esym_index; | |
| 1405 | const esym = self.local_esyms.items(.elf_sym)[esym_index]; | |
| 1406 | const esym_shndx = self.local_esyms.items(.shndx)[esym_index]; | |
| 1415 | const esym_index = self.symbol(sym_index).esym_index; | |
| 1416 | const esym = self.symtab.items(.elf_sym)[esym_index]; | |
| 1417 | const esym_shndx = self.symtab.items(.shndx)[esym_index]; | |
| 1407 | 1418 | |
| 1408 | 1419 | for (export_indices) |export_idx| { |
| 1409 | 1420 | const exp = mod.all_exports.items[export_idx]; |
| ... | ... | @@ -1437,22 +1448,27 @@ pub fn updateExports( |
| 1437 | 1448 | const stt_bits: u8 = @as(u4, @truncate(esym.st_info)); |
| 1438 | 1449 | const exp_name = exp.opts.name.toSlice(&mod.intern_pool); |
| 1439 | 1450 | const name_off = try self.strtab.insert(gpa, exp_name); |
| 1440 | const global_esym_index = if (metadata.@"export"(self, exp_name)) |exp_index| | |
| 1451 | const global_sym_index = if (metadata.@"export"(self, exp_name)) |exp_index| | |
| 1441 | 1452 | exp_index.* |
| 1442 | 1453 | else blk: { |
| 1443 | const global_esym_index = try self.getGlobalSymbol(elf_file, exp_name, null); | |
| 1444 | try metadata.exports.append(gpa, global_esym_index); | |
| 1445 | break :blk global_esym_index; | |
| 1454 | const global_sym_index = try self.getGlobalSymbol(elf_file, exp_name, null); | |
| 1455 | try metadata.exports.append(gpa, global_sym_index); | |
| 1456 | break :blk global_sym_index; | |
| 1446 | 1457 | }; |
| 1447 | 1458 | |
| 1448 | const actual_esym_index = global_esym_index & symbol_mask; | |
| 1449 | const global_esym = &self.global_esyms.items(.elf_sym)[actual_esym_index]; | |
| 1450 | global_esym.st_value = @intCast(elf_file.symbol(sym_index).value); | |
| 1459 | const value = self.symbol(sym_index).value; | |
| 1460 | const global_sym = self.symbol(global_sym_index); | |
| 1461 | global_sym.value = value; | |
| 1462 | global_sym.flags.weak = exp.opts.linkage == .weak; | |
| 1463 | global_sym.version_index = elf_file.default_sym_version; | |
| 1464 | global_sym.ref = .{ .index = esym_shndx, .file = self.index }; | |
| 1465 | const global_esym = &self.symtab.items(.elf_sym)[global_sym.esym_index]; | |
| 1466 | global_esym.st_value = @intCast(value); | |
| 1451 | 1467 | global_esym.st_shndx = esym.st_shndx; |
| 1452 | 1468 | global_esym.st_info = (stb_bits << 4) | stt_bits; |
| 1453 | 1469 | global_esym.st_name = name_off; |
| 1454 | 1470 | global_esym.st_size = esym.st_size; |
| 1455 | self.global_esyms.items(.shndx)[actual_esym_index] = esym_shndx; | |
| 1471 | self.symtab.items(.shndx)[global_sym.esym_index] = esym_shndx; | |
| 1456 | 1472 | } |
| 1457 | 1473 | } |
| 1458 | 1474 | |
| ... | ... | @@ -1488,16 +1504,10 @@ pub fn deleteExport( |
| 1488 | 1504 | const exp_name = name.toSlice(&mod.intern_pool); |
| 1489 | 1505 | const esym_index = metadata.@"export"(self, exp_name) orelse return; |
| 1490 | 1506 | log.debug("deleting export '{s}'", .{exp_name}); |
| 1491 | const esym = &self.global_esyms.items(.elf_sym)[esym_index.*]; | |
| 1507 | const esym = &self.symtab.items(.elf_sym)[esym_index.*]; | |
| 1492 | 1508 | _ = self.globals_lookup.remove(esym.st_name); |
| 1493 | const sym_index = elf_file.resolver.get(esym.st_name).?; | |
| 1494 | const sym = elf_file.symbol(sym_index); | |
| 1495 | if (sym.file_index == self.index) { | |
| 1496 | _ = elf_file.resolver.swapRemove(esym.st_name); | |
| 1497 | sym.* = .{}; | |
| 1498 | } | |
| 1499 | 1509 | esym.* = Elf.null_sym; |
| 1500 | self.global_esyms.items(.shndx)[esym_index.*] = elf.SHN_UNDEF; | |
| 1510 | self.symtab.items(.shndx)[esym_index.*] = elf.SHN_UNDEF; | |
| 1501 | 1511 | } |
| 1502 | 1512 | |
| 1503 | 1513 | pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 { |
| ... | ... | @@ -1506,16 +1516,19 @@ pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_n |
| 1506 | 1516 | const off = try self.strtab.insert(gpa, name); |
| 1507 | 1517 | const lookup_gop = try self.globals_lookup.getOrPut(gpa, off); |
| 1508 | 1518 | if (!lookup_gop.found_existing) { |
| 1509 | const esym_index = try self.addGlobalEsym(gpa); | |
| 1510 | const esym = self.elfSym(esym_index); | |
| 1511 | esym.st_name = off; | |
| 1512 | lookup_gop.value_ptr.* = esym_index; | |
| 1513 | const gop = try elf_file.getOrPutGlobal(name); | |
| 1514 | try self.global_symbols.append(gpa, gop.index); | |
| 1519 | lookup_gop.value_ptr.* = try self.newGlobalSymbol(gpa, off); | |
| 1515 | 1520 | } |
| 1516 | 1521 | return lookup_gop.value_ptr.*; |
| 1517 | 1522 | } |
| 1518 | 1523 | |
| 1524 | pub fn asFile(self: *ZigObject) File { | |
| 1525 | return .{ .zig_object = self }; | |
| 1526 | } | |
| 1527 | ||
| 1528 | fn addString(self: *ZigObject, allocator: Allocator, string: []const u8) !u32 { | |
| 1529 | return self.strtab.insert(allocator, string); | |
| 1530 | } | |
| 1531 | ||
| 1519 | 1532 | pub fn getString(self: ZigObject, off: u32) [:0]const u8 { |
| 1520 | 1533 | return self.strtab.getAssumeExists(off); |
| 1521 | 1534 | } |
| ... | ... | @@ -1586,6 +1599,77 @@ pub fn setAtomExtra(self: *ZigObject, index: u32, extra: Atom.Extra) void { |
| 1586 | 1599 | } |
| 1587 | 1600 | } |
| 1588 | 1601 | |
| 1602 | inline fn isGlobal(index: Symbol.Index) bool { | |
| 1603 | return index & global_symbol_bit != 0; | |
| 1604 | } | |
| 1605 | ||
| 1606 | pub fn symbol(self: *ZigObject, index: Symbol.Index) *Symbol { | |
| 1607 | const actual_index = index & symbol_mask; | |
| 1608 | if (isGlobal(index)) return &self.symbols.items[self.global_symbols.items[actual_index]]; | |
| 1609 | return &self.symbols.items[self.local_symbols.items[actual_index]]; | |
| 1610 | } | |
| 1611 | ||
| 1612 | pub fn resolveSymbol(self: ZigObject, index: Symbol.Index, elf_file: *Elf) Elf.Ref { | |
| 1613 | if (isGlobal(index)) { | |
| 1614 | const resolv = self.symbols_resolver.items[index & symbol_mask]; | |
| 1615 | return elf_file.resolver.get(resolv).?; | |
| 1616 | } | |
| 1617 | return .{ .index = index, .file = self.index }; | |
| 1618 | } | |
| 1619 | ||
| 1620 | fn addSymbol(self: *ZigObject, allocator: Allocator) !Symbol.Index { | |
| 1621 | try self.symbols.ensureUnusedCapacity(allocator, 1); | |
| 1622 | return self.addSymbolAssumeCapacity(); | |
| 1623 | } | |
| 1624 | ||
| 1625 | fn addSymbolAssumeCapacity(self: *ZigObject) Symbol.Index { | |
| 1626 | const index: Symbol.Index = @intCast(self.symbols.items.len); | |
| 1627 | self.symbols.appendAssumeCapacity(.{ .file_index = self.index }); | |
| 1628 | return index; | |
| 1629 | } | |
| 1630 | ||
| 1631 | pub fn addSymbolExtra(self: *ZigObject, allocator: Allocator, extra: Symbol.Extra) !u32 { | |
| 1632 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 1633 | try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len); | |
| 1634 | return self.addSymbolExtraAssumeCapacity(extra); | |
| 1635 | } | |
| 1636 | ||
| 1637 | pub fn addSymbolExtraAssumeCapacity(self: *ZigObject, extra: Symbol.Extra) u32 { | |
| 1638 | const index = @as(u32, @intCast(self.symbols_extra.items.len)); | |
| 1639 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 1640 | inline for (fields) |field| { | |
| 1641 | self.symbols_extra.appendAssumeCapacity(switch (field.type) { | |
| 1642 | u32 => @field(extra, field.name), | |
| 1643 | else => @compileError("bad field type"), | |
| 1644 | }); | |
| 1645 | } | |
| 1646 | return index; | |
| 1647 | } | |
| 1648 | ||
| 1649 | pub fn symbolExtra(self: *ZigObject, index: u32) Symbol.Extra { | |
| 1650 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 1651 | var i: usize = index; | |
| 1652 | var result: Symbol.Extra = undefined; | |
| 1653 | inline for (fields) |field| { | |
| 1654 | @field(result, field.name) = switch (field.type) { | |
| 1655 | u32 => self.symbols_extra.items[i], | |
| 1656 | else => @compileError("bad field type"), | |
| 1657 | }; | |
| 1658 | i += 1; | |
| 1659 | } | |
| 1660 | return result; | |
| 1661 | } | |
| 1662 | ||
| 1663 | pub fn setSymbolExtra(self: *ZigObject, index: u32, extra: Symbol.Extra) void { | |
| 1664 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | |
| 1665 | inline for (fields, 0..) |field, i| { | |
| 1666 | self.symbols_extra.items[index + i] = switch (field.type) { | |
| 1667 | u32 => @field(extra, field.name), | |
| 1668 | else => @compileError("bad field type"), | |
| 1669 | }; | |
| 1670 | } | |
| 1671 | } | |
| 1672 | ||
| 1589 | 1673 | pub fn fmtSymtab(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatSymtab) { |
| 1590 | 1674 | return .{ .data = .{ |
| 1591 | 1675 | .self = self, |
| ... | ... | @@ -1606,15 +1690,17 @@ fn formatSymtab( |
| 1606 | 1690 | ) !void { |
| 1607 | 1691 | _ = unused_fmt_string; |
| 1608 | 1692 | _ = options; |
| 1693 | const self = ctx.self; | |
| 1694 | const elf_file = ctx.elf_file; | |
| 1609 | 1695 | try writer.writeAll(" locals\n"); |
| 1610 | for (ctx.self.locals()) |index| { | |
| 1611 | const local = ctx.elf_file.symbol(index); | |
| 1612 | try writer.print(" {}\n", .{local.fmt(ctx.elf_file)}); | |
| 1696 | for (self.local_symbols.items) |index| { | |
| 1697 | const local = self.symbols.items[index]; | |
| 1698 | try writer.print(" {}\n", .{local.fmt(elf_file)}); | |
| 1613 | 1699 | } |
| 1614 | 1700 | try writer.writeAll(" globals\n"); |
| 1615 | for (ctx.self.globals()) |index| { | |
| 1616 | const global = ctx.elf_file.symbol(index); | |
| 1617 | try writer.print(" {}\n", .{global.fmt(ctx.elf_file)}); | |
| 1701 | for (ctx.self.global_symbols.items) |index| { | |
| 1702 | const global = self.symbols.items[index]; | |
| 1703 | try writer.print(" {}\n", .{global.fmt(elf_file)}); | |
| 1618 | 1704 | } |
| 1619 | 1705 | } |
| 1620 | 1706 | |
| ... | ... | @@ -1658,9 +1744,9 @@ const DeclMetadata = struct { |
| 1658 | 1744 | /// A list of all exports aliases of this Decl. |
| 1659 | 1745 | exports: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 1660 | 1746 | |
| 1661 | fn @"export"(m: DeclMetadata, zig_object: *ZigObject, name: []const u8) ?*u32 { | |
| 1747 | fn @"export"(m: DeclMetadata, zo: *ZigObject, name: []const u8) ?*u32 { | |
| 1662 | 1748 | for (m.exports.items) |*exp| { |
| 1663 | const exp_name = zig_object.getString(zig_object.elfSym(exp.*).st_name); | |
| 1749 | const exp_name = zo.getString(zo.symbol(exp.*).name_offset); | |
| 1664 | 1750 | if (mem.eql(u8, name, exp_name)) return exp; |
| 1665 | 1751 | } |
| 1666 | 1752 | return null; |
src/link/Elf/eh_frame.zig+13-8| ... | ... | @@ -145,10 +145,10 @@ pub const Cie = struct { |
| 145 | 145 | if (cie_rel.r_addend != other_rel.r_addend) return false; |
| 146 | 146 | |
| 147 | 147 | const cie_object = elf_file.file(cie.file_index).?.object; |
| 148 | const cie_ref = cie_object.resolveSymbol(cie_rel.r_sym(), elf_file); | |
| 148 | 149 | const other_object = elf_file.file(other.file_index).?.object; |
| 149 | const cie_sym = cie_object.symbols.items[cie_rel.r_sym()]; | |
| 150 | const other_sym = other_object.symbols.items[other_rel.r_sym()]; | |
| 151 | if (!std.mem.eql(u8, std.mem.asBytes(&cie_sym), std.mem.asBytes(&other_sym))) return false; | |
| 150 | const other_ref = other_object.resolveSymbol(other_rel.r_sym(), elf_file); | |
| 151 | if (!cie_ref.eql(other_ref)) return false; | |
| 152 | 152 | } |
| 153 | 153 | return true; |
| 154 | 154 | } |
| ... | ... | @@ -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+80-25| ... | ... | @@ -61,20 +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 | } | |
| 68 | } | |
| 69 | ||
| 70 | pub fn resetGlobals(file: File, elf_file: *Elf) void { | |
| 71 | for (file.globals()) |global_index| { | |
| 72 | const global = elf_file.symbol(global_index); | |
| 73 | const name_offset = global.name_offset; | |
| 74 | global.* = .{}; | |
| 75 | global.name_offset = name_offset; | |
| 76 | global.flags.global = true; | |
| 77 | } | |
| 67 | }; | |
| 78 | 68 | } |
| 79 | 69 | |
| 80 | 70 | pub fn setAlive(file: File) void { |
| ... | ... | @@ -98,6 +88,77 @@ pub const File = union(enum) { |
| 98 | 88 | } |
| 99 | 89 | } |
| 100 | 90 | |
| 91 | pub fn createSymbolIndirection(file: File, elf_file: *Elf) !void { | |
| 92 | const impl = struct { | |
| 93 | fn impl(sym: *Symbol, ref: Elf.Ref, ef: *Elf) !void { | |
| 94 | if (!sym.isLocal(ef) and !sym.flags.has_dynamic) { | |
| 95 | log.debug("'{s}' is non-local", .{sym.name(ef)}); | |
| 96 | try ef.dynsym.addSymbol(ref, ef); | |
| 97 | } | |
| 98 | if (sym.flags.needs_got) { | |
| 99 | log.debug("'{s}' needs GOT", .{sym.name(ef)}); | |
| 100 | _ = try ef.got.addGotSymbol(ref, ef); | |
| 101 | } | |
| 102 | if (sym.flags.needs_plt) { | |
| 103 | if (sym.flags.is_canonical) { | |
| 104 | log.debug("'{s}' needs CPLT", .{sym.name(ef)}); | |
| 105 | sym.flags.@"export" = true; | |
| 106 | try ef.plt.addSymbol(ref, ef); | |
| 107 | } else if (sym.flags.needs_got) { | |
| 108 | log.debug("'{s}' needs PLTGOT", .{sym.name(ef)}); | |
| 109 | try ef.plt_got.addSymbol(ref, ef); | |
| 110 | } else { | |
| 111 | log.debug("'{s}' needs PLT", .{sym.name(ef)}); | |
| 112 | try ef.plt.addSymbol(ref, ef); | |
| 113 | } | |
| 114 | } | |
| 115 | if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) { | |
| 116 | log.debug("'{s}' needs COPYREL", .{sym.name(ef)}); | |
| 117 | try ef.copy_rel.addSymbol(ref, ef); | |
| 118 | } | |
| 119 | if (sym.flags.needs_tlsgd) { | |
| 120 | log.debug("'{s}' needs TLSGD", .{sym.name(ef)}); | |
| 121 | try ef.got.addTlsGdSymbol(ref, ef); | |
| 122 | } | |
| 123 | if (sym.flags.needs_gottp) { | |
| 124 | log.debug("'{s}' needs GOTTP", .{sym.name(ef)}); | |
| 125 | try ef.got.addGotTpSymbol(ref, ef); | |
| 126 | } | |
| 127 | if (sym.flags.needs_tlsdesc) { | |
| 128 | log.debug("'{s}' needs TLSDESC", .{sym.name(ef)}); | |
| 129 | try ef.got.addTlsDescSymbol(ref, ef); | |
| 130 | } | |
| 131 | } | |
| 132 | }.impl; | |
| 133 | ||
| 134 | switch (file) { | |
| 135 | .zig_object => |x| { | |
| 136 | for (x.local_symbols.items, 0..) |idx, i| { | |
| 137 | const sym = &x.symbols.items[idx]; | |
| 138 | const ref = x.resolveSymbol(@intCast(i), elf_file); | |
| 139 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 140 | if (ref_sym.file(elf_file).?.index() != x.index) continue; | |
| 141 | try impl(sym, ref, elf_file); | |
| 142 | } | |
| 143 | for (x.global_symbols.items, 0..) |idx, i| { | |
| 144 | const sym = &x.symbols.items[idx]; | |
| 145 | const ref = x.resolveSymbol(@intCast(i | ZigObject.global_symbol_bit), elf_file); | |
| 146 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 147 | if (ref_sym.file(elf_file).?.index() != x.index) continue; | |
| 148 | try impl(sym, ref, elf_file); | |
| 149 | } | |
| 150 | }, | |
| 151 | inline else => |x| { | |
| 152 | for (x.symbols.items, 0..) |*sym, i| { | |
| 153 | const ref = x.resolveSymbol(@intCast(i), elf_file); | |
| 154 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 155 | if (ref_sym.file(elf_file).?.index() != x.index) continue; | |
| 156 | try impl(sym, ref, elf_file); | |
| 157 | } | |
| 158 | }, | |
| 159 | } | |
| 160 | } | |
| 161 | ||
| 101 | 162 | pub fn atom(file: File, atom_index: Atom.Index) ?*Atom { |
| 102 | 163 | return switch (file) { |
| 103 | 164 | .shared_object => unreachable, |
| ... | ... | @@ -144,23 +205,16 @@ pub const File = union(enum) { |
| 144 | 205 | }; |
| 145 | 206 | } |
| 146 | 207 | |
| 147 | pub fn symbol(file: File, ind: Symbol.Index) Symbol.Index { | |
| 208 | pub fn resolveSymbol(file: File, ind: Symbol.Index, elf_file: *Elf) Elf.Ref { | |
| 148 | 209 | return switch (file) { |
| 149 | .zig_object => |x| x.symbol(ind), | |
| 150 | inline else => |x| x.symbols.items[ind], | |
| 210 | inline else => |x| x.resolveSymbol(ind, elf_file), | |
| 151 | 211 | }; |
| 152 | 212 | } |
| 153 | 213 | |
| 154 | pub fn locals(file: File) []const Symbol.Index { | |
| 214 | pub fn symbol(file: File, ind: Symbol.Index) *Symbol { | |
| 155 | 215 | return switch (file) { |
| 156 | .linker_defined, .shared_object => &[0]Symbol.Index{}, | |
| 157 | inline else => |x| x.locals(), | |
| 158 | }; | |
| 159 | } | |
| 160 | ||
| 161 | pub fn globals(file: File) []const Symbol.Index { | |
| 162 | return switch (file) { | |
| 163 | inline else => |x| x.globals(), | |
| 216 | .zig_object => |x| x.symbol(ind), | |
| 217 | inline else => |x| &x.symbols.items[ind], | |
| 164 | 218 | }; |
| 165 | 219 | } |
| 166 | 220 | |
| ... | ... | @@ -237,6 +291,7 @@ pub const File = union(enum) { |
| 237 | 291 | |
| 238 | 292 | const std = @import("std"); |
| 239 | 293 | const elf = std.elf; |
| 294 | const log = std.log.scoped(.link); | |
| 240 | 295 | |
| 241 | 296 | const Allocator = std.mem.Allocator; |
| 242 | 297 | const Archive = @import("Archive.zig"); |
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+130-135| ... | ... | @@ -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; | |
| 412 | 420 | try writer.writeAll(".zig.got\n"); |
| 413 | for (ctx.zig_got.entries.items, 0..) |entry, index| { | |
| 414 | const symbol = ctx.elf_file.symbol(entry); | |
| 421 | for (zig_got.entries.items, 0..) |entry, index| { | |
| 422 | const zo = elf_file.zigObjectPtr().?; | |
| 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,11 +643,8 @@ 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 | }; | |
| 644 | const extra = if (symbol) |s| s.extra(elf_file).? else null; | |
| 646 | const symbol = elf_file.symbol(entry.ref); | |
| 647 | const extra = if (symbol) |s| s.extra(elf_file) else null; | |
| 645 | 648 | |
| 646 | 649 | switch (entry.tag) { |
| 647 | 650 | .got => { |
| ... | ... | @@ -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,10 +888,10 @@ 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 | const extra = sym.extra(elf_file).?; | |
| 894 | const extra = sym.extra(elf_file); | |
| 902 | 895 | const r_offset: u64 = @intCast(sym.gotPltAddress(elf_file)); |
| 903 | 896 | const r_sym: u64 = extra.dynamic; |
| 904 | 897 | const r_type = relocation.encode(.jump_slot, cpu_arch); |
| ... | ... | @@ -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,10 +1259,10 @@ 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 | const extra = sym.extra(elf_file).?; | |
| 1265 | const extra = sym.extra(elf_file); | |
| 1271 | 1266 | elf_file.addRelaDynAssumeCapacity(.{ |
| 1272 | 1267 | .offset = @intCast(sym.address(.{}, elf_file)), |
| 1273 | 1268 | .sym = extra.dynamic, |
| ... | ... | @@ -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"; |
| ... | ... | @@ -1322,14 +1317,14 @@ pub const DynsymSection = struct { |
| 1322 | 1317 | const rhs_hash = GnuHashSection.hasher(rhs_sym.name(ctx)) % nbuckets; |
| 1323 | 1318 | |
| 1324 | 1319 | if (lhs_hash == rhs_hash) |
| 1325 | return lhs_sym.extra(ctx).?.dynamic < rhs_sym.extra(ctx).?.dynamic; | |
| 1320 | return lhs_sym.extra(ctx).dynamic < rhs_sym.extra(ctx).dynamic; | |
| 1326 | 1321 | return lhs_hash < rhs_hash; |
| 1327 | 1322 | } |
| 1328 | 1323 | }; |
| 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,8 +1333,8 @@ 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); | |
| 1342 | var extra = sym.extra(elf_file).?; | |
| 1336 | const sym = elf_file.symbol(entry.ref).?; | |
| 1337 | var extra = sym.extra(elf_file); | |
| 1343 | 1338 | extra.dynamic = @as(u32, @intCast(index)); |
| 1344 | 1339 | sym.setExtra(extra, elf_file); |
| 1345 | 1340 | } |
| ... | ... | @@ -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); |