Commit 518c7908f0

Jakub Konka <kubkon@jakubkonka.com>
2024-07-30 14:59:59
elf: always create symbol extra
1 parent f9f8942
src/link/Elf/Atom.zig
@@ -845,7 +845,7 @@ fn resolveDynAbsReloc(
             if (is_writeable or elf_file.z_nocopyreloc) {
                 elf_file.addRelaDynAssumeCapacity(.{
                     .offset = P,
-                    .sym = target.extra(elf_file).?.dynamic,
+                    .sym = target.extra(elf_file).dynamic,
                     .type = relocation.encode(.abs, cpu_arch),
                     .addend = A,
                 });
@@ -859,7 +859,7 @@ fn resolveDynAbsReloc(
             if (is_writeable) {
                 elf_file.addRelaDynAssumeCapacity(.{
                     .offset = P,
-                    .sym = target.extra(elf_file).?.dynamic,
+                    .sym = target.extra(elf_file).dynamic,
                     .type = relocation.encode(.abs, cpu_arch),
                     .addend = A,
                 });
@@ -872,7 +872,7 @@ fn resolveDynAbsReloc(
         .dynrel => {
             elf_file.addRelaDynAssumeCapacity(.{
                 .offset = P,
-                .sym = target.extra(elf_file).?.dynamic,
+                .sym = target.extra(elf_file).dynamic,
                 .type = relocation.encode(.abs, cpu_arch),
                 .addend = A,
             });
src/link/Elf/file.zig
@@ -71,9 +71,11 @@ pub const File = union(enum) {
         for (file.globals()) |global_index| {
             const global = elf_file.symbol(global_index);
             const name_offset = global.name_offset;
+            const extra_index = global.extra_index;
             global.* = .{};
             global.name_offset = name_offset;
             global.flags.global = true;
+            global.extra_index = extra_index;
         }
     }
 
src/link/Elf/Object.zig
@@ -387,6 +387,7 @@ fn initSymtab(self: *Object, allocator: Allocator, elf_file: *Elf) !void {
         sym_ptr.name_offset = sym.st_name;
         sym_ptr.esym_index = @as(u32, @intCast(i));
         sym_ptr.file_index = self.index;
+        sym_ptr.extra_index = try elf_file.addSymbolExtra(.{});
         if (sym.st_shndx != elf.SHN_ABS) {
             sym_ptr.ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index };
         }
@@ -865,6 +866,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
                 .name_offset = try self.addString(gpa, name),
                 .esym_index = rel.r_sym(),
                 .file_index = self.index,
+                .extra_index = try elf_file.addSymbolExtra(.{}),
             };
             sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index };
             sym.flags.merge_subsection = true;
src/link/Elf/Symbol.zig
@@ -159,20 +159,20 @@ pub fn outputSymtabIndex(symbol: Symbol, elf_file: *Elf) ?u32 {
     const symtab_ctx = switch (file_ptr) {
         inline else => |x| x.output_symtab_ctx,
     };
-    const idx = symbol.extra(elf_file).?.symtab;
+    const idx = symbol.extra(elf_file).symtab;
     return if (symbol.isLocal(elf_file)) idx + symtab_ctx.ilocal else idx + symtab_ctx.iglobal;
 }
 
 pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 {
     if (!symbol.flags.has_got) return 0;
-    const extras = symbol.extra(elf_file).?;
+    const extras = symbol.extra(elf_file);
     const entry = elf_file.got.entries.items[extras.got];
     return entry.address(elf_file);
 }
 
 pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
     if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0;
-    const extras = symbol.extra(elf_file).?;
+    const extras = symbol.extra(elf_file);
     const shdr = elf_file.shdrs.items[elf_file.plt_got_section_index.?];
     const cpu_arch = elf_file.getTarget().cpu.arch;
     return @intCast(shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch));
@@ -180,7 +180,7 @@ pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
 
 pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 {
     if (!symbol.flags.has_plt) return 0;
-    const extras = symbol.extra(elf_file).?;
+    const extras = symbol.extra(elf_file);
     const shdr = elf_file.shdrs.items[elf_file.plt_section_index.?];
     const cpu_arch = elf_file.getTarget().cpu.arch;
     return @intCast(shdr.sh_addr + extras.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch));
@@ -188,7 +188,7 @@ pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 {
 
 pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) i64 {
     if (!symbol.flags.has_plt) return 0;
-    const extras = symbol.extra(elf_file).?;
+    const extras = symbol.extra(elf_file);
     const shdr = elf_file.shdrs.items[elf_file.got_plt_section_index.?];
     return @intCast(shdr.sh_addr + extras.plt * 8 + GotPltSection.preamble_size);
 }
@@ -201,21 +201,21 @@ pub fn copyRelAddress(symbol: Symbol, elf_file: *Elf) i64 {
 
 pub fn tlsGdAddress(symbol: Symbol, elf_file: *Elf) i64 {
     if (!symbol.flags.has_tlsgd) return 0;
-    const extras = symbol.extra(elf_file).?;
+    const extras = symbol.extra(elf_file);
     const entry = elf_file.got.entries.items[extras.tlsgd];
     return entry.address(elf_file);
 }
 
 pub fn gotTpAddress(symbol: Symbol, elf_file: *Elf) i64 {
     if (!symbol.flags.has_gottp) return 0;
-    const extras = symbol.extra(elf_file).?;
+    const extras = symbol.extra(elf_file);
     const entry = elf_file.got.entries.items[extras.gottp];
     return entry.address(elf_file);
 }
 
 pub fn tlsDescAddress(symbol: Symbol, elf_file: *Elf) i64 {
     if (!symbol.flags.has_tlsdesc) return 0;
-    const extras = symbol.extra(elf_file).?;
+    const extras = symbol.extra(elf_file);
     const entry = elf_file.got.entries.items[extras.tlsdesc];
     return entry.address(elf_file);
 }
@@ -228,14 +228,14 @@ const GetOrCreateZigGotEntryResult = struct {
 pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, elf_file: *Elf) !GetOrCreateZigGotEntryResult {
     assert(!elf_file.base.isRelocatable());
     assert(symbol.flags.needs_zig_got);
-    if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.extra(elf_file).?.zig_got };
+    if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.extra(elf_file).zig_got };
     const index = try elf_file.zig_got.addSymbol(symbol_index, elf_file);
     return .{ .found_existing = false, .index = index };
 }
 
 pub fn zigGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
     if (!symbol.flags.has_zig_got) return 0;
-    const extras = symbol.extra(elf_file).?;
+    const extras = symbol.extra(elf_file);
     return elf_file.zig_got.entryAddress(extras.zig_got, elf_file);
 }
 
@@ -266,10 +266,7 @@ const AddExtraOpts = struct {
 };
 
 pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void {
-    if (symbol.extra(elf_file) == null) {
-        symbol.extra_index = try elf_file.addSymbolExtra(.{});
-    }
-    var extras = symbol.extra(elf_file).?;
+    var extras = symbol.extra(elf_file);
     inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| {
         if (@field(opts, field.name)) |x| {
             @field(extras, field.name) = x;
@@ -278,7 +275,7 @@ pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void {
     symbol.setExtra(extras, elf_file);
 }
 
-pub fn extra(symbol: Symbol, elf_file: *Elf) ?Extra {
+pub fn extra(symbol: Symbol, elf_file: *Elf) Extra {
     return elf_file.symbolExtra(symbol.extra_index);
 }
 
src/link/Elf/synthetic_sections.zig
@@ -641,7 +641,7 @@ pub const GotSection = struct {
                 .tlsld => null,
                 inline else => elf_file.symbol(entry.symbol_index),
             };
-            const extra = if (symbol) |s| s.extra(elf_file).? else null;
+            const extra = if (symbol) |s| s.extra(elf_file) else null;
 
             switch (entry.tag) {
                 .got => {
@@ -898,7 +898,7 @@ pub const PltSection = struct {
         for (plt.symbols.items) |sym_index| {
             const sym = elf_file.symbol(sym_index);
             assert(sym.flags.import);
-            const extra = sym.extra(elf_file).?;
+            const extra = sym.extra(elf_file);
             const r_offset: u64 = @intCast(sym.gotPltAddress(elf_file));
             const r_sym: u64 = extra.dynamic;
             const r_type = relocation.encode(.jump_slot, cpu_arch);
@@ -1267,7 +1267,7 @@ pub const CopyRelSection = struct {
         for (copy_rel.symbols.items) |sym_index| {
             const sym = elf_file.symbol(sym_index);
             assert(sym.flags.import and sym.flags.has_copy_rel);
-            const extra = sym.extra(elf_file).?;
+            const extra = sym.extra(elf_file);
             elf_file.addRelaDynAssumeCapacity(.{
                 .offset = @intCast(sym.address(.{}, elf_file)),
                 .sym = extra.dynamic,
@@ -1322,7 +1322,7 @@ pub const DynsymSection = struct {
                 const rhs_hash = GnuHashSection.hasher(rhs_sym.name(ctx)) % nbuckets;
 
                 if (lhs_hash == rhs_hash)
-                    return lhs_sym.extra(ctx).?.dynamic < rhs_sym.extra(ctx).?.dynamic;
+                    return lhs_sym.extra(ctx).dynamic < rhs_sym.extra(ctx).dynamic;
                 return lhs_hash < rhs_hash;
             }
         };
@@ -1339,7 +1339,7 @@ pub const DynsymSection = struct {
 
         for (dynsym.entries.items, 1..) |entry, index| {
             const sym = elf_file.symbol(entry.symbol_index);
-            var extra = sym.extra(elf_file).?;
+            var extra = sym.extra(elf_file);
             extra.dynamic = @as(u32, @intCast(index));
             sym.setExtra(extra, elf_file);
         }
src/link/Elf/ZigObject.zig
@@ -92,6 +92,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
     const symbol_ptr = elf_file.symbol(symbol_index);
     symbol_ptr.file_index = self.index;
     symbol_ptr.name_offset = name_off;
+    symbol_ptr.extra_index = try elf_file.addSymbolExtra(.{});
 
     const esym_index = try self.addLocalEsym(gpa);
     const esym = &self.local_esyms.items(.elf_sym)[esym_index];
@@ -292,6 +293,7 @@ pub fn newAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {
     const symbol_ptr = elf_file.symbol(symbol_index);
     symbol_ptr.file_index = self.index;
     symbol_ptr.ref = .{ .index = atom_index, .file = self.index };
+    symbol_ptr.extra_index = try elf_file.addSymbolExtra(.{});
 
     self.local_esyms.items(.shndx)[esym_index] = atom_index;
     self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM;
@@ -779,11 +781,9 @@ fn freeUnnamedConsts(self: *ZigObject, elf_file: *Elf, decl_index: InternPool.De
 
 fn freeDeclMetadata(self: *ZigObject, elf_file: *Elf, sym_index: Symbol.Index) void {
     _ = self;
-    const gpa = elf_file.base.comp.gpa;
     const sym = elf_file.symbol(sym_index);
     sym.atom(elf_file).?.free(elf_file);
     log.debug("adding %{d} to local symbols free list", .{sym_index});
-    elf_file.symbols_free_list.append(gpa, sym_index) catch {};
     elf_file.symbols.items[sym_index] = .{};
     // TODO free GOT entry here
 }
@@ -940,7 +940,7 @@ fn updateDeclCode(
                 if (!elf_file.base.isRelocatable()) {
                     log.debug("  (writing new offset table entry)", .{});
                     assert(sym.flags.has_zig_got);
-                    const extra = sym.extra(elf_file).?;
+                    const extra = sym.extra(elf_file);
                     try elf_file.zig_got.writeOne(elf_file, extra.zig_got);
                 }
             }
src/link/Elf.zig
@@ -176,7 +176,6 @@ symtab_section_index: ?u32 = null,
 /// An array of symbols parsed across all input files.
 symbols: std.ArrayListUnmanaged(Symbol) = .{},
 symbols_extra: std.ArrayListUnmanaged(u32) = .{},
-symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
 
 resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{},
 
@@ -343,8 +342,6 @@ pub fn createEmpty(
 
     // Index 0 is always a null symbol.
     try self.symbols.append(gpa, .{});
-    // Index 0 is always a null symbol.
-    try self.symbols_extra.append(gpa, 0);
     // Append null file at index 0
     try self.files.append(gpa, .null);
     // Append null byte to string tables
@@ -462,7 +459,6 @@ pub fn deinit(self: *Elf) void {
     self.strtab.deinit(gpa);
     self.symbols.deinit(gpa);
     self.symbols_extra.deinit(gpa);
-    self.symbols_free_list.deinit(gpa);
     self.resolver.deinit(gpa);
 
     for (self.thunks.items) |*th| {
@@ -5389,17 +5385,8 @@ pub fn symbol(self: *Elf, sym_index: Symbol.Index) *Symbol {
 pub fn addSymbol(self: *Elf) !Symbol.Index {
     const gpa = self.base.comp.gpa;
     try self.symbols.ensureUnusedCapacity(gpa, 1);
-    const index = blk: {
-        if (self.symbols_free_list.popOrNull()) |index| {
-            log.debug("  (reusing symbol index {d})", .{index});
-            break :blk index;
-        } else {
-            log.debug("  (allocating symbol index {d})", .{self.symbols.items.len});
-            const index: Symbol.Index = @intCast(self.symbols.items.len);
-            _ = self.symbols.addOneAssumeCapacity();
-            break :blk index;
-        }
-    };
+    const index: Symbol.Index = @intCast(self.symbols.items.len);
+    _ = self.symbols.addOneAssumeCapacity();
     self.symbols.items[index] = .{};
     return index;
 }
@@ -5423,8 +5410,7 @@ pub fn addSymbolExtraAssumeCapacity(self: *Elf, extra: Symbol.Extra) u32 {
     return index;
 }
 
-pub fn symbolExtra(self: *Elf, index: u32) ?Symbol.Extra {
-    if (index == 0) return null;
+pub fn symbolExtra(self: *Elf, index: u32) Symbol.Extra {
     const fields = @typeInfo(Symbol.Extra).Struct.fields;
     var i: usize = index;
     var result: Symbol.Extra = undefined;
@@ -5439,7 +5425,6 @@ pub fn symbolExtra(self: *Elf, index: u32) ?Symbol.Extra {
 }
 
 pub fn setSymbolExtra(self: *Elf, index: u32, extra: Symbol.Extra) void {
-    assert(index > 0);
     const fields = @typeInfo(Symbol.Extra).Struct.fields;
     inline for (fields, 0..) |field, i| {
         self.symbols_extra.items[index + i] = switch (field.type) {
@@ -5464,6 +5449,7 @@ pub fn getOrPutGlobal(self: *Elf, name: []const u8) !GetOrPutGlobalResult {
         const global = self.symbol(index);
         global.name_offset = name_off;
         global.flags.global = true;
+        global.extra_index = try self.addSymbolExtra(.{});
         gop.value_ptr.* = index;
     }
     return .{