authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-31 15:45:36+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-07 10:21:02+02:00
log9fe69cc0b588ff96075854d687f3fce3d4457258
treeca08a39f9fb895d001d49773a25218db383f6555
parentd0367b02199417c10b2cde6d0deae4242689d127

elf: move symbol ownership to SharedObject


2 files changed, 200 insertions(+), 131 deletions(-)

src/link/Elf/Object.zig+75-84
......@@ -562,7 +562,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {
562562 }
563563}
564564
565pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {
565pub fn resolveSymbols(self: *Object, elf_file: *Elf) !void {
566566 const gpa = elf_file.base.comp.gpa;
567567
568568 const first_global = self.first_global orelse return;
......@@ -585,12 +585,12 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {
585585 resolv.* = gop.index;
586586
587587 if (esym.st_shndx == elf.SHN_UNDEF) continue;
588 if (elf_file.symbol(gop.ref) == null) {
588 if (elf_file.symbol(gop.ref.*) == null) {
589589 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
590590 continue;
591591 }
592592
593 if (self.asFile().symbolRank(esym, !self.alive) < elf_file.symbol(gop.ref).?.symbolRank(elf_file)) {
593 if (self.asFile().symbolRank(esym, !self.alive) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) {
594594 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
595595 }
596596 }
......@@ -625,34 +625,40 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {
625625
626626pub fn claimUnresolvedObject(self: *Object, elf_file: *Elf) void {
627627 const first_global = self.first_global orelse return;
628 for (self.globals(), 0..) |index, i| {
628 for (self.globals(), 0..) |*sym, i| {
629629 const esym_index = @as(u32, @intCast(first_global + i));
630630 const esym = self.symtab.items[esym_index];
631631 if (esym.st_shndx != elf.SHN_UNDEF) continue;
632 if (elf_file.symbol(self.resolveSymbol(esym_index, elf_file)) != null) continue;
632633
633 const global = elf_file.symbol(index);
634 if (global.file(elf_file)) |file| {
635 if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or file.index() <= self.index) continue;
636 }
634 // TODO: audit this
635 // const global = elf_file.symbol(index);
636 // if (global.file(elf_file)) |file| {
637 // if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or file.index() <= self.index) continue;
638 // }
637639
638 global.value = 0;
639 global.ref = .{ .index = 0, .file = 0 };
640 global.esym_index = esym_index;
641 global.file_index = self.index;
640 sym.value = 0;
641 sym.ref = .{ .index = 0, .file = 0 };
642 sym.esym_index = esym_index;
643 sym.file_index = self.index;
644
645 const idx = self.symbols_resolver.items[i];
646 elf_file.resolver.items[idx - 1] = .{ .index = esym_index, .file = self.index };
642647 }
643648}
644649
645650pub fn markLive(self: *Object, elf_file: *Elf) void {
646651 const first_global = self.first_global orelse return;
647 for (self.globals(), 0..) |index, i| {
648 const sym_idx = first_global + i;
649 const sym = self.symtab.items[sym_idx];
650 if (sym.st_bind() == elf.STB_WEAK) continue;
651
652 const global = elf_file.symbol(index);
653 const file = global.file(elf_file) orelse continue;
654 const should_keep = sym.st_shndx == elf.SHN_UNDEF or
655 (sym.st_shndx == elf.SHN_COMMON and global.elfSym(elf_file).st_shndx != elf.SHN_COMMON);
652 for (0..self.globals().len) |i| {
653 const esym_idx = first_global + i;
654 const esym = self.symtab.items[esym_idx];
655 if (esym.st_bind() == elf.STB_WEAK) continue;
656
657 const ref = self.resolveSymbol(@intCast(esym_idx), elf_file);
658 const sym = elf_file.symbol(ref) orelse continue;
659 const file = sym.file(elf_file).?;
660 const should_keep = esym.st_shndx == elf.SHN_UNDEF or
661 (esym.st_shndx == elf.SHN_COMMON and sym.elfSym(elf_file).st_shndx != elf.SHN_COMMON);
656662 if (should_keep and !file.isAlive()) {
657663 file.setAlive();
658664 file.markLive(elf_file);
......@@ -672,24 +678,25 @@ pub fn markEhFrameAtomsDead(self: *Object, elf_file: *Elf) void {
672678
673679pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {
674680 const first_global = self.first_global orelse return;
675 for (self.globals(), 0..) |index, i| {
676 const sym_idx = first_global + i;
677 const sym = self.symtab.items[sym_idx];
678 const global = elf_file.symbol(index);
679 const global_file = global.file(elf_file) orelse continue;
680
681 if (self.index == global_file.index() or
682 sym.st_shndx == elf.SHN_UNDEF or
683 sym.st_bind() == elf.STB_WEAK or
684 sym.st_shndx == elf.SHN_COMMON) continue;
685
686 if (sym.st_shndx != elf.SHN_ABS) {
687 const atom_index = self.atoms_indexes.items[sym.st_shndx];
681 for (0..self.globals().len) |i| {
682 const esym_idx = first_global + i;
683 const esym = self.symtab.items[esym_idx];
684 const ref = self.resolveSymbol(@intCast(esym_idx), elf_file);
685 const ref_sym = elf_file.symbol(ref) orelse continue;
686 const ref_file = ref_sym.file(elf_file).?;
687
688 if (self.index == ref_file.index() or
689 esym.st_shndx == elf.SHN_UNDEF or
690 esym.st_bind() == elf.STB_WEAK or
691 esym.st_shndx == elf.SHN_COMMON) continue;
692
693 if (esym.st_shndx != elf.SHN_ABS) {
694 const atom_index = self.atoms_indexes.items[esym.st_shndx];
688695 const atom_ptr = self.atom(atom_index) orelse continue;
689696 if (!atom_ptr.alive) continue;
690697 }
691698
692 const gop = try dupes.getOrPut(index);
699 const gop = try dupes.getOrPut(self.symbols_resolver.items[i]);
693700 if (!gop.found_existing) {
694701 gop.value_ptr.* = .{};
695702 }
......@@ -819,8 +826,8 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
819826 }
820827
821828 for (self.symtab.items, 0..) |*esym, idx| {
822 const sym_index = self.symbols.items[idx];
823 const sym = elf_file.symbol(sym_index);
829 const sym = &self.symbols.items[idx];
830 // TODO: do we need ref here?
824831
825832 if (esym.st_shndx == elf.SHN_COMMON or esym.st_shndx == elf.SHN_UNDEF or esym.st_shndx == elf.SHN_ABS) continue;
826833
......@@ -860,23 +867,20 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
860867 return error.MalformedObject;
861868 };
862869
863 const out_sym_idx: u64 = @intCast(self.symbols.items.len);
864 try self.symbols.ensureUnusedCapacity(gpa, 1);
870 const sym_index = try self.addSymbol(gpa);
871 const sym = &self.symbols.items[sym_index];
865872 const name = try std.fmt.allocPrint(gpa, "{s}$subsection{d}", .{ msec.name(elf_file), res.msub_index });
866873 defer gpa.free(name);
867 const sym_index = try elf_file.addSymbol();
868 const sym = elf_file.symbol(sym_index);
869874 sym.* = .{
870875 .value = @bitCast(@as(i64, @intCast(res.offset)) - rel.r_addend),
871876 .name_offset = try self.addString(gpa, name),
872877 .esym_index = rel.r_sym(),
873878 .file_index = self.index,
874 .extra_index = try elf_file.addSymbolExtra(.{}),
879 .extra_index = try self.addSymbolExtra(gpa, .{}),
875880 };
876881 sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index };
877882 sym.flags.merge_subsection = true;
878 self.symbols.addOneAssumeCapacity().* = sym_index;
879 rel.r_info = (out_sym_idx << 32) | rel.r_type();
883 rel.r_info = (@as(u64, @intCast(sym_index)) << 32) | rel.r_type();
880884 }
881885 }
882886}
......@@ -885,27 +889,16 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
885889/// play nicely with the rest of the system.
886890pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
887891 const first_global = self.first_global orelse return;
888 for (self.globals(), 0..) |index, i| {
889 const sym_idx = @as(u32, @intCast(first_global + i));
890 const this_sym = self.symtab.items[sym_idx];
891 if (this_sym.st_shndx != elf.SHN_COMMON) continue;
892
893 const global = elf_file.symbol(index);
894 const global_file = global.file(elf_file).?;
895 if (global_file.index() != self.index) {
896 // if (elf_file.options.warn_common) {
897 // elf_file.base.warn("{}: multiple common symbols: {s}", .{
898 // self.fmtPath(),
899 // global.getName(elf_file),
900 // });
901 // }
902 continue;
903 }
892 for (self.globals(), self.symbols_resolver.items, 0..) |*sym, resolv, i| {
893 const esym_idx = @as(u32, @intCast(first_global + i));
894 const esym = self.symtab.items[esym_idx];
895 if (esym.st_shndx != elf.SHN_COMMON) continue;
896 if (elf_file.resolver.get(resolv).?.file != self.index) continue;
904897
905898 const comp = elf_file.base.comp;
906899 const gpa = comp.gpa;
907900
908 const is_tls = global.type(elf_file) == elf.STT_TLS;
901 const is_tls = sym.type(elf_file) == elf.STT_TLS;
909902 const name = if (is_tls) ".tls_common" else ".common";
910903 const name_offset = @as(u32, @intCast(self.strtab.items.len));
911904 try self.strtab.writer(gpa).print("{s}\x00", .{name});
......@@ -914,7 +907,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
914907 if (is_tls) sh_flags |= elf.SHF_TLS;
915908 const shndx = @as(u32, @intCast(self.shdrs.items.len));
916909 const shdr = try self.shdrs.addOne(gpa);
917 const sh_size = math.cast(usize, this_sym.st_size) orelse return error.Overflow;
910 const sh_size = math.cast(usize, esym.st_size) orelse return error.Overflow;
918911 shdr.* = .{
919912 .sh_name = name_offset,
920913 .sh_type = elf.SHT_NOBITS,
......@@ -924,21 +917,21 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
924917 .sh_size = sh_size,
925918 .sh_link = 0,
926919 .sh_info = 0,
927 .sh_addralign = this_sym.st_value,
920 .sh_addralign = esym.st_value,
928921 .sh_entsize = 0,
929922 };
930923
931924 const atom_index = try self.addAtom(gpa, .{
932925 .name = name_offset,
933926 .shndx = shndx,
934 .size = this_sym.st_size,
935 .alignment = Alignment.fromNonzeroByteUnits(this_sym.st_value),
927 .size = esym.st_size,
928 .alignment = Alignment.fromNonzeroByteUnits(esym.st_value),
936929 });
937930 try self.atoms_indexes.append(gpa, atom_index);
938931
939 global.value = 0;
940 global.ref = .{ .index = atom_index, .file = self.index };
941 global.flags.weak = false;
932 sym.value = 0;
933 sym.ref = .{ .index = atom_index, .file = self.index };
934 sym.flags.weak = false;
942935 }
943936}
944937
......@@ -1080,7 +1073,7 @@ pub fn writeAr(self: Object, elf_file: *Elf, writer: anytype) !void {
10801073 try writer.writeAll(data);
10811074}
10821075
1083pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void {
1076pub fn updateSymtabSize(self: *Object, elf_file: *Elf) void {
10841077 const isAlive = struct {
10851078 fn isAlive(sym: *const Symbol, ctx: *Elf) bool {
10861079 if (sym.mergeSubsection(ctx)) |msub| return msub.alive;
......@@ -1089,8 +1082,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void {
10891082 }
10901083 }.isAlive;
10911084
1092 for (self.locals()) |local_index| {
1093 const local = elf_file.symbol(local_index);
1085 for (self.locals()) |*local| {
10941086 if (!isAlive(local, elf_file)) continue;
10951087 const esym = local.elfSym(elf_file);
10961088 switch (esym.st_type()) {
......@@ -1099,22 +1091,22 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void {
10991091 else => {},
11001092 }
11011093 local.flags.output_symtab = true;
1102 try local.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
1094 local.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
11031095 self.output_symtab_ctx.nlocals += 1;
11041096 self.output_symtab_ctx.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1;
11051097 }
11061098
1107 for (self.globals()) |global_index| {
1108 const global = elf_file.symbol(global_index);
1109 const file_ptr = global.file(elf_file) orelse continue;
1110 if (file_ptr.index() != self.index) continue;
1099 for (self.globals(), self.symbols_resolver.items) |*global, resolv| {
1100 const ref = elf_file.resolver.items[resolv];
1101 const ref_sym = elf_file.symbol(ref) orelse continue;
1102 if (ref_sym.file(elf_file).?.index() != self.index) continue;
11111103 if (!isAlive(global, elf_file)) continue;
11121104 global.flags.output_symtab = true;
11131105 if (global.isLocal(elf_file)) {
1114 try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
1106 global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
11151107 self.output_symtab_ctx.nlocals += 1;
11161108 } else {
1117 try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
1109 global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
11181110 self.output_symtab_ctx.nglobals += 1;
11191111 }
11201112 self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1;
......@@ -1122,8 +1114,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void {
11221114}
11231115
11241116pub fn writeSymtab(self: Object, elf_file: *Elf) void {
1125 for (self.locals()) |local_index| {
1126 const local = elf_file.symbol(local_index);
1117 for (self.locals()) |local| {
11271118 const idx = local.outputSymtabIndex(elf_file) orelse continue;
11281119 const out_sym = &elf_file.symtab.items[idx];
11291120 out_sym.st_name = @intCast(elf_file.strtab.items.len);
......@@ -1132,10 +1123,10 @@ pub fn writeSymtab(self: Object, elf_file: *Elf) void {
11321123 local.setOutputSym(elf_file, out_sym);
11331124 }
11341125
1135 for (self.globals()) |global_index| {
1136 const global = elf_file.symbol(global_index);
1137 const file_ptr = global.file(elf_file) orelse continue;
1138 if (file_ptr.index() != self.index) continue;
1126 for (self.globals(), self.symbols_resolver.items) |global, resolv| {
1127 const ref = elf_file.resolver.items[resolv];
1128 const ref_sym = elf_file.symbol(ref) orelse continue;
1129 if (ref_sym.file(elf_file).?.index() != self.index) continue;
11391130 const idx = global.outputSymtabIndex(elf_file) orelse continue;
11401131 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
11411132 elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file));
src/link/Elf/SharedObject.zig+125-47
......@@ -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;
......@@ -214,41 +223,56 @@ fn initSymtab(self: *SharedObject, elf_file: *Elf, opts: struct {
214223 try self.strtab.writer(gpa).print("{s}\x00", .{mangled});
215224 break :blk name_off;
216225 } 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;
226 const out_esym_index: u32 = @intCast(self.symtab.items.len);
227 const out_esym = self.symtab.addOneAssumeCapacity();
228 out_esym.* = sym;
229 out_esym.st_name = name_off;
230 const out_sym_index = self.addSymbolAssumeCapacity();
231 const out_sym = &self.symbols.items[out_sym_index];
232 out_sym.* = .{
233 .value = @intCast(out_esym.st_value),
234 .ref = .{ .index = 0, .file = 0 },
235 .esym_index = out_esym_index,
236 .version_index = self.versyms.items[out_esym_index],
237 .extra_index = self.addSymbolExtraAssumeCapacity(.{}),
238 };
222239 }
223240}
224241
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];
242pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) !void {
243 const gpa = elf_file.base.comp.gpa;
244
245 for (self.symtab.items, self.symbols_resolver.items, 0..) |esym, *resolv, i| {
246 const gop = try elf_file.resolver.getOrPut(gpa, .{
247 .index = @intCast(i),
248 .file = self.index,
249 }, elf_file);
250 if (!gop.found_existing) {
251 gop.ref.* = .{ .index = 0, .file = 0 };
252 }
253 resolv.* = gop.index;
229254
230 if (this_sym.st_shndx == elf.SHN_UNDEF) continue;
255 if (esym.st_shndx == elf.SHN_UNDEF) continue;
256 if (elf_file.symbol(gop.ref.*) == null) {
257 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
258 continue;
259 }
231260
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;
261 if (self.asFile().symbolRank(esym, false) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) {
262 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
239263 }
240264 }
241265}
242266
243267pub 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;
268 for (self.symtab.items, 0..) |esym, i| {
269 if (esym.st_shndx != elf.SHN_UNDEF) continue;
247270
248 const global = elf_file.symbol(index);
249 const file = global.file(elf_file) orelse continue;
271 const ref = self.resolveSymbol(@intCast(i), elf_file);
272 const sym = elf_file.symbol(ref) orelse continue;
273 const file = sym.file(elf_file).?;
250274 const should_drop = switch (file) {
251 .shared_object => |sh| !sh.needed and sym.st_bind() == elf.STB_WEAK,
275 .shared_object => |sh| !sh.needed and esym.st_bind() == elf.STB_WEAK,
252276 else => false,
253277 };
254278 if (!should_drop and !file.isAlive()) {
......@@ -262,24 +286,24 @@ pub fn globals(self: SharedObject) []const Symbol.Index {
262286 return self.symbols.items;
263287}
264288
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;
289pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) void {
290 for (self.globals(), self.symbols_resolver.items) |*global, resolv| {
291 const ref = elf_file.resolver.get(resolv).?;
292 const ref_sym = elf_file.symbol(ref) orelse continue;
293 if (ref_sym.file(elf_file).?.index() != self.index) continue;
270294 if (global.isLocal(elf_file)) continue;
271295 global.flags.output_symtab = true;
272 try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
296 global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
273297 self.output_symtab_ctx.nglobals += 1;
274298 self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1;
275299 }
276300}
277301
278302pub 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;
303 for (self.globals(), self.symbols_resolver.items) |global, resolv| {
304 const ref = elf_file.resolver.get(resolv).?;
305 const ref_sym = elf_file.symbol(ref) orelse continue;
306 if (ref_sym.file(elf_file).?.index() != self.index) continue;
283307 const idx = global.outputSymtabIndex(elf_file) orelse continue;
284308 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
285309 elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file));
......@@ -332,10 +356,10 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void {
332356 defer aliases.deinit();
333357 try aliases.ensureTotalCapacityPrecise(self.globals().len);
334358
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;
359 for (self.symbols_resolvers.items, 0..) |resolv, index| {
360 const ref = elf_file.resolver.get(resolv).?;
361 const ref_sym = elf_file.symbol(ref) orelse continue;
362 if (ref_sym.file(elf_file).?.index() != self.index) continue;
339363 aliases.appendAssumeCapacity(index);
340364 }
341365
......@@ -347,16 +371,16 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void {
347371pub fn symbolAliases(self: *SharedObject, index: u32, elf_file: *Elf) []const u32 {
348372 assert(self.aliases != null);
349373
350 const symbol = elf_file.symbol(index).elfSym(elf_file);
374 const symbol = self.symbol(index).elfSym(elf_file);
351375 const aliases = self.aliases.?;
352376
353377 const start = for (aliases.items, 0..) |alias, i| {
354 const alias_sym = elf_file.symbol(alias).elfSym(elf_file);
378 const alias_sym = self.symbol(alias).elfSym(elf_file);
355379 if (symbol.st_value == alias_sym.st_value) break i;
356380 } else aliases.items.len;
357381
358382 const end = for (aliases.items[start..], 0..) |alias, i| {
359 const alias_sym = elf_file.symbol(alias).elfSym(elf_file);
383 const alias_sym = self.symbol(alias).elfSym(elf_file);
360384 if (symbol.st_value < alias_sym.st_value) break i + start;
361385 } else aliases.items.len;
362386
......@@ -368,6 +392,60 @@ pub fn getString(self: SharedObject, off: u32) [:0]const u8 {
368392 return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0);
369393}
370394
395pub fn resolveSymbol(self: SharedObject, index: Symbol.Index, elf_file: *Elf) Elf.Ref {
396 const resolv = self.symbols_resolver.items[index];
397 return elf_file.resolver.get(resolv).?;
398}
399
400pub fn addSymbol(self: *SharedObject, allocator: Allocator) !Symbol.Index {
401 try self.symbols.ensureUnusedCapacity(allocator, 1);
402 const index: Symbol.Index = @intCast(self.symbols.items.len);
403 self.symbols.appendAssumeCapacity(.{ .file_index = self.index });
404 return index;
405}
406
407pub fn addSymbolExtra(self: *SharedObject, allocator: Allocator, extra: Symbol.Extra) !u32 {
408 const fields = @typeInfo(Symbol.Extra).Struct.fields;
409 try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len);
410 return self.addSymbolExtraAssumeCapacity(extra);
411}
412
413pub fn addSymbolExtraAssumeCapacity(self: *SharedObject, extra: Symbol.Extra) u32 {
414 const index = @as(u32, @intCast(self.symbols_extra.items.len));
415 const fields = @typeInfo(Symbol.Extra).Struct.fields;
416 inline for (fields) |field| {
417 self.symbols_extra.appendAssumeCapacity(switch (field.type) {
418 u32 => @field(extra, field.name),
419 else => @compileError("bad field type"),
420 });
421 }
422 return index;
423}
424
425pub fn symbolExtra(self: *SharedObject, index: u32) Symbol.Extra {
426 const fields = @typeInfo(Symbol.Extra).Struct.fields;
427 var i: usize = index;
428 var result: Symbol.Extra = undefined;
429 inline for (fields) |field| {
430 @field(result, field.name) = switch (field.type) {
431 u32 => self.symbols_extra.items[i],
432 else => @compileError("bad field type"),
433 };
434 i += 1;
435 }
436 return result;
437}
438
439pub fn setSymbolExtra(self: *SharedObject, index: u32, extra: Symbol.Extra) void {
440 const fields = @typeInfo(Symbol.Extra).Struct.fields;
441 inline for (fields, 0..) |field, i| {
442 self.symbols_extra.items[index + i] = switch (field.type) {
443 u32 => @field(extra, field.name),
444 else => @compileError("bad field type"),
445 };
446 }
447}
448
371449pub fn format(
372450 self: SharedObject,
373451 comptime unused_fmt_string: []const u8,