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