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