authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-18 18:33:30+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-18 18:33:35+02:00
log1448d6b77c1367d6d42c5dfe51878e7ef19c1743
tree66cf45b7e08891e1c182197ce85a826a23c45ce2
parent9ced0ecbbd82288e5680130d64d1d864a647c905

elf: store shndx to Zig module atoms out-of-band

This allows us to increase the effective resolution of `st_shndx` from `u8` to `u32`.

2 files changed, 55 insertions(+), 38 deletions(-)

src/link/Elf.zig+16-11
......@@ -331,7 +331,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
331331 symbol_ptr.name_offset = name_off;
332332
333333 const esym_index = try zig_module.addLocalEsym(allocator);
334 const esym = &zig_module.local_esyms.items[esym_index];
334 const esym = &zig_module.local_esyms.items(.elf_sym)[esym_index];
335335 esym.st_name = name_off;
336336 esym.st_info |= elf.STT_FILE;
337337 esym.st_shndx = elf.SHN_ABS;
......@@ -3172,7 +3172,7 @@ fn updateDeclCode(
31723172 const required_alignment = decl.getAlignment(mod);
31733173
31743174 const sym = self.symbol(sym_index);
3175 const esym = &zig_module.local_esyms.items[sym.esym_index];
3175 const esym = &zig_module.local_esyms.items(.elf_sym)[sym.esym_index];
31763176 const atom_ptr = sym.atom(self).?;
31773177
31783178 const shdr_index = self.getDeclShdrIndex(decl_index, code);
......@@ -3438,7 +3438,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
34383438 const phdr_index = self.phdr_to_shdr_table.get(output_section_index).?;
34393439 local_sym.name_offset = name_str_index;
34403440 local_sym.output_section_index = output_section_index;
3441 const local_esym = &zig_module.local_esyms.items[local_sym.esym_index];
3441 const local_esym = &zig_module.local_esyms.items(.elf_sym)[local_sym.esym_index];
34423442 local_esym.st_name = name_str_index;
34433443 local_esym.st_info |= elf.STT_OBJECT;
34443444 local_esym.st_size = code.len;
......@@ -3527,7 +3527,7 @@ fn lowerConst(
35273527 const name_str_index = try self.strtab.insert(gpa, name);
35283528 local_sym.name_offset = name_str_index;
35293529 local_sym.output_section_index = output_section_index;
3530 const local_esym = &zig_module.local_esyms.items[local_sym.esym_index];
3530 const local_esym = &zig_module.local_esyms.items(.elf_sym)[local_sym.esym_index];
35313531 local_esym.st_name = name_str_index;
35323532 local_esym.st_info |= elf.STT_OBJECT;
35333533 local_esym.st_size = code.len;
......@@ -3573,7 +3573,9 @@ pub fn updateDeclExports(
35733573 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
35743574 const decl = mod.declPtr(decl_index);
35753575 const decl_sym_index = try self.getOrCreateMetadataForDecl(decl_index);
3576 const decl_esym = zig_module.local_esyms.items[self.symbol(decl_sym_index).esym_index];
3576 const decl_esym_index = self.symbol(decl_sym_index).esym_index;
3577 const decl_esym = zig_module.local_esyms.items(.elf_sym)[decl_esym_index];
3578 const decl_esym_shndx = zig_module.local_esyms.items(.shndx)[decl_esym_index];
35773579 const decl_metadata = self.decls.getPtr(decl_index).?;
35783580
35793581 for (exports) |exp| {
......@@ -3615,11 +3617,13 @@ pub fn updateDeclExports(
36153617 try zig_module.global_symbols.append(gpa, gop.index);
36163618 break :blk sym_index;
36173619 };
3618 const esym = &zig_module.global_esyms.items[sym_index & 0x0fffffff];
3619 esym.st_value = self.symbol(decl_sym_index).value;
3620 esym.st_shndx = decl_esym.st_shndx;
3621 esym.st_info = (stb_bits << 4) | stt_bits;
3622 esym.st_name = name_off;
3620 const global_esym_index = sym_index & ZigModule.symbol_mask;
3621 const global_esym = &zig_module.global_esyms.items(.elf_sym)[global_esym_index];
3622 global_esym.st_value = self.symbol(decl_sym_index).value;
3623 global_esym.st_shndx = decl_esym.st_shndx;
3624 global_esym.st_info = (stb_bits << 4) | stt_bits;
3625 global_esym.st_name = name_off;
3626 zig_module.global_esyms.items(.shndx)[global_esym_index] = decl_esym_shndx;
36233627 }
36243628}
36253629
......@@ -3651,7 +3655,7 @@ pub fn deleteDeclExport(
36513655 const exp_name = mod.intern_pool.stringToSlice(name);
36523656 const esym_index = metadata.@"export"(self, exp_name) orelse return;
36533657 log.debug("deleting export '{s}'", .{exp_name});
3654 const esym = &zig_module.global_esyms.items[esym_index.*];
3658 const esym = &zig_module.global_esyms.items(.elf_sym)[esym_index.*];
36553659 _ = zig_module.globals_lookup.remove(esym.st_name);
36563660 const sym_index = self.resolver.get(esym.st_name).?;
36573661 const sym = self.symbol(sym_index);
......@@ -3660,6 +3664,7 @@ pub fn deleteDeclExport(
36603664 sym.* = .{};
36613665 }
36623666 esym.* = null_sym;
3667 zig_module.global_esyms.items(.shndx)[esym_index.*] = elf.SHN_UNDEF;
36633668}
36643669
36653670fn addLinkerDefinedSymbols(self: *Elf) !void {
src/link/Elf/ZigModule.zig+39-27
......@@ -7,8 +7,8 @@
77path: []const u8,
88index: File.Index,
99
10local_esyms: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
11global_esyms: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
10local_esyms: std.MultiArrayList(ElfSym) = .{},
11global_esyms: std.MultiArrayList(ElfSym) = .{},
1212local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
1313global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
1414globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
......@@ -20,6 +20,10 @@ num_dynrelocs: u32 = 0,
2020
2121output_symtab_size: Elf.SymtabSize = .{},
2222
23pub const global_symbol_bit: u32 = 0x80000000;
24pub const symbol_mask: u32 = 0x7fffffff;
25pub const SHN_ATOM: u16 = 0x100;
26
2327pub fn deinit(self: *ZigModule, allocator: Allocator) void {
2428 self.local_esyms.deinit(allocator);
2529 self.global_esyms.deinit(allocator);
......@@ -35,20 +39,20 @@ pub fn deinit(self: *ZigModule, allocator: Allocator) void {
3539
3640pub fn addLocalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index {
3741 try self.local_esyms.ensureUnusedCapacity(allocator, 1);
38 const index = @as(Symbol.Index, @intCast(self.local_esyms.items.len));
39 const esym = self.local_esyms.addOneAssumeCapacity();
40 esym.* = Elf.null_sym;
41 esym.st_info = elf.STB_LOCAL << 4;
42 const index = @as(Symbol.Index, @intCast(self.local_esyms.addOneAssumeCapacity()));
43 var esym = ElfSym{ .elf_sym = Elf.null_sym };
44 esym.elf_sym.st_info = elf.STB_LOCAL << 4;
45 self.local_esyms.set(index, esym);
4246 return index;
4347}
4448
4549pub fn addGlobalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index {
4650 try self.global_esyms.ensureUnusedCapacity(allocator, 1);
47 const index = @as(Symbol.Index, @intCast(self.global_esyms.items.len));
48 const esym = self.global_esyms.addOneAssumeCapacity();
49 esym.* = Elf.null_sym;
50 esym.st_info = elf.STB_GLOBAL << 4;
51 return index | 0x10000000;
51 const index = @as(Symbol.Index, @intCast(self.global_esyms.addOneAssumeCapacity()));
52 var esym = ElfSym{ .elf_sym = Elf.null_sym };
53 esym.elf_sym.st_info = elf.STB_GLOBAL << 4;
54 self.global_esyms.set(index, esym);
55 return index | global_symbol_bit;
5256}
5357
5458pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index {
......@@ -58,7 +62,7 @@ pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index {
5862 const symbol_index = try elf_file.addSymbol();
5963 const esym_index = try self.addLocalEsym(gpa);
6064
61 const shndx = @as(u16, @intCast(self.atoms.items.len));
65 const shndx = @as(u32, @intCast(self.atoms.items.len));
6266 try self.atoms.append(gpa, atom_index);
6367 try self.local_symbols.append(gpa, symbol_index);
6468
......@@ -69,8 +73,8 @@ pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index {
6973 symbol_ptr.file_index = self.index;
7074 symbol_ptr.atom_index = atom_index;
7175
72 const esym = &self.local_esyms.items[esym_index];
73 esym.st_shndx = shndx;
76 self.local_esyms.items(.shndx)[esym_index] = shndx;
77 self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM;
7478 symbol_ptr.esym_index = esym_index;
7579
7680 const relocs_index = @as(u32, @intCast(self.relocs.items.len));
......@@ -99,13 +103,15 @@ pub fn inputShdr(self: ZigModule, atom_index: Atom.Index, elf_file: *Elf) Object
99103
100104pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {
101105 for (self.globals(), 0..) |index, i| {
102 const esym_index = @as(Symbol.Index, @intCast(i)) | 0x10000000;
103 const esym = self.global_esyms.items[i];
106 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
107 const esym = self.global_esyms.items(.elf_sym)[i];
108 const shndx = self.global_esyms.items(.shndx)[i];
104109
105110 if (esym.st_shndx == elf.SHN_UNDEF) continue;
106111
107112 if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {
108 const atom_index = self.atoms.items[esym.st_shndx];
113 assert(esym.st_shndx == SHN_ATOM);
114 const atom_index = self.atoms.items[shndx];
109115 const atom = elf_file.atom(atom_index) orelse continue;
110116 if (!atom.flags.alive) continue;
111117 }
......@@ -114,7 +120,8 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {
114120 if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) {
115121 const atom_index = switch (esym.st_shndx) {
116122 elf.SHN_ABS, elf.SHN_COMMON => 0,
117 else => self.atoms.items[esym.st_shndx],
123 SHN_ATOM => self.atoms.items[shndx],
124 else => unreachable,
118125 };
119126 const output_section_index = if (elf_file.atom(atom_index)) |atom|
120127 atom.outputShndx().?
......@@ -133,8 +140,8 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {
133140
134141pub fn claimUnresolved(self: *ZigModule, elf_file: *Elf) void {
135142 for (self.globals(), 0..) |index, i| {
136 const esym_index = @as(Symbol.Index, @intCast(i)) | 0x10000000;
137 const esym = self.global_esyms.items[i];
143 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
144 const esym = self.global_esyms.items(.elf_sym)[i];
138145
139146 if (esym.st_shndx != elf.SHN_UNDEF) continue;
140147
......@@ -187,7 +194,7 @@ pub fn resetGlobals(self: *ZigModule, elf_file: *Elf) void {
187194
188195pub fn markLive(self: *ZigModule, elf_file: *Elf) void {
189196 for (self.globals(), 0..) |index, i| {
190 const esym = self.global_esyms.items[i];
197 const esym = self.global_esyms.items(.elf_sym)[i];
191198 if (esym.st_bind() == elf.STB_WEAK) continue;
192199
193200 const global = elf_file.symbol(index);
......@@ -256,17 +263,17 @@ pub fn writeSymtab(self: *ZigModule, elf_file: *Elf, ctx: anytype) void {
256263}
257264
258265pub fn symbol(self: *ZigModule, index: Symbol.Index) Symbol.Index {
259 const is_global = index & 0x10000000 != 0;
260 const actual_index = index & 0x0fffffff;
266 const is_global = index & global_symbol_bit != 0;
267 const actual_index = index & symbol_mask;
261268 if (is_global) return self.global_symbols.items[actual_index];
262269 return self.local_symbols.items[actual_index];
263270}
264271
265272pub fn elfSym(self: *ZigModule, index: Symbol.Index) *elf.Elf64_Sym {
266 const is_global = index & 0x10000000 != 0;
267 const actual_index = index & 0x0fffffff;
268 if (is_global) return &self.global_esyms.items[actual_index];
269 return &self.local_esyms.items[actual_index];
273 const is_global = index & global_symbol_bit != 0;
274 const actual_index = index & symbol_mask;
275 if (is_global) return &self.global_esyms.items(.elf_sym)[actual_index];
276 return &self.local_esyms.items(.elf_sym)[actual_index];
270277}
271278
272279pub fn locals(self: *ZigModule) []const Symbol.Index {
......@@ -354,6 +361,11 @@ fn formatAtoms(
354361 }
355362}
356363
364const ElfSym = struct {
365 elf_sym: elf.Elf64_Sym,
366 shndx: u32 = elf.SHN_UNDEF,
367};
368
357369const assert = std.debug.assert;
358370const std = @import("std");
359371const elf = std.elf;