Commit 93120a81fe

Jakub Konka <kubkon@jakubkonka.com>
2023-09-06 14:42:32
elf: lift-off - get it to compile and run until the error!
1 parent a9df098
src/link/Elf/Atom.zig
@@ -79,7 +79,7 @@ pub fn freeRelocations(elf_file: *Elf, atom_index: Index) void {
     if (removed_relocs) |*relocs| relocs.value.deinit(elf_file.base.allocator);
 }
 
-pub fn allocate(self: *Atom, elf_file: *Elf) !u64 {
+pub fn allocate(self: *Atom, elf_file: *Elf) !void {
     const phdr_index = elf_file.sections.items(.phdr_index)[self.output_section_index];
     const phdr = &elf_file.program_headers.items[phdr_index];
     const shdr = &elf_file.sections.items(.shdr)[self.output_section_index];
@@ -98,7 +98,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !u64 {
 
     // First we look for an appropriately sized free list node.
     // The list is unordered. We'll just take the first thing that works.
-    const vaddr = blk: {
+    self.value = blk: {
         var i: usize = if (elf_file.base.child_pid == null) 0 else free_list.items.len;
         while (i < free_list.items.len) {
             const big_atom_index = free_list.items[i];
@@ -152,7 +152,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !u64 {
     else
         true;
     if (expand_section) {
-        const needed_size = (vaddr + self.size) - phdr.p_vaddr;
+        const needed_size = (self.value + self.size) - phdr.p_vaddr;
         try elf_file.growAllocSection(self.output_section_index, needed_size);
         maybe_last_atom_index.* = self.atom_index;
 
@@ -193,7 +193,6 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !u64 {
     if (free_list_removal) |i| {
         _ = free_list.swapRemove(i);
     }
-    return vaddr;
 }
 
 pub fn shrink(self: *Atom, elf_file: *Elf) void {
@@ -201,12 +200,69 @@ pub fn shrink(self: *Atom, elf_file: *Elf) void {
     _ = elf_file;
 }
 
-pub fn grow(self: *Atom, elf_file: *Elf) !u64 {
+pub fn grow(self: *Atom, elf_file: *Elf) !void {
     const alignment = try std.math.powi(u64, 2, self.alignment);
     const align_ok = std.mem.alignBackward(u64, self.value, alignment) == self.value;
     const need_realloc = !align_ok or self.size > self.capacity(elf_file);
-    if (!need_realloc) return self.value;
-    return self.allocate(elf_file);
+    if (need_realloc) try self.allocate(elf_file);
+}
+
+pub fn free(self: *Atom, elf_file: *Elf) void {
+    log.debug("freeAtom {d} ({s})", .{ self.atom_index, self.name(elf_file) });
+
+    Atom.freeRelocations(elf_file, self.atom_index);
+
+    const gpa = elf_file.base.allocator;
+    const shndx = self.output_section_index;
+    const free_list = &elf_file.sections.items(.free_list)[shndx];
+    var already_have_free_list_node = false;
+    {
+        var i: usize = 0;
+        // TODO turn free_list into a hash map
+        while (i < free_list.items.len) {
+            if (free_list.items[i] == self.atom_index) {
+                _ = free_list.swapRemove(i);
+                continue;
+            }
+            if (free_list.items[i] == self.prev_index) {
+                already_have_free_list_node = true;
+            }
+            i += 1;
+        }
+    }
+
+    const maybe_last_atom_index = &elf_file.sections.items(.last_atom_index)[shndx];
+    if (maybe_last_atom_index.*) |last_atom_index| {
+        if (last_atom_index == self.atom_index) {
+            if (self.prev_index) |prev_index| {
+                // TODO shrink the section size here
+                maybe_last_atom_index.* = prev_index;
+            } else {
+                maybe_last_atom_index.* = null;
+            }
+        }
+    }
+
+    if (self.prev_index) |prev_index| {
+        const prev = elf_file.atom(prev_index);
+        prev.next_index = self.next_index;
+
+        if (!already_have_free_list_node and prev.*.freeListEligible(elf_file)) {
+            // The free list is heuristics, it doesn't have to be perfect, so we can
+            // ignore the OOM here.
+            free_list.append(gpa, prev_index) catch {};
+        }
+    } else {
+        self.prev_index = null;
+    }
+
+    if (self.next_index) |next_index| {
+        elf_file.atom(next_index).prev_index = self.prev_index;
+    } else {
+        self.next_index = null;
+    }
+
+    self.* = .{};
 }
 
 pub const Index = u32;
@@ -221,6 +277,7 @@ pub const Reloc = struct {
 const std = @import("std");
 const assert = std.debug.assert;
 const elf = std.elf;
+const log = std.log.scoped(.link);
 
 const Atom = @This();
 const Elf = @import("../Elf.zig");
src/link/Elf/file.zig
@@ -10,12 +10,6 @@ pub const File = union(enum) {
         };
     }
 
-    pub fn sourceSymbol(file: File, symbol_index: Symbol.Index) *elf.Elf64_Sym {
-        return switch (file) {
-            inline else => |x| x.sourceSymbol(symbol_index),
-        };
-    }
-
     pub fn fmtPath(file: File) std.fmt.Formatter(formatPath) {
         return .{ .data = file };
     }
src/link/Elf/Symbol.zig
@@ -1,5 +1,7 @@
 //! Represents a defined symbol.
 
+index: Index = 0,
+
 /// Allocated address value of this symbol.
 value: u64 = 0,
 
@@ -18,8 +20,8 @@ atom_index: Atom.Index = 0,
 output_section_index: u16 = 0,
 
 /// Index of the source symbol this symbol references.
-/// Use `getSourceSymbol` to pull the source symbol from the relevant file.
-symbol_index: Index = 0,
+/// Use `sourceSymbol` to pull the source symbol from the relevant file.
+esym_index: Index = 0,
 
 /// Index of the source version symbol this symbol references if any.
 /// If the symbol is unversioned it will have either VER_NDX_LOCAL or VER_NDX_GLOBAL.
@@ -64,7 +66,11 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File {
 }
 
 pub fn sourceSymbol(symbol: Symbol, elf_file: *Elf) *elf.Elf64_Sym {
-    return symbol.file(elf_file).?.sourceSymbol(symbol.symbol_index);
+    const file_ptr = symbol.file(elf_file).?;
+    switch (file_ptr) {
+        .zig_module => return file_ptr.zig_module.sourceSymbol(symbol.index, elf_file),
+        .linker_defined => return file_ptr.linker_defined.sourceSymbol(symbol.esym_index),
+    }
 }
 
 pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 {
@@ -80,14 +86,14 @@ pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 {
 /// If entry already exists, returns index to it.
 /// Otherwise, creates a new entry in the Global Offset Table for this Symbol.
 pub fn getOrCreateOffsetTableEntry(self: Symbol, elf_file: *Elf) !Symbol.Index {
-    if (elf_file.got_table.lookup.get(self.symbol_index)) |index| return index;
-    const index = try elf_file.got_table.allocateEntry(elf_file.base.allocator, self.symbol_index);
+    if (elf_file.got_table.lookup.get(self.index)) |index| return index;
+    const index = try elf_file.got_table.allocateEntry(elf_file.base.allocator, self.index);
     elf_file.got_table_count_dirty = true;
     return index;
 }
 
 pub fn getOffsetTableAddress(self: Symbol, elf_file: *Elf) u64 {
-    const got_entry_index = elf_file.got_table.lookup.get(self.symbol_index).?;
+    const got_entry_index = elf_file.got_table.lookup.get(self.index).?;
     const target = elf_file.base.options.target;
     const ptr_bits = target.ptrBitWidth();
     const ptr_bytes: u64 = @divExact(ptr_bits, 8);
@@ -263,7 +269,7 @@ fn format2(
     _ = options;
     _ = unused_fmt_string;
     const symbol = ctx.symbol;
-    try writer.print("%{d} : {s} : @{x}", .{ symbol.symbol_index, symbol.fmtName(ctx.elf_file), symbol.value });
+    try writer.print("%{d} : {s} : @{x}", .{ symbol.index, symbol.fmtName(ctx.elf_file), symbol.value });
     if (symbol.file(ctx.elf_file)) |file_ptr| {
         if (symbol.isAbs(ctx.elf_file)) {
             if (symbol.sourceSymbol(ctx.elf_file).st_shndx == elf.SHN_UNDEF) {
src/link/Elf/ZigModule.zig
@@ -33,6 +33,7 @@ pub fn createAtom(self: *ZigModule, output_section_index: u16, elf_file: *Elf) !
     symbol_ptr.file_index = self.index;
     symbol_ptr.atom_index = atom_index;
     symbol_ptr.output_section_index = output_section_index;
+    symbol_ptr.esym_index = @as(Symbol.Index, @intCast(self.elf_local_symbols.items.len));
 
     const local_esym = try self.elf_local_symbols.addOne(gpa);
     local_esym.* = .{
@@ -55,6 +56,7 @@ pub fn addGlobal(self: *ZigModule, name: [:0]const u8, elf_file: *Elf) !Symbol.I
     try self.elf_global_symbols.ensureUnusedCapacity(gpa, 1);
     try self.global_symbols.ensureUnusedCapacity(gpa, 1);
     const off = try elf_file.strtab.insert(gpa, name);
+    const esym_index = @as(Symbol.Index, @intCast(self.elf_global_symbols.items.len));
     self.elf_global_symbols.appendAssumeCapacity(.{
         .st_name = off,
         .st_info = elf.STB_GLOBAL << 4,
@@ -64,14 +66,18 @@ pub fn addGlobal(self: *ZigModule, name: [:0]const u8, elf_file: *Elf) !Symbol.I
         .st_size = 0,
     });
     const gop = try elf_file.getOrPutGlobal(off);
+    const sym = elf_file.symbol(gop.index);
+    sym.file_index = self.index;
+    sym.esym_index = esym_index;
     self.global_symbols.putAssumeCapacityNoClobber(gop.index, {});
     return gop.index;
 }
 
-pub fn sourceSymbol(self: *ZigModule, symbol_index: Symbol.Index) *elf.Elf64_Sym {
-    if (self.local_symbols.get(symbol_index)) |_| return &self.elf_local_symbols.items[symbol_index];
+pub fn sourceSymbol(self: *ZigModule, symbol_index: Symbol.Index, elf_file: *Elf) *elf.Elf64_Sym {
+    const sym = elf_file.symbol(symbol_index);
+    if (self.local_symbols.get(symbol_index)) |_| return &self.elf_local_symbols.items[sym.esym_index];
     assert(self.global_symbols.get(symbol_index) != null);
-    return &self.elf_global_symbols.items[symbol_index];
+    return &self.elf_global_symbols.items[sym.esym_index];
 }
 
 pub fn locals(self: *ZigModule) []const Symbol.Index {
src/link/Elf.zig
@@ -105,7 +105,7 @@ atoms: std.ArrayListUnmanaged(Atom) = .{},
 ///
 /// value assigned to label `foo` is an unnamed constant belonging/associated
 /// with `Decl` `main`, and lives as long as that `Decl`.
-unnamed_const_atoms: UnnamedConstTable = .{},
+unnamed_consts: UnnamedConstTable = .{},
 
 /// A table of relocations indexed by the owning them `TextBlock`.
 relocs: RelocTable = .{},
@@ -251,11 +251,11 @@ pub fn deinit(self: *Elf) void {
     self.lazy_syms.deinit(gpa);
 
     {
-        var it = self.unnamed_const_atoms.valueIterator();
-        while (it.next()) |atoms| {
-            atoms.deinit(gpa);
+        var it = self.unnamed_consts.valueIterator();
+        while (it.next()) |syms| {
+            syms.deinit(gpa);
         }
-        self.unnamed_const_atoms.deinit(gpa);
+        self.unnamed_consts.deinit(gpa);
     }
 
     {
@@ -279,7 +279,7 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.
     const vaddr = this_sym.value;
     const parent_atom_index = self.symbol(reloc_info.parent_atom_index).atom_index;
     try Atom.addRelocation(self, parent_atom_index, .{
-        .target = this_sym,
+        .target = this_sym_index,
         .offset = reloc_info.offset,
         .addend = reloc_info.addend,
         .prev_vaddr = vaddr,
@@ -830,6 +830,12 @@ pub fn populateMissingMetadata(self: *Elf) !void {
 
         try self.base.file.?.pwriteAll(&[_]u8{0}, max_file_offset);
     }
+
+    if (self.zig_module_index == null) {
+        const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
+        self.files.set(index, .{ .zig_module = .{ .index = index } });
+        self.zig_module_index = index;
+    }
 }
 
 pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {
@@ -967,12 +973,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
     const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
     _ = module;
 
-    self.zig_module_index = blk: {
-        const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
-        self.files.set(index, .{ .zig_module = .{ .index = index } });
-        break :blk index;
-    };
-
     self.linker_defined_index = blk: {
         const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
         self.files.set(index, .{ .linker_defined = .{ .index = index } });
@@ -980,6 +980,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
     };
 
     std.debug.print("{}\n", .{self.dumpState()});
+    return error.FlushFailure;
 
     // if (self.lazy_syms.getPtr(.none)) |metadata| {
     //     // Most lazy symbols can be updated on first use, but
@@ -2078,78 +2079,21 @@ fn writeElfHeader(self: *Elf) !void {
     try self.base.file.?.pwriteAll(hdr_buf[0..index], 0);
 }
 
-fn freeAtom(self: *Elf, atom_index: Atom.Index) void {
-    const atom_ptr = self.atom(atom_index);
-    log.debug("freeAtom {d} ({s})", .{ atom_index, atom_ptr.name(self) });
-
-    Atom.freeRelocations(self, atom_index);
-
-    const gpa = self.base.allocator;
-    const shndx = atom_ptr.symbol(self).st_shndx;
-    const free_list = &self.sections.items(.free_list)[shndx];
-    var already_have_free_list_node = false;
-    {
-        var i: usize = 0;
-        // TODO turn free_list into a hash map
-        while (i < free_list.items.len) {
-            if (free_list.items[i] == atom_index) {
-                _ = free_list.swapRemove(i);
-                continue;
-            }
-            if (free_list.items[i] == atom_ptr.prev_index) {
-                already_have_free_list_node = true;
-            }
-            i += 1;
-        }
-    }
-
-    const maybe_last_atom_index = &self.sections.items(.last_atom_index)[shndx];
-    if (maybe_last_atom_index.*) |last_atom_index| {
-        if (last_atom_index == atom_index) {
-            if (atom_ptr.prev_index) |prev_index| {
-                // TODO shrink the section size here
-                maybe_last_atom_index.* = prev_index;
-            } else {
-                maybe_last_atom_index.* = null;
-            }
-        }
-    }
-
-    if (atom_ptr.prev_index) |prev_index| {
-        const prev = self.atom(prev_index);
-        prev.next_index = atom_ptr.next_index;
-
-        if (!already_have_free_list_node and prev.*.freeListEligible(self)) {
-            // The free list is heuristics, it doesn't have to be perfect, so we can
-            // ignore the OOM here.
-            free_list.append(gpa, prev_index) catch {};
-        }
-    } else {
-        atom_ptr.prev_index = null;
-    }
-
-    if (atom_ptr.next_index) |next_index| {
-        self.atom(next_index).prev_index = atom_ptr.prev_index;
-    } else {
-        atom_ptr.next_index = null;
+fn freeUnnamedConsts(self: *Elf, decl_index: Module.Decl.Index) void {
+    const unnamed_consts = self.unnamed_consts.getPtr(decl_index) orelse return;
+    for (unnamed_consts.items) |sym_index| {
+        self.freeDeclMetadata(sym_index);
     }
+    unnamed_consts.clearAndFree(self.base.allocator);
+}
 
-    // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
-    const sym_index = atom_ptr.symbolIndex().?;
-
+fn freeDeclMetadata(self: *Elf, sym_index: Symbol.Index) void {
+    const sym = self.symbol(sym_index);
+    sym.atom(self).?.free(self);
     log.debug("adding %{d} to local symbols free list", .{sym_index});
-    self.symbols_free_list.append(gpa, sym_index) catch {};
+    self.symbols_free_list.append(self.base.allocator, sym_index) catch {};
     self.symbols.items[sym_index] = .{};
-    atom_ptr.sym_index = 0;
-    self.got_table.freeEntry(gpa, sym_index);
-}
-
-fn freeUnnamedConsts(self: *Elf, decl_index: Module.Decl.Index) void {
-    const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;
-    for (unnamed_consts.items) |atom_index| {
-        self.freeAtom(atom_index);
-    }
-    unnamed_consts.clearAndFree(self.base.allocator);
+    self.got_table.freeEntry(self.base.allocator, sym_index);
 }
 
 pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void {
@@ -2162,7 +2106,8 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void {
 
     if (self.decls.fetchRemove(decl_index)) |const_kv| {
         var kv = const_kv;
-        self.freeAtom(kv.value.atom);
+        const sym_index = kv.value.symbol_index;
+        self.freeDeclMetadata(sym_index);
         self.freeUnnamedConsts(decl_index);
         kv.value.exports.deinit(self.base.allocator);
     }
@@ -2196,7 +2141,7 @@ pub fn getOrCreateMetadataForLazySymbol(self: *Elf, sym: link.File.LazySymbol) !
             .code => self.text_section_index.?,
             .const_data => self.rodata_section_index.?,
         }, self),
-        .pending_flush => return metadata.atom.*,
+        .pending_flush => return metadata.symbol_index.*,
         .flushed => {},
     }
     metadata.state.* = .pending_flush;
@@ -2271,6 +2216,7 @@ fn updateDeclCode(
     esym.st_size = code.len;
 
     const old_size = atom_ptr.size;
+    const old_vaddr = atom_ptr.value;
     atom_ptr.alignment = math.log2_int(u64, required_alignment);
     atom_ptr.size = code.len;
 
@@ -2278,11 +2224,11 @@ fn updateDeclCode(
         const capacity = atom_ptr.capacity(self);
         const need_realloc = code.len > capacity or !mem.isAlignedGeneric(u64, sym.value, required_alignment);
         if (need_realloc) {
-            const vaddr = try atom_ptr.grow(self);
-            log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl_name, sym.value, vaddr });
-            if (vaddr != sym.value) {
-                sym.value = vaddr;
-                esym.st_value = vaddr;
+            try atom_ptr.grow(self);
+            log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl_name, old_vaddr, atom_ptr.value });
+            if (old_vaddr != atom_ptr.value) {
+                sym.value = atom_ptr.value;
+                esym.st_value = atom_ptr.value;
 
                 log.debug("  (writing new offset table entry)", .{});
                 const got_entry_index = self.got_table.lookup.get(sym_index).?;
@@ -2293,12 +2239,16 @@ fn updateDeclCode(
             atom_ptr.shrink(self);
         }
     } else {
-        const vaddr = try atom_ptr.allocate(self);
-        errdefer self.freeAtom(atom_ptr);
-        log.debug("allocated text block for {s} at 0x{x}", .{ decl_name, vaddr });
+        try atom_ptr.allocate(self);
+        errdefer self.freeDeclMetadata(sym_index);
+        log.debug("allocated atom for {s} at 0x{x} to 0x{x}", .{
+            decl_name,
+            atom_ptr.value,
+            atom_ptr.value + atom_ptr.size,
+        });
 
-        sym.value = vaddr;
-        esym.st_value = vaddr;
+        sym.value = atom_ptr.value;
+        esym.st_value = atom_ptr.value;
 
         const got_entry_index = try sym.getOrCreateOffsetTableEntry(self);
         try self.writeOffsetTableEntry(got_entry_index);
@@ -2518,17 +2468,23 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
     const atom_ptr = local_sym.atom(self).?;
     atom_ptr.alignment = math.log2_int(u64, required_alignment);
     atom_ptr.size = code.len;
-    const vaddr = try atom_ptr.allocate(self);
-    errdefer self.freeAtom(atom_ptr);
-    log.debug("allocated text block for {s} at 0x{x}", .{ name, vaddr });
 
-    local_sym.value = vaddr;
-    local_esym.st_value = vaddr;
+    try atom_ptr.allocate(self);
+    errdefer self.freeDeclMetadata(symbol_index);
+
+    log.debug("allocated atom for {s} at 0x{x} to 0x{x}", .{
+        name,
+        atom_ptr.value,
+        atom_ptr.value + atom_ptr.size,
+    });
+
+    local_sym.value = atom_ptr.value;
+    local_esym.st_value = atom_ptr.value;
 
     const got_entry_index = try local_sym.getOrCreateOffsetTableEntry(self);
     try self.writeOffsetTableEntry(got_entry_index);
 
-    const section_offset = vaddr - self.program_headers.items[phdr_index].p_vaddr;
+    const section_offset = atom_ptr.value - self.program_headers.items[phdr_index].p_vaddr;
     const file_offset = self.sections.items(.shdr)[local_sym.output_section_index].sh_offset + section_offset;
     try self.base.file.?.pwriteAll(code, file_offset);
 }
@@ -2540,7 +2496,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
     defer code_buffer.deinit();
 
     const mod = self.base.options.module.?;
-    const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index);
+    const gop = try self.unnamed_consts.getOrPut(gpa, decl_index);
     if (!gop.found_existing) {
         gop.value_ptr.* = .{};
     }
@@ -2586,17 +2542,18 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
     const atom_ptr = local_sym.atom(self).?;
     atom_ptr.alignment = math.log2_int(u64, required_alignment);
     atom_ptr.size = code.len;
-    const vaddr = try atom_ptr.allocateAtom(self);
-    errdefer self.freeAtom(atom_ptr);
 
-    log.debug("allocated text block for {s} at 0x{x}", .{ name, local_sym.st_value });
+    try atom_ptr.allocate(self);
+    errdefer self.freeDeclMetadata(sym_index);
+
+    log.debug("allocated atom for {s} at 0x{x} to 0x{x}", .{ name, atom_ptr.value, atom_ptr.value + atom_ptr.size });
 
-    local_sym.value = vaddr;
-    local_esym.st_value = vaddr;
+    local_sym.value = atom_ptr.value;
+    local_esym.st_value = atom_ptr.value;
 
     try unnamed_consts.append(gpa, atom_ptr.atom_index);
 
-    const section_offset = local_sym.value - self.program_headers.items[phdr_index].p_vaddr;
+    const section_offset = atom_ptr.value - self.program_headers.items[phdr_index].p_vaddr;
     const file_offset = self.sections.items(.shdr)[shdr_index].sh_offset + section_offset;
     try self.base.file.?.pwriteAll(code, file_offset);
 
@@ -2624,7 +2581,7 @@ pub fn updateDeclExports(
     const decl = mod.declPtr(decl_index);
     const decl_sym_index = try self.getOrCreateMetadataForDecl(decl_index);
     const decl_sym = self.symbol(decl_sym_index);
-    const decl_esym = symbol.sourceSymbol(self);
+    const decl_esym = decl_sym.sourceSymbol(self);
     const decl_metadata = self.decls.getPtr(decl_index).?;
 
     for (exports) |exp| {
@@ -2658,7 +2615,7 @@ pub fn updateDeclExports(
                 continue;
             },
         };
-        const stt_bits: u8 = @as(u4, @truncate(decl_sym.st_info));
+        const stt_bits: u8 = @as(u4, @truncate(decl_esym.st_info));
 
         const sym_index = if (decl_metadata.@"export"(self, exp_name)) |exp_index| exp_index.* else blk: {
             const zig_module = self.file(self.zig_module_index.?).?.zig_module;
@@ -3220,7 +3177,7 @@ pub fn addSymbol(self: *Elf) !Symbol.Index {
             break :blk index;
         }
     };
-    self.symbols.items[index] = .{ .symbol_index = index };
+    self.symbols.items[index] = .{ .index = index };
     return index;
 }