authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-08 00:27:36+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-08-08 00:27:36+02:00
logcfe6ff4301d43ccd2739b2f4495e371211252afd
tree065a3fcfb21e8d3d986be2e5779a2ef43ee7ef78
parentb8705ed6527e779a140e8beccb48d424dbbdf856
parentb058545970efb6f533f9930d23af2a6d0c6ce9c3
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #20971 from ziglang/elf-ownership-2

elf: move ownership of symbols into owning objects

22 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
43544354 if (try self.air.value(callee, pt)) |func_value| {
43554355 if (func_value.getFunction(mod)) |func| {
43564356 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
4357 const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
4358 const sym = elf_file.symbol(sym_index);
4357 const zo = elf_file.zigObjectPtr().?;
4358 const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
4359 const sym = zo.symbol(sym_index);
43594360 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
43604361 const got_addr = @as(u32, @intCast(sym.zigGotAddress(elf_file)));
43614362 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
43364336 if (try self.air.value(callee, pt)) |func_value| {
43374337 if (func_value.getFunction(mod)) |func| {
43384338 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
4339 const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
4340 const sym = elf_file.symbol(sym_index);
4339 const zo = elf_file.zigObjectPtr().?;
4340 const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
4341 const sym = zo.symbol(sym_index);
43414342 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
43424343 const got_addr: u32 = @intCast(sym.zigGotAddress(elf_file));
43434344 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 {
14091409 defer func.register_manager.unlockReg(data_lock);
14101410
14111411 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, .{
14131414 .kind = .const_data,
14141415 .ty = enum_ty,
14151416 }) catch |err|
14161417 return func.fail("{s} creating lazy symbol", .{@errorName(err)});
1417 const sym = elf_file.symbol(sym_index);
14181418
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 } });
14201420
14211421 const cmp_reg, const cmp_lock = try func.allocReg(.int);
14221422 defer func.register_manager.unlockReg(cmp_lock);
......@@ -4946,13 +4946,13 @@ fn genCall(
49464946 }) {
49474947 .func => |func_val| {
49484948 if (func.bin_file.cast(link.File.Elf)) |elf_file| {
4949 const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func_val.owner_decl);
4950 const sym = elf_file.symbol(sym_index);
4949 const zo = elf_file.zigObjectPtr().?;
4950 const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func_val.owner_decl);
49514951
49524952 if (func.mod.pic) {
49534953 return func.fail("TODO: genCall pic", .{});
49544954 } 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 } });
49564956 _ = try func.addInst(.{
49574957 .tag = .jalr,
49584958 .data = .{ .i_type = .{
......@@ -7822,14 +7822,14 @@ fn airTagName(func: *Func, inst: Air.Inst.Index) !void {
78227822
78237823 const lazy_sym = link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(zcu), zcu);
78247824 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|
78267827 return func.fail("{s} creating lazy symbol", .{@errorName(err)});
7827 const sym = elf_file.symbol(sym_index);
78287828
78297829 if (func.mod.pic) {
78307830 return func.fail("TODO: airTagName pic", .{});
78317831 } 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 } });
78337833 _ = try func.addInst(.{
78347834 .tag = .jalr,
78357835 .data = .{ .i_type = .{
......@@ -8047,11 +8047,7 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {
80478047 return error.CodegenFail;
80488048 };
80498049 switch (lf.tag) {
8050 .elf => {
8051 const elf_file = lf.cast(link.File.Elf).?;
8052 const local = elf_file.symbol(local_sym_index);
8053 return MCValue{ .undef = local.esym_index };
8054 },
8050 .elf => return MCValue{ .undef = local_sym_index },
80558051 else => unreachable,
80568052 }
80578053 }
src/arch/riscv64/Emit.zig+8-6
......@@ -50,16 +50,16 @@ pub fn emitMir(emit: *Emit) Error!void {
5050 };
5151
5252 const elf_file = emit.bin_file.cast(link.File.Elf).?;
53 const zo = elf_file.zigObjectPtr().?;
5354
54 const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
55 const sym_index = elf_file.zigObjectPtr().?.symbol(symbol.sym_index);
56 const sym = elf_file.symbol(sym_index);
55 const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?;
56 const sym = zo.symbol(symbol.sym_index);
5757
5858 var hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);
5959 var lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I);
6060
6161 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);
6363
6464 hi_r_type = Elf.R_ZIG_GOT_HI20;
6565 lo_r_type = Elf.R_ZIG_GOT_LO12;
......@@ -82,8 +82,9 @@ pub fn emitMir(emit: *Emit) Error!void {
8282 },
8383 .load_tlv_reloc => |symbol| {
8484 const elf_file = emit.bin_file.cast(link.File.Elf).?;
85 const zo = elf_file.zigObjectPtr().?;
8586
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).?;
8788
8889 const R_RISCV = std.elf.R_RISCV;
8990
......@@ -107,7 +108,8 @@ pub fn emitMir(emit: *Emit) Error!void {
107108 },
108109 .call_extern_fn_reloc => |symbol| {
109110 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).?;
111113
112114 const r_type: u32 = @intFromEnum(std.elf.R_RISCV.CALL_PLT);
113115
src/arch/sparc64/CodeGen.zig+3-2
......@@ -1354,8 +1354,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
13541354 switch (mod.intern_pool.indexToKey(func_value.ip_index)) {
13551355 .func => |func| {
13561356 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
1357 const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
1358 const sym = elf_file.symbol(sym_index);
1357 const zo = elf_file.zigObjectPtr().?;
1358 const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
1359 const sym = zo.symbol(sym_index);
13591360 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
13601361 break :blk @as(u32, @intCast(sym.zigGotAddress(elf_file)));
13611362 } else unreachable;
src/arch/x86_64/CodeGen.zig+9-9
......@@ -12327,8 +12327,8 @@ fn genCall(self: *Self, info: union(enum) {
1232712327 }) {
1232812328 .func => |func| {
1232912329 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
12330 const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
12331 const sym = elf_file.symbol(sym_index);
12330 const zo = elf_file.zigObjectPtr().?;
12331 const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
1233212332 if (self.mod.pic) {
1233312333 const callee_reg: Register = switch (resolved_cc) {
1233412334 .SysV => callee: {
......@@ -12345,14 +12345,14 @@ fn genCall(self: *Self, info: union(enum) {
1234512345 try self.genSetReg(
1234612346 callee_reg,
1234712347 Type.usize,
12348 .{ .load_symbol = .{ .sym = sym.esym_index } },
12348 .{ .load_symbol = .{ .sym = sym_index } },
1234912349 .{},
1235012350 );
1235112351 try self.asmRegister(.{ ._, .call }, callee_reg);
1235212352 } else try self.asmMemory(.{ ._, .call }, .{
1235312353 .base = .{ .reloc = .{
1235412354 .atom_index = try self.owner.getSymbolIndex(self),
12355 .sym_index = sym.esym_index,
12355 .sym_index = sym_index,
1235612356 } },
1235712357 .mod = .{ .rm = .{ .size = .qword } },
1235812358 });
......@@ -15320,16 +15320,16 @@ fn genLazySymbolRef(
1532015320) InnerError!void {
1532115321 const pt = self.pt;
1532215322 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|
1532415325 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
15325 const sym = elf_file.symbol(sym_index);
1532615326 if (self.mod.pic) {
1532715327 switch (tag) {
1532815328 .lea, .call => try self.genSetReg(reg, Type.usize, .{
15329 .load_symbol = .{ .sym = sym.esym_index },
15329 .load_symbol = .{ .sym = sym_index },
1533015330 }, .{}),
1533115331 .mov => try self.genSetReg(reg, Type.usize, .{
15332 .load_symbol = .{ .sym = sym.esym_index },
15332 .load_symbol = .{ .sym = sym_index },
1533315333 }, .{}),
1533415334 else => unreachable,
1533515335 }
......@@ -15341,7 +15341,7 @@ fn genLazySymbolRef(
1534115341 } else {
1534215342 const reloc = bits.Symbol{
1534315343 .atom_index = try self.owner.getSymbolIndex(self),
15344 .sym_index = sym.esym_index,
15344 .sym_index = sym_index,
1534515345 };
1534615346 switch (tag) {
1534715347 .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 {
4242 }),
4343 .linker_extern_fn => |symbol| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {
4444 // 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).?;
4647 const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);
4748 try atom_ptr.addReloc(elf_file, .{
4849 .r_offset = end_offset - 4,
......@@ -88,7 +89,8 @@ pub fn emitMir(emit: *Emit) Error!void {
8889 }),
8990 .linker_tlsld => |data| {
9091 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).?;
9294 const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);
9395 try atom.addReloc(elf_file, .{
9496 .r_offset = end_offset - 4,
......@@ -98,7 +100,8 @@ pub fn emitMir(emit: *Emit) Error!void {
98100 },
99101 .linker_dtpoff => |data| {
100102 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).?;
102105 const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);
103106 try atom.addReloc(elf_file, .{
104107 .r_offset = end_offset - 4,
......@@ -112,11 +115,11 @@ pub fn emitMir(emit: *Emit) Error!void {
112115 .Obj => true,
113116 .Lib => emit.lower.link_mode == .static,
114117 };
115 const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
116 const sym_index = elf_file.zigObjectPtr().?.symbol(data.sym_index);
117 const sym = elf_file.symbol(sym_index);
118 const zo = elf_file.zigObjectPtr().?;
119 const atom = zo.symbol(data.atom_index).atom(elf_file).?;
120 const sym = zo.symbol(data.sym_index);
118121 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);
120123 }
121124 if (emit.lower.pic) {
122125 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)
349349 assert(mem_op.sib.scale_index.scale == 0);
350350
351351 if (lower.bin_file.cast(link.File.Elf)) |elf_file| {
352 const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
353 const elf_sym = elf_file.symbol(sym_index);
352 const zo = elf_file.zigObjectPtr().?;
353 const elf_sym = zo.symbol(sym.sym_index);
354354
355355 if (elf_sym.flags.is_tls) {
356356 // TODO handle extern TLS vars, i.e., emit GD model
src/codegen.zig+6-8
......@@ -906,20 +906,20 @@ fn genDeclRef(
906906 const is_extern = decl.isExtern(zcu);
907907
908908 if (lf.cast(link.File.Elf)) |elf_file| {
909 const zo = elf_file.zigObjectPtr().?;
909910 if (is_extern) {
910911 const name = decl.name.toSlice(ip);
911912 // TODO audit this
912913 const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null;
913914 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;
915916 return GenResult.mcv(.{ .load_symbol = sym_index });
916917 }
917 const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
918 const sym = elf_file.symbol(sym_index);
918 const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, decl_index);
919919 if (is_threadlocal) {
920 return GenResult.mcv(.{ .load_tlv = sym.esym_index });
920 return GenResult.mcv(.{ .load_tlv = sym_index });
921921 }
922 return GenResult.mcv(.{ .load_symbol = sym.esym_index });
922 return GenResult.mcv(.{ .load_symbol = sym_index });
923923 } else if (lf.cast(link.File.MachO)) |macho_file| {
924924 const zo = macho_file.getZigObject().?;
925925 if (is_extern) {
......@@ -971,9 +971,7 @@ fn genUnnamedConst(
971971 };
972972 switch (lf.tag) {
973973 .elf => {
974 const elf_file = lf.cast(link.File.Elf).?;
975 const local = elf_file.symbol(local_sym_index);
976 return GenResult.mcv(.{ .load_symbol = local.esym_index });
974 return GenResult.mcv(.{ .load_symbol = local_sym_index });
977975 },
978976 .macho => {
979977 const macho_file = lf.cast(link.File.MachO).?;
src/link/Elf.zig+186-249
......@@ -173,12 +173,7 @@ shstrtab_section_index: ?u32 = null,
173173strtab_section_index: ?u32 = null,
174174symtab_section_index: ?u32 = null,
175175
176/// An array of symbols parsed across all input files.
177symbols: std.ArrayListUnmanaged(Symbol) = .{},
178symbols_extra: std.ArrayListUnmanaged(u32) = .{},
179symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
180
181resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{},
176resolver: SymbolResolver = .{},
182177
183178has_text_reloc: bool = false,
184179num_ifunc_dynrelocs: usize = 0,
......@@ -192,10 +187,6 @@ merge_sections: std.ArrayListUnmanaged(MergeSection) = .{},
192187/// Table of last atom index in a section and matching atom free list if any.
193188last_atom_and_free_list_table: LastAtomAndFreeListTable = .{},
194189
195/// Global string table used to provide quick access to global symbol resolvers
196/// such as `resolver`.
197strings: StringTable = .{},
198
199190first_eflags: ?elf.Elf64_Word = null,
200191
201192/// When allocating, the ideal_capacity is calculated by
......@@ -341,10 +332,6 @@ pub fn createEmpty(
341332
342333 const gpa = comp.gpa;
343334
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);
348335 // Append null file at index 0
349336 try self.files.append(gpa, .null);
350337 // Append null byte to string tables
......@@ -460,9 +447,6 @@ pub fn deinit(self: *Elf) void {
460447 self.shstrtab.deinit(gpa);
461448 self.symtab.deinit(gpa);
462449 self.strtab.deinit(gpa);
463 self.symbols.deinit(gpa);
464 self.symbols_extra.deinit(gpa);
465 self.symbols_free_list.deinit(gpa);
466450 self.resolver.deinit(gpa);
467451
468452 for (self.thunks.items) |*th| {
......@@ -478,8 +462,6 @@ pub fn deinit(self: *Elf) void {
478462 }
479463 self.last_atom_and_free_list_table.deinit(gpa);
480464
481 self.strings.deinit(gpa);
482
483465 self.got.deinit(gpa);
484466 self.plt.deinit(gpa);
485467 self.plt_got.deinit(gpa);
......@@ -1300,6 +1282,9 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
13001282 try self.finalizeMergeSections();
13011283 try self.initOutputSections();
13021284 try self.initMergeSections();
1285 if (self.linkerDefinedPtr()) |obj| {
1286 try obj.initStartStopSymbols(self);
1287 }
13031288 self.claimUnresolved();
13041289
13051290 // Scan and create missing synthetic entries such as GOT indirection.
......@@ -1922,20 +1907,17 @@ fn accessLibPath(
19221907/// 6. Re-run symbol resolution on pruned objects and shared objects sets.
19231908pub fn resolveSymbols(self: *Elf) !void {
19241909 // 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);
19261911 // Resolve symbols on the set of all objects and shared objects (even if some are unneeded).
1927 for (self.objects.items) |index| self.file(index).?.resolveSymbols(self);
1928 for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self);
1929 if (self.linkerDefinedPtr()) |obj| obj.asFile().resolveSymbols(self);
1912 for (self.objects.items) |index| try self.file(index).?.resolveSymbols(self);
1913 for (self.shared_objects.items) |index| try self.file(index).?.resolveSymbols(self);
1914 if (self.linkerDefinedPtr()) |obj| try obj.asFile().resolveSymbols(self);
19301915
19311916 // Mark live objects.
19321917 self.markLive();
19331918
19341919 // Reset state of all globals after marking live objects.
1935 if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resetGlobals(self);
1936 for (self.objects.items) |index| self.file(index).?.resetGlobals(self);
1937 for (self.shared_objects.items) |index| self.file(index).?.resetGlobals(self);
1938 if (self.linkerDefinedPtr()) |obj| obj.asFile().resetGlobals(self);
1920 self.resolver.reset();
19391921
19401922 // Prune dead objects and shared objects.
19411923 var i: usize = 0;
......@@ -1968,10 +1950,10 @@ pub fn resolveSymbols(self: *Elf) !void {
19681950 }
19691951
19701952 // Re-resolve the symbols.
1971 if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resolveSymbols(self);
1972 for (self.objects.items) |index| self.file(index).?.resolveSymbols(self);
1973 for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self);
1974 if (self.linkerDefinedPtr()) |obj| obj.asFile().resolveSymbols(self);
1953 if (self.zigObjectPtr()) |zo| try zo.asFile().resolveSymbols(self);
1954 for (self.objects.items) |index| try self.file(index).?.resolveSymbols(self);
1955 for (self.shared_objects.items) |index| try self.file(index).?.resolveSymbols(self);
1956 if (self.linkerDefinedPtr()) |obj| try obj.asFile().resolveSymbols(self);
19751957}
19761958
19771959/// Traverses all objects and shared objects marking any object referenced by
......@@ -2005,46 +1987,17 @@ fn convertCommonSymbols(self: *Elf) !void {
20051987}
20061988
20071989fn markImportsExports(self: *Elf) void {
2008 const mark = struct {
2009 fn mark(elf_file: *Elf, file_index: File.Index) void {
2010 for (elf_file.file(file_index).?.globals()) |global_index| {
2011 const global = elf_file.symbol(global_index);
2012 if (global.version_index == elf.VER_NDX_LOCAL) continue;
2013 const file_ptr = global.file(elf_file) orelse continue;
2014 const vis = @as(elf.STV, @enumFromInt(global.elfSym(elf_file).st_other));
2015 if (vis == .HIDDEN) continue;
2016 if (file_ptr == .shared_object and !global.isAbs(elf_file)) {
2017 global.flags.import = true;
2018 continue;
2019 }
2020 if (file_ptr.index() == file_index) {
2021 global.flags.@"export" = true;
2022 if (elf_file.isEffectivelyDynLib() and vis != .PROTECTED) {
2023 global.flags.import = true;
2024 }
2025 }
2026 }
2027 }
2028 }.mark;
2029
1990 if (self.zigObjectPtr()) |zo| {
1991 zo.markImportsExports(self);
1992 }
1993 for (self.objects.items) |index| {
1994 self.file(index).?.object.markImportsExports(self);
1995 }
20301996 if (!self.isEffectivelyDynLib()) {
20311997 for (self.shared_objects.items) |index| {
2032 for (self.file(index).?.globals()) |global_index| {
2033 const global = self.symbol(global_index);
2034 const file_ptr = global.file(self) orelse continue;
2035 const vis = @as(elf.STV, @enumFromInt(global.elfSym(self).st_other));
2036 if (file_ptr != .shared_object and vis != .HIDDEN) global.flags.@"export" = true;
2037 }
1998 self.file(index).?.shared_object.markImportExports(self);
20381999 }
20392000 }
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 }
20482001}
20492002
20502003fn claimUnresolved(self: *Elf) void {
......@@ -2063,22 +2016,27 @@ fn claimUnresolved(self: *Elf) void {
20632016fn scanRelocs(self: *Elf) !void {
20642017 const gpa = self.base.comp.gpa;
20652018
2066 var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Ref)).init(gpa);
2019 var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa);
20672020 defer {
2068 var it = undefs.iterator();
2069 while (it.next()) |entry| {
2070 entry.value_ptr.deinit();
2021 for (undefs.values()) |*refs| {
2022 refs.deinit();
20712023 }
20722024 undefs.deinit();
20732025 }
20742026
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
20802027 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| {
20822040 self.file(index).?.scanRelocs(self, &undefs) catch |err| switch (err) {
20832041 error.RelaxFailure => unreachable,
20842042 error.UnsupportedCpuArch => {
......@@ -2094,47 +2052,18 @@ fn scanRelocs(self: *Elf) !void {
20942052
20952053 if (has_reloc_errors) return error.FlushFailure;
20962054
2097 for (self.symbols.items, 0..) |*sym, i| {
2098 const index = @as(u32, @intCast(i));
2099 if (!sym.isLocal(self) and !sym.flags.has_dynamic) {
2100 log.debug("'{s}' is non-local", .{sym.name(self)});
2101 try self.dynsym.addSymbol(index, self);
2102 }
2103 if (sym.flags.needs_got) {
2104 log.debug("'{s}' needs GOT", .{sym.name(self)});
2105 _ = try self.got.addGotSymbol(index, self);
2106 }
2107 if (sym.flags.needs_plt) {
2108 if (sym.flags.is_canonical) {
2109 log.debug("'{s}' needs CPLT", .{sym.name(self)});
2110 sym.flags.@"export" = true;
2111 try self.plt.addSymbol(index, self);
2112 } else if (sym.flags.needs_got) {
2113 log.debug("'{s}' needs PLTGOT", .{sym.name(self)});
2114 try self.plt_got.addSymbol(index, self);
2115 } else {
2116 log.debug("'{s}' needs PLT", .{sym.name(self)});
2117 try self.plt.addSymbol(index, self);
2118 }
2119 }
2120 if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) {
2121 log.debug("'{s}' needs COPYREL", .{sym.name(self)});
2122 try self.copy_rel.addSymbol(index, self);
2123 }
2124 if (sym.flags.needs_tlsgd) {
2125 log.debug("'{s}' needs TLSGD", .{sym.name(self)});
2126 try self.got.addTlsGdSymbol(index, self);
2127 }
2128 if (sym.flags.needs_gottp) {
2129 log.debug("'{s}' needs GOTTP", .{sym.name(self)});
2130 try self.got.addGotTpSymbol(index, self);
2131 }
2132 if (sym.flags.needs_tlsdesc) {
2133 log.debug("'{s}' needs TLSDESC", .{sym.name(self)});
2134 try self.got.addTlsDescSymbol(index, self);
2135 }
2055 if (self.zigObjectPtr()) |zo| {
2056 try zo.asFile().createSymbolIndirection(self);
2057 }
2058 for (self.objects.items) |index| {
2059 try self.file(index).?.createSymbolIndirection(self);
2060 }
2061 for (self.shared_objects.items) |index| {
2062 try self.file(index).?.createSymbolIndirection(self);
2063 }
2064 if (self.linkerDefinedPtr()) |obj| {
2065 try obj.asFile().createSymbolIndirection(self);
21362066 }
2137
21382067 if (self.got.flags.needs_tlsld) {
21392068 log.debug("program needs TLSLD", .{});
21402069 try self.got.addTlsLdSymbol(self);
......@@ -2911,8 +2840,8 @@ pub fn writeElfHeader(self: *Elf) !void {
29112840 index += 4;
29122841
29132842 const e_entry: u64 = if (self.linkerDefinedPtr()) |obj| blk: {
2914 const entry_index = obj.entry_index orelse break :blk 0;
2915 break :blk @intCast(self.symbol(entry_index).address(.{}, self));
2843 const entry_sym = obj.entrySymbol(self) orelse break :blk 0;
2844 break :blk @intCast(entry_sym.address(.{}, self));
29162845 } else 0;
29172846 const phdr_table_offset = if (self.phdr_table_index) |phndx| self.phdrs.items[phndx].p_offset else 0;
29182847 switch (self.ptr_width) {
......@@ -3043,7 +2972,7 @@ pub fn deleteExport(
30432972fn checkDuplicates(self: *Elf) !void {
30442973 const gpa = self.base.comp.gpa;
30452974
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);
30472976 defer {
30482977 for (dupes.values()) |*list| {
30492978 list.deinit(gpa);
......@@ -3351,7 +3280,7 @@ fn initSyntheticSections(self: *Elf) !void {
33513280 });
33523281
33533282 const needs_versions = for (self.dynsym.entries.items) |entry| {
3354 const sym = self.symbol(entry.symbol_index);
3283 const sym = self.symbol(entry.ref).?;
33553284 if (sym.flags.import and sym.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) break true;
33563285 } else false;
33573286 if (needs_versions) {
......@@ -3565,7 +3494,7 @@ fn setVersionSymtab(self: *Elf) !void {
35653494 try self.versym.resize(gpa, self.dynsym.count());
35663495 self.versym.items[0] = elf.VER_NDX_LOCAL;
35673496 for (self.dynsym.entries.items, 1..) |entry, i| {
3568 const sym = self.symbol(entry.symbol_index);
3497 const sym = self.symbol(entry.ref).?;
35693498 self.versym.items[i] = sym.version_index;
35703499 }
35713500
......@@ -4357,11 +4286,10 @@ fn allocateSpecialPhdrs(self: *Elf) void {
43574286fn writeAtoms(self: *Elf) !void {
43584287 const gpa = self.base.comp.gpa;
43594288
4360 var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Ref)).init(gpa);
4289 var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa);
43614290 defer {
4362 var it = undefs.iterator();
4363 while (it.next()) |entry| {
4364 entry.value_ptr.deinit();
4291 for (undefs.values()) |*refs| {
4292 refs.deinit();
43654293 }
43664294 undefs.deinit();
43674295 }
......@@ -4507,11 +4435,13 @@ pub fn updateSymtabSize(self: *Elf) !void {
45074435 strsize += ctx.strsize;
45084436 }
45094437
4510 if (self.zig_got_section_index) |_| {
4511 self.zig_got.output_symtab_ctx.ilocal = nlocals + 1;
4512 self.zig_got.updateSymtabSize(self);
4513 nlocals += self.zig_got.output_symtab_ctx.nlocals;
4514 strsize += self.zig_got.output_symtab_ctx.strsize;
4438 if (self.zigObjectPtr()) |_| {
4439 if (self.zig_got_section_index) |_| {
4440 self.zig_got.output_symtab_ctx.ilocal = nlocals + 1;
4441 self.zig_got.updateSymtabSize(self);
4442 nlocals += self.zig_got.output_symtab_ctx.nlocals;
4443 strsize += self.zig_got.output_symtab_ctx.strsize;
4444 }
45154445 }
45164446
45174447 if (self.got_section_index) |_| {
......@@ -4650,7 +4580,9 @@ fn writeSyntheticSections(self: *Elf) !void {
46504580 const shdr = self.shdrs.items[shndx];
46514581 try self.got.addRela(self);
46524582 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 }
46544586 self.sortRelaDyn();
46554587 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_dyn.items), shdr.sh_offset);
46564588 }
......@@ -5311,13 +5243,21 @@ pub fn calcNumIRelativeRelocs(self: *Elf) usize {
53115243
53125244 for (self.got.entries.items) |entry| {
53135245 if (entry.tag != .got) continue;
5314 const sym = self.symbol(entry.symbol_index);
5246 const sym = self.symbol(entry.ref).?;
53155247 if (sym.isIFunc(self)) count += 1;
53165248 }
53175249
53185250 return count;
53195251}
53205252
5253pub 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
53215261pub fn isCIdentifier(name: []const u8) bool {
53225262 if (name.len == 0) return false;
53235263 const first_c = name[0];
......@@ -5328,14 +5268,6 @@ pub fn isCIdentifier(name: []const u8) bool {
53285268 return true;
53295269}
53305270
5331pub 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
53395271pub fn addThunk(self: *Elf) !Thunk.Index {
53405272 const index = @as(Thunk.Index, @intCast(self.thunks.items.len));
53415273 const th = try self.thunks.addOne(self.base.comp.gpa);
......@@ -5381,95 +5313,9 @@ pub fn comdatGroup(self: *Elf, ref: Ref) *ComdatGroup {
53815313 return self.file(ref.file).?.comdatGroup(ref.index);
53825314}
53835315
5384/// Returns pointer-to-symbol described at sym_index.
5385pub fn symbol(self: *Elf, sym_index: Symbol.Index) *Symbol {
5386 return &self.symbols.items[sym_index];
5387}
5388
5389pub 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
5407pub 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
5414pub 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
5426pub 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
5441pub 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
5452const GetOrPutGlobalResult = struct {
5453 found_existing: bool,
5454 index: Symbol.Index,
5455};
5456
5457pub 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 };
5316pub fn symbol(self: *Elf, ref: Ref) ?*Symbol {
5317 const file_ptr = self.file(ref.file) orelse return null;
5318 return file_ptr.symbol(ref.index);
54735319}
54745320
54755321pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 {
......@@ -5579,36 +5425,34 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {
55795425
55805426 try self.base.comp.link_errors.ensureUnusedCapacity(gpa, undefs.count());
55815427
5582 var it = undefs.iterator();
5583 while (it.next()) |entry| {
5584 const undef_index = entry.key_ptr.*;
5585 const atoms = entry.value_ptr.*.items;
5586 const natoms = @min(atoms.len, max_notes);
5587 const nnotes = natoms + @intFromBool(atoms.len > max_notes);
5428 for (undefs.keys(), undefs.values()) |key, refs| {
5429 const undef_sym = self.resolver.keys.items[key - 1];
5430 const nrefs = @min(refs.items.len, max_notes);
5431 const nnotes = nrefs + @intFromBool(refs.items.len > max_notes);
55885432
55895433 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)});
55915435
5592 for (atoms[0..natoms]) |ref| {
5436 for (refs.items[0..nrefs]) |ref| {
55935437 const atom_ptr = self.atom(ref).?;
5594 const file_ptr = self.file(ref.file).?;
5438 const file_ptr = atom_ptr.file(self).?;
55955439 try err.addNote("referenced by {s}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) });
55965440 }
55975441
5598 if (atoms.len > max_notes) {
5599 const remaining = atoms.len - max_notes;
5442 if (refs.items.len > max_notes) {
5443 const remaining = refs.items.len - max_notes;
56005444 try err.addNote("referenced {d} more times", .{remaining});
56015445 }
56025446 }
56035447}
56045448
56055449fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemory }!void {
5450 if (dupes.keys().len == 0) return; // Nothing to do
5451
56065452 const max_notes = 3;
5607 var has_dupes = false;
5608 var it = dupes.iterator();
5609 while (it.next()) |entry| {
5610 const sym = self.symbol(entry.key_ptr.*);
5611 const notes = entry.value_ptr.*;
5453
5454 for (dupes.keys(), dupes.values()) |key, notes| {
5455 const sym = self.resolver.keys.items[key - 1];
56125456 const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes);
56135457
56145458 var err = try self.base.addErrorWithNotes(nnotes + 1);
......@@ -5625,11 +5469,9 @@ fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemor
56255469 const remaining = notes.items.len - max_notes;
56265470 try err.addNote("defined {d} more times", .{remaining});
56275471 }
5628
5629 has_dupes = true;
56305472 }
56315473
5632 if (has_dupes) return error.HasDuplicates;
5474 return error.HasDuplicates;
56335475}
56345476
56355477fn reportMissingLibraryError(
......@@ -6018,6 +5860,10 @@ pub const Ref = struct {
60185860 index: u32,
60195861 file: u32,
60205862
5863 pub fn eql(ref: Ref, other: Ref) bool {
5864 return ref.index == other.index and ref.file == other.file;
5865 }
5866
60215867 pub fn format(
60225868 ref: Ref,
60235869 comptime unused_fmt_string: []const u8,
......@@ -6030,6 +5876,96 @@ pub const Ref = struct {
60305876 }
60315877};
60325878
5879pub 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
60335969const LastAtomAndFreeList = struct {
60345970 /// Index of the last allocated atom in this section.
60355971 last_atom_index: Atom.Index = 0,
......@@ -6143,6 +6079,7 @@ const File = @import("Elf/file.zig").File;
61436079const GnuHashSection = synthetic_sections.GnuHashSection;
61446080const GotSection = synthetic_sections.GotSection;
61456081const GotPltSection = synthetic_sections.GotPltSection;
6082const Hash = std.hash.Wyhash;
61466083const HashSection = synthetic_sections.HashSection;
61476084const InputMergeSection = merge_section.InputMergeSection;
61486085const 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
326326 const cpu_arch = elf_file.getTarget().cpu.arch;
327327 const file_ptr = self.file(elf_file).?;
328328 for (self.relocs(elf_file)) |rel| {
329 const target_index = switch (file_ptr) {
330 .zig_object => |x| x.symbol(rel.r_sym()),
331 .object => |x| x.symbols.items[rel.r_sym()],
332 else => unreachable,
333 };
334 const target = elf_file.symbol(target_index);
329 const target_ref = file_ptr.resolveSymbol(rel.r_sym(), elf_file);
330 const target = elf_file.symbol(target_ref).?;
335331 const r_type = rel.r_type();
336332 const r_offset: u64 = @intCast(self.value + @as(i64, @intCast(rel.r_offset)));
337333 var r_addend = rel.r_addend;
......@@ -422,12 +418,21 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype
422418 const r_kind = relocation.decode(rel.r_type(), cpu_arch);
423419 if (r_kind == .none) continue;
424420
425 const symbol_index = switch (file_ptr) {
426 .zig_object => |x| x.symbol(rel.r_sym()),
427 .object => |x| x.symbols.items[rel.r_sym()],
428 else => unreachable,
421 const symbol_ref = file_ptr.resolveSymbol(rel.r_sym(), elf_file);
422 const symbol = elf_file.symbol(symbol_ref) orelse {
423 const sym_name = switch (file_ptr) {
424 .zig_object => |x| x.symbol(rel.r_sym()).name(elf_file),
425 inline else => |x| x.symbols.items[rel.r_sym()].name(elf_file),
426 };
427 // Violation of One Definition Rule for COMDATs.
428 // TODO convert into an error
429 log.debug("{}: {s}: {s} refers to a discarded COMDAT section", .{
430 file_ptr.fmtPath(),
431 self.name(elf_file),
432 sym_name,
433 });
434 continue;
429435 };
430 const symbol = elf_file.symbol(symbol_index);
431436
432437 const is_synthetic_symbol = switch (file_ptr) {
433438 .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
435440 else => unreachable,
436441 };
437442
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
449443 // 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)))
451445 continue;
452446
453447 if (symbol.isIFunc(elf_file)) {
......@@ -694,16 +688,15 @@ fn reportUndefined(
694688 self: Atom,
695689 elf_file: *Elf,
696690 sym: *const Symbol,
697 sym_index: Symbol.Index,
698691 rel: elf.Elf64_Rela,
699692 undefs: anytype,
700693) !bool {
701694 const comp = elf_file.base.comp;
702695 const gpa = comp.gpa;
703 const rel_esym = switch (self.file(elf_file).?) {
704 .zig_object => |x| x.elfSym(rel.r_sym()).*,
705 .object => |x| x.symtab.items[rel.r_sym()],
706 else => unreachable,
696 const file_ptr = self.file(elf_file).?;
697 const rel_esym = switch (file_ptr) {
698 .zig_object => |x| x.symbol(rel.r_sym()).elfSym(elf_file),
699 inline else => |x| x.symtab.items[rel.r_sym()],
707700 };
708701 const esym = sym.elfSym(elf_file);
709702 if (rel_esym.st_shndx == elf.SHN_UNDEF and
......@@ -712,7 +705,12 @@ fn reportUndefined(
712705 !sym.flags.import and
713706 esym.st_shndx == elf.SHN_UNDEF)
714707 {
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);
716714 if (!gop.found_existing) {
717715 gop.value_ptr.* = std.ArrayList(Elf.Ref).init(gpa);
718716 }
......@@ -737,11 +735,8 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
737735 const r_kind = relocation.decode(rel.r_type(), cpu_arch);
738736 if (r_kind == .none) continue;
739737
740 const target = switch (file_ptr) {
741 .zig_object => |x| elf_file.symbol(x.symbol(rel.r_sym())),
742 .object => |x| elf_file.symbol(x.symbols.items[rel.r_sym()]),
743 else => unreachable,
744 };
738 const target_ref = file_ptr.resolveSymbol(rel.r_sym(), elf_file);
739 const target = elf_file.symbol(target_ref).?;
745740 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
746741
747742 // We will use equation format to resolve relocations:
......@@ -845,7 +840,7 @@ fn resolveDynAbsReloc(
845840 if (is_writeable or elf_file.z_nocopyreloc) {
846841 elf_file.addRelaDynAssumeCapacity(.{
847842 .offset = P,
848 .sym = target.extra(elf_file).?.dynamic,
843 .sym = target.extra(elf_file).dynamic,
849844 .type = relocation.encode(.abs, cpu_arch),
850845 .addend = A,
851846 });
......@@ -859,7 +854,7 @@ fn resolveDynAbsReloc(
859854 if (is_writeable) {
860855 elf_file.addRelaDynAssumeCapacity(.{
861856 .offset = P,
862 .sym = target.extra(elf_file).?.dynamic,
857 .sym = target.extra(elf_file).dynamic,
863858 .type = relocation.encode(.abs, cpu_arch),
864859 .addend = A,
865860 });
......@@ -872,7 +867,7 @@ fn resolveDynAbsReloc(
872867 .dynrel => {
873868 elf_file.addRelaDynAssumeCapacity(.{
874869 .offset = P,
875 .sym = target.extra(elf_file).?.dynamic,
870 .sym = target.extra(elf_file).dynamic,
876871 .type = relocation.encode(.abs, cpu_arch),
877872 .addend = A,
878873 });
......@@ -923,31 +918,29 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
923918
924919 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
925920
926 const target_index = switch (file_ptr) {
927 .zig_object => |x| x.symbol(rel.r_sym()),
928 .object => |x| x.symbols.items[rel.r_sym()],
929 else => unreachable,
930 };
931 const target = elf_file.symbol(target_index);
932 const is_synthetic_symbol = switch (file_ptr) {
933 .zig_object => false, // TODO: implement this once we support merge sections in ZigObject
934 .object => |x| rel.r_sym() >= x.symtab.items.len,
935 else => unreachable,
936 };
937
938 // Check for violation of One Definition Rule for COMDATs.
939 if (target.file(elf_file) == null) {
921 const target_ref = file_ptr.resolveSymbol(rel.r_sym(), elf_file);
922 const target = elf_file.symbol(target_ref) orelse {
923 const sym_name = switch (file_ptr) {
924 .zig_object => |x| x.symbol(rel.r_sym()).name(elf_file),
925 inline else => |x| x.symbols.items[rel.r_sym()].name(elf_file),
926 };
927 // Violation of One Definition Rule for COMDATs.
940928 // TODO convert into an error
941929 log.debug("{}: {s}: {s} refers to a discarded COMDAT section", .{
942930 file_ptr.fmtPath(),
943931 self.name(elf_file),
944 target.name(elf_file),
932 sym_name,
945933 });
946934 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 };
948941
949942 // 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)))
951944 continue;
952945
953946 // We will use equation format to resolve relocations:
......@@ -1766,11 +1759,7 @@ const aarch64 = struct {
17661759 => {
17671760 const disp: i28 = math.cast(i28, S + A - P) orelse blk: {
17681761 const th = atom.thunk(elf_file);
1769 const target_index = switch (file_ptr) {
1770 .zig_object => |x| x.symbol(rel.r_sym()),
1771 .object => |x| x.symbols.items[rel.r_sym()],
1772 else => unreachable,
1773 };
1762 const target_index = file_ptr.resolveSymbol(rel.r_sym(), elf_file);
17741763 const S_ = th.targetAddress(target_index, elf_file);
17751764 break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;
17761765 };
......@@ -2106,11 +2095,8 @@ const riscv = struct {
21062095 return error.RelocFailure;
21072096 };
21082097 it.pos = pos;
2109 const target_ = switch (file_ptr) {
2110 .zig_object => |x| elf_file.symbol(x.symbol(pair.r_sym())),
2111 .object => |x| elf_file.symbol(x.symbols.items[pair.r_sym()]),
2112 else => unreachable,
2113 };
2098 const target_ref_ = file_ptr.resolveSymbol(pair.r_sym(), elf_file);
2099 const target_ = elf_file.symbol(target_ref_).?;
21142100 const S_ = target_.address(.{}, elf_file);
21152101 const A_ = pair.r_addend;
21162102 const P_ = atom_addr + @as(i64, @intCast(pair.r_offset));
......@@ -2313,4 +2299,5 @@ const File = @import("file.zig").File;
23132299const Object = @import("Object.zig");
23142300const Symbol = @import("Symbol.zig");
23152301const Thunk = @import("thunks.zig").Thunk;
2302const ZigObject = @import("ZigObject.zig");
23162303const dev = @import("../../dev.zig");
src/link/Elf/LinkerDefined.zig+268-143
......@@ -2,7 +2,10 @@ index: File.Index,
22
33symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
44strtab: std.ArrayListUnmanaged(u8) = .{},
5symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
5
6symbols: std.ArrayListUnmanaged(Symbol) = .{},
7symbols_extra: std.ArrayListUnmanaged(u32) = .{},
8symbols_resolver: std.ArrayListUnmanaged(Elf.SymbolResolver.Index) = .{},
69
710entry_index: ?Symbol.Index = null,
811dynamic_index: ?Symbol.Index = null,
......@@ -29,6 +32,8 @@ pub fn deinit(self: *LinkerDefined, allocator: Allocator) void {
2932 self.symtab.deinit(allocator);
3033 self.strtab.deinit(allocator);
3134 self.symbols.deinit(allocator);
35 self.symbols_extra.deinit(allocator);
36 self.symbols_resolver.deinit(allocator);
3237 self.start_stop_indexes.deinit(allocator);
3338}
3439
......@@ -37,86 +42,150 @@ pub fn init(self: *LinkerDefined, allocator: Allocator) !void {
3742 try self.strtab.append(allocator, 0);
3843}
3944
45fn 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
4066pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
4167 const gpa = elf_file.base.comp.gpa;
4268
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
43101 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);
45103 }
46104
47 self.dynamic_index = try self.addGlobal("_DYNAMIC", elf_file);
48 self.ehdr_start_index = try self.addGlobal("__ehdr_start", elf_file);
49 self.init_array_start_index = try self.addGlobal("__init_array_start", elf_file);
50 self.init_array_end_index = try self.addGlobal("__init_array_end", elf_file);
51 self.fini_array_start_index = try self.addGlobal("__fini_array_start", elf_file);
52 self.fini_array_end_index = try self.addGlobal("__fini_array_end", elf_file);
53 self.preinit_array_start_index = try self.addGlobal("__preinit_array_start", elf_file);
54 self.preinit_array_end_index = try self.addGlobal("__preinit_array_end", elf_file);
55 self.got_index = try self.addGlobal("_GLOBAL_OFFSET_TABLE_", elf_file);
56 self.plt_index = try self.addGlobal("_PROCEDURE_LINKAGE_TABLE_", elf_file);
57 self.end_index = try self.addGlobal("_end", elf_file);
105 self.dynamic_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_DYNAMIC"), elf_file);
106 self.ehdr_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__ehdr_start"), elf_file);
107 self.init_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__init_array_start"), elf_file);
108 self.init_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__init_array_end"), elf_file);
109 self.fini_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__fini_array_start"), elf_file);
110 self.fini_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__fini_array_end"), elf_file);
111 self.preinit_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__preinit_array_start"), elf_file);
112 self.preinit_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__preinit_array_end"), elf_file);
113 self.got_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_GLOBAL_OFFSET_TABLE_"), elf_file);
114 self.plt_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_PROCEDURE_LINKAGE_TABLE_"), elf_file);
115 self.end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_end"), elf_file);
58116
59117 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);
61119 }
62120
63 self.dso_handle_index = try self.addGlobal("__dso_handle", elf_file);
64 self.rela_iplt_start_index = try self.addGlobal("__rela_iplt_start", elf_file);
65 self.rela_iplt_end_index = try self.addGlobal("__rela_iplt_end", elf_file);
121 self.dso_handle_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__dso_handle"), elf_file);
122 self.rela_iplt_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__rela_iplt_start"), elf_file);
123 self.rela_iplt_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__rela_iplt_end"), elf_file);
66124
67 for (elf_file.shdrs.items) |shdr| {
68 if (elf_file.getStartStopBasename(shdr)) |name| {
69 try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2);
125 if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) {
126 self.global_pointer_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__global_pointer$"), elf_file);
127 }
128}
70129
71 const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});
72 defer gpa.free(start);
73 const stop = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name});
74 defer gpa.free(stop);
130pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
131 const gpa = elf_file.base.comp.gpa;
75132
76 self.start_stop_indexes.appendAssumeCapacity(try self.addGlobal(start, elf_file));
77 self.start_stop_indexes.appendAssumeCapacity(try self.addGlobal(stop, elf_file));
133 var nsyms: usize = 0;
134 for (elf_file.shdrs.items) |shdr| {
135 if (elf_file.getStartStopBasename(shdr)) |_| {
136 nsyms += 2; // __start_, __stop_
78137 }
79138 }
80139
81 if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) {
82 self.global_pointer_index = try self.addGlobal("__global_pointer$", elf_file);
140 try self.start_stop_indexes.ensureTotalCapacityPrecise(gpa, nsyms);
141 try self.symtab.ensureUnusedCapacity(gpa, nsyms);
142 try self.symbols.ensureUnusedCapacity(gpa, nsyms);
143 try self.symbols_extra.ensureUnusedCapacity(gpa, nsyms * @sizeOf(Symbol.Extra));
144 try self.symbols_resolver.ensureUnusedCapacity(gpa, nsyms);
145
146 for (elf_file.shdrs.items) |shdr| {
147 if (elf_file.getStartStopBasename(shdr)) |name| {
148 const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});
149 defer gpa.free(start_name);
150 const stop_name = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name});
151 defer gpa.free(stop_name);
152
153 for (&[_][]const u8{ start_name, stop_name }) |nn| {
154 const index = self.newSymbolAssumeCapacity(try self.addString(gpa, nn), elf_file);
155 self.start_stop_indexes.appendAssumeCapacity(index);
156 const gop = try elf_file.resolver.getOrPut(gpa, .{
157 .index = index,
158 .file = self.index,
159 }, elf_file);
160 assert(!gop.found_existing);
161 gop.ref.* = .{ .index = index, .file = self.index };
162 self.symbols_resolver.appendAssumeCapacity(gop.index);
163 }
164 }
83165 }
84166}
85167
86fn addGlobal(self: *LinkerDefined, name: []const u8, elf_file: *Elf) !u32 {
87 const comp = elf_file.base.comp;
88 const gpa = comp.gpa;
89 try self.symtab.ensureUnusedCapacity(gpa, 1);
90 try self.symbols.ensureUnusedCapacity(gpa, 1);
91 const name_off = @as(u32, @intCast(self.strtab.items.len));
92 try self.strtab.writer(gpa).print("{s}\x00", .{name});
93 self.symtab.appendAssumeCapacity(.{
94 .st_name = name_off,
95 .st_info = elf.STB_GLOBAL << 4,
96 .st_other = @intFromEnum(elf.STV.HIDDEN),
97 .st_shndx = elf.SHN_ABS,
98 .st_value = 0,
99 .st_size = 0,
100 });
101 const gop = try elf_file.getOrPutGlobal(name);
102 self.symbols.addOneAssumeCapacity().* = gop.index;
103 return gop.index;
104}
168pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
169 const gpa = elf_file.base.comp.gpa;
105170
106pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void {
107 for (self.symbols.items, 0..) |index, i| {
108 const sym_idx = @as(Symbol.Index, @intCast(i));
109 const this_sym = self.symtab.items[sym_idx];
171 for (self.symtab.items, self.symbols_resolver.items, 0..) |esym, *resolv, i| {
172 const gop = try elf_file.resolver.getOrPut(gpa, .{
173 .index = @intCast(i),
174 .file = self.index,
175 }, elf_file);
176 if (!gop.found_existing) {
177 gop.ref.* = .{ .index = 0, .file = 0 };
178 }
179 resolv.* = gop.index;
110180
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 }
112186
113 const global = elf_file.symbol(index);
114 if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {
115 global.value = 0;
116 global.ref = .{ .index = 0, .file = 0 };
117 global.file_index = self.index;
118 global.esym_index = sym_idx;
119 global.version_index = elf_file.default_sym_version;
187 if (self.asFile().symbolRank(esym, false) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) {
188 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
120189 }
121190 }
122191}
......@@ -125,93 +194,73 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
125194 const comp = elf_file.base.comp;
126195 const link_mode = comp.config.link_mode;
127196
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
128205 // _DYNAMIC
129206 if (elf_file.dynamic_section_index) |shndx| {
130207 const shdr = &elf_file.shdrs.items[shndx];
131 const symbol_ptr = elf_file.symbol(self.dynamic_index.?);
132 symbol_ptr.value = @intCast(shdr.sh_addr);
133 symbol_ptr.output_section_index = shndx;
208 allocSymbol(self, self.dynamic_index.?, shdr.sh_addr, shndx, elf_file);
134209 }
135210
136211 // __ehdr_start
137 {
138 const symbol_ptr = elf_file.symbol(self.ehdr_start_index.?);
139 symbol_ptr.value = @intCast(elf_file.image_base);
140 symbol_ptr.output_section_index = 1;
141 }
212 allocSymbol(self, self.ehdr_start_index.?, elf_file.image_base, 1, elf_file);
142213
143214 // __init_array_start, __init_array_end
144215 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.?);
147216 const shdr = &elf_file.shdrs.items[shndx];
148 start_sym.output_section_index = shndx;
149 start_sym.value = @intCast(shdr.sh_addr);
150 end_sym.output_section_index = shndx;
151 end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size);
217 allocSymbol(self, self.init_array_start_index.?, shdr.sh_addr, shndx, elf_file);
218 allocSymbol(self, self.init_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file);
152219 }
153220
154221 // __fini_array_start, __fini_array_end
155222 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.?);
158223 const shdr = &elf_file.shdrs.items[shndx];
159 start_sym.output_section_index = shndx;
160 start_sym.value = @intCast(shdr.sh_addr);
161 end_sym.output_section_index = shndx;
162 end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size);
224 allocSymbol(self, self.fini_array_start_index.?, shdr.sh_addr, shndx, elf_file);
225 allocSymbol(self, self.fini_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file);
163226 }
164227
165228 // __preinit_array_start, __preinit_array_end
166229 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.?);
169230 const shdr = &elf_file.shdrs.items[shndx];
170 start_sym.output_section_index = shndx;
171 start_sym.value = @intCast(shdr.sh_addr);
172 end_sym.output_section_index = shndx;
173 end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size);
231 allocSymbol(self, self.preinit_array_start_index.?, shdr.sh_addr, shndx, elf_file);
232 allocSymbol(self, self.preinit_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file);
174233 }
175234
176235 // _GLOBAL_OFFSET_TABLE_
177236 if (elf_file.getTarget().cpu.arch == .x86_64) {
178237 if (elf_file.got_plt_section_index) |shndx| {
179238 const shdr = elf_file.shdrs.items[shndx];
180 const sym = elf_file.symbol(self.got_index.?);
181 sym.value = @intCast(shdr.sh_addr);
182 sym.output_section_index = shndx;
239 allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file);
183240 }
184241 } else {
185242 if (elf_file.got_section_index) |shndx| {
186243 const shdr = elf_file.shdrs.items[shndx];
187 const sym = elf_file.symbol(self.got_index.?);
188 sym.value = @intCast(shdr.sh_addr);
189 sym.output_section_index = shndx;
244 allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file);
190245 }
191246 }
192247
193248 // _PROCEDURE_LINKAGE_TABLE_
194249 if (elf_file.plt_section_index) |shndx| {
195250 const shdr = &elf_file.shdrs.items[shndx];
196 const symbol_ptr = elf_file.symbol(self.plt_index.?);
197 symbol_ptr.value = @intCast(shdr.sh_addr);
198 symbol_ptr.output_section_index = shndx;
251 allocSymbol(self, self.plt_index.?, shdr.sh_addr, shndx, elf_file);
199252 }
200253
201254 // __dso_handle
202255 if (self.dso_handle_index) |index| {
203256 const shdr = &elf_file.shdrs.items[1];
204 const symbol_ptr = elf_file.symbol(index);
205 symbol_ptr.value = @intCast(shdr.sh_addr);
206 symbol_ptr.output_section_index = 0;
257 allocSymbol(self, index, shdr.sh_addr, 0, elf_file);
207258 }
208259
209260 // __GNU_EH_FRAME_HDR
210261 if (elf_file.eh_frame_hdr_section_index) |shndx| {
211262 const shdr = &elf_file.shdrs.items[shndx];
212 const symbol_ptr = elf_file.symbol(self.gnu_eh_frame_hdr_index.?);
213 symbol_ptr.value = @intCast(shdr.sh_addr);
214 symbol_ptr.output_section_index = shndx;
263 allocSymbol(self, self.gnu_eh_frame_hdr_index.?, shdr.sh_addr, shndx, elf_file);
215264 }
216265
217266 // __rela_iplt_start, __rela_iplt_end
......@@ -220,32 +269,41 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
220269 const shdr = &elf_file.shdrs.items[shndx];
221270 const end_addr = shdr.sh_addr + shdr.sh_size;
222271 const start_addr = end_addr - elf_file.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela);
223 const start_sym = elf_file.symbol(self.rela_iplt_start_index.?);
224 const end_sym = elf_file.symbol(self.rela_iplt_end_index.?);
225 start_sym.value = @intCast(start_addr);
226 start_sym.output_section_index = shndx;
227 end_sym.value = @intCast(end_addr);
228 end_sym.output_section_index = shndx;
272 allocSymbol(self, self.rela_iplt_start_index.?, start_addr, shndx, elf_file);
273 allocSymbol(self, self.rela_iplt_end_index.?, end_addr, shndx, elf_file);
229274 }
230275
231276 // _end
232277 {
233 const end_symbol = elf_file.symbol(self.end_index.?);
278 var value: u64 = 0;
279 var osec: u32 = 0;
234280 for (elf_file.shdrs.items, 0..) |shdr, shndx| {
235281 if (shdr.sh_flags & elf.SHF_ALLOC != 0) {
236 end_symbol.value = @intCast(shdr.sh_addr + shdr.sh_size);
237 end_symbol.output_section_index = @intCast(shndx);
282 value = shdr.sh_addr + shdr.sh_size;
283 osec = @intCast(shndx);
238284 }
239285 }
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);
240296 }
241297
242298 // __start_*, __stop_*
243299 {
244300 var index: usize = 0;
245301 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).?;
247304 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).?;
249307 const shndx = elf_file.sectionByName(name["__start_".len..]).?;
250308 const shdr = &elf_file.shdrs.items[shndx];
251309 start.value = @intCast(shdr.sh_addr);
......@@ -254,47 +312,30 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
254312 stop.output_section_index = shndx;
255313 }
256314 }
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
272pub fn globals(self: LinkerDefined) []const Symbol.Index {
273 return self.symbols.items;
274315}
275316
276pub fn updateSymtabSize(self: *LinkerDefined, elf_file: *Elf) !void {
277 for (self.globals()) |global_index| {
278 const global = elf_file.symbol(global_index);
279 const file_ptr = global.file(elf_file) orelse continue;
280 if (file_ptr.index() != self.index) continue;
317pub fn updateSymtabSize(self: *LinkerDefined, elf_file: *Elf) void {
318 for (self.symbols.items, self.symbols_resolver.items) |*global, resolv| {
319 const ref = elf_file.resolver.get(resolv).?;
320 const ref_sym = elf_file.symbol(ref) orelse continue;
321 if (ref_sym.file(elf_file).?.index() != self.index) continue;
281322 global.flags.output_symtab = true;
282323 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);
284325 self.output_symtab_ctx.nlocals += 1;
285326 } else {
286 try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
327 global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
287328 self.output_symtab_ctx.nglobals += 1;
288329 }
289330 self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1;
290331 }
291332}
292333
293pub fn writeSymtab(self: LinkerDefined, elf_file: *Elf) void {
294 for (self.globals()) |global_index| {
295 const global = elf_file.symbol(global_index);
296 const file_ptr = global.file(elf_file) orelse continue;
297 if (file_ptr.index() != self.index) continue;
334pub fn writeSymtab(self: *LinkerDefined, elf_file: *Elf) void {
335 for (self.symbols.items, self.symbols_resolver.items) |global, resolv| {
336 const ref = elf_file.resolver.get(resolv).?;
337 const ref_sym = elf_file.symbol(ref) orelse continue;
338 if (ref_sym.file(elf_file).?.index() != self.index) continue;
298339 const idx = global.outputSymtabIndex(elf_file) orelse continue;
299340 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
300341 elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file));
......@@ -305,15 +346,93 @@ pub fn writeSymtab(self: LinkerDefined, elf_file: *Elf) void {
305346 }
306347}
307348
349pub 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
355pub 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
308361pub fn asFile(self: *LinkerDefined) File {
309362 return .{ .linker_defined = self };
310363}
311364
365fn 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
312373pub fn getString(self: LinkerDefined, off: u32) [:0]const u8 {
313374 assert(off < self.strtab.items.len);
314375 return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0);
315376}
316377
378pub 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
383fn addSymbol(self: *LinkerDefined, allocator: Allocator) !Symbol.Index {
384 try self.symbols.ensureUnusedCapacity(allocator, 1);
385 return self.addSymbolAssumeCapacity();
386}
387
388fn 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
394pub 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
400pub 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
412pub 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
426pub 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
317436pub fn fmtSymtab(self: *LinkerDefined, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {
318437 return .{ .data = .{
319438 .self = self,
......@@ -334,10 +453,16 @@ fn formatSymtab(
334453) !void {
335454 _ = unused_fmt_string;
336455 _ = options;
456 const self = ctx.self;
457 const elf_file = ctx.elf_file;
337458 try writer.writeAll(" globals\n");
338 for (ctx.self.globals()) |index| {
339 const global = ctx.elf_file.symbol(index);
340 try writer.print(" {}\n", .{global.fmt(ctx.elf_file)});
459 for (self.symbols.items, 0..) |sym, i| {
460 const ref = self.resolveSymbol(@intCast(i), elf_file);
461 if (elf_file.symbol(ref)) |ref_sym| {
462 try writer.print(" {}\n", .{ref_sym.fmt(elf_file)});
463 } else {
464 try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)});
465 }
341466 }
342467}
343468
src/link/Elf/Object.zig+232-154
......@@ -9,7 +9,9 @@ shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{},
99symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
1010strtab: std.ArrayListUnmanaged(u8) = .{},
1111first_global: ?Symbol.Index = null,
12symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
12symbols: std.ArrayListUnmanaged(Symbol) = .{},
13symbols_extra: std.ArrayListUnmanaged(u32) = .{},
14symbols_resolver: std.ArrayListUnmanaged(Elf.SymbolResolver.Index) = .{},
1315relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
1416
1517atoms: std.ArrayListUnmanaged(Atom) = .{},
......@@ -51,6 +53,8 @@ pub fn deinit(self: *Object, allocator: Allocator) void {
5153 self.symtab.deinit(allocator);
5254 self.strtab.deinit(allocator);
5355 self.symbols.deinit(allocator);
56 self.symbols_extra.deinit(allocator);
57 self.symbols_resolver.deinit(allocator);
5458 self.atoms.deinit(allocator);
5559 self.atoms_indexes.deinit(allocator);
5660 self.atoms_extra.deinit(allocator);
......@@ -80,7 +84,7 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {
8084 try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) });
8185
8286 try self.initAtoms(gpa, handle, elf_file);
83 try self.initSymtab(gpa, elf_file);
87 try self.initSymbols(gpa, elf_file);
8488
8589 for (self.shdrs.items, 0..) |shdr, i| {
8690 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 {
374378 return ignore;
375379}
376380
377fn initSymtab(self: *Object, allocator: Allocator, elf_file: *Elf) !void {
381fn initSymbols(self: *Object, allocator: Allocator, elf_file: *Elf) !void {
378382 const first_global = self.first_global orelse self.symtab.items.len;
383 const nglobals = self.symtab.items.len - first_global;
379384
380385 try self.symbols.ensureTotalCapacityPrecise(allocator, self.symtab.items.len);
381
382 for (self.symtab.items[0..first_global], 0..) |sym, i| {
383 const index = try elf_file.addSymbol();
384 self.symbols.appendAssumeCapacity(index);
385 const sym_ptr = elf_file.symbol(index);
386 try self.symbols_extra.ensureTotalCapacityPrecise(allocator, self.symtab.items.len * @sizeOf(Symbol.Extra));
387 try self.symbols_resolver.ensureTotalCapacityPrecise(allocator, nglobals);
388 self.symbols_resolver.resize(allocator, nglobals) catch unreachable;
389 @memset(self.symbols_resolver.items, 0);
390
391 for (self.symtab.items, 0..) |sym, i| {
392 const index = self.addSymbolAssumeCapacity();
393 const sym_ptr = &self.symbols.items[index];
386394 sym_ptr.value = @intCast(sym.st_value);
387395 sym_ptr.name_offset = sym.st_name;
388 sym_ptr.esym_index = @as(u32, @intCast(i));
389 sym_ptr.file_index = self.index;
390 if (sym.st_shndx != elf.SHN_ABS) {
396 sym_ptr.esym_index = @intCast(i);
397 sym_ptr.extra_index = self.addSymbolExtraAssumeCapacity(.{});
398 sym_ptr.version_index = if (i >= first_global) elf_file.default_sym_version else elf.VER_NDX_LOCAL;
399 sym_ptr.flags.weak = sym.st_bind() == elf.STB_WEAK;
400 if (sym.st_shndx != elf.SHN_ABS and sym.st_shndx != elf.SHN_COMMON) {
391401 sym_ptr.ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index };
392402 }
393403 }
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 }
400404}
401405
402406fn 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 {
543547
544548 for (self.cies.items) |cie| {
545549 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)).?;
547551 if (sym.flags.import) {
548552 if (sym.type(elf_file) != elf.STT_FUNC)
549553 // TODO convert into an error
......@@ -557,49 +561,47 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {
557561 }
558562}
559563
560pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {
561 const first_global = self.first_global orelse return;
562 for (self.globals(), 0..) |index, i| {
563 const esym_index = @as(Symbol.Index, @intCast(first_global + i));
564 const esym = self.symtab.items[esym_index];
565
566 if (esym.st_shndx == elf.SHN_UNDEF) continue;
564pub fn resolveSymbols(self: *Object, elf_file: *Elf) !void {
565 const gpa = elf_file.base.comp.gpa;
567566
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) {
569571 const atom_index = self.atoms_indexes.items[esym.st_shndx];
570572 const atom_ptr = self.atom(atom_index) orelse continue;
571573 if (!atom_ptr.alive) continue;
572574 }
573575
574 const global = elf_file.symbol(index);
575 if (self.asFile().symbolRank(esym, !self.alive) < global.symbolRank(elf_file)) {
576 switch (esym.st_shndx) {
577 elf.SHN_ABS, elf.SHN_COMMON => {},
578 else => global.ref = .{
579 .index = self.atoms_indexes.items[esym.st_shndx],
580 .file = self.index,
581 },
582 }
583 global.value = @intCast(esym.st_value);
584 global.esym_index = esym_index;
585 global.file_index = self.index;
586 global.version_index = elf_file.default_sym_version;
587 if (esym.st_bind() == elf.STB_WEAK) global.flags.weak = true;
576 const resolv = &self.symbols_resolver.items[i - first_global];
577 const gop = try elf_file.resolver.getOrPut(gpa, .{
578 .index = @intCast(i),
579 .file = self.index,
580 }, elf_file);
581 if (!gop.found_existing) {
582 gop.ref.* = .{ .index = 0, .file = 0 };
583 }
584 resolv.* = gop.index;
585
586 if (esym.st_shndx == elf.SHN_UNDEF) continue;
587 if (elf_file.symbol(gop.ref.*) == null) {
588 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
589 continue;
590 }
591
592 if (self.asFile().symbolRank(esym, !self.alive) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) {
593 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
588594 }
589595 }
590596}
591597
592598pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {
593599 const first_global = self.first_global orelse return;
594 for (self.globals(), 0..) |index, i| {
600 for (self.globals(), 0..) |*sym, i| {
595601 const esym_index = @as(u32, @intCast(first_global + i));
596602 const esym = self.symtab.items[esym_index];
597603 if (esym.st_shndx != elf.SHN_UNDEF) continue;
598
599 const global = elf_file.symbol(index);
600 if (global.file(elf_file)) |_| {
601 if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF) continue;
602 }
604 if (elf_file.symbol(self.resolveSymbol(esym_index, elf_file)) != null) continue;
603605
604606 const is_import = blk: {
605607 if (!elf_file.isEffectivelyDynLib()) break :blk false;
......@@ -608,45 +610,48 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {
608610 break :blk true;
609611 };
610612
611 global.value = 0;
612 global.ref = .{ .index = 0, .file = 0 };
613 global.esym_index = esym_index;
614 global.file_index = self.index;
615 global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
616 global.flags.import = is_import;
613 sym.value = 0;
614 sym.ref = .{ .index = 0, .file = 0 };
615 sym.esym_index = esym_index;
616 sym.file_index = self.index;
617 sym.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
618 sym.flags.import = is_import;
619
620 const idx = self.symbols_resolver.items[i];
621 elf_file.resolver.values.items[idx - 1] = .{ .index = esym_index, .file = self.index };
617622 }
618623}
619624
620625pub fn claimUnresolvedObject(self: *Object, elf_file: *Elf) void {
621626 const first_global = self.first_global orelse return;
622 for (self.globals(), 0..) |index, i| {
627 for (self.globals(), 0..) |*sym, i| {
623628 const esym_index = @as(u32, @intCast(first_global + i));
624629 const esym = self.symtab.items[esym_index];
625630 if (esym.st_shndx != elf.SHN_UNDEF) continue;
631 if (elf_file.symbol(self.resolveSymbol(esym_index, elf_file)) != null) continue;
626632
627 const global = elf_file.symbol(index);
628 if (global.file(elf_file)) |file| {
629 if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or file.index() <= self.index) continue;
630 }
633 sym.value = 0;
634 sym.ref = .{ .index = 0, .file = 0 };
635 sym.esym_index = esym_index;
636 sym.file_index = self.index;
631637
632 global.value = 0;
633 global.ref = .{ .index = 0, .file = 0 };
634 global.esym_index = esym_index;
635 global.file_index = self.index;
638 const idx = self.symbols_resolver.items[i];
639 elf_file.resolver.values.items[idx - 1] = .{ .index = esym_index, .file = self.index };
636640 }
637641}
638642
639643pub fn markLive(self: *Object, elf_file: *Elf) void {
640644 const first_global = self.first_global orelse return;
641 for (self.globals(), 0..) |index, i| {
642 const sym_idx = first_global + i;
643 const sym = self.symtab.items[sym_idx];
644 if (sym.st_bind() == elf.STB_WEAK) continue;
645
646 const global = elf_file.symbol(index);
647 const file = global.file(elf_file) orelse continue;
648 const should_keep = sym.st_shndx == elf.SHN_UNDEF or
649 (sym.st_shndx == elf.SHN_COMMON and global.elfSym(elf_file).st_shndx != elf.SHN_COMMON);
645 for (0..self.globals().len) |i| {
646 const esym_idx = first_global + i;
647 const esym = self.symtab.items[esym_idx];
648 if (esym.st_bind() == elf.STB_WEAK) continue;
649
650 const ref = self.resolveSymbol(@intCast(esym_idx), elf_file);
651 const sym = elf_file.symbol(ref) orelse continue;
652 const file = sym.file(elf_file).?;
653 const should_keep = esym.st_shndx == elf.SHN_UNDEF or
654 (esym.st_shndx == elf.SHN_COMMON and sym.elfSym(elf_file).st_shndx != elf.SHN_COMMON);
650655 if (should_keep and !file.isAlive()) {
651656 file.setAlive();
652657 file.markLive(elf_file);
......@@ -664,26 +669,50 @@ pub fn markEhFrameAtomsDead(self: *Object, elf_file: *Elf) void {
664669 }
665670}
666671
672pub 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
667695pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {
668696 const first_global = self.first_global orelse return;
669 for (self.globals(), 0..) |index, i| {
670 const sym_idx = first_global + i;
671 const sym = self.symtab.items[sym_idx];
672 const global = elf_file.symbol(index);
673 const global_file = global.file(elf_file) orelse continue;
674
675 if (self.index == global_file.index() or
676 sym.st_shndx == elf.SHN_UNDEF or
677 sym.st_bind() == elf.STB_WEAK or
678 sym.st_shndx == elf.SHN_COMMON) continue;
679
680 if (sym.st_shndx != elf.SHN_ABS) {
681 const atom_index = self.atoms_indexes.items[sym.st_shndx];
697 for (0..self.globals().len) |i| {
698 const esym_idx = first_global + i;
699 const esym = self.symtab.items[esym_idx];
700 const ref = self.resolveSymbol(@intCast(esym_idx), elf_file);
701 const ref_sym = elf_file.symbol(ref) orelse continue;
702 const ref_file = ref_sym.file(elf_file).?;
703
704 if (self.index == ref_file.index() or
705 esym.st_shndx == elf.SHN_UNDEF or
706 esym.st_bind() == elf.STB_WEAK or
707 esym.st_shndx == elf.SHN_COMMON) continue;
708
709 if (esym.st_shndx != elf.SHN_ABS) {
710 const atom_index = self.atoms_indexes.items[esym.st_shndx];
682711 const atom_ptr = self.atom(atom_index) orelse continue;
683712 if (!atom_ptr.alive) continue;
684713 }
685714
686 const gop = try dupes.getOrPut(index);
715 const gop = try dupes.getOrPut(self.symbols_resolver.items[i]);
687716 if (!gop.found_existing) {
688717 gop.value_ptr.* = .{};
689718 }
......@@ -813,9 +842,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
813842 }
814843
815844 for (self.symtab.items, 0..) |*esym, idx| {
816 const sym_index = self.symbols.items[idx];
817 const sym = elf_file.symbol(sym_index);
818
845 const sym = &self.symbols.items[idx];
819846 if (esym.st_shndx == elf.SHN_COMMON or esym.st_shndx == elf.SHN_UNDEF or esym.st_shndx == elf.SHN_ABS) continue;
820847
821848 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 {
854881 return error.MalformedObject;
855882 };
856883
857 const out_sym_idx: u64 = @intCast(self.symbols.items.len);
858 try self.symbols.ensureUnusedCapacity(gpa, 1);
884 const sym_index = try self.addSymbol(gpa);
885 const sym = &self.symbols.items[sym_index];
859886 const name = try std.fmt.allocPrint(gpa, "{s}$subsection{d}", .{ msec.name(elf_file), res.msub_index });
860887 defer gpa.free(name);
861 const sym_index = try elf_file.addSymbol();
862 const sym = elf_file.symbol(sym_index);
863888 sym.* = .{
864889 .value = @bitCast(@as(i64, @intCast(res.offset)) - rel.r_addend),
865890 .name_offset = try self.addString(gpa, name),
866891 .esym_index = rel.r_sym(),
867892 .file_index = self.index,
893 .extra_index = try self.addSymbolExtra(gpa, .{}),
868894 };
869895 sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index };
870896 sym.flags.merge_subsection = true;
871 self.symbols.addOneAssumeCapacity().* = sym_index;
872 rel.r_info = (out_sym_idx << 32) | rel.r_type();
897 rel.r_info = (@as(u64, @intCast(sym_index)) << 32) | rel.r_type();
873898 }
874899 }
875900}
......@@ -878,27 +903,16 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
878903/// play nicely with the rest of the system.
879904pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
880905 const first_global = self.first_global orelse return;
881 for (self.globals(), 0..) |index, i| {
882 const sym_idx = @as(u32, @intCast(first_global + i));
883 const this_sym = self.symtab.items[sym_idx];
884 if (this_sym.st_shndx != elf.SHN_COMMON) continue;
885
886 const global = elf_file.symbol(index);
887 const global_file = global.file(elf_file).?;
888 if (global_file.index() != self.index) {
889 // if (elf_file.options.warn_common) {
890 // elf_file.base.warn("{}: multiple common symbols: {s}", .{
891 // self.fmtPath(),
892 // global.getName(elf_file),
893 // });
894 // }
895 continue;
896 }
906 for (self.globals(), self.symbols_resolver.items, 0..) |*sym, resolv, i| {
907 const esym_idx = @as(u32, @intCast(first_global + i));
908 const esym = self.symtab.items[esym_idx];
909 if (esym.st_shndx != elf.SHN_COMMON) continue;
910 if (elf_file.resolver.get(resolv).?.file != self.index) continue;
897911
898912 const comp = elf_file.base.comp;
899913 const gpa = comp.gpa;
900914
901 const is_tls = global.type(elf_file) == elf.STT_TLS;
915 const is_tls = sym.type(elf_file) == elf.STT_TLS;
902916 const name = if (is_tls) ".tls_common" else ".common";
903917 const name_offset = @as(u32, @intCast(self.strtab.items.len));
904918 try self.strtab.writer(gpa).print("{s}\x00", .{name});
......@@ -907,7 +921,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
907921 if (is_tls) sh_flags |= elf.SHF_TLS;
908922 const shndx = @as(u32, @intCast(self.shdrs.items.len));
909923 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;
911925 shdr.* = .{
912926 .sh_name = name_offset,
913927 .sh_type = elf.SHT_NOBITS,
......@@ -917,21 +931,21 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
917931 .sh_size = sh_size,
918932 .sh_link = 0,
919933 .sh_info = 0,
920 .sh_addralign = this_sym.st_value,
934 .sh_addralign = esym.st_value,
921935 .sh_entsize = 0,
922936 };
923937
924938 const atom_index = try self.addAtom(gpa, .{
925939 .name = name_offset,
926940 .shndx = shndx,
927 .size = this_sym.st_size,
928 .alignment = Alignment.fromNonzeroByteUnits(this_sym.st_value),
941 .size = esym.st_size,
942 .alignment = Alignment.fromNonzeroByteUnits(esym.st_value),
929943 });
930944 try self.atoms_indexes.append(gpa, atom_index);
931945
932 global.value = 0;
933 global.ref = .{ .index = atom_index, .file = self.index };
934 global.flags.weak = false;
946 sym.value = 0;
947 sym.ref = .{ .index = atom_index, .file = self.index };
948 sym.flags.weak = false;
935949 }
936950}
937951
......@@ -1073,7 +1087,7 @@ pub fn writeAr(self: Object, elf_file: *Elf, writer: anytype) !void {
10731087 try writer.writeAll(data);
10741088}
10751089
1076pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void {
1090pub fn updateSymtabSize(self: *Object, elf_file: *Elf) void {
10771091 const isAlive = struct {
10781092 fn isAlive(sym: *const Symbol, ctx: *Elf) bool {
10791093 if (sym.mergeSubsection(ctx)) |msub| return msub.alive;
......@@ -1082,8 +1096,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void {
10821096 }
10831097 }.isAlive;
10841098
1085 for (self.locals()) |local_index| {
1086 const local = elf_file.symbol(local_index);
1099 for (self.locals()) |*local| {
10871100 if (!isAlive(local, elf_file)) continue;
10881101 const esym = local.elfSym(elf_file);
10891102 switch (esym.st_type()) {
......@@ -1092,31 +1105,30 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void {
10921105 else => {},
10931106 }
10941107 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);
10961109 self.output_symtab_ctx.nlocals += 1;
10971110 self.output_symtab_ctx.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1;
10981111 }
10991112
1100 for (self.globals()) |global_index| {
1101 const global = elf_file.symbol(global_index);
1102 const file_ptr = global.file(elf_file) orelse continue;
1103 if (file_ptr.index() != self.index) continue;
1113 for (self.globals(), self.symbols_resolver.items) |*global, resolv| {
1114 const ref = elf_file.resolver.values.items[resolv - 1];
1115 const ref_sym = elf_file.symbol(ref) orelse continue;
1116 if (ref_sym.file(elf_file).?.index() != self.index) continue;
11041117 if (!isAlive(global, elf_file)) continue;
11051118 global.flags.output_symtab = true;
11061119 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);
11081121 self.output_symtab_ctx.nlocals += 1;
11091122 } else {
1110 try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
1123 global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
11111124 self.output_symtab_ctx.nglobals += 1;
11121125 }
11131126 self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1;
11141127 }
11151128}
11161129
1117pub fn writeSymtab(self: Object, elf_file: *Elf) void {
1118 for (self.locals()) |local_index| {
1119 const local = elf_file.symbol(local_index);
1130pub fn writeSymtab(self: *Object, elf_file: *Elf) void {
1131 for (self.locals()) |local| {
11201132 const idx = local.outputSymtabIndex(elf_file) orelse continue;
11211133 const out_sym = &elf_file.symtab.items[idx];
11221134 out_sym.st_name = @intCast(elf_file.strtab.items.len);
......@@ -1125,10 +1137,10 @@ pub fn writeSymtab(self: Object, elf_file: *Elf) void {
11251137 local.setOutputSym(elf_file, out_sym);
11261138 }
11271139
1128 for (self.globals()) |global_index| {
1129 const global = elf_file.symbol(global_index);
1130 const file_ptr = global.file(elf_file) orelse continue;
1131 if (file_ptr.index() != self.index) continue;
1140 for (self.globals(), self.symbols_resolver.items) |global, resolv| {
1141 const ref = elf_file.resolver.values.items[resolv - 1];
1142 const ref_sym = elf_file.symbol(ref) orelse continue;
1143 if (ref_sym.file(elf_file).?.index() != self.index) continue;
11321144 const idx = global.outputSymtabIndex(elf_file) orelse continue;
11331145 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
11341146 elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file));
......@@ -1139,20 +1151,6 @@ pub fn writeSymtab(self: Object, elf_file: *Elf) void {
11391151 }
11401152}
11411153
1142pub 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
1149pub 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
11561154/// Returns atom's code and optionally uncompresses data if required (for compressed sections).
11571155/// Caller owns the memory.
11581156pub 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
11851183 return data;
11861184}
11871185
1186fn 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
1193pub 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
1200pub 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
1208fn addSymbol(self: *Object, allocator: Allocator) !Symbol.Index {
1209 try self.symbols.ensureUnusedCapacity(allocator, 1);
1210 return self.addSymbolAssumeCapacity();
1211}
1212
1213fn 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
1219pub 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
1225pub 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
1237pub 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
1251pub 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
11881261pub fn asFile(self: *Object) File {
11891262 return .{ .object = self };
11901263}
......@@ -1352,15 +1425,20 @@ fn formatSymtab(
13521425 _ = unused_fmt_string;
13531426 _ = options;
13541427 const object = ctx.object;
1428 const elf_file = ctx.elf_file;
13551429 try writer.writeAll(" locals\n");
1356 for (object.locals()) |index| {
1357 const local = ctx.elf_file.symbol(index);
1358 try writer.print(" {}\n", .{local.fmt(ctx.elf_file)});
1430 for (object.locals()) |sym| {
1431 try writer.print(" {}\n", .{sym.fmt(elf_file)});
13591432 }
13601433 try writer.writeAll(" globals\n");
1361 for (object.globals()) |index| {
1362 const global = ctx.elf_file.symbol(index);
1363 try writer.print(" {}\n", .{global.fmt(ctx.elf_file)});
1434 for (object.globals(), 0..) |sym, i| {
1435 const first_global = object.first_global.?;
1436 const ref = object.resolveSymbol(@intCast(i + first_global), elf_file);
1437 if (elf_file.symbol(ref)) |ref_sym| {
1438 try writer.print(" {}\n", .{ref_sym.fmt(elf_file)});
1439 } else {
1440 try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)});
1441 }
13641442 }
13651443}
13661444
src/link/Elf/SharedObject.zig+163-62
......@@ -10,7 +10,10 @@ strtab: std.ArrayListUnmanaged(u8) = .{},
1010versyms: std.ArrayListUnmanaged(elf.Elf64_Versym) = .{},
1111verstrings: std.ArrayListUnmanaged(u32) = .{},
1212
13symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
13symbols: std.ArrayListUnmanaged(Symbol) = .{},
14symbols_extra: std.ArrayListUnmanaged(u32) = .{},
15symbols_resolver: std.ArrayListUnmanaged(Elf.SymbolResolver.Index) = .{},
16
1417aliases: ?std.ArrayListUnmanaged(u32) = null,
1518dynamic_table: std.ArrayListUnmanaged(elf.Elf64_Dyn) = .{},
1619
......@@ -38,6 +41,8 @@ pub fn deinit(self: *SharedObject, allocator: Allocator) void {
3841 self.versyms.deinit(allocator);
3942 self.verstrings.deinit(allocator);
4043 self.symbols.deinit(allocator);
44 self.symbols_extra.deinit(allocator);
45 self.symbols_resolver.deinit(allocator);
4146 if (self.aliases) |*aliases| aliases.deinit(allocator);
4247 self.dynamic_table.deinit(allocator);
4348}
......@@ -129,7 +134,7 @@ pub fn parse(self: *SharedObject, elf_file: *Elf, handle: std.fs.File) !void {
129134 .versym_sect_index = versym_sect_index,
130135 });
131136
132 try self.initSymtab(elf_file, .{
137 try self.initSymbols(elf_file, .{
133138 .symtab = symtab,
134139 .strtab = strtab,
135140 });
......@@ -188,16 +193,20 @@ fn parseVersions(self: *SharedObject, elf_file: *Elf, handle: std.fs.File, opts:
188193 }
189194}
190195
191fn initSymtab(self: *SharedObject, elf_file: *Elf, opts: struct {
196fn initSymbols(self: *SharedObject, elf_file: *Elf, opts: struct {
192197 symtab: []align(1) const elf.Elf64_Sym,
193198 strtab: []const u8,
194199}) !void {
195 const comp = elf_file.base.comp;
196 const gpa = comp.gpa;
200 const gpa = elf_file.base.comp.gpa;
201 const nsyms = opts.symtab.len;
197202
198203 try self.strtab.appendSlice(gpa, opts.strtab);
199 try self.symtab.ensureTotalCapacityPrecise(gpa, opts.symtab.len);
200 try self.symbols.ensureTotalCapacityPrecise(gpa, opts.symtab.len);
204 try self.symtab.ensureTotalCapacityPrecise(gpa, nsyms);
205 try self.symbols.ensureTotalCapacityPrecise(gpa, nsyms);
206 try self.symbols_extra.ensureTotalCapacityPrecise(gpa, nsyms * @sizeOf(Symbol.Extra));
207 try self.symbols_resolver.ensureTotalCapacityPrecise(gpa, nsyms);
208 self.symbols_resolver.resize(gpa, nsyms) catch unreachable;
209 @memset(self.symbols_resolver.items, 0);
201210
202211 for (opts.symtab, 0..) |sym, i| {
203212 const hidden = self.versyms.items[i] & elf.VERSYM_HIDDEN != 0;
......@@ -210,45 +219,57 @@ fn initSymtab(self: *SharedObject, elf_file: *Elf, opts: struct {
210219 self.versionString(self.versyms.items[i]),
211220 });
212221 defer gpa.free(mangled);
213 const name_off = @as(u32, @intCast(self.strtab.items.len));
214 try self.strtab.writer(gpa).print("{s}\x00", .{mangled});
215 break :blk name_off;
222 break :blk try self.addString(gpa, mangled);
216223 } else sym.st_name;
217 const out_sym = self.symtab.addOneAssumeCapacity();
218 out_sym.* = sym;
219 out_sym.st_name = name_off;
220 const gop = try elf_file.getOrPutGlobal(self.getString(name_off));
221 self.symbols.addOneAssumeCapacity().* = gop.index;
224 const out_esym_index: u32 = @intCast(self.symtab.items.len);
225 const out_esym = self.symtab.addOneAssumeCapacity();
226 out_esym.* = sym;
227 out_esym.st_name = name_off;
228 const out_sym_index = self.addSymbolAssumeCapacity();
229 const out_sym = &self.symbols.items[out_sym_index];
230 out_sym.value = @intCast(out_esym.st_value);
231 out_sym.name_offset = name_off;
232 out_sym.ref = .{ .index = 0, .file = 0 };
233 out_sym.esym_index = out_esym_index;
234 out_sym.version_index = self.versyms.items[out_esym_index];
235 out_sym.extra_index = self.addSymbolExtraAssumeCapacity(.{});
222236 }
223237}
224238
225pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) void {
226 for (self.globals(), 0..) |index, i| {
227 const esym_index = @as(u32, @intCast(i));
228 const this_sym = self.symtab.items[esym_index];
239pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) !void {
240 const gpa = elf_file.base.comp.gpa;
241
242 for (self.symtab.items, self.symbols_resolver.items, 0..) |esym, *resolv, i| {
243 const gop = try elf_file.resolver.getOrPut(gpa, .{
244 .index = @intCast(i),
245 .file = self.index,
246 }, elf_file);
247 if (!gop.found_existing) {
248 gop.ref.* = .{ .index = 0, .file = 0 };
249 }
250 resolv.* = gop.index;
229251
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 }
231257
232 const global = elf_file.symbol(index);
233 if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {
234 global.value = @intCast(this_sym.st_value);
235 global.ref = .{ .index = 0, .file = 0 };
236 global.esym_index = esym_index;
237 global.version_index = self.versyms.items[esym_index];
238 global.file_index = self.index;
258 if (self.asFile().symbolRank(esym, false) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) {
259 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
239260 }
240261 }
241262}
242263
243264pub fn markLive(self: *SharedObject, elf_file: *Elf) void {
244 for (self.globals(), 0..) |index, i| {
245 const sym = self.symtab.items[i];
246 if (sym.st_shndx != elf.SHN_UNDEF) continue;
265 for (self.symtab.items, 0..) |esym, i| {
266 if (esym.st_shndx != elf.SHN_UNDEF) continue;
247267
248 const global = elf_file.symbol(index);
249 const file = global.file(elf_file) orelse continue;
268 const ref = self.resolveSymbol(@intCast(i), elf_file);
269 const sym = elf_file.symbol(ref) orelse continue;
270 const file = sym.file(elf_file).?;
250271 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,
252273 else => false,
253274 };
254275 if (!should_drop and !file.isAlive()) {
......@@ -258,28 +279,34 @@ pub fn markLive(self: *SharedObject, elf_file: *Elf) void {
258279 }
259280}
260281
261pub fn globals(self: SharedObject) []const Symbol.Index {
262 return self.symbols.items;
282pub fn markImportExports(self: *SharedObject, elf_file: *Elf) void {
283 for (0..self.symbols.items.len) |i| {
284 const ref = self.resolveSymbol(@intCast(i), elf_file);
285 const ref_sym = elf_file.symbol(ref) orelse continue;
286 const ref_file = ref_sym.file(elf_file).?;
287 const vis = @as(elf.STV, @enumFromInt(ref_sym.elfSym(elf_file).st_other));
288 if (ref_file != .shared_object and vis != .HIDDEN) ref_sym.flags.@"export" = true;
289 }
263290}
264291
265pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) !void {
266 for (self.globals()) |global_index| {
267 const global = elf_file.symbol(global_index);
268 const file_ptr = global.file(elf_file) orelse continue;
269 if (file_ptr.index() != self.index) continue;
292pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) void {
293 for (self.symbols.items, self.symbols_resolver.items) |*global, resolv| {
294 const ref = elf_file.resolver.get(resolv).?;
295 const ref_sym = elf_file.symbol(ref) orelse continue;
296 if (ref_sym.file(elf_file).?.index() != self.index) continue;
270297 if (global.isLocal(elf_file)) continue;
271298 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);
273300 self.output_symtab_ctx.nglobals += 1;
274301 self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1;
275302 }
276303}
277304
278pub fn writeSymtab(self: SharedObject, elf_file: *Elf) void {
279 for (self.globals()) |global_index| {
280 const global = elf_file.symbol(global_index);
281 const file_ptr = global.file(elf_file) orelse continue;
282 if (file_ptr.index() != self.index) continue;
305pub fn writeSymtab(self: *SharedObject, elf_file: *Elf) void {
306 for (self.symbols.items, self.symbols_resolver.items) |global, resolv| {
307 const ref = elf_file.resolver.get(resolv).?;
308 const ref_sym = elf_file.symbol(ref) orelse continue;
309 if (ref_sym.file(elf_file).?.index() != self.index) continue;
283310 const idx = global.outputSymtabIndex(elf_file) orelse continue;
284311 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
285312 elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file));
......@@ -319,9 +346,12 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void {
319346 assert(self.aliases == null);
320347
321348 const SortAlias = struct {
322 pub fn lessThan(ctx: *Elf, lhs: Symbol.Index, rhs: Symbol.Index) bool {
323 const lhs_sym = ctx.symbol(lhs).elfSym(ctx);
324 const rhs_sym = ctx.symbol(rhs).elfSym(ctx);
349 so: *SharedObject,
350 ef: *Elf,
351
352 pub fn lessThan(ctx: @This(), lhs: Symbol.Index, rhs: Symbol.Index) bool {
353 const lhs_sym = ctx.so.symbols.items[lhs].elfSym(ctx.ef);
354 const rhs_sym = ctx.so.symbols.items[rhs].elfSym(ctx.ef);
325355 return lhs_sym.st_value < rhs_sym.st_value;
326356 }
327357 };
......@@ -330,16 +360,16 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void {
330360 const gpa = comp.gpa;
331361 var aliases = std.ArrayList(Symbol.Index).init(gpa);
332362 defer aliases.deinit();
333 try aliases.ensureTotalCapacityPrecise(self.globals().len);
363 try aliases.ensureTotalCapacityPrecise(self.symbols.items.len);
334364
335 for (self.globals()) |index| {
336 const global = elf_file.symbol(index);
337 const global_file = global.file(elf_file) orelse continue;
338 if (global_file.index() != self.index) continue;
339 aliases.appendAssumeCapacity(index);
365 for (self.symbols_resolver.items, 0..) |resolv, index| {
366 const ref = elf_file.resolver.get(resolv).?;
367 const ref_sym = elf_file.symbol(ref) orelse continue;
368 if (ref_sym.file(elf_file).?.index() != self.index) continue;
369 aliases.appendAssumeCapacity(@intCast(index));
340370 }
341371
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);
343373
344374 self.aliases = aliases.moveToUnmanaged();
345375}
......@@ -347,27 +377,93 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void {
347377pub fn symbolAliases(self: *SharedObject, index: u32, elf_file: *Elf) []const u32 {
348378 assert(self.aliases != null);
349379
350 const symbol = elf_file.symbol(index).elfSym(elf_file);
380 const symbol = self.symbols.items[index].elfSym(elf_file);
351381 const aliases = self.aliases.?;
352382
353383 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);
355385 if (symbol.st_value == alias_sym.st_value) break i;
356386 } else aliases.items.len;
357387
358388 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);
360390 if (symbol.st_value < alias_sym.st_value) break i + start;
361391 } else aliases.items.len;
362392
363393 return aliases.items[start..end];
364394}
365395
396fn 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
366404pub fn getString(self: SharedObject, off: u32) [:0]const u8 {
367405 assert(off < self.strtab.items.len);
368406 return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0);
369407}
370408
409pub 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
414fn addSymbol(self: *SharedObject, allocator: Allocator) !Symbol.Index {
415 try self.symbols.ensureUnusedCapacity(allocator, 1);
416 return self.addSymbolAssumeCapacity();
417}
418
419fn 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
425pub 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
431pub 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
443pub 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
457pub 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
371467pub fn format(
372468 self: SharedObject,
373469 comptime unused_fmt_string: []const u8,
......@@ -402,10 +498,15 @@ fn formatSymtab(
402498 _ = unused_fmt_string;
403499 _ = options;
404500 const shared = ctx.shared;
501 const elf_file = ctx.elf_file;
405502 try writer.writeAll(" globals\n");
406 for (shared.symbols.items) |index| {
407 const global = ctx.elf_file.symbol(index);
408 try writer.print(" {}\n", .{global.fmt(ctx.elf_file)});
503 for (shared.symbols.items, 0..) |sym, i| {
504 const ref = shared.resolveSymbol(@intCast(i), elf_file);
505 if (elf_file.symbol(ref)) |ref_sym| {
506 try writer.print(" {}\n", .{ref_sym.fmt(elf_file)});
507 } else {
508 try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)});
509 }
409510 }
410511}
411512
src/link/Elf/Symbol.zig+22-30
......@@ -63,9 +63,7 @@ pub fn @"type"(symbol: Symbol, elf_file: *Elf) u4 {
6363}
6464
6565pub fn name(symbol: Symbol, elf_file: *Elf) [:0]const u8 {
66 if (symbol.flags.global) return elf_file.strings.getAssumeExists(symbol.name_offset);
67 const file_ptr = symbol.file(elf_file).?;
68 return switch (file_ptr) {
66 return switch (symbol.file(elf_file).?) {
6967 inline else => |x| x.getString(symbol.name_offset),
7068 };
7169}
......@@ -87,9 +85,8 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File {
8785}
8886
8987pub fn elfSym(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {
90 const file_ptr = symbol.file(elf_file).?;
91 return switch (file_ptr) {
92 .zig_object => |x| x.elfSym(symbol.esym_index).*,
88 return switch (symbol.file(elf_file).?) {
89 .zig_object => |x| x.symtab.items(.elf_sym)[symbol.esym_index],
9390 inline else => |x| x.symtab.items[symbol.esym_index],
9491 };
9592}
......@@ -159,20 +156,20 @@ pub fn outputSymtabIndex(symbol: Symbol, elf_file: *Elf) ?u32 {
159156 const symtab_ctx = switch (file_ptr) {
160157 inline else => |x| x.output_symtab_ctx,
161158 };
162 const idx = symbol.extra(elf_file).?.symtab;
159 const idx = symbol.extra(elf_file).symtab;
163160 return if (symbol.isLocal(elf_file)) idx + symtab_ctx.ilocal else idx + symtab_ctx.iglobal;
164161}
165162
166163pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 {
167164 if (!symbol.flags.has_got) return 0;
168 const extras = symbol.extra(elf_file).?;
165 const extras = symbol.extra(elf_file);
169166 const entry = elf_file.got.entries.items[extras.got];
170167 return entry.address(elf_file);
171168}
172169
173170pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
174171 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);
176173 const shdr = elf_file.shdrs.items[elf_file.plt_got_section_index.?];
177174 const cpu_arch = elf_file.getTarget().cpu.arch;
178175 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 {
180177
181178pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 {
182179 if (!symbol.flags.has_plt) return 0;
183 const extras = symbol.extra(elf_file).?;
180 const extras = symbol.extra(elf_file);
184181 const shdr = elf_file.shdrs.items[elf_file.plt_section_index.?];
185182 const cpu_arch = elf_file.getTarget().cpu.arch;
186183 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 {
188185
189186pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) i64 {
190187 if (!symbol.flags.has_plt) return 0;
191 const extras = symbol.extra(elf_file).?;
188 const extras = symbol.extra(elf_file);
192189 const shdr = elf_file.shdrs.items[elf_file.got_plt_section_index.?];
193190 return @intCast(shdr.sh_addr + extras.plt * 8 + GotPltSection.preamble_size);
194191}
......@@ -201,21 +198,21 @@ pub fn copyRelAddress(symbol: Symbol, elf_file: *Elf) i64 {
201198
202199pub fn tlsGdAddress(symbol: Symbol, elf_file: *Elf) i64 {
203200 if (!symbol.flags.has_tlsgd) return 0;
204 const extras = symbol.extra(elf_file).?;
201 const extras = symbol.extra(elf_file);
205202 const entry = elf_file.got.entries.items[extras.tlsgd];
206203 return entry.address(elf_file);
207204}
208205
209206pub fn gotTpAddress(symbol: Symbol, elf_file: *Elf) i64 {
210207 if (!symbol.flags.has_gottp) return 0;
211 const extras = symbol.extra(elf_file).?;
208 const extras = symbol.extra(elf_file);
212209 const entry = elf_file.got.entries.items[extras.gottp];
213210 return entry.address(elf_file);
214211}
215212
216213pub fn tlsDescAddress(symbol: Symbol, elf_file: *Elf) i64 {
217214 if (!symbol.flags.has_tlsdesc) return 0;
218 const extras = symbol.extra(elf_file).?;
215 const extras = symbol.extra(elf_file);
219216 const entry = elf_file.got.entries.items[extras.tlsdesc];
220217 return entry.address(elf_file);
221218}
......@@ -228,14 +225,14 @@ const GetOrCreateZigGotEntryResult = struct {
228225pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, elf_file: *Elf) !GetOrCreateZigGotEntryResult {
229226 assert(!elf_file.base.isRelocatable());
230227 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 };
232229 const index = try elf_file.zig_got.addSymbol(symbol_index, elf_file);
233230 return .{ .found_existing = false, .index = index };
234231}
235232
236233pub fn zigGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
237234 if (!symbol.flags.has_zig_got) return 0;
238 const extras = symbol.extra(elf_file).?;
235 const extras = symbol.extra(elf_file);
239236 return elf_file.zig_got.entryAddress(extras.zig_got, elf_file);
240237}
241238
......@@ -265,11 +262,8 @@ const AddExtraOpts = struct {
265262 zig_got: ?u32 = null,
266263};
267264
268pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void {
269 if (symbol.extra(elf_file) == null) {
270 symbol.extra_index = try elf_file.addSymbolExtra(.{});
271 }
272 var extras = symbol.extra(elf_file).?;
265pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) void {
266 var extras = symbol.extra(elf_file);
273267 inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| {
274268 if (@field(opts, field.name)) |x| {
275269 @field(extras, field.name) = x;
......@@ -278,12 +272,16 @@ pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void {
278272 symbol.setExtra(extras, elf_file);
279273}
280274
281pub fn extra(symbol: Symbol, elf_file: *Elf) ?Extra {
282 return elf_file.symbolExtra(symbol.extra_index);
275pub fn extra(symbol: Symbol, elf_file: *Elf) Extra {
276 return switch (symbol.file(elf_file).?) {
277 inline else => |x| x.symbolExtra(symbol.extra_index),
278 };
283279}
284280
285281pub 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 };
287285}
288286
289287pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
......@@ -426,12 +424,6 @@ pub const Flags = packed struct {
426424 /// Whether this symbol is weak.
427425 weak: bool = false,
428426
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
435427 /// Whether the symbol makes into the output symtab.
436428 output_symtab: bool = false,
437429
src/link/Elf/ZigObject.zig+309-223
......@@ -8,9 +8,11 @@ data: std.ArrayListUnmanaged(u8) = .{},
88path: []const u8,
99index: File.Index,
1010
11local_esyms: std.MultiArrayList(ElfSym) = .{},
12global_esyms: std.MultiArrayList(ElfSym) = .{},
11symtab: std.MultiArrayList(ElfSym) = .{},
1312strtab: StringTable = .{},
13symbols: std.ArrayListUnmanaged(Symbol) = .{},
14symbols_extra: std.ArrayListUnmanaged(u32) = .{},
15symbols_resolver: std.ArrayListUnmanaged(Elf.SymbolResolver.Index) = .{},
1416local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
1517global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
1618globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
......@@ -87,18 +89,11 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
8789 try self.strtab.buffer.append(gpa, 0);
8890
8991 const name_off = try self.strtab.insert(gpa, self.path);
90 const symbol_index = try elf_file.addSymbol();
91 try self.local_symbols.append(gpa, symbol_index);
92 const symbol_ptr = elf_file.symbol(symbol_index);
93 symbol_ptr.file_index = self.index;
94 symbol_ptr.name_offset = name_off;
95
96 const esym_index = try self.addLocalEsym(gpa);
97 const esym = &self.local_esyms.items(.elf_sym)[esym_index];
98 esym.st_name = name_off;
92 const symbol_index = try self.newLocalSymbol(gpa, name_off);
93 const sym = self.symbol(symbol_index);
94 const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
9995 esym.st_info = elf.STT_FILE;
10096 esym.st_shndx = elf.SHN_ABS;
101 symbol_ptr.esym_index = esym_index;
10297
10398 switch (comp.config.debug_format) {
10499 .strip => {},
......@@ -112,9 +107,11 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
112107
113108pub fn deinit(self: *ZigObject, allocator: Allocator) void {
114109 self.data.deinit(allocator);
115 self.local_esyms.deinit(allocator);
116 self.global_esyms.deinit(allocator);
110 self.symtab.deinit(allocator);
117111 self.strtab.deinit(allocator);
112 self.symbols.deinit(allocator);
113 self.symbols_extra.deinit(allocator);
114 self.symbols_resolver.deinit(allocator);
118115 self.local_symbols.deinit(allocator);
119116 self.global_symbols.deinit(allocator);
120117 self.globals_lookup.deinit(allocator);
......@@ -262,50 +259,75 @@ fn saveDebugSectionsSizes(self: *ZigObject, elf_file: *Elf) void {
262259 }
263260}
264261
265pub fn addLocalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index {
266 try self.local_esyms.ensureUnusedCapacity(allocator, 1);
267 const index = @as(Symbol.Index, @intCast(self.local_esyms.addOneAssumeCapacity()));
268 var esym = ElfSym{ .elf_sym = Elf.null_sym };
269 esym.elf_sym.st_info = elf.STB_LOCAL << 4;
270 self.local_esyms.set(index, esym);
262fn newSymbol(self: *ZigObject, allocator: Allocator, name_off: u32, st_bind: u4) !Symbol.Index {
263 try self.symtab.ensureUnusedCapacity(allocator, 1);
264 try self.symbols.ensureUnusedCapacity(allocator, 1);
265 try self.symbols_extra.ensureUnusedCapacity(allocator, @sizeOf(Symbol.Extra));
266
267 const index = self.addSymbolAssumeCapacity();
268 const sym = &self.symbols.items[index];
269 sym.name_offset = name_off;
270 sym.extra_index = self.addSymbolExtraAssumeCapacity(.{});
271
272 const esym_idx: u32 = @intCast(self.symtab.addOneAssumeCapacity());
273 const esym = ElfSym{ .elf_sym = .{
274 .st_value = 0,
275 .st_name = name_off,
276 .st_info = @as(u8, @intCast(st_bind)) << 4,
277 .st_other = 0,
278 .st_size = 0,
279 .st_shndx = 0,
280 } };
281 self.symtab.set(index, esym);
282 sym.esym_index = esym_idx;
283
271284 return index;
272285}
273286
274pub fn addGlobalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index {
275 try self.global_esyms.ensureUnusedCapacity(allocator, 1);
276 const index = @as(Symbol.Index, @intCast(self.global_esyms.addOneAssumeCapacity()));
277 var esym = ElfSym{ .elf_sym = Elf.null_sym };
278 esym.elf_sym.st_info = elf.STB_GLOBAL << 4;
279 self.global_esyms.set(index, esym);
280 return index | global_symbol_bit;
287fn newLocalSymbol(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {
288 try self.local_symbols.ensureUnusedCapacity(allocator, 1);
289 const fake_index: Symbol.Index = @intCast(self.local_symbols.items.len);
290 const index = try self.newSymbol(allocator, name_off, elf.STB_LOCAL);
291 self.local_symbols.appendAssumeCapacity(index);
292 return fake_index;
281293}
282294
283pub fn newAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {
284 const gpa = elf_file.base.comp.gpa;
285 const atom_index = try self.addAtom(gpa);
286 const symbol_index = try elf_file.addSymbol();
287 const esym_index = try self.addLocalEsym(gpa);
288
289 try self.atoms_indexes.append(gpa, atom_index);
290 try self.local_symbols.append(gpa, symbol_index);
291
292 const symbol_ptr = elf_file.symbol(symbol_index);
293 symbol_ptr.file_index = self.index;
294 symbol_ptr.ref = .{ .index = atom_index, .file = self.index };
295fn newGlobalSymbol(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {
296 try self.global_symbols.ensureUnusedCapacity(allocator, 1);
297 try self.symbols_resolver.ensureUnusedCapacity(allocator, 1);
298 const fake_index: Symbol.Index = @intCast(self.global_symbols.items.len);
299 const index = try self.newSymbol(allocator, name_off, elf.STB_GLOBAL);
300 self.global_symbols.appendAssumeCapacity(index);
301 self.symbols_resolver.addOneAssumeCapacity().* = 0;
302 return fake_index | global_symbol_bit;
303}
295304
296 self.local_esyms.items(.shndx)[esym_index] = atom_index;
297 self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM;
298 symbol_ptr.esym_index = esym_index;
305fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index {
306 try self.atoms.ensureUnusedCapacity(allocator, 1);
307 try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra));
308 try self.atoms_indexes.ensureUnusedCapacity(allocator, 1);
309 try self.relocs.ensureUnusedCapacity(allocator, 1);
299310
300 // TODO I'm thinking that maybe we shouldn' set this value unless it's actually needed?
301 const relocs_index = @as(u32, @intCast(self.relocs.items.len));
302 const relocs = try self.relocs.addOne(gpa);
303 relocs.* = .{};
311 const index = self.addAtomAssumeCapacity();
312 self.atoms_indexes.appendAssumeCapacity(index);
313 const atom_ptr = self.atom(index).?;
314 atom_ptr.name_offset = name_off;
304315
305 const atom_ptr = self.atom(atom_index).?;
316 const relocs_index: u32 = @intCast(self.relocs.items.len);
317 self.relocs.addOneAssumeCapacity().* = .{};
306318 atom_ptr.relocs_section_index = relocs_index;
307319
308 return symbol_index;
320 return index;
321}
322
323fn 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;
309331}
310332
311333/// 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
320342 return shdr;
321343}
322344
323pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void {
324 for (self.globals(), 0..) |index, i| {
325 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
326 const esym = self.global_esyms.items(.elf_sym)[i];
327 const shndx = self.global_esyms.items(.shndx)[i];
328
329 if (esym.st_shndx == elf.SHN_UNDEF) continue;
345pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) !void {
346 const gpa = elf_file.base.comp.gpa;
330347
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) {
332353 assert(esym.st_shndx == SHN_ATOM);
333354 const atom_ptr = self.atom(shndx) orelse continue;
334355 if (!atom_ptr.alive) continue;
335356 }
336357
337 const global = elf_file.symbol(index);
338 if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) {
339 const atom_index = switch (esym.st_shndx) {
340 elf.SHN_ABS, elf.SHN_COMMON => 0,
341 SHN_ATOM => shndx,
342 else => unreachable,
343 };
344 global.value = @intCast(esym.st_value);
345 global.ref = .{ .index = atom_index, .file = self.index };
346 global.esym_index = esym_index;
347 global.file_index = self.index;
348 global.version_index = elf_file.default_sym_version;
349 if (esym.st_bind() == elf.STB_WEAK) global.flags.weak = true;
358 const resolv = &self.symbols_resolver.items[i];
359 const gop = try elf_file.resolver.getOrPut(gpa, .{
360 .index = @intCast(i | global_symbol_bit),
361 .file = self.index,
362 }, elf_file);
363 if (!gop.found_existing) {
364 gop.ref.* = .{ .index = 0, .file = 0 };
365 }
366 resolv.* = gop.index;
367
368 if (esym.st_shndx == elf.SHN_UNDEF) continue;
369 if (elf_file.symbol(gop.ref.*) == null) {
370 gop.ref.* = .{ .index = @intCast(i | global_symbol_bit), .file = self.index };
371 continue;
372 }
373
374 if (self.asFile().symbolRank(esym, false) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) {
375 gop.ref.* = .{ .index = @intCast(i | global_symbol_bit), .file = self.index };
350376 }
351377 }
352378}
353379
354pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void {
355 for (self.globals(), 0..) |index, i| {
356 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
357 const esym = self.global_esyms.items(.elf_sym)[i];
358
380pub fn claimUnresolved(self: *ZigObject, elf_file: *Elf) void {
381 for (self.global_symbols.items, 0..) |index, i| {
382 const global = &self.symbols.items[index];
383 const esym = self.symtab.items(.elf_sym)[index];
359384 if (esym.st_shndx != elf.SHN_UNDEF) continue;
360
361 const global = elf_file.symbol(index);
362 if (global.file(elf_file)) |_| {
363 if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF) continue;
364 }
385 if (elf_file.symbol(self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file)) != null) continue;
365386
366387 const is_import = blk: {
367388 if (!elf_file.isEffectivelyDynLib()) break :blk false;
......@@ -372,29 +393,30 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void {
372393
373394 global.value = 0;
374395 global.ref = .{ .index = 0, .file = 0 };
375 global.esym_index = esym_index;
396 global.esym_index = @intCast(index);
376397 global.file_index = self.index;
377398 global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
378399 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 };
379403 }
380404}
381405
382406pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void {
383 for (self.globals(), 0..) |index, i| {
384 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
385 const esym = self.global_esyms.items(.elf_sym)[i];
386
407 for (self.global_symbols.items, 0..) |index, i| {
408 const global = &self.symbols.items[index];
409 const esym = self.symtab.items(.elf_sym)[index];
387410 if (esym.st_shndx != elf.SHN_UNDEF) continue;
388
389 const global = elf_file.symbol(index);
390 if (global.file(elf_file)) |file| {
391 if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or file.index() <= self.index) continue;
392 }
411 if (elf_file.symbol(self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file)) != null) continue;
393412
394413 global.value = 0;
395414 global.ref = .{ .index = 0, .file = 0 };
396 global.esym_index = esym_index;
415 global.esym_index = @intCast(index);
397416 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 };
398420 }
399421}
400422
......@@ -417,12 +439,14 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {
417439}
418440
419441pub fn markLive(self: *ZigObject, elf_file: *Elf) void {
420 for (self.globals(), 0..) |index, i| {
421 const esym = self.global_esyms.items(.elf_sym)[i];
442 for (self.global_symbols.items, 0..) |index, i| {
443 const global = self.symbols.items[index];
444 const esym = self.symtab.items(.elf_sym)[index];
422445 if (esym.st_bind() == elf.STB_WEAK) continue;
423446
424 const global = elf_file.symbol(index);
425 const file = global.file(elf_file) orelse continue;
447 const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file);
448 const sym = elf_file.symbol(ref) orelse continue;
449 const file = sym.file(elf_file).?;
426450 const should_keep = esym.st_shndx == elf.SHN_UNDEF or
427451 (esym.st_shndx == elf.SHN_COMMON and global.elfSym(elf_file).st_shndx != elf.SHN_COMMON);
428452 if (should_keep and !file.isAlive()) {
......@@ -432,14 +456,36 @@ pub fn markLive(self: *ZigObject, elf_file: *Elf) void {
432456 }
433457}
434458
435pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {
436 for (self.globals(), 0..) |index, i| {
437 const esym = self.global_esyms.items(.elf_sym)[i];
438 const shndx = self.global_esyms.items(.shndx)[i];
439 const global = elf_file.symbol(index);
440 const global_file = global.file(elf_file) orelse continue;
459pub fn markImportsExports(self: *ZigObject, elf_file: *Elf) void {
460 for (0..self.global_symbols.items.len) |i| {
461 const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file);
462 const sym = elf_file.symbol(ref) orelse continue;
463 const file = sym.file(elf_file).?;
464 if (sym.version_index == elf.VER_NDX_LOCAL) continue;
465 const vis = @as(elf.STV, @enumFromInt(sym.elfSym(elf_file).st_other));
466 if (vis == .HIDDEN) continue;
467 if (file == .shared_object and !sym.isAbs(elf_file)) {
468 sym.flags.import = true;
469 continue;
470 }
471 if (file.index() == self.index) {
472 sym.flags.@"export" = true;
473 if (elf_file.isEffectivelyDynLib() and vis != .PROTECTED) {
474 sym.flags.import = true;
475 }
476 }
477 }
478}
441479
442 if (self.index == global_file.index() or
480pub 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
443489 esym.st_shndx == elf.SHN_UNDEF or
444490 esym.st_bind() == elf.STB_WEAK or
445491 esym.st_shndx == elf.SHN_COMMON) continue;
......@@ -449,7 +495,7 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O
449495 if (!atom_ptr.alive) continue;
450496 }
451497
452 const gop = try dupes.getOrPut(index);
498 const gop = try dupes.getOrPut(self.symbols_resolver.items[i]);
453499 if (!gop.found_existing) {
454500 gop.value_ptr.* = .{};
455501 }
......@@ -481,12 +527,13 @@ pub fn readFileContents(self: *ZigObject, elf_file: *Elf) !void {
481527pub fn updateArSymtab(self: ZigObject, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) error{OutOfMemory}!void {
482528 const gpa = elf_file.base.comp.gpa;
483529
484 try ar_symtab.symtab.ensureUnusedCapacity(gpa, self.globals().len);
530 try ar_symtab.symtab.ensureUnusedCapacity(gpa, self.global_symbols.items.len);
485531
486 for (self.globals()) |global_index| {
487 const global = elf_file.symbol(global_index);
488 const file_ptr = global.file(elf_file).?;
489 assert(file_ptr.index() == self.index);
532 for (self.global_symbols.items, 0..) |index, i| {
533 const global = self.symbols.items[index];
534 const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file);
535 const sym = elf_file.symbol(ref).?;
536 assert(sym.file(elf_file).?.index() == self.index);
490537 if (global.outputShndx(elf_file) == null) continue;
491538
492539 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 {
528575 }
529576}
530577
531inline fn isGlobal(index: Symbol.Index) bool {
532 return index & global_symbol_bit != 0;
533}
534
535pub 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
541pub 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
547pub fn locals(self: ZigObject) []const Symbol.Index {
548 return self.local_symbols.items;
549}
550
551pub fn globals(self: ZigObject) []const Symbol.Index {
552 return self.global_symbols.items;
553}
554
555578pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void {
556 for (self.locals()) |local_index| {
557 const local = elf_file.symbol(local_index);
579 for (self.local_symbols.items) |index| {
580 const local = &self.symbols.items[index];
558581 if (local.atom(elf_file)) |atom_ptr| if (!atom_ptr.alive) continue;
559582 const esym = local.elfSym(elf_file);
560583 switch (esym.st_type()) {
......@@ -562,22 +585,23 @@ pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void {
562585 else => {},
563586 }
564587 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);
566589 self.output_symtab_ctx.nlocals += 1;
567590 self.output_symtab_ctx.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1;
568591 }
569592
570 for (self.globals()) |global_index| {
571 const global = elf_file.symbol(global_index);
572 const file_ptr = global.file(elf_file) orelse continue;
573 if (file_ptr.index() != self.index) continue;
593 for (self.global_symbols.items, self.symbols_resolver.items) |index, resolv| {
594 const global = &self.symbols.items[index];
595 const ref = elf_file.resolver.values.items[resolv - 1];
596 const ref_sym = elf_file.symbol(ref) orelse continue;
597 if (ref_sym.file(elf_file).?.index() != self.index) continue;
574598 if (global.atom(elf_file)) |atom_ptr| if (!atom_ptr.alive) continue;
575599 global.flags.output_symtab = true;
576600 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);
578602 self.output_symtab_ctx.nlocals += 1;
579603 } else {
580 try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
604 global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
581605 self.output_symtab_ctx.nglobals += 1;
582606 }
583607 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 {
585609}
586610
587611pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void {
588 for (self.locals()) |local_index| {
589 const local = elf_file.symbol(local_index);
612 for (self.local_symbols.items) |index| {
613 const local = &self.symbols.items[index];
590614 const idx = local.outputSymtabIndex(elf_file) orelse continue;
591615 const out_sym = &elf_file.symtab.items[idx];
592616 out_sym.st_name = @intCast(elf_file.strtab.items.len);
......@@ -595,10 +619,11 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void {
595619 local.setOutputSym(elf_file, out_sym);
596620 }
597621
598 for (self.globals()) |global_index| {
599 const global = elf_file.symbol(global_index);
600 const file_ptr = global.file(elf_file) orelse continue;
601 if (file_ptr.index() != self.index) continue;
622 for (self.global_symbols.items, self.symbols_resolver.items) |index, resolv| {
623 const global = self.symbols.items[index];
624 const ref = elf_file.resolver.values.items[resolv - 1];
625 const ref_sym = elf_file.symbol(ref) orelse continue;
626 if (ref_sym.file(elf_file).?.index() != self.index) continue;
602627 const idx = global.outputSymtabIndex(elf_file) orelse continue;
603628 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
604629 elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file));
......@@ -609,10 +634,6 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void {
609634 }
610635}
611636
612pub fn asFile(self: *ZigObject) File {
613 return .{ .zig_object = self };
614}
615
616637/// Returns atom's code.
617638/// Caller owns the memory.
618639pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
......@@ -645,13 +666,13 @@ pub fn getDeclVAddr(
645666 reloc_info: link.File.RelocInfo,
646667) !u64 {
647668 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);
649670 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).?;
651672 const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch);
652673 try parent_atom.addReloc(elf_file, .{
653674 .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,
655676 .r_addend = reloc_info.addend,
656677 });
657678 return @intCast(vaddr);
......@@ -664,13 +685,13 @@ pub fn getAnonDeclVAddr(
664685 reloc_info: link.File.RelocInfo,
665686) !u64 {
666687 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);
668689 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).?;
670691 const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch);
671692 try parent_atom.addReloc(elf_file, .{
672693 .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,
674695 .r_addend = reloc_info.addend,
675696 });
676697 return @intCast(vaddr);
......@@ -692,7 +713,7 @@ pub fn lowerAnonDecl(
692713 else => explicit_alignment,
693714 };
694715 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;
696717 if (decl_alignment.order(existing_alignment).compare(.lte))
697718 return .ok;
698719 }
......@@ -753,8 +774,8 @@ pub fn getOrCreateMetadataForLazySymbol(
753774 };
754775 switch (metadata.state.*) {
755776 .unused => {
756 const symbol_index = try self.newAtom(elf_file);
757 const sym = elf_file.symbol(symbol_index);
777 const symbol_index = try self.newSymbolWithAtom(gpa, 0);
778 const sym = self.symbol(symbol_index);
758779 sym.flags.needs_zig_got = true;
759780 metadata.symbol_index.* = symbol_index;
760781 },
......@@ -778,13 +799,10 @@ fn freeUnnamedConsts(self: *ZigObject, elf_file: *Elf, decl_index: InternPool.De
778799}
779800
780801fn freeDeclMetadata(self: *ZigObject, elf_file: *Elf, sym_index: Symbol.Index) void {
781 _ = self;
782 const gpa = elf_file.base.comp.gpa;
783 const sym = elf_file.symbol(sym_index);
802 const sym = self.symbol(sym_index);
784803 sym.atom(elf_file).?.free(elf_file);
785804 log.debug("adding %{d} to local symbols free list", .{sym_index});
786 elf_file.symbols_free_list.append(gpa, sym_index) catch {};
787 elf_file.symbols.items[sym_index] = .{};
805 self.symbols.items[sym_index] = .{};
788806 // TODO free GOT entry here
789807}
790808
......@@ -817,10 +835,10 @@ pub fn getOrCreateMetadataForDecl(
817835 const gop = try self.decls.getOrPut(gpa, decl_index);
818836 if (!gop.found_existing) {
819837 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);
821839 const mod = elf_file.base.comp.module.?;
822840 const decl = mod.declPtr(decl_index);
823 const sym = elf_file.symbol(symbol_index);
841 const sym = self.symbol(symbol_index);
824842 if (decl.getOwnedVariable(mod)) |variable| {
825843 if (variable.is_threadlocal and any_non_single_threaded) {
826844 sym.flags.is_tls = true;
......@@ -909,8 +927,8 @@ fn updateDeclCode(
909927 target_util.minFunctionAlignment(mod.getTarget()),
910928 );
911929
912 const sym = elf_file.symbol(sym_index);
913 const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index];
930 const sym = self.symbol(sym_index);
931 const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
914932 const atom_ptr = sym.atom(elf_file).?;
915933 const name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip));
916934
......@@ -940,7 +958,7 @@ fn updateDeclCode(
940958 if (!elf_file.base.isRelocatable()) {
941959 log.debug(" (writing new offset table entry)", .{});
942960 assert(sym.flags.has_zig_got);
943 const extra = sym.extra(elf_file).?;
961 const extra = sym.extra(elf_file);
944962 try elf_file.zig_got.writeOne(elf_file, extra.zig_got);
945963 }
946964 }
......@@ -1007,8 +1025,8 @@ fn updateTlv(
10071025
10081026 const required_alignment = decl.getAlignment(pt);
10091027
1010 const sym = elf_file.symbol(sym_index);
1011 const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index];
1028 const sym = self.symbol(sym_index);
1029 const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
10121030 const atom_ptr = sym.atom(elf_file).?;
10131031 const name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip));
10141032
......@@ -1064,7 +1082,7 @@ pub fn updateFunc(
10641082
10651083 const sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index);
10661084 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);
10681086
10691087 var code_buffer = std.ArrayList(u8).init(gpa);
10701088 defer code_buffer.deinit();
......@@ -1096,7 +1114,7 @@ pub fn updateFunc(
10961114 try self.updateDeclCode(elf_file, pt, decl_index, sym_index, shndx, code, elf.STT_FUNC);
10971115
10981116 if (decl_state) |*ds| {
1099 const sym = elf_file.symbol(sym_index);
1117 const sym = self.symbol(sym_index);
11001118 try self.dwarf.?.commitDeclState(
11011119 pt,
11021120 decl_index,
......@@ -1130,13 +1148,13 @@ pub fn updateDecl(
11301148 const variable = decl.getOwnedVariable(mod).?;
11311149 const name = decl.name.toSlice(&mod.intern_pool);
11321150 const lib_name = variable.lib_name.toSlice(&mod.intern_pool);
1133 const esym_index = try self.getGlobalSymbol(elf_file, name, lib_name);
1134 elf_file.symbol(self.symbol(esym_index)).flags.needs_got = true;
1151 const sym_index = try self.getGlobalSymbol(elf_file, name, lib_name);
1152 self.symbol(sym_index).flags.needs_got = true;
11351153 return;
11361154 }
11371155
11381156 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);
11401158
11411159 const gpa = elf_file.base.comp.gpa;
11421160 var code_buffer = std.ArrayList(u8).init(gpa);
......@@ -1174,7 +1192,7 @@ pub fn updateDecl(
11741192 try self.updateDeclCode(elf_file, pt, decl_index, sym_index, shndx, code, elf.STT_OBJECT);
11751193
11761194 if (decl_state) |*ds| {
1177 const sym = elf_file.symbol(sym_index);
1195 const sym = self.symbol(sym_index);
11781196 try self.dwarf.?.commitDeclState(
11791197 pt,
11801198 decl_index,
......@@ -1233,9 +1251,9 @@ fn updateLazySymbol(
12331251 .code => elf_file.zig_text_section_index.?,
12341252 .const_data => elf_file.zig_data_rel_ro_section_index.?,
12351253 };
1236 const local_sym = elf_file.symbol(symbol_index);
1254 const local_sym = self.symbol(symbol_index);
12371255 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];
12391257 local_esym.st_name = name_str_index;
12401258 local_esym.st_info |= elf.STT_OBJECT;
12411259 local_esym.st_size = code.len;
......@@ -1323,7 +1341,8 @@ fn lowerConst(
13231341 var code_buffer = std.ArrayList(u8).init(gpa);
13241342 defer code_buffer.deinit();
13251343
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);
13271346
13281347 const res = try codegen.generateSymbol(
13291348 &elf_file.base,
......@@ -1339,27 +1358,19 @@ fn lowerConst(
13391358 .fail => |em| return .{ .fail = em },
13401359 };
13411360
1342 const local_sym = elf_file.symbol(sym_index);
1343 const name_str_index = try self.strtab.insert(gpa, name);
1344 local_sym.name_offset = name_str_index;
1345 const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index];
1346 local_esym.st_name = name_str_index;
1361 const local_sym = self.symbol(sym_index);
1362 const local_esym = &self.symtab.items(.elf_sym)[local_sym.esym_index];
13471363 local_esym.st_info |= elf.STT_OBJECT;
13481364 local_esym.st_size = code.len;
13491365 const atom_ptr = local_sym.atom(elf_file).?;
13501366 atom_ptr.alive = true;
1351 atom_ptr.name_offset = name_str_index;
13521367 atom_ptr.alignment = required_alignment;
13531368 atom_ptr.size = code.len;
13541369 atom_ptr.output_section_index = output_section_index;
13551370
13561371 try atom_ptr.allocate(elf_file);
1357 // TODO rename and re-audit this method
13581372 errdefer self.freeDeclMetadata(elf_file, sym_index);
13591373
1360 local_sym.value = 0;
1361 local_esym.st_value = 0;
1362
13631374 const shdr = elf_file.shdrs.items[output_section_index];
13641375 const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
13651376 try elf_file.base.file.?.pwriteAll(code, file_offset);
......@@ -1401,9 +1412,9 @@ pub fn updateExports(
14011412 },
14021413 };
14031414 const sym_index = metadata.symbol_index;
1404 const esym_index = elf_file.symbol(sym_index).esym_index;
1405 const esym = self.local_esyms.items(.elf_sym)[esym_index];
1406 const esym_shndx = self.local_esyms.items(.shndx)[esym_index];
1415 const esym_index = self.symbol(sym_index).esym_index;
1416 const esym = self.symtab.items(.elf_sym)[esym_index];
1417 const esym_shndx = self.symtab.items(.shndx)[esym_index];
14071418
14081419 for (export_indices) |export_idx| {
14091420 const exp = mod.all_exports.items[export_idx];
......@@ -1437,22 +1448,27 @@ pub fn updateExports(
14371448 const stt_bits: u8 = @as(u4, @truncate(esym.st_info));
14381449 const exp_name = exp.opts.name.toSlice(&mod.intern_pool);
14391450 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|
14411452 exp_index.*
14421453 else blk: {
1443 const global_esym_index = try self.getGlobalSymbol(elf_file, exp_name, null);
1444 try metadata.exports.append(gpa, global_esym_index);
1445 break :blk global_esym_index;
1454 const global_sym_index = try self.getGlobalSymbol(elf_file, exp_name, null);
1455 try metadata.exports.append(gpa, global_sym_index);
1456 break :blk global_sym_index;
14461457 };
14471458
1448 const actual_esym_index = global_esym_index & symbol_mask;
1449 const global_esym = &self.global_esyms.items(.elf_sym)[actual_esym_index];
1450 global_esym.st_value = @intCast(elf_file.symbol(sym_index).value);
1459 const value = self.symbol(sym_index).value;
1460 const global_sym = self.symbol(global_sym_index);
1461 global_sym.value = value;
1462 global_sym.flags.weak = exp.opts.linkage == .weak;
1463 global_sym.version_index = elf_file.default_sym_version;
1464 global_sym.ref = .{ .index = esym_shndx, .file = self.index };
1465 const global_esym = &self.symtab.items(.elf_sym)[global_sym.esym_index];
1466 global_esym.st_value = @intCast(value);
14511467 global_esym.st_shndx = esym.st_shndx;
14521468 global_esym.st_info = (stb_bits << 4) | stt_bits;
14531469 global_esym.st_name = name_off;
14541470 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;
14561472 }
14571473}
14581474
......@@ -1488,16 +1504,10 @@ pub fn deleteExport(
14881504 const exp_name = name.toSlice(&mod.intern_pool);
14891505 const esym_index = metadata.@"export"(self, exp_name) orelse return;
14901506 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.*];
14921508 _ = 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 }
14991509 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;
15011511}
15021512
15031513pub 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
15061516 const off = try self.strtab.insert(gpa, name);
15071517 const lookup_gop = try self.globals_lookup.getOrPut(gpa, off);
15081518 if (!lookup_gop.found_existing) {
1509 const esym_index = try self.addGlobalEsym(gpa);
1510 const esym = self.elfSym(esym_index);
1511 esym.st_name = off;
1512 lookup_gop.value_ptr.* = esym_index;
1513 const gop = try elf_file.getOrPutGlobal(name);
1514 try self.global_symbols.append(gpa, gop.index);
1519 lookup_gop.value_ptr.* = try self.newGlobalSymbol(gpa, off);
15151520 }
15161521 return lookup_gop.value_ptr.*;
15171522}
15181523
1524pub fn asFile(self: *ZigObject) File {
1525 return .{ .zig_object = self };
1526}
1527
1528fn addString(self: *ZigObject, allocator: Allocator, string: []const u8) !u32 {
1529 return self.strtab.insert(allocator, string);
1530}
1531
15191532pub fn getString(self: ZigObject, off: u32) [:0]const u8 {
15201533 return self.strtab.getAssumeExists(off);
15211534}
......@@ -1586,6 +1599,77 @@ pub fn setAtomExtra(self: *ZigObject, index: u32, extra: Atom.Extra) void {
15861599 }
15871600}
15881601
1602inline fn isGlobal(index: Symbol.Index) bool {
1603 return index & global_symbol_bit != 0;
1604}
1605
1606pub 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
1612pub 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
1620fn addSymbol(self: *ZigObject, allocator: Allocator) !Symbol.Index {
1621 try self.symbols.ensureUnusedCapacity(allocator, 1);
1622 return self.addSymbolAssumeCapacity();
1623}
1624
1625fn 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
1631pub 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
1637pub 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
1649pub 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
1663pub 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
15891673pub fn fmtSymtab(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {
15901674 return .{ .data = .{
15911675 .self = self,
......@@ -1606,15 +1690,17 @@ fn formatSymtab(
16061690) !void {
16071691 _ = unused_fmt_string;
16081692 _ = options;
1693 const self = ctx.self;
1694 const elf_file = ctx.elf_file;
16091695 try writer.writeAll(" locals\n");
1610 for (ctx.self.locals()) |index| {
1611 const local = ctx.elf_file.symbol(index);
1612 try writer.print(" {}\n", .{local.fmt(ctx.elf_file)});
1696 for (self.local_symbols.items) |index| {
1697 const local = self.symbols.items[index];
1698 try writer.print(" {}\n", .{local.fmt(elf_file)});
16131699 }
16141700 try writer.writeAll(" globals\n");
1615 for (ctx.self.globals()) |index| {
1616 const global = ctx.elf_file.symbol(index);
1617 try writer.print(" {}\n", .{global.fmt(ctx.elf_file)});
1701 for (ctx.self.global_symbols.items) |index| {
1702 const global = self.symbols.items[index];
1703 try writer.print(" {}\n", .{global.fmt(elf_file)});
16181704 }
16191705}
16201706
......@@ -1658,9 +1744,9 @@ const DeclMetadata = struct {
16581744 /// A list of all exports aliases of this Decl.
16591745 exports: std.ArrayListUnmanaged(Symbol.Index) = .{},
16601746
1661 fn @"export"(m: DeclMetadata, zig_object: *ZigObject, name: []const u8) ?*u32 {
1747 fn @"export"(m: DeclMetadata, zo: *ZigObject, name: []const u8) ?*u32 {
16621748 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);
16641750 if (mem.eql(u8, name, exp_name)) return exp;
16651751 }
16661752 return null;
src/link/Elf/eh_frame.zig+13-8
......@@ -145,10 +145,10 @@ pub const Cie = struct {
145145 if (cie_rel.r_addend != other_rel.r_addend) return false;
146146
147147 const cie_object = elf_file.file(cie.file_index).?.object;
148 const cie_ref = cie_object.resolveSymbol(cie_rel.r_sym(), elf_file);
148149 const other_object = elf_file.file(other.file_index).?.object;
149 const cie_sym = cie_object.symbols.items[cie_rel.r_sym()];
150 const other_sym = other_object.symbols.items[other_rel.r_sym()];
151 if (!std.mem.eql(u8, std.mem.asBytes(&cie_sym), std.mem.asBytes(&other_sym))) return false;
150 const other_ref = other_object.resolveSymbol(other_rel.r_sym(), elf_file);
151 if (!cie_ref.eql(other_ref)) return false;
152152 }
153153 return true;
154154 }
......@@ -339,7 +339,8 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
339339 const contents = cie.data(elf_file);
340340
341341 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).?;
343344 resolveReloc(cie, sym, rel, elf_file, contents) catch |err| switch (err) {
344345 error.RelocFailure => has_reloc_errors = true,
345346 else => |e| return e,
......@@ -366,7 +367,8 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
366367 );
367368
368369 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).?;
370372 resolveReloc(fde, sym, rel, elf_file, contents) catch |err| switch (err) {
371373 error.RelocFailure => has_reloc_errors = true,
372374 else => |e| return e,
......@@ -452,7 +454,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
452454 for (object.cies.items) |cie| {
453455 if (!cie.alive) continue;
454456 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).?;
456459 const out_rel = emitReloc(elf_file, cie, sym, rel);
457460 try writer.writeStruct(out_rel);
458461 }
......@@ -461,7 +464,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
461464 for (object.fdes.items) |fde| {
462465 if (!fde.alive) continue;
463466 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).?;
465469 const out_rel = emitReloc(elf_file, fde, sym, rel);
466470 try writer.writeStruct(out_rel);
467471 }
......@@ -513,7 +517,8 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
513517 const relocs = fde.relocs(elf_file);
514518 assert(relocs.len > 0); // Should this be an error? Things are completely broken anyhow if this trips...
515519 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).?;
517522 const P = @as(i64, @intCast(fde.address(elf_file)));
518523 const S = @as(i64, @intCast(sym.address(.{}, elf_file)));
519524 const A = rel.r_addend;
src/link/Elf/file.zig+80-25
......@@ -61,20 +61,10 @@ pub const File = union(enum) {
6161 return (@as(u32, base) << 24) + file.index();
6262 }
6363
64 pub fn resolveSymbols(file: File, elf_file: *Elf) void {
65 switch (file) {
64 pub fn resolveSymbols(file: File, elf_file: *Elf) !void {
65 return switch (file) {
6666 inline else => |x| x.resolveSymbols(elf_file),
67 }
68 }
69
70 pub fn resetGlobals(file: File, elf_file: *Elf) void {
71 for (file.globals()) |global_index| {
72 const global = elf_file.symbol(global_index);
73 const name_offset = global.name_offset;
74 global.* = .{};
75 global.name_offset = name_offset;
76 global.flags.global = true;
77 }
67 };
7868 }
7969
8070 pub fn setAlive(file: File) void {
......@@ -98,6 +88,77 @@ pub const File = union(enum) {
9888 }
9989 }
10090
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
101162 pub fn atom(file: File, atom_index: Atom.Index) ?*Atom {
102163 return switch (file) {
103164 .shared_object => unreachable,
......@@ -144,23 +205,16 @@ pub const File = union(enum) {
144205 };
145206 }
146207
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 {
148209 return switch (file) {
149 .zig_object => |x| x.symbol(ind),
150 inline else => |x| x.symbols.items[ind],
210 inline else => |x| x.resolveSymbol(ind, elf_file),
151211 };
152212 }
153213
154 pub fn locals(file: File) []const Symbol.Index {
214 pub fn symbol(file: File, ind: Symbol.Index) *Symbol {
155215 return switch (file) {
156 .linker_defined, .shared_object => &[0]Symbol.Index{},
157 inline else => |x| x.locals(),
158 };
159 }
160
161 pub fn globals(file: File) []const Symbol.Index {
162 return switch (file) {
163 inline else => |x| x.globals(),
216 .zig_object => |x| x.symbol(ind),
217 inline else => |x| &x.symbols.items[ind],
164218 };
165219 }
166220
......@@ -237,6 +291,7 @@ pub const File = union(enum) {
237291
238292const std = @import("std");
239293const elf = std.elf;
294const log = std.log.scoped(.link);
240295
241296const Allocator = std.mem.Allocator;
242297const Archive = @import("Archive.zig");
src/link/Elf/gc.zig+81-58
......@@ -1,71 +1,84 @@
11pub fn gcAtoms(elf_file: *Elf) !void {
22 const comp = elf_file.base.comp;
33 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
104 var roots = std.ArrayList(*Atom).init(gpa);
115 defer roots.deinit();
12 try collectRoots(&roots, files.items, elf_file);
13
6 try collectRoots(&roots, elf_file);
147 mark(roots, elf_file);
15 prune(files.items, elf_file);
8 prune(elf_file);
169}
1710
18fn collectRoots(roots: *std.ArrayList(*Atom), files: []const File.Index, elf_file: *Elf) !void {
11fn collectRoots(roots: *std.ArrayList(*Atom), elf_file: *Elf) !void {
1912 if (elf_file.linkerDefinedPtr()) |obj| {
20 if (obj.entry_index) |index| {
21 const global = elf_file.symbol(index);
22 try markSymbol(global, roots, elf_file);
13 if (obj.entrySymbol(elf_file)) |sym| {
14 try markSymbol(sym, roots, elf_file);
2315 }
2416 }
2517
26 for (files) |index| {
27 for (elf_file.file(index).?.globals()) |global_index| {
28 const global = elf_file.symbol(global_index);
29 if (global.file(elf_file)) |file| {
30 if (file.index() == index and global.flags.@"export")
31 try markSymbol(global, roots, elf_file);
18 if (elf_file.zigObjectPtr()) |zo| {
19 for (0..zo.global_symbols.items.len) |i| {
20 const ref = zo.resolveSymbol(@intCast(i | ZigObject.global_symbol_bit), elf_file);
21 const sym = elf_file.symbol(ref) orelse continue;
22 if (sym.file(elf_file).?.index() != zo.index) continue;
23 if (sym.flags.@"export") {
24 try markSymbol(sym, roots, elf_file);
3225 }
3326 }
3427 }
3528
36 for (files) |index| {
37 const file = elf_file.file(index).?;
38
39 for (file.atoms()) |atom_index| {
40 const atom = file.atom(atom_index) orelse continue;
41 if (!atom.alive) continue;
42
43 const shdr = atom.inputShdr(elf_file);
44 const name = atom.name(elf_file);
45 const is_gc_root = blk: {
46 if (shdr.sh_flags & elf.SHF_GNU_RETAIN != 0) break :blk true;
47 if (shdr.sh_type == elf.SHT_NOTE) break :blk true;
48 if (shdr.sh_type == elf.SHT_PREINIT_ARRAY) break :blk true;
49 if (shdr.sh_type == elf.SHT_INIT_ARRAY) break :blk true;
50 if (shdr.sh_type == elf.SHT_FINI_ARRAY) break :blk true;
51 if (mem.startsWith(u8, name, ".ctors")) break :blk true;
52 if (mem.startsWith(u8, name, ".dtors")) break :blk true;
53 if (mem.startsWith(u8, name, ".init")) break :blk true;
54 if (mem.startsWith(u8, name, ".fini")) break :blk true;
55 if (Elf.isCIdentifier(name)) break :blk true;
56 break :blk false;
57 };
58 if (is_gc_root and markAtom(atom)) try roots.append(atom);
59 if (shdr.sh_flags & elf.SHF_ALLOC == 0) atom.visited = true;
29 for (elf_file.objects.items) |index| {
30 const object = elf_file.file(index).?.object;
31 for (0..object.globals().len) |i| {
32 const ref = object.resolveSymbol(@intCast(i), elf_file);
33 const sym = elf_file.symbol(ref) orelse continue;
34 if (sym.file(elf_file).?.index() != object.index) continue;
35 if (sym.flags.@"export") {
36 try markSymbol(sym, roots, elf_file);
37 }
6038 }
39 }
6140
62 // Mark every atom referenced by CIE as alive.
63 for (file.cies()) |cie| {
64 for (cie.relocs(elf_file)) |rel| {
65 const sym = elf_file.symbol(file.symbol(rel.r_sym()));
66 try markSymbol(sym, roots, elf_file);
41 const atomRoots = struct {
42 fn atomRoots(file: File, rs: anytype, ef: *Elf) !void {
43 for (file.atoms()) |atom_index| {
44 const atom = file.atom(atom_index) orelse continue;
45 if (!atom.alive) continue;
46
47 const shdr = atom.inputShdr(ef);
48 const name = atom.name(ef);
49 const is_gc_root = blk: {
50 if (shdr.sh_flags & elf.SHF_GNU_RETAIN != 0) break :blk true;
51 if (shdr.sh_type == elf.SHT_NOTE) break :blk true;
52 if (shdr.sh_type == elf.SHT_PREINIT_ARRAY) break :blk true;
53 if (shdr.sh_type == elf.SHT_INIT_ARRAY) break :blk true;
54 if (shdr.sh_type == elf.SHT_FINI_ARRAY) break :blk true;
55 if (mem.startsWith(u8, name, ".ctors")) break :blk true;
56 if (mem.startsWith(u8, name, ".dtors")) break :blk true;
57 if (mem.startsWith(u8, name, ".init")) break :blk true;
58 if (mem.startsWith(u8, name, ".fini")) break :blk true;
59 if (Elf.isCIdentifier(name)) break :blk true;
60 break :blk false;
61 };
62 if (is_gc_root and markAtom(atom)) try rs.append(atom);
63 if (shdr.sh_flags & elf.SHF_ALLOC == 0) atom.visited = true;
64 }
65
66 // Mark every atom referenced by CIE as alive.
67 for (file.cies()) |cie| {
68 for (cie.relocs(ef)) |rel| {
69 const ref = file.resolveSymbol(rel.r_sym(), ef);
70 const sym = ef.symbol(ref) orelse continue;
71 try markSymbol(sym, rs, ef);
72 }
6773 }
6874 }
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);
6982 }
7083}
7184
......@@ -92,7 +105,8 @@ fn markLive(atom: *Atom, elf_file: *Elf) void {
92105
93106 for (atom.fdes(elf_file)) |fde| {
94107 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;
96110 const target_atom = target_sym.atom(elf_file) orelse continue;
97111 target_atom.alive = true;
98112 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 {
101115 }
102116
103117 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;
105120 if (target_sym.mergeSubsection(elf_file)) |msub| {
106121 msub.alive = true;
107122 continue;
......@@ -120,16 +135,23 @@ fn mark(roots: std.ArrayList(*Atom), elf_file: *Elf) void {
120135 }
121136}
122137
123fn prune(files: []const File.Index, elf_file: *Elf) void {
124 for (files) |index| {
125 const file = elf_file.file(index).?;
126 for (file.atoms()) |atom_index| {
127 const atom = file.atom(atom_index) orelse continue;
128 if (atom.alive and !atom.visited) {
129 atom.alive = false;
130 atom.markFdesDead(elf_file);
138fn prune(elf_file: *Elf) void {
139 const pruneInFile = struct {
140 fn pruneInFile(file: File, ef: *Elf) void {
141 for (file.atoms()) |atom_index| {
142 const atom = file.atom(atom_index) orelse continue;
143 if (atom.alive and !atom.visited) {
144 atom.alive = false;
145 atom.markFdesDead(ef);
146 }
131147 }
132148 }
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);
133155 }
134156}
135157
......@@ -181,3 +203,4 @@ const Atom = @import("Atom.zig");
181203const Elf = @import("../Elf.zig");
182204const File = @import("file.zig").File;
183205const Symbol = @import("Symbol.zig");
206const 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
3737
3838 // First, we flush relocatable object file generated with our backends.
3939 if (elf_file.zigObjectPtr()) |zig_object| {
40 zig_object.resolveSymbols(elf_file);
40 try zig_object.resolveSymbols(elf_file);
4141 try elf_file.addCommentString();
4242 try elf_file.finalizeMergeSections();
4343 zig_object.claimUnresolvedObject(elf_file);
......@@ -383,7 +383,7 @@ fn updateComdatGroupsSizes(elf_file: *Elf) void {
383383 shdr.sh_size = cg.size(elf_file);
384384 shdr.sh_link = elf_file.symtab_section_index.?;
385385
386 const sym = elf_file.symbol(cg.symbol(elf_file));
386 const sym = cg.symbol(elf_file);
387387 shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse
388388 elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx(elf_file).?);
389389 }
src/link/Elf/synthetic_sections.zig+130-135
......@@ -251,15 +251,16 @@ pub const ZigGotSection = struct {
251251 pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index {
252252 const comp = elf_file.base.comp;
253253 const gpa = comp.gpa;
254 const zo = elf_file.zigObjectPtr().?;
254255 const index = try zig_got.allocateEntry(gpa);
255256 const entry = &zig_got.entries.items[index];
256257 entry.* = sym_index;
257 const symbol = elf_file.symbol(sym_index);
258 const symbol = zo.symbol(sym_index);
258259 symbol.flags.has_zig_got = true;
259260 if (elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) {
260261 zig_got.flags.needs_rela = true;
261262 }
262 try symbol.addExtra(.{ .zig_got = index }, elf_file);
263 symbol.addExtra(.{ .zig_got = index }, elf_file);
263264 return index;
264265 }
265266
......@@ -282,6 +283,7 @@ pub const ZigGotSection = struct {
282283 }
283284
284285 pub fn writeOne(zig_got: *ZigGotSection, elf_file: *Elf, index: Index) !void {
286 const zo = elf_file.zigObjectPtr().?;
285287 if (zig_got.flags.dirty) {
286288 const needed_size = zig_got.size(elf_file);
287289 try elf_file.growAllocSection(elf_file.zig_got_section_index.?, needed_size);
......@@ -293,7 +295,7 @@ pub const ZigGotSection = struct {
293295 const off = zig_got.entryOffset(index, elf_file);
294296 const vaddr: u64 = @intCast(zig_got.entryAddress(index, elf_file));
295297 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);
297299 switch (entry_size) {
298300 2 => {
299301 var buf: [2]u8 = undefined;
......@@ -336,8 +338,9 @@ pub const ZigGotSection = struct {
336338 }
337339
338340 pub fn writeAll(zig_got: ZigGotSection, elf_file: *Elf, writer: anytype) !void {
341 const zo = elf_file.zigObjectPtr().?;
339342 for (zig_got.entries.items) |entry| {
340 const symbol = elf_file.symbol(entry);
343 const symbol = zo.symbol(entry);
341344 const value = symbol.address(.{ .plt = false }, elf_file);
342345 try writeInt(value, elf_file, writer);
343346 }
......@@ -351,9 +354,10 @@ pub const ZigGotSection = struct {
351354 const comp = elf_file.base.comp;
352355 const gpa = comp.gpa;
353356 const cpu_arch = elf_file.getTarget().cpu.arch;
357 const zo = elf_file.zigObjectPtr().?;
354358 try elf_file.rela_dyn.ensureUnusedCapacity(gpa, zig_got.numRela());
355359 for (zig_got.entries.items) |entry| {
356 const symbol = elf_file.symbol(entry);
360 const symbol = zo.symbol(entry);
357361 const offset = symbol.zigGotAddress(elf_file);
358362 elf_file.addRelaDynAssumeCapacity(.{
359363 .offset = @intCast(offset),
......@@ -364,16 +368,18 @@ pub const ZigGotSection = struct {
364368 }
365369
366370 pub fn updateSymtabSize(zig_got: *ZigGotSection, elf_file: *Elf) void {
371 const zo = elf_file.zigObjectPtr().?;
367372 zig_got.output_symtab_ctx.nlocals = @as(u32, @intCast(zig_got.entries.items.len));
368373 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);
370375 zig_got.output_symtab_ctx.strsize += @as(u32, @intCast(name.len + "$ziggot".len)) + 1;
371376 }
372377 }
373378
374379 pub fn writeSymtab(zig_got: ZigGotSection, elf_file: *Elf) void {
380 const zo = elf_file.zigObjectPtr().?;
375381 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);
377383 const symbol_name = symbol.name(elf_file);
378384 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
379385 elf_file.strtab.appendSliceAssumeCapacity(symbol_name);
......@@ -409,15 +415,18 @@ pub const ZigGotSection = struct {
409415 ) !void {
410416 _ = options;
411417 _ = unused_fmt_string;
418 const zig_got = ctx.zig_got;
419 const elf_file = ctx.elf_file;
412420 try writer.writeAll(".zig.got\n");
413 for (ctx.zig_got.entries.items, 0..) |entry, index| {
414 const symbol = ctx.elf_file.symbol(entry);
421 for (zig_got.entries.items, 0..) |entry, index| {
422 const zo = elf_file.zigObjectPtr().?;
423 const symbol = zo.symbol(entry);
415424 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
416425 index,
417 ctx.zig_got.entryAddress(@intCast(index), ctx.elf_file),
426 zig_got.entryAddress(@intCast(index), elf_file),
418427 entry,
419 symbol.address(.{}, ctx.elf_file),
420 symbol.name(ctx.elf_file),
428 symbol.address(.{}, elf_file),
429 symbol.name(elf_file),
421430 });
422431 }
423432 }
......@@ -446,7 +455,7 @@ pub const GotSection = struct {
446455
447456 const Entry = struct {
448457 tag: Tag,
449 symbol_index: Symbol.Index,
458 ref: Elf.Ref,
450459 cell_index: Index,
451460
452461 /// Returns how many indexes in the GOT this entry uses.
......@@ -477,25 +486,25 @@ pub const GotSection = struct {
477486 const last = got.entries.items[index - 1];
478487 break :blk last.cell_index + @as(Index, @intCast(last.len()));
479488 } else 0;
480 entry.* = .{ .tag = undefined, .symbol_index = undefined, .cell_index = cell_index };
489 entry.* = .{ .tag = undefined, .ref = undefined, .cell_index = cell_index };
481490 return index;
482491 }
483492
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 {
485494 const comp = elf_file.base.comp;
486495 const gpa = comp.gpa;
487496 const index = try got.allocateEntry(gpa);
488497 const entry = &got.entries.items[index];
489498 entry.tag = .got;
490 entry.symbol_index = sym_index;
491 const symbol = elf_file.symbol(sym_index);
499 entry.ref = ref;
500 const symbol = elf_file.symbol(ref).?;
492501 symbol.flags.has_got = true;
493502 if (symbol.flags.import or symbol.isIFunc(elf_file) or
494503 ((elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) and !symbol.isAbs(elf_file)))
495504 {
496505 got.flags.needs_rela = true;
497506 }
498 try symbol.addExtra(.{ .got = index }, elf_file);
507 symbol.addExtra(.{ .got = index }, elf_file);
499508 return index;
500509 }
501510
......@@ -506,48 +515,48 @@ pub const GotSection = struct {
506515 const index = try got.allocateEntry(gpa);
507516 const entry = &got.entries.items[index];
508517 entry.tag = .tlsld;
509 entry.symbol_index = undefined; // unused
518 entry.ref = .{ .index = 0, .file = 0 }; // unused
510519 got.flags.needs_rela = true;
511520 got.tlsld_index = index;
512521 }
513522
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 {
515524 const comp = elf_file.base.comp;
516525 const gpa = comp.gpa;
517526 const index = try got.allocateEntry(gpa);
518527 const entry = &got.entries.items[index];
519528 entry.tag = .tlsgd;
520 entry.symbol_index = sym_index;
521 const symbol = elf_file.symbol(sym_index);
529 entry.ref = ref;
530 const symbol = elf_file.symbol(ref).?;
522531 symbol.flags.has_tlsgd = true;
523532 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);
525534 }
526535
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 {
528537 const comp = elf_file.base.comp;
529538 const gpa = comp.gpa;
530539 const index = try got.allocateEntry(gpa);
531540 const entry = &got.entries.items[index];
532541 entry.tag = .gottp;
533 entry.symbol_index = sym_index;
534 const symbol = elf_file.symbol(sym_index);
542 entry.ref = ref;
543 const symbol = elf_file.symbol(ref).?;
535544 symbol.flags.has_gottp = true;
536545 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);
538547 }
539548
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 {
541550 const comp = elf_file.base.comp;
542551 const gpa = comp.gpa;
543552 const index = try got.allocateEntry(gpa);
544553 const entry = &got.entries.items[index];
545554 entry.tag = .tlsdesc;
546 entry.symbol_index = sym_index;
547 const symbol = elf_file.symbol(sym_index);
555 entry.ref = ref;
556 const symbol = elf_file.symbol(ref).?;
548557 symbol.flags.has_tlsdesc = true;
549558 got.flags.needs_rela = true;
550 try symbol.addExtra(.{ .tlsdesc = index }, elf_file);
559 symbol.addExtra(.{ .tlsdesc = index }, elf_file);
551560 }
552561
553562 pub fn size(got: GotSection, elf_file: *Elf) usize {
......@@ -564,10 +573,7 @@ pub const GotSection = struct {
564573 const apply_relocs = true; // TODO add user option for this
565574
566575 for (got.entries.items) |entry| {
567 const symbol = switch (entry.tag) {
568 .tlsld => null,
569 inline else => elf_file.symbol(entry.symbol_index),
570 };
576 const symbol = elf_file.symbol(entry.ref);
571577 switch (entry.tag) {
572578 .got => {
573579 const value = blk: {
......@@ -637,11 +643,8 @@ pub const GotSection = struct {
637643 try elf_file.rela_dyn.ensureUnusedCapacity(gpa, got.numRela(elf_file));
638644
639645 for (got.entries.items) |entry| {
640 const symbol = switch (entry.tag) {
641 .tlsld => null,
642 inline else => elf_file.symbol(entry.symbol_index),
643 };
644 const extra = if (symbol) |s| s.extra(elf_file).? else null;
646 const symbol = elf_file.symbol(entry.ref);
647 const extra = if (symbol) |s| s.extra(elf_file) else null;
645648
646649 switch (entry.tag) {
647650 .got => {
......@@ -740,10 +743,7 @@ pub const GotSection = struct {
740743 const is_dyn_lib = elf_file.isEffectivelyDynLib();
741744 var num: usize = 0;
742745 for (got.entries.items) |entry| {
743 const symbol = switch (entry.tag) {
744 .tlsld => null,
745 inline else => elf_file.symbol(entry.symbol_index),
746 };
746 const symbol = elf_file.symbol(entry.ref);
747747 switch (entry.tag) {
748748 .got => if (symbol.?.flags.import or symbol.?.isIFunc(elf_file) or
749749 ((elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) and
......@@ -775,24 +775,15 @@ pub const GotSection = struct {
775775 pub fn updateSymtabSize(got: *GotSection, elf_file: *Elf) void {
776776 got.output_symtab_ctx.nlocals = @as(u32, @intCast(got.entries.items.len));
777777 for (got.entries.items) |entry| {
778 const symbol_name = switch (entry.tag) {
779 .tlsld => "",
780 inline else => elf_file.symbol(entry.symbol_index).name(elf_file),
781 };
778 const symbol_name = if (elf_file.symbol(entry.ref)) |sym| sym.name(elf_file) else "";
782779 got.output_symtab_ctx.strsize += @as(u32, @intCast(symbol_name.len + @tagName(entry.tag).len)) + 1 + 1;
783780 }
784781 }
785782
786783 pub fn writeSymtab(got: GotSection, elf_file: *Elf) void {
787784 for (got.entries.items, got.output_symtab_ctx.ilocal..) |entry, ilocal| {
788 const symbol = switch (entry.tag) {
789 .tlsld => null,
790 inline else => elf_file.symbol(entry.symbol_index),
791 };
792 const symbol_name = switch (entry.tag) {
793 .tlsld => "",
794 inline else => symbol.?.name(elf_file),
795 };
785 const symbol = elf_file.symbol(entry.ref);
786 const symbol_name = if (symbol) |s| s.name(elf_file) else "";
796787 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
797788 elf_file.strtab.appendSliceAssumeCapacity(symbol_name);
798789 elf_file.strtab.appendAssumeCapacity('$');
......@@ -828,36 +819,38 @@ pub const GotSection = struct {
828819 ) !void {
829820 _ = options;
830821 _ = unused_fmt_string;
822 const got = ctx.got;
823 const elf_file = ctx.elf_file;
831824 try writer.writeAll("GOT\n");
832 for (ctx.got.entries.items) |entry| {
833 const symbol = ctx.elf_file.symbol(entry.symbol_index);
834 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
825 for (got.entries.items) |entry| {
826 const symbol = elf_file.symbol(entry.ref).?;
827 try writer.print(" {d}@0x{x} => {}@0x{x} ({s})\n", .{
835828 entry.cell_index,
836 entry.address(ctx.elf_file),
837 entry.symbol_index,
838 symbol.address(.{}, ctx.elf_file),
839 symbol.name(ctx.elf_file),
829 entry.address(elf_file),
830 entry.ref,
831 symbol.address(.{}, elf_file),
832 symbol.name(elf_file),
840833 });
841834 }
842835 }
843836};
844837
845838pub const PltSection = struct {
846 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
839 symbols: std.ArrayListUnmanaged(Elf.Ref) = .{},
847840 output_symtab_ctx: Elf.SymtabCtx = .{},
848841
849842 pub fn deinit(plt: *PltSection, allocator: Allocator) void {
850843 plt.symbols.deinit(allocator);
851844 }
852845
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 {
854847 const comp = elf_file.base.comp;
855848 const gpa = comp.gpa;
856849 const index = @as(u32, @intCast(plt.symbols.items.len));
857 const symbol = elf_file.symbol(sym_index);
850 const symbol = elf_file.symbol(ref).?;
858851 symbol.flags.has_plt = true;
859 try symbol.addExtra(.{ .plt = index }, elf_file);
860 try plt.symbols.append(gpa, sym_index);
852 symbol.addExtra(.{ .plt = index }, elf_file);
853 try plt.symbols.append(gpa, ref);
861854 }
862855
863856 pub fn size(plt: PltSection, elf_file: *Elf) usize {
......@@ -895,10 +888,10 @@ pub const PltSection = struct {
895888 const gpa = comp.gpa;
896889 const cpu_arch = elf_file.getTarget().cpu.arch;
897890 try elf_file.rela_plt.ensureUnusedCapacity(gpa, plt.numRela());
898 for (plt.symbols.items) |sym_index| {
899 const sym = elf_file.symbol(sym_index);
891 for (plt.symbols.items) |ref| {
892 const sym = elf_file.symbol(ref).?;
900893 assert(sym.flags.import);
901 const extra = sym.extra(elf_file).?;
894 const extra = sym.extra(elf_file);
902895 const r_offset: u64 = @intCast(sym.gotPltAddress(elf_file));
903896 const r_sym: u64 = extra.dynamic;
904897 const r_type = relocation.encode(.jump_slot, cpu_arch);
......@@ -916,16 +909,16 @@ pub const PltSection = struct {
916909
917910 pub fn updateSymtabSize(plt: *PltSection, elf_file: *Elf) void {
918911 plt.output_symtab_ctx.nlocals = @as(u32, @intCast(plt.symbols.items.len));
919 for (plt.symbols.items) |sym_index| {
920 const name = elf_file.symbol(sym_index).name(elf_file);
912 for (plt.symbols.items) |ref| {
913 const name = elf_file.symbol(ref).?.name(elf_file);
921914 plt.output_symtab_ctx.strsize += @as(u32, @intCast(name.len + "$plt".len)) + 1;
922915 }
923916 }
924917
925918 pub fn writeSymtab(plt: PltSection, elf_file: *Elf) void {
926919 const cpu_arch = elf_file.getTarget().cpu.arch;
927 for (plt.symbols.items, plt.output_symtab_ctx.ilocal..) |sym_index, ilocal| {
928 const sym = elf_file.symbol(sym_index);
920 for (plt.symbols.items, plt.output_symtab_ctx.ilocal..) |ref, ilocal| {
921 const sym = elf_file.symbol(ref).?;
929922 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
930923 elf_file.strtab.appendSliceAssumeCapacity(sym.name(elf_file));
931924 elf_file.strtab.appendSliceAssumeCapacity("$plt");
......@@ -958,15 +951,17 @@ pub const PltSection = struct {
958951 ) !void {
959952 _ = options;
960953 _ = unused_fmt_string;
954 const plt = ctx.plt;
955 const elf_file = ctx.elf_file;
961956 try writer.writeAll("PLT\n");
962 for (ctx.plt.symbols.items, 0..) |symbol_index, i| {
963 const symbol = ctx.elf_file.symbol(symbol_index);
964 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
957 for (plt.symbols.items, 0..) |ref, i| {
958 const symbol = elf_file.symbol(ref).?;
959 try writer.print(" {d}@0x{x} => {}@0x{x} ({s})\n", .{
965960 i,
966 symbol.pltAddress(ctx.elf_file),
967 symbol_index,
968 symbol.address(.{}, ctx.elf_file),
969 symbol.name(ctx.elf_file),
961 symbol.pltAddress(elf_file),
962 ref,
963 symbol.address(.{}, elf_file),
964 symbol.name(elf_file),
970965 });
971966 }
972967 }
......@@ -988,8 +983,8 @@ pub const PltSection = struct {
988983 try writer.writeAll(&preamble);
989984 try writer.writeByteNTimes(0xcc, preambleSize(.x86_64) - preamble.len);
990985
991 for (plt.symbols.items, 0..) |sym_index, i| {
992 const sym = elf_file.symbol(sym_index);
986 for (plt.symbols.items, 0..) |ref, i| {
987 const sym = elf_file.symbol(ref).?;
993988 const target_addr = sym.gotPltAddress(elf_file);
994989 const source_addr = sym.pltAddress(elf_file);
995990 disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 12)) - 4;
......@@ -1037,8 +1032,8 @@ pub const PltSection = struct {
10371032 }
10381033 }
10391034
1040 for (plt.symbols.items) |sym_index| {
1041 const sym = elf_file.symbol(sym_index);
1035 for (plt.symbols.items) |ref| {
1036 const sym = elf_file.symbol(ref).?;
10421037 const target_addr = sym.gotPltAddress(elf_file);
10431038 const source_addr = sym.pltAddress(elf_file);
10441039 const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);
......@@ -1075,7 +1070,7 @@ pub const GotPltSection = struct {
10751070 _ = got_plt;
10761071 {
10771072 // [0]: _DYNAMIC
1078 const symbol = elf_file.symbol(elf_file.linkerDefinedPtr().?.dynamic_index.?);
1073 const symbol = elf_file.linkerDefinedPtr().?.dynamicSymbol(elf_file).?;
10791074 try writer.writeInt(u64, @intCast(symbol.address(.{}, elf_file)), .little);
10801075 }
10811076 // [1]: 0x0
......@@ -1093,22 +1088,22 @@ pub const GotPltSection = struct {
10931088};
10941089
10951090pub const PltGotSection = struct {
1096 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
1091 symbols: std.ArrayListUnmanaged(Elf.Ref) = .{},
10971092 output_symtab_ctx: Elf.SymtabCtx = .{},
10981093
10991094 pub fn deinit(plt_got: *PltGotSection, allocator: Allocator) void {
11001095 plt_got.symbols.deinit(allocator);
11011096 }
11021097
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 {
11041099 const comp = elf_file.base.comp;
11051100 const gpa = comp.gpa;
11061101 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).?;
11081103 symbol.flags.has_plt = true;
11091104 symbol.flags.has_got = true;
1110 try symbol.addExtra(.{ .plt_got = index }, elf_file);
1111 try plt_got.symbols.append(gpa, sym_index);
1105 symbol.addExtra(.{ .plt_got = index }, elf_file);
1106 try plt_got.symbols.append(gpa, ref);
11121107 }
11131108
11141109 pub fn size(plt_got: PltGotSection, elf_file: *Elf) usize {
......@@ -1134,15 +1129,15 @@ pub const PltGotSection = struct {
11341129
11351130 pub fn updateSymtabSize(plt_got: *PltGotSection, elf_file: *Elf) void {
11361131 plt_got.output_symtab_ctx.nlocals = @as(u32, @intCast(plt_got.symbols.items.len));
1137 for (plt_got.symbols.items) |sym_index| {
1138 const name = elf_file.symbol(sym_index).name(elf_file);
1132 for (plt_got.symbols.items) |ref| {
1133 const name = elf_file.symbol(ref).?.name(elf_file);
11391134 plt_got.output_symtab_ctx.strsize += @as(u32, @intCast(name.len + "$pltgot".len)) + 1;
11401135 }
11411136 }
11421137
11431138 pub fn writeSymtab(plt_got: PltGotSection, elf_file: *Elf) void {
1144 for (plt_got.symbols.items, plt_got.output_symtab_ctx.ilocal..) |sym_index, ilocal| {
1145 const sym = elf_file.symbol(sym_index);
1139 for (plt_got.symbols.items, plt_got.output_symtab_ctx.ilocal..) |ref, ilocal| {
1140 const sym = elf_file.symbol(ref).?;
11461141 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
11471142 elf_file.strtab.appendSliceAssumeCapacity(sym.name(elf_file));
11481143 elf_file.strtab.appendSliceAssumeCapacity("$pltgot");
......@@ -1160,8 +1155,8 @@ pub const PltGotSection = struct {
11601155
11611156 const x86_64 = struct {
11621157 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
1163 for (plt_got.symbols.items) |sym_index| {
1164 const sym = elf_file.symbol(sym_index);
1158 for (plt_got.symbols.items) |ref| {
1159 const sym = elf_file.symbol(ref).?;
11651160 const target_addr = sym.gotAddress(elf_file);
11661161 const source_addr = sym.pltGotAddress(elf_file);
11671162 const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 6)) - 4;
......@@ -1178,8 +1173,8 @@ pub const PltGotSection = struct {
11781173
11791174 const aarch64 = struct {
11801175 fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
1181 for (plt_got.symbols.items) |sym_index| {
1182 const sym = elf_file.symbol(sym_index);
1176 for (plt_got.symbols.items) |ref| {
1177 const sym = elf_file.symbol(ref).?;
11831178 const target_addr = sym.gotAddress(elf_file);
11841179 const source_addr = sym.pltGotAddress(elf_file);
11851180 const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);
......@@ -1204,56 +1199,56 @@ pub const PltGotSection = struct {
12041199};
12051200
12061201pub const CopyRelSection = struct {
1207 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
1202 symbols: std.ArrayListUnmanaged(Elf.Ref) = .{},
12081203
12091204 pub fn deinit(copy_rel: *CopyRelSection, allocator: Allocator) void {
12101205 copy_rel.symbols.deinit(allocator);
12111206 }
12121207
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 {
12141209 const comp = elf_file.base.comp;
12151210 const gpa = comp.gpa;
12161211 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).?;
12181213 symbol.flags.import = true;
12191214 symbol.flags.@"export" = true;
12201215 symbol.flags.has_copy_rel = true;
12211216 symbol.flags.weak = false;
1222 try symbol.addExtra(.{ .copy_rel = index }, elf_file);
1223 try copy_rel.symbols.append(gpa, sym_index);
1217 symbol.addExtra(.{ .copy_rel = index }, elf_file);
1218 try copy_rel.symbols.append(gpa, ref);
12241219
12251220 const shared_object = symbol.file(elf_file).?.shared_object;
12261221 if (shared_object.aliases == null) {
12271222 try shared_object.initSymbolAliases(elf_file);
12281223 }
12291224
1230 const aliases = shared_object.symbolAliases(sym_index, elf_file);
1225 const aliases = shared_object.symbolAliases(ref.index, elf_file);
12311226 for (aliases) |alias| {
1232 if (alias == sym_index) continue;
1233 const alias_sym = elf_file.symbol(alias);
1227 if (alias == ref.index) continue;
1228 const alias_sym = &shared_object.symbols.items[alias];
12341229 alias_sym.flags.import = true;
12351230 alias_sym.flags.@"export" = true;
12361231 alias_sym.flags.has_copy_rel = true;
12371232 alias_sym.flags.needs_copy_rel = true;
12381233 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);
12401235 }
12411236 }
12421237
12431238 pub fn updateSectionSize(copy_rel: CopyRelSection, shndx: u32, elf_file: *Elf) !void {
12441239 const shdr = &elf_file.shdrs.items[shndx];
1245 for (copy_rel.symbols.items) |sym_index| {
1246 const symbol = elf_file.symbol(sym_index);
1240 for (copy_rel.symbols.items) |ref| {
1241 const symbol = elf_file.symbol(ref).?;
12471242 const shared_object = symbol.file(elf_file).?.shared_object;
12481243 const alignment = try symbol.dsoAlignment(elf_file);
12491244 symbol.value = @intCast(mem.alignForward(u64, shdr.sh_size, alignment));
12501245 shdr.sh_addralign = @max(shdr.sh_addralign, alignment);
12511246 shdr.sh_size = @as(u64, @intCast(symbol.value)) + symbol.elfSym(elf_file).st_size;
12521247
1253 const aliases = shared_object.symbolAliases(sym_index, elf_file);
1248 const aliases = shared_object.symbolAliases(ref.index, elf_file);
12541249 for (aliases) |alias| {
1255 if (alias == sym_index) continue;
1256 const alias_sym = elf_file.symbol(alias);
1250 if (alias == ref.index) continue;
1251 const alias_sym = &shared_object.symbols.items[alias];
12571252 alias_sym.value = symbol.value;
12581253 }
12591254 }
......@@ -1264,10 +1259,10 @@ pub const CopyRelSection = struct {
12641259 const gpa = comp.gpa;
12651260 const cpu_arch = elf_file.getTarget().cpu.arch;
12661261 try elf_file.rela_dyn.ensureUnusedCapacity(gpa, copy_rel.numRela());
1267 for (copy_rel.symbols.items) |sym_index| {
1268 const sym = elf_file.symbol(sym_index);
1262 for (copy_rel.symbols.items) |ref| {
1263 const sym = elf_file.symbol(ref).?;
12691264 assert(sym.flags.import and sym.flags.has_copy_rel);
1270 const extra = sym.extra(elf_file).?;
1265 const extra = sym.extra(elf_file);
12711266 elf_file.addRelaDynAssumeCapacity(.{
12721267 .offset = @intCast(sym.address(.{}, elf_file)),
12731268 .sym = extra.dynamic,
......@@ -1285,8 +1280,8 @@ pub const DynsymSection = struct {
12851280 entries: std.ArrayListUnmanaged(Entry) = .{},
12861281
12871282 pub const Entry = struct {
1288 /// Index of the symbol which gets privilege of getting a dynamic treatment
1289 symbol_index: Symbol.Index,
1283 /// Ref of the symbol which gets privilege of getting a dynamic treatment
1284 ref: Elf.Ref,
12901285 /// Offset into .dynstrtab
12911286 off: u32,
12921287 };
......@@ -1295,22 +1290,22 @@ pub const DynsymSection = struct {
12951290 dynsym.entries.deinit(allocator);
12961291 }
12971292
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 {
12991294 const comp = elf_file.base.comp;
13001295 const gpa = comp.gpa;
13011296 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).?;
13031298 sym.flags.has_dynamic = true;
1304 try sym.addExtra(.{ .dynamic = index }, elf_file);
1299 sym.addExtra(.{ .dynamic = index }, elf_file);
13051300 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 });
13071302 }
13081303
13091304 pub fn sort(dynsym: *DynsymSection, elf_file: *Elf) void {
13101305 const Sort = struct {
13111306 pub fn lessThan(ctx: *Elf, lhs: Entry, rhs: Entry) bool {
1312 const lhs_sym = ctx.symbol(lhs.symbol_index);
1313 const rhs_sym = ctx.symbol(rhs.symbol_index);
1307 const lhs_sym = ctx.symbol(lhs.ref).?;
1308 const rhs_sym = ctx.symbol(rhs.ref).?;
13141309
13151310 if (lhs_sym.flags.@"export" != rhs_sym.flags.@"export") {
13161311 return rhs_sym.flags.@"export";
......@@ -1322,14 +1317,14 @@ pub const DynsymSection = struct {
13221317 const rhs_hash = GnuHashSection.hasher(rhs_sym.name(ctx)) % nbuckets;
13231318
13241319 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;
13261321 return lhs_hash < rhs_hash;
13271322 }
13281323 };
13291324
13301325 var num_exports: u32 = 0;
13311326 for (dynsym.entries.items) |entry| {
1332 const sym = elf_file.symbol(entry.symbol_index);
1327 const sym = elf_file.symbol(entry.ref).?;
13331328 if (sym.flags.@"export") num_exports += 1;
13341329 }
13351330
......@@ -1338,8 +1333,8 @@ pub const DynsymSection = struct {
13381333 std.mem.sort(Entry, dynsym.entries.items, elf_file, Sort.lessThan);
13391334
13401335 for (dynsym.entries.items, 1..) |entry, index| {
1341 const sym = elf_file.symbol(entry.symbol_index);
1342 var extra = sym.extra(elf_file).?;
1336 const sym = elf_file.symbol(entry.ref).?;
1337 var extra = sym.extra(elf_file);
13431338 extra.dynamic = @as(u32, @intCast(index));
13441339 sym.setExtra(extra, elf_file);
13451340 }
......@@ -1356,7 +1351,7 @@ pub const DynsymSection = struct {
13561351 pub fn write(dynsym: DynsymSection, elf_file: *Elf, writer: anytype) !void {
13571352 try writer.writeStruct(Elf.null_sym);
13581353 for (dynsym.entries.items) |entry| {
1359 const sym = elf_file.symbol(entry.symbol_index);
1354 const sym = elf_file.symbol(entry.ref).?;
13601355 var out_sym: elf.Elf64_Sym = Elf.null_sym;
13611356 sym.setOutputSym(elf_file, &out_sym);
13621357 out_sym.st_name = entry.off;
......@@ -1429,7 +1424,7 @@ pub const GnuHashSection = struct {
14291424
14301425 fn getExports(elf_file: *Elf) []const DynsymSection.Entry {
14311426 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).?;
14331428 if (sym.flags.@"export") break i;
14341429 } else elf_file.dynsym.entries.items.len;
14351430 return elf_file.dynsym.entries.items[start..];
......@@ -1477,7 +1472,7 @@ pub const GnuHashSection = struct {
14771472 @memset(bloom, 0);
14781473
14791474 for (exports, 0..) |entry, i| {
1480 const sym = elf_file.symbol(entry.symbol_index);
1475 const sym = elf_file.symbol(entry.ref).?;
14811476 const h = hasher(sym.name(elf_file));
14821477 hashes[i] = h;
14831478 indices[i] = h % hash.num_buckets;
......@@ -1574,7 +1569,7 @@ pub const VerneedSection = struct {
15741569 try verneed.ensureTotalCapacity(dynsyms.len);
15751570
15761571 for (dynsyms, 1..) |entry, i| {
1577 const symbol = elf_file.symbol(entry.symbol_index);
1572 const symbol = elf_file.symbol(entry.ref).?;
15781573 if (symbol.flags.import and symbol.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) {
15791574 const shared_object = symbol.file(elf_file).?.shared_object;
15801575 verneed.appendAssumeCapacity(.{
......@@ -1677,11 +1672,11 @@ pub const ComdatGroupSection = struct {
16771672 return cg_file.object.comdatGroup(cgs.cg_ref.index);
16781673 }
16791674
1680 pub fn symbol(cgs: ComdatGroupSection, elf_file: *Elf) Symbol.Index {
1675 pub fn symbol(cgs: ComdatGroupSection, elf_file: *Elf) *Symbol {
16811676 const cg = cgs.comdatGroup(elf_file);
16821677 const object = cg.file(elf_file).object;
16831678 const shdr = object.shdrs.items[cg.shndx];
1684 return object.symbols.items[shdr.sh_info];
1679 return &object.symbols.items[shdr.sh_info];
16851680 }
16861681
16871682 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 {
4343 else => @panic("unsupported arch"),
4444 };
4545 if (is_reachable) continue;
46 const target = switch (file) {
47 .zig_object => |x| x.symbol(rel.r_sym()),
48 .object => |x| x.symbols.items[rel.r_sym()],
49 else => unreachable,
50 };
46 const target = file.resolveSymbol(rel.r_sym(), elf_file);
5147 try thunk.symbols.put(gpa, target, {});
5248 }
5349 atom.addExtra(.{ .thunk = thunk_index }, elf_file);
......@@ -80,7 +76,7 @@ fn maxAllowedDistance(cpu_arch: std.Target.Cpu.Arch) u32 {
8076pub const Thunk = struct {
8177 value: i64 = 0,
8278 output_section_index: u32 = 0,
83 symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{},
79 symbols: std.AutoArrayHashMapUnmanaged(Elf.Ref, void) = .{},
8480 output_symtab_ctx: Elf.SymtabCtx = .{},
8581
8682 pub fn deinit(thunk: *Thunk, allocator: Allocator) void {
......@@ -97,9 +93,9 @@ pub const Thunk = struct {
9793 return @as(i64, @intCast(shdr.sh_addr)) + thunk.value;
9894 }
9995
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 {
10197 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)));
10399 }
104100
105101 pub fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void {
......@@ -112,16 +108,16 @@ pub const Thunk = struct {
112108
113109 pub fn calcSymtabSize(thunk: *Thunk, elf_file: *Elf) void {
114110 thunk.output_symtab_ctx.nlocals = @as(u32, @intCast(thunk.symbols.keys().len));
115 for (thunk.symbols.keys()) |sym_index| {
116 const sym = elf_file.symbol(sym_index);
111 for (thunk.symbols.keys()) |ref| {
112 const sym = elf_file.symbol(ref).?;
117113 thunk.output_symtab_ctx.strsize += @as(u32, @intCast(sym.name(elf_file).len + "$thunk".len + 1));
118114 }
119115 }
120116
121117 pub fn writeSymtab(thunk: Thunk, elf_file: *Elf) void {
122118 const cpu_arch = elf_file.getTarget().cpu.arch;
123 for (thunk.symbols.keys(), thunk.output_symtab_ctx.ilocal..) |sym_index, ilocal| {
124 const sym = elf_file.symbol(sym_index);
119 for (thunk.symbols.keys(), thunk.output_symtab_ctx.ilocal..) |ref, ilocal| {
120 const sym = elf_file.symbol(ref).?;
125121 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
126122 elf_file.strtab.appendSliceAssumeCapacity(sym.name(elf_file));
127123 elf_file.strtab.appendSliceAssumeCapacity("$thunk");
......@@ -131,7 +127,7 @@ pub const Thunk = struct {
131127 .st_info = elf.STT_FUNC,
132128 .st_other = 0,
133129 .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)),
135131 .st_size = trampolineSize(cpu_arch),
136132 };
137133 }
......@@ -181,9 +177,9 @@ pub const Thunk = struct {
181177 const thunk = ctx.thunk;
182178 const elf_file = ctx.elf_file;
183179 try writer.print("@{x} : size({x})\n", .{ thunk.value, thunk.size(elf_file) });
184 for (thunk.symbols.keys()) |index| {
185 const sym = elf_file.symbol(index);
186 try writer.print(" %{d} : {s} : @{x}\n", .{ index, sym.name(elf_file), sym.value });
180 for (thunk.symbols.keys()) |ref| {
181 const sym = elf_file.symbol(ref).?;
182 try writer.print(" {} : {s} : @{x}\n", .{ ref, sym.name(elf_file), sym.value });
187183 }
188184 }
189185
......@@ -195,12 +191,8 @@ const aarch64 = struct {
195191 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
196192 if (r_type != .CALL26 and r_type != .JUMP26) return true;
197193 const file = atom.file(elf_file).?;
198 const target_index = switch (file) {
199 .zig_object => |x| x.symbol(rel.r_sym()),
200 .object => |x| x.symbols.items[rel.r_sym()],
201 else => unreachable,
202 };
203 const target = elf_file.symbol(target_index);
194 const target_ref = file.resolveSymbol(rel.r_sym(), elf_file);
195 const target = elf_file.symbol(target_ref).?;
204196 if (target.flags.has_plt) return false;
205197 if (atom.output_section_index != target.output_section_index) return false;
206198 const target_atom = target.atom(elf_file).?;
......@@ -212,8 +204,8 @@ const aarch64 = struct {
212204 }
213205
214206 fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void {
215 for (thunk.symbols.keys(), 0..) |sym_index, i| {
216 const sym = elf_file.symbol(sym_index);
207 for (thunk.symbols.keys(), 0..) |ref, i| {
208 const sym = elf_file.symbol(ref).?;
217209 const saddr = thunk.address(elf_file) + @as(i64, @intCast(i * trampoline_size));
218210 const taddr = sym.address(.{}, elf_file);
219211 const pages = try util.calcNumberOfPages(saddr, taddr);