authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-31 12:16:31+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-07 10:21:02+02:00
logd0367b02199417c10b2cde6d0deae4242689d127
tree02aa57392d556c2e01222ec4f4eaffa4ff1767c3
parent9ec415d4de1dcdac4c5fc772883c952b337d65e7

elf: move symbol ownership to Object


2 files changed, 222 insertions(+), 144 deletions(-)

src/link/Elf.zig+95-79
...@@ -5375,85 +5375,9 @@ pub fn comdatGroup(self: *Elf, ref: Ref) *ComdatGroup {...@@ -5375,85 +5375,9 @@ pub fn comdatGroup(self: *Elf, ref: Ref) *ComdatGroup {
5375 return self.file(ref.file).?.comdatGroup(ref.index);5375 return self.file(ref.file).?.comdatGroup(ref.index);
5376}5376}
53775377
5378/// Returns pointer-to-symbol described at sym_index.5378pub fn symbol(self: *Elf, ref: Ref) ?*Symbol {
5379pub fn symbol(self: *Elf, sym_index: Symbol.Index) *Symbol {5379 const file_ptr = self.file(ref.file) orelse return null;
5380 return &self.symbols.items[sym_index];5380 return file_ptr.symbol(ref.index);
5381}
5382
5383pub fn addSymbol(self: *Elf) !Symbol.Index {
5384 const gpa = self.base.comp.gpa;
5385 try self.symbols.ensureUnusedCapacity(gpa, 1);
5386 const index: Symbol.Index = @intCast(self.symbols.items.len);
5387 _ = self.symbols.addOneAssumeCapacity();
5388 self.symbols.items[index] = .{};
5389 return index;
5390}
5391
5392pub fn addSymbolExtra(self: *Elf, extra: Symbol.Extra) !u32 {
5393 const gpa = self.base.comp.gpa;
5394 const fields = @typeInfo(Symbol.Extra).Struct.fields;
5395 try self.symbols_extra.ensureUnusedCapacity(gpa, fields.len);
5396 return self.addSymbolExtraAssumeCapacity(extra);
5397}
5398
5399pub fn addSymbolExtraAssumeCapacity(self: *Elf, extra: Symbol.Extra) u32 {
5400 const index = @as(u32, @intCast(self.symbols_extra.items.len));
5401 const fields = @typeInfo(Symbol.Extra).Struct.fields;
5402 inline for (fields) |field| {
5403 self.symbols_extra.appendAssumeCapacity(switch (field.type) {
5404 u32 => @field(extra, field.name),
5405 else => @compileError("bad field type"),
5406 });
5407 }
5408 return index;
5409}
5410
5411pub fn symbolExtra(self: *Elf, index: u32) Symbol.Extra {
5412 const fields = @typeInfo(Symbol.Extra).Struct.fields;
5413 var i: usize = index;
5414 var result: Symbol.Extra = undefined;
5415 inline for (fields) |field| {
5416 @field(result, field.name) = switch (field.type) {
5417 u32 => self.symbols_extra.items[i],
5418 else => @compileError("bad field type"),
5419 };
5420 i += 1;
5421 }
5422 return result;
5423}
5424
5425pub fn setSymbolExtra(self: *Elf, index: u32, extra: Symbol.Extra) void {
5426 const fields = @typeInfo(Symbol.Extra).Struct.fields;
5427 inline for (fields, 0..) |field, i| {
5428 self.symbols_extra.items[index + i] = switch (field.type) {
5429 u32 => @field(extra, field.name),
5430 else => @compileError("bad field type"),
5431 };
5432 }
5433}
5434
5435const GetOrPutGlobalResult = struct {
5436 found_existing: bool,
5437 index: Symbol.Index,
5438};
5439
5440pub fn getOrPutGlobal(self: *Elf, name: []const u8) !GetOrPutGlobalResult {
5441 const gpa = self.base.comp.gpa;
5442 const name_off = try self.strings.insert(gpa, name);
5443 const gop = try self.resolver.getOrPut(gpa, name_off);
5444 if (!gop.found_existing) {
5445 const index = try self.addSymbol();
5446 log.debug("added symbol '{s}' at index {d}", .{ name, index });
5447 const global = self.symbol(index);
5448 global.name_offset = name_off;
5449 global.flags.global = true;
5450 global.extra_index = try self.addSymbolExtra(.{});
5451 gop.value_ptr.* = index;
5452 }
5453 return .{
5454 .found_existing = gop.found_existing,
5455 .index = gop.value_ptr.*,
5456 };
5457}5381}
54585382
5459pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 {5383pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 {
...@@ -6014,6 +5938,97 @@ pub const Ref = struct {...@@ -6014,6 +5938,97 @@ pub const Ref = struct {
6014 }5938 }
6015};5939};
60165940
5941pub const SymbolResolver = struct {
5942 keys: std.ArrayListUnmanaged(Key) = .{},
5943 values: std.ArrayListUnmanaged(Ref) = .{},
5944 table: std.AutoArrayHashMapUnmanaged(void, void) = .{},
5945
5946 const Result = struct {
5947 found_existing: bool,
5948 index: Index,
5949 ref: *Ref,
5950 };
5951
5952 pub fn deinit(resolver: *SymbolResolver, allocator: Allocator) void {
5953 resolver.keys.deinit(allocator);
5954 resolver.values.deinit(allocator);
5955 resolver.table.deinit(allocator);
5956 }
5957
5958 pub fn getOrPut(
5959 resolver: *SymbolResolver,
5960 allocator: Allocator,
5961 ref: Ref,
5962 elf_file: *Elf,
5963 ) !Result {
5964 const adapter = Adapter{ .keys = resolver.keys.items, .elf_file = elf_file };
5965 const key = Key{ .index = ref.index, .file = ref.file };
5966 const gop = try resolver.table.getOrPutAdapted(allocator, key, adapter);
5967 if (!gop.found_existing) {
5968 try resolver.keys.append(allocator, key);
5969 _ = try resolver.values.addOne(allocator);
5970 }
5971 return .{
5972 .found_existing = gop.found_existing,
5973 .index = @intCast(gop.index + 1),
5974 .ref = &resolver.values.items[gop.index],
5975 };
5976 }
5977
5978 pub fn get(resolver: SymbolResolver, index: Index) ?Ref {
5979 if (index == 0) return null;
5980 return resolver.values.items[index - 1];
5981 }
5982
5983 pub fn reset(resolver: *SymbolResolver) void {
5984 resolver.keys.clearRetainingCapacity();
5985 resolver.values.clearRetainingCapacity();
5986 resolver.table.clearRetainingCapacity();
5987 }
5988
5989 const Key = struct {
5990 index: Symbol.Index,
5991 file: File.Index,
5992
5993 fn name(key: Key, elf_file: *Elf) [:0]const u8 {
5994 const ref = Ref{ .index = key.index, .file = key.file };
5995 return ref.symbol(elf_file).?.name(elf_file);
5996 }
5997
5998 pub fn file(key: Key, elf_file: *Elf) ?File {
5999 const ref = Ref{ .index = key.index, .file = key.file };
6000 return ref.file(elf_file);
6001 }
6002
6003 fn eql(key: Key, other: Key, elf_file: *Elf) bool {
6004 const key_name = key.name(elf_file);
6005 const other_name = other.name(elf_file);
6006 return mem.eql(u8, key_name, other_name);
6007 }
6008
6009 fn hash(key: Key, elf_file: *Elf) u32 {
6010 return @truncate(Hash.hash(0, key.name(elf_file)));
6011 }
6012 };
6013
6014 const Adapter = struct {
6015 keys: []const Key,
6016 elf_file: *Elf,
6017
6018 pub fn eql(ctx: @This(), key: Key, b_void: void, b_map_index: usize) bool {
6019 _ = b_void;
6020 const other = ctx.keys[b_map_index];
6021 return key.eql(other, ctx.elf_file);
6022 }
6023
6024 pub fn hash(ctx: @This(), key: Key) u32 {
6025 return key.hash(ctx.elf_file);
6026 }
6027 };
6028
6029 pub const Index = u32;
6030};
6031
6017const LastAtomAndFreeList = struct {6032const LastAtomAndFreeList = struct {
6018 /// Index of the last allocated atom in this section.6033 /// Index of the last allocated atom in this section.
6019 last_atom_index: Atom.Index = 0,6034 last_atom_index: Atom.Index = 0,
...@@ -6127,6 +6142,7 @@ const File = @import("Elf/file.zig").File;...@@ -6127,6 +6142,7 @@ const File = @import("Elf/file.zig").File;
6127const GnuHashSection = synthetic_sections.GnuHashSection;6142const GnuHashSection = synthetic_sections.GnuHashSection;
6128const GotSection = synthetic_sections.GotSection;6143const GotSection = synthetic_sections.GotSection;
6129const GotPltSection = synthetic_sections.GotPltSection;6144const GotPltSection = synthetic_sections.GotPltSection;
6145const Hash = std.hash.Wyhash;
6130const HashSection = synthetic_sections.HashSection;6146const HashSection = synthetic_sections.HashSection;
6131const InputMergeSection = merge_section.InputMergeSection;6147const InputMergeSection = merge_section.InputMergeSection;
6132const LdScript = @import("Elf/LdScript.zig");6148const LdScript = @import("Elf/LdScript.zig");
src/link/Elf/Object.zig+127-65
...@@ -9,7 +9,9 @@ shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{},...@@ -9,7 +9,9 @@ shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{},
9symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},9symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
10strtab: std.ArrayListUnmanaged(u8) = .{},10strtab: std.ArrayListUnmanaged(u8) = .{},
11first_global: ?Symbol.Index = null,11first_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) = .{},
13relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},15relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
1416
15atoms: std.ArrayListUnmanaged(Atom) = .{},17atoms: std.ArrayListUnmanaged(Atom) = .{},
...@@ -51,6 +53,8 @@ pub fn deinit(self: *Object, allocator: Allocator) void {...@@ -51,6 +53,8 @@ pub fn deinit(self: *Object, allocator: Allocator) void {
51 self.symtab.deinit(allocator);53 self.symtab.deinit(allocator);
52 self.strtab.deinit(allocator);54 self.strtab.deinit(allocator);
53 self.symbols.deinit(allocator);55 self.symbols.deinit(allocator);
56 self.symbols_extra.deinit(allocator);
57 self.symbols_resolver.deinit(allocator);
54 self.atoms.deinit(allocator);58 self.atoms.deinit(allocator);
55 self.atoms_indexes.deinit(allocator);59 self.atoms_indexes.deinit(allocator);
56 self.atoms_extra.deinit(allocator);60 self.atoms_extra.deinit(allocator);
...@@ -80,7 +84,7 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {...@@ -80,7 +84,7 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {
80 try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) });84 try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) });
8185
82 try self.initAtoms(gpa, handle, elf_file);86 try self.initAtoms(gpa, handle, elf_file);
83 try self.initSymtab(gpa, elf_file);87 try self.initSymbols(gpa, elf_file);
8488
85 for (self.shdrs.items, 0..) |shdr, i| {89 for (self.shdrs.items, 0..) |shdr, i| {
86 const atom_ptr = self.atom(self.atoms_indexes.items[i]) orelse continue;90 const atom_ptr = self.atom(self.atoms_indexes.items[i]) orelse continue;
...@@ -374,30 +378,30 @@ fn skipShdr(self: *Object, index: u32, elf_file: *Elf) bool {...@@ -374,30 +378,30 @@ fn skipShdr(self: *Object, index: u32, elf_file: *Elf) bool {
374 return ignore;378 return ignore;
375}379}
376380
377fn initSymtab(self: *Object, allocator: Allocator, elf_file: *Elf) !void {381fn initSymbols(self: *Object, allocator: Allocator, elf_file: *Elf) !void {
378 const first_global = self.first_global orelse self.symtab.items.len;382 const first_global = self.first_global orelse self.symtab.items.len;
383 const nglobals = self.symtab.items.len - first_global;
379384
380 try self.symbols.ensureTotalCapacityPrecise(allocator, self.symtab.items.len);385 try self.symbols.ensureTotalCapacityPrecise(allocator, self.symtab.items.len);
381386 try self.symbols_extra.ensureTotalCapacityPrecise(allocator, self.symtab.items.len * @sizeOf(Symbol.Extra));
382 for (self.symtab.items[0..first_global], 0..) |sym, i| {387 try self.symbols_resolver.ensureTotalCapacityPrecise(allocator, nglobals);
383 const index = try elf_file.addSymbol();388 self.symbols_resolver.resize(allocator, nglobals) catch unreachable;
384 self.symbols.appendAssumeCapacity(index);389 @memset(self.symbols_resolver.items, 0);
385 const sym_ptr = elf_file.symbol(index);390
391 for (self.symtab.items, 0..) |sym, i| {
392 const index = self.addSymbolAssumeCapacity();
393 const sym_ptr = &self.symbols.items[index];
386 sym_ptr.value = @intCast(sym.st_value);394 sym_ptr.value = @intCast(sym.st_value);
387 sym_ptr.name_offset = sym.st_name;395 sym_ptr.name_offset = sym.st_name;
388 sym_ptr.esym_index = @as(u32, @intCast(i));396 sym_ptr.esym_index = @intCast(i);
389 sym_ptr.file_index = self.index;397 sym_ptr.extra_index = self.addSymbolExtraAssumeCapacity(.{
390 sym_ptr.extra_index = try elf_file.addSymbolExtra(.{});398 .weak = sym.st_bind() == elf.STB_WEAK,
391 if (sym.st_shndx != elf.SHN_ABS) {399 });
400 sym_ptr.version_index = if (i >= first_global) elf_file.default_sym_version else elf.VER_NDX_LOCAL;
401 if (sym.st_shndx != elf.SHN_ABS and sym.st_shndx != elf.SHN_COMMON) {
392 sym_ptr.ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index };402 sym_ptr.ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index };
393 }403 }
394 }404 }
395
396 for (self.symtab.items[first_global..]) |sym| {
397 const name = self.getString(sym.st_name);
398 const gop = try elf_file.getOrPutGlobal(name);
399 self.symbols.addOneAssumeCapacity().* = gop.index;
400 }
401}405}
402406
403fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx: u32, elf_file: *Elf) !void {407fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx: u32, elf_file: *Elf) !void {
...@@ -544,7 +548,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {...@@ -544,7 +548,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {
544548
545 for (self.cies.items) |cie| {549 for (self.cies.items) |cie| {
546 for (cie.relocs(elf_file)) |rel| {550 for (cie.relocs(elf_file)) |rel| {
547 const sym = elf_file.symbol(self.symbols.items[rel.r_sym()]);551 const sym = elf_file.symbol(self.resolveSymbol(rel.r_sym()));
548 if (sym.flags.import) {552 if (sym.flags.import) {
549 if (sym.type(elf_file) != elf.STT_FUNC)553 if (sym.type(elf_file) != elf.STT_FUNC)
550 // TODO convert into an error554 // TODO convert into an error
...@@ -559,48 +563,46 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {...@@ -559,48 +563,46 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {
559}563}
560564
561pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {565pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {
562 const first_global = self.first_global orelse return;566 const gpa = elf_file.base.comp.gpa;
563 for (self.globals(), 0..) |index, i| {
564 const esym_index = @as(Symbol.Index, @intCast(first_global + i));
565 const esym = self.symtab.items[esym_index];
566
567 if (esym.st_shndx == elf.SHN_UNDEF) continue;
568567
568 const first_global = self.first_global orelse return;
569 for (self.globals(), first_global..) |_, i| {
570 const esym = self.symtab.items[i];
569 if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {571 if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {
570 const atom_index = self.atoms_indexes.items[esym.st_shndx];572 const atom_index = self.atoms_indexes.items[esym.st_shndx];
571 const atom_ptr = self.atom(atom_index) orelse continue;573 const atom_ptr = self.atom(atom_index) orelse continue;
572 if (!atom_ptr.alive) continue;574 if (!atom_ptr.alive) continue;
573 }575 }
574576
575 const global = elf_file.symbol(index);577 const resolv = &self.symbols_resolver.items[i - first_global];
576 if (self.asFile().symbolRank(esym, !self.alive) < global.symbolRank(elf_file)) {578 const gop = try elf_file.resolver.getOrPut(gpa, .{
577 switch (esym.st_shndx) {579 .index = @intCast(i),
578 elf.SHN_ABS, elf.SHN_COMMON => {},580 .file = self.index,
579 else => global.ref = .{581 }, elf_file);
580 .index = self.atoms_indexes.items[esym.st_shndx],582 if (!gop.found_existing) {
581 .file = self.index,583 gop.ref.* = .{ .index = 0, .file = 0 };
582 },584 }
583 }585 resolv.* = gop.index;
584 global.value = @intCast(esym.st_value);586
585 global.esym_index = esym_index;587 if (esym.st_shndx == elf.SHN_UNDEF) continue;
586 global.file_index = self.index;588 if (elf_file.symbol(gop.ref) == null) {
587 global.version_index = elf_file.default_sym_version;589 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
588 if (esym.st_bind() == elf.STB_WEAK) global.flags.weak = true;590 continue;
591 }
592
593 if (self.asFile().symbolRank(esym, !self.alive) < elf_file.symbol(gop.ref).?.symbolRank(elf_file)) {
594 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
589 }595 }
590 }596 }
591}597}
592598
593pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {599pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {
594 const first_global = self.first_global orelse return;600 const first_global = self.first_global orelse return;
595 for (self.globals(), 0..) |index, i| {601 for (self.globals(), 0..) |*sym, i| {
596 const esym_index = @as(u32, @intCast(first_global + i));602 const esym_index = @as(u32, @intCast(first_global + i));
597 const esym = self.symtab.items[esym_index];603 const esym = self.symtab.items[esym_index];
598 if (esym.st_shndx != elf.SHN_UNDEF) continue;604 if (esym.st_shndx != elf.SHN_UNDEF) continue;
599605 if (elf_file.symbol(self.resolveSymbol(esym_index, elf_file)) != null) continue;
600 const global = elf_file.symbol(index);
601 if (global.file(elf_file)) |_| {
602 if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF) continue;
603 }
604606
605 const is_import = blk: {607 const is_import = blk: {
606 if (!elf_file.isEffectivelyDynLib()) break :blk false;608 if (!elf_file.isEffectivelyDynLib()) break :blk false;
...@@ -609,12 +611,15 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {...@@ -609,12 +611,15 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {
609 break :blk true;611 break :blk true;
610 };612 };
611613
612 global.value = 0;614 sym.value = 0;
613 global.ref = .{ .index = 0, .file = 0 };615 sym.ref = .{ .index = 0, .file = 0 };
614 global.esym_index = esym_index;616 sym.esym_index = esym_index;
615 global.file_index = self.index;617 sym.file_index = self.index;
616 global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;618 sym.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
617 global.flags.import = is_import;619 sym.flags.import = is_import;
620
621 const idx = self.symbols_resolver.items[i];
622 elf_file.resolver.values.items[idx - 1] = .{ .index = esym_index, .file = self.index };
618 }623 }
619}624}
620625
...@@ -1141,20 +1146,6 @@ pub fn writeSymtab(self: Object, elf_file: *Elf) void {...@@ -1141,20 +1146,6 @@ pub fn writeSymtab(self: Object, elf_file: *Elf) void {
1141 }1146 }
1142}1147}
11431148
1144pub fn locals(self: Object) []const Symbol.Index {
1145 if (self.symbols.items.len == 0) return &[0]Symbol.Index{};
1146 assert(self.symbols.items.len >= self.symtab.items.len);
1147 const end = self.first_global orelse self.symtab.items.len;
1148 return self.symbols.items[0..end];
1149}
1150
1151pub fn globals(self: Object) []const Symbol.Index {
1152 if (self.symbols.items.len == 0) return &[0]Symbol.Index{};
1153 assert(self.symbols.items.len >= self.symtab.items.len);
1154 const start = self.first_global orelse self.symtab.items.len;
1155 return self.symbols.items[start..self.symtab.items.len];
1156}
1157
1158/// Returns atom's code and optionally uncompresses data if required (for compressed sections).1149/// Returns atom's code and optionally uncompresses data if required (for compressed sections).
1159/// Caller owns the memory.1150/// Caller owns the memory.
1160pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {1151pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
...@@ -1187,6 +1178,77 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index...@@ -1187,6 +1178,77 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index
1187 return data;1178 return data;
1188}1179}
11891180
1181pub fn locals(self: *Object) []Symbol {
1182 if (self.symbols.items.len == 0) return &[0]Symbol{};
1183 assert(self.symbols.items.len >= self.symtab.items.len);
1184 const end = self.first_global orelse self.symtab.items.len;
1185 return self.symbols.items[0..end];
1186}
1187
1188pub fn globals(self: *Object) []Symbol {
1189 if (self.symbols.items.len == 0) return &[0]Symbol{};
1190 assert(self.symbols.items.len >= self.symtab.items.len);
1191 const start = self.first_global orelse self.symtab.items.len;
1192 return self.symbols.items[start..self.symtab.items.len];
1193}
1194
1195pub fn resolveSymbol(self: Object, index: Symbol.Index, elf_file: *Elf) Elf.Ref {
1196 const start = self.first_global orelse self.symtab.items.len;
1197 const end = self.symtab.items.len;
1198 if (index < start or index >= end) return .{ .index = index, .file = self.index };
1199 const resolv = self.symbols_resolver.items[index - start];
1200 return elf_file.resolver.get(resolv).?;
1201}
1202
1203pub fn addSymbol(self: *Object, allocator: Allocator) !Symbol.Index {
1204 try self.symbols.ensureUnusedCapacity(allocator, 1);
1205 const index: Symbol.Index = @intCast(self.symbols.items.len);
1206 self.symbols.appendAssumeCapacity(.{ .file_index = self.index });
1207 return index;
1208}
1209
1210pub fn addSymbolExtra(self: *Object, allocator: Allocator, extra: Symbol.Extra) !u32 {
1211 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1212 try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len);
1213 return self.addSymbolExtraAssumeCapacity(extra);
1214}
1215
1216pub fn addSymbolExtraAssumeCapacity(self: *Object, extra: Symbol.Extra) u32 {
1217 const index = @as(u32, @intCast(self.symbols_extra.items.len));
1218 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1219 inline for (fields) |field| {
1220 self.symbols_extra.appendAssumeCapacity(switch (field.type) {
1221 u32 => @field(extra, field.name),
1222 else => @compileError("bad field type"),
1223 });
1224 }
1225 return index;
1226}
1227
1228pub fn symbolExtra(self: *Object, index: u32) Symbol.Extra {
1229 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1230 var i: usize = index;
1231 var result: Symbol.Extra = undefined;
1232 inline for (fields) |field| {
1233 @field(result, field.name) = switch (field.type) {
1234 u32 => self.symbols_extra.items[i],
1235 else => @compileError("bad field type"),
1236 };
1237 i += 1;
1238 }
1239 return result;
1240}
1241
1242pub fn setSymbolExtra(self: *Object, index: u32, extra: Symbol.Extra) void {
1243 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1244 inline for (fields, 0..) |field, i| {
1245 self.symbols_extra.items[index + i] = switch (field.type) {
1246 u32 => @field(extra, field.name),
1247 else => @compileError("bad field type"),
1248 };
1249 }
1250}
1251
1190pub fn asFile(self: *Object) File {1252pub fn asFile(self: *Object) File {
1191 return .{ .object = self };1253 return .{ .object = self };
1192}1254}