diff --git a/src/link/Elf/LinkerDefined.zig b/src/link/Elf/LinkerDefined.zig index 676c49cc7d..1247a08ef1 100644 --- a/src/link/Elf/LinkerDefined.zig +++ b/src/link/Elf/LinkerDefined.zig @@ -2,7 +2,10 @@ index: File.Index, symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, strtab: std.ArrayListUnmanaged(u8) = .{}, -symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, + +symbols: std.ArrayListUnmanaged(Symbol) = .{}, +symbols_extra: std.ArrayListUnmanaged(u32) = .{}, +symbols_resolver: std.ArrayListUnmanaged(Elf.SymbolResolver.Index) = .{}, entry_index: ?Symbol.Index = null, dynamic_index: ?Symbol.Index = null, @@ -29,6 +32,8 @@ pub fn deinit(self: *LinkerDefined, allocator: Allocator) void { self.symtab.deinit(allocator); self.strtab.deinit(allocator); self.symbols.deinit(allocator); + self.symbols_extra.deinit(allocator); + self.symbols_resolver.deinit(allocator); self.start_stop_indexes.deinit(allocator); } @@ -38,85 +43,137 @@ pub fn init(self: *LinkerDefined, allocator: Allocator) !void { } pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void { + const newSymbolAssumeCapacity = struct { + fn newSymbolAssumeCapacity(ld: *LinkerDefined, name_off: u32) Symbol.Index { + const esym_index: u32 = @intCast(ld.symtab.items.len); + const esym = ld.symtab.addOneAssumeCapacity(); + esym.* = .{ + .st_name = name_off, + .st_info = elf.STB_GLOBAL << 4, + .st_other = @intFromEnum(elf.STV.HIDDEN), + .st_shndx = elf.SHN_ABS, + .st_value = 0, + .st_size = 0, + }; + const index = ld.addSymbolAssumeCapacity(); + const symbol = &ld.symbols.items[index]; + symbol.name_offset = name_off; + symbol.extra_index = ld.addSymbolExtraAssumeCapacity(.{}); + symbol.ref = .{ .index = 0, .file = 0 }; + symbol.esym_index = esym_index; + symbol.version_index = elf_file.default_sym_version; + } + }.newSymbolAssumeCapacity; + const gpa = elf_file.base.comp.gpa; - if (elf_file.entry_name) |name| { - self.entry_index = try self.addGlobal(name, elf_file); + var nsyms: usize = 0; + if (elf_file.entry_name) |_| { + nsyms += 1; // entry } - - self.dynamic_index = try self.addGlobal("_DYNAMIC", elf_file); - self.ehdr_start_index = try self.addGlobal("__ehdr_start", elf_file); - self.init_array_start_index = try self.addGlobal("__init_array_start", elf_file); - self.init_array_end_index = try self.addGlobal("__init_array_end", elf_file); - self.fini_array_start_index = try self.addGlobal("__fini_array_start", elf_file); - self.fini_array_end_index = try self.addGlobal("__fini_array_end", elf_file); - self.preinit_array_start_index = try self.addGlobal("__preinit_array_start", elf_file); - self.preinit_array_end_index = try self.addGlobal("__preinit_array_end", elf_file); - self.got_index = try self.addGlobal("_GLOBAL_OFFSET_TABLE_", elf_file); - self.plt_index = try self.addGlobal("_PROCEDURE_LINKAGE_TABLE_", elf_file); - self.end_index = try self.addGlobal("_end", elf_file); - + nsyms += 1; // _DYNAMIC + nsyms += 1; // __ehdr_start + nsyms += 1; // __init_array_start + nsyms += 1; // __init_array_end + nsyms += 1; // __fini_array_start + nsyms += 1; // __fini_array_end + nsyms += 1; // __preinit_array_start + nsyms += 1; // __preinit_array_end + nsyms += 1; // _GLOBAL_OFFSET_TABLE_ + nsyms += 1; // _PROCEDURE_LINKAGE_TABLE_ + nsyms += 1; // _end if (elf_file.base.comp.link_eh_frame_hdr) { - self.gnu_eh_frame_hdr_index = try self.addGlobal("__GNU_EH_FRAME_HDR", elf_file); + nsyms += 1; // __GNU_EH_FRAME_HDR + } + nsyms += 1; // __dso_handle + nsyms += 1; // __rela_iplt_start + nsyms += 1; // __rela_iplt_end + if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) { + nsyms += 1; // __global_pointer$ } - self.dso_handle_index = try self.addGlobal("__dso_handle", elf_file); - self.rela_iplt_start_index = try self.addGlobal("__rela_iplt_start", elf_file); - self.rela_iplt_end_index = try self.addGlobal("__rela_iplt_end", elf_file); - - for (elf_file.shdrs.items) |shdr| { - if (elf_file.getStartStopBasename(shdr)) |name| { - try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2); - - const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); - defer gpa.free(start); - const stop = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name}); - defer gpa.free(stop); - - self.start_stop_indexes.appendAssumeCapacity(try self.addGlobal(start, elf_file)); - self.start_stop_indexes.appendAssumeCapacity(try self.addGlobal(stop, elf_file)); + var start_stop_count: usize = 0; + for (elf_file.objects.items) |index| { + for (elf_file.file(index).?.object.shdrs.items) |shdr| { + if (elf_file.getStartStopBasename(shdr)) |_| { + start_stop_count += 2; // __start_, __stop_ + } } } + nsyms += start_stop_count; + + try self.start_stop_indexes.ensureTotalCapacityPrecise(gpa, start_stop_count); + try self.symtab.ensureTotalCapacityPrecise(gpa, nsyms); + try self.symbols.ensureTotalCapacityPrecise(gpa, nsyms); + try self.symbols_extra.ensureTotalCapacityPrecise(gpa, nsyms * @sizeOf(Symbol.Extra)); + try self.symbols_resolver.ensureTotalCapacityPrecise(gpa, nsyms); + self.symbols_resolver.resize(gpa, nsyms) catch unreachable; + @memset(self.symbols_resolver.items, 0); + + if (elf_file.entry_name) |name| { + self.entry_index = newSymbolAssumeCapacity(self, try self.addString(gpa, name)); + } + + self.dynamic_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_DYNAMIC")); + self.ehdr_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__ehdr_start")); + self.init_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_start")); + self.init_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_end")); + self.fini_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_start")); + self.fini_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_end")); + self.preinit_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_start")); + self.preinit_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_end")); + self.got_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_GLOBAL_OFFSET_TABLE_")); + self.plt_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_PROCEDURE_LINKAGE_TABLE_")); + self.end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_end")); + + if (elf_file.base.comp.link_eh_frame_hdr) { + self.gnu_eh_frame_hdr_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__GNU_EH_FRAME_HDR")); + } + + self.dso_handle_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__dso_handle")); + self.rela_iplt_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_start")); + self.rela_iplt_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_end")); if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) { - self.global_pointer_index = try self.addGlobal("__global_pointer$", elf_file); + self.global_pointer_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__global_pointer$")); + } + + for (elf_file.objects.items) |index| { + for (elf_file.file(index).?.object.shdrs.items) |shdr| { + if (elf_file.getStartStopBasename(shdr)) |name| { + const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); + defer gpa.free(start_name); + const stop_name = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name}); + defer gpa.free(stop_name); + const start = newSymbolAssumeCapacity(self, try self.addString(gpa, start_name)); + const stop = newSymbolAssumeCapacity(self, try self.addString(gpa, stop_name)); + self.start_stop_indexes.appendSliceAssumeCapacity(&.{ start, stop }); + } + } } } -fn addGlobal(self: *LinkerDefined, name: []const u8, elf_file: *Elf) !u32 { - const comp = elf_file.base.comp; - const gpa = comp.gpa; - try self.symtab.ensureUnusedCapacity(gpa, 1); - try self.symbols.ensureUnusedCapacity(gpa, 1); - const name_off = @as(u32, @intCast(self.strtab.items.len)); - try self.strtab.writer(gpa).print("{s}\x00", .{name}); - self.symtab.appendAssumeCapacity(.{ - .st_name = name_off, - .st_info = elf.STB_GLOBAL << 4, - .st_other = @intFromEnum(elf.STV.HIDDEN), - .st_shndx = elf.SHN_ABS, - .st_value = 0, - .st_size = 0, - }); - const gop = try elf_file.getOrPutGlobal(name); - self.symbols.addOneAssumeCapacity().* = gop.index; - return gop.index; -} +pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) !void { + const gpa = elf_file.base.comp.gpa; -pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void { - for (self.symbols.items, 0..) |index, i| { - const sym_idx = @as(Symbol.Index, @intCast(i)); - const this_sym = self.symtab.items[sym_idx]; + for (self.symtab.items, self.symbols_resolver.items, 0..) |esym, *resolv, i| { + const gop = try elf_file.resolver.getOrPut(gpa, .{ + .index = @intCast(i), + .file = self.index, + }, elf_file); + if (!gop.found_existing) { + gop.ref.* = .{ .index = 0, .file = 0 }; + } + resolv.* = gop.index; - if (this_sym.st_shndx == elf.SHN_UNDEF) continue; + if (esym.st_shndx == elf.SHN_UNDEF) continue; + if (elf_file.symbol(gop.ref.*) == null) { + gop.ref.* = .{ .index = @intCast(i), .file = self.index }; + continue; + } - const global = elf_file.symbol(index); - if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) { - global.value = 0; - global.ref = .{ .index = 0, .file = 0 }; - global.file_index = self.index; - global.esym_index = sym_idx; - global.version_index = elf_file.default_sym_version; + if (self.asFile().symbolRank(esym, false) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) { + gop.ref.* = .{ .index = @intCast(i), .file = self.index }; } } } @@ -125,93 +182,73 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { const comp = elf_file.base.comp; const link_mode = comp.config.link_mode; + const allocSymbol = struct { + fn allocSymbol(ld: *LinkerDefined, index: Symbol.Index, value: u64, osec: u32, ef: *Elf) void { + const sym = ef.symbol(ld.resolveSymbol(index, ef)).?; + sym.value = @intCast(value); + sym.output_section_index = osec; + } + }.allocSymbol; + // _DYNAMIC if (elf_file.dynamic_section_index) |shndx| { const shdr = &elf_file.shdrs.items[shndx]; - const symbol_ptr = elf_file.symbol(self.dynamic_index.?); - symbol_ptr.value = @intCast(shdr.sh_addr); - symbol_ptr.output_section_index = shndx; + allocSymbol(self, self.dynamic_index.?, shdr.sh_addr, shndx, elf_file); } // __ehdr_start - { - const symbol_ptr = elf_file.symbol(self.ehdr_start_index.?); - symbol_ptr.value = @intCast(elf_file.image_base); - symbol_ptr.output_section_index = 1; - } + allocSymbol(self, self.ehdr_start_index.?, elf_file.image_base, 1, elf_file); // __init_array_start, __init_array_end if (elf_file.sectionByName(".init_array")) |shndx| { - const start_sym = elf_file.symbol(self.init_array_start_index.?); - const end_sym = elf_file.symbol(self.init_array_end_index.?); const shdr = &elf_file.shdrs.items[shndx]; - start_sym.output_section_index = shndx; - start_sym.value = @intCast(shdr.sh_addr); - end_sym.output_section_index = shndx; - end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); + allocSymbol(self, self.init_array_start_index.?, shdr.sh_addr, shndx, elf_file); + allocSymbol(self, self.init_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file); } // __fini_array_start, __fini_array_end if (elf_file.sectionByName(".fini_array")) |shndx| { - const start_sym = elf_file.symbol(self.fini_array_start_index.?); - const end_sym = elf_file.symbol(self.fini_array_end_index.?); const shdr = &elf_file.shdrs.items[shndx]; - start_sym.output_section_index = shndx; - start_sym.value = @intCast(shdr.sh_addr); - end_sym.output_section_index = shndx; - end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); + allocSymbol(self, self.fini_array_start_index.?, shdr.sh_addr, shndx, elf_file); + allocSymbol(self, self.fini_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file); } // __preinit_array_start, __preinit_array_end if (elf_file.sectionByName(".preinit_array")) |shndx| { - const start_sym = elf_file.symbol(self.preinit_array_start_index.?); - const end_sym = elf_file.symbol(self.preinit_array_end_index.?); const shdr = &elf_file.shdrs.items[shndx]; - start_sym.output_section_index = shndx; - start_sym.value = @intCast(shdr.sh_addr); - end_sym.output_section_index = shndx; - end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); + allocSymbol(self, self.preinit_array_start_index.?, shdr.sh_addr, shndx, elf_file); + allocSymbol(self, self.preinit_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file); } // _GLOBAL_OFFSET_TABLE_ if (elf_file.getTarget().cpu.arch == .x86_64) { if (elf_file.got_plt_section_index) |shndx| { const shdr = elf_file.shdrs.items[shndx]; - const sym = elf_file.symbol(self.got_index.?); - sym.value = @intCast(shdr.sh_addr); - sym.output_section_index = shndx; + allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file); } } else { if (elf_file.got_section_index) |shndx| { const shdr = elf_file.shdrs.items[shndx]; - const sym = elf_file.symbol(self.got_index.?); - sym.value = @intCast(shdr.sh_addr); - sym.output_section_index = shndx; + allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file); } } // _PROCEDURE_LINKAGE_TABLE_ if (elf_file.plt_section_index) |shndx| { const shdr = &elf_file.shdrs.items[shndx]; - const symbol_ptr = elf_file.symbol(self.plt_index.?); - symbol_ptr.value = @intCast(shdr.sh_addr); - symbol_ptr.output_section_index = shndx; + allocSymbol(self, self.plt_index.?, shdr.sh_addr, shndx, elf_file); } // __dso_handle if (self.dso_handle_index) |index| { const shdr = &elf_file.shdrs.items[1]; - const symbol_ptr = elf_file.symbol(index); - symbol_ptr.value = @intCast(shdr.sh_addr); - symbol_ptr.output_section_index = 0; + allocSymbol(self, index, shdr.sh_addr, 0, elf_file); } // __GNU_EH_FRAME_HDR if (elf_file.eh_frame_hdr_section_index) |shndx| { const shdr = &elf_file.shdrs.items[shndx]; - const symbol_ptr = elf_file.symbol(self.gnu_eh_frame_hdr_index.?); - symbol_ptr.value = @intCast(shdr.sh_addr); - symbol_ptr.output_section_index = shndx; + allocSymbol(self, self.gnu_eh_frame_hdr_index.?, shdr.sh_addr, shndx, elf_file); } // __rela_iplt_start, __rela_iplt_end @@ -220,32 +257,41 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { const shdr = &elf_file.shdrs.items[shndx]; const end_addr = shdr.sh_addr + shdr.sh_size; const start_addr = end_addr - elf_file.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela); - const start_sym = elf_file.symbol(self.rela_iplt_start_index.?); - const end_sym = elf_file.symbol(self.rela_iplt_end_index.?); - start_sym.value = @intCast(start_addr); - start_sym.output_section_index = shndx; - end_sym.value = @intCast(end_addr); - end_sym.output_section_index = shndx; + allocSymbol(self, self.rela_iplt_start_index.?, start_addr, shndx, elf_file); + allocSymbol(self, self.rela_iplt_end_index.?, end_addr, shndx, elf_file); } // _end { - const end_symbol = elf_file.symbol(self.end_index.?); + var value: u64 = 0; + var osec: u32 = 0; for (elf_file.shdrs.items, 0..) |shdr, shndx| { if (shdr.sh_flags & elf.SHF_ALLOC != 0) { - end_symbol.value = @intCast(shdr.sh_addr + shdr.sh_size); - end_symbol.output_section_index = @intCast(shndx); + value = shdr.sh_addr + shdr.sh_size; + osec = shndx; } } + allocSymbol(self, self.end_index.?, value, osec, elf_file); + } + + // __global_pointer$ + if (self.global_pointer_index) |index| { + const value, const osec = if (elf_file.sectionByName(".sdata")) |shndx| .{ + elf_file.shdrs.items[shndx].sh_addr + 0x800, + shndx, + } else .{ 0, 0 }; + allocSymbol(self, index, value, osec, elf_file); } // __start_*, __stop_* { var index: usize = 0; while (index < self.start_stop_indexes.items.len) : (index += 2) { - const start = elf_file.symbol(self.start_stop_indexes.items[index]); + const start_ref = self.resolveSymbol(self.start_stop_indexes.items[index]); + const start = elf_file.symbol(start_ref).?; const name = start.name(elf_file); - const stop = elf_file.symbol(self.start_stop_indexes.items[index + 1]); + const stop_ref = self.resolveSymbol(self.start_stop_indexes.items[index + 1]); + const stop = elf_file.symbol(stop_ref).?; const shndx = elf_file.sectionByName(name["__start_".len..]).?; const shdr = &elf_file.shdrs.items[shndx]; start.value = @intCast(shdr.sh_addr); @@ -254,47 +300,34 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { stop.output_section_index = shndx; } } - - // __global_pointer$ - if (self.global_pointer_index) |index| { - const sym = elf_file.symbol(index); - if (elf_file.sectionByName(".sdata")) |shndx| { - const shdr = elf_file.shdrs.items[shndx]; - sym.value = @intCast(shdr.sh_addr + 0x800); - sym.output_section_index = shndx; - } else { - sym.value = 0; - sym.output_section_index = 0; - } - } } -pub fn globals(self: LinkerDefined) []const Symbol.Index { +pub fn globals(self: *LinkerDefined) []Symbol { return self.symbols.items; } -pub fn updateSymtabSize(self: *LinkerDefined, elf_file: *Elf) !void { - for (self.globals()) |global_index| { - const global = elf_file.symbol(global_index); - const file_ptr = global.file(elf_file) orelse continue; - if (file_ptr.index() != self.index) continue; +pub fn updateSymtabSize(self: *LinkerDefined, elf_file: *Elf) void { + for (self.globals(), self.symbols_resolver.items) |*global, resolv| { + const ref = elf_file.resolver.get(resolv).?; + const ref_sym = elf_file.symbol(ref) orelse continue; + if (ref_sym.file(elf_file).?.index() != self.index) continue; global.flags.output_symtab = true; if (global.isLocal(elf_file)) { - try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); + global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); self.output_symtab_ctx.nlocals += 1; } else { - try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file); + global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file); self.output_symtab_ctx.nglobals += 1; } self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1; } } -pub fn writeSymtab(self: LinkerDefined, elf_file: *Elf) void { - for (self.globals()) |global_index| { - const global = elf_file.symbol(global_index); - const file_ptr = global.file(elf_file) orelse continue; - if (file_ptr.index() != self.index) continue; +pub fn writeSymtab(self: *LinkerDefined, elf_file: *Elf) void { + for (self.globals(), self.symbols_resolver.items) |global, resolv| { + const ref = elf_file.resolver.get(resolv).?; + const ref_sym = elf_file.symbol(ref) orelse continue; + if (ref_sym.file(elf_file).?.index() != self.index) continue; const idx = global.outputSymtabIndex(elf_file) orelse continue; const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file)); @@ -309,11 +342,73 @@ pub fn asFile(self: *LinkerDefined) File { return .{ .linker_defined = self }; } +fn addString(self: *LinkerDefined, allocator: Allocator, str: []const u8) !u32 { + const off: u32 = @intCast(self.strtab.items.len); + try self.strtab.ensureUnusedCapacity(allocator, str.len + 1); + self.strtab.appendSliceAssumeCapacity(str); + self.strtab.appendAssumeCapacity(0); + return off; +} + pub fn getString(self: LinkerDefined, off: u32) [:0]const u8 { assert(off < self.strtab.items.len); return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0); } +pub fn resolveSymbol(self: LinkerDefined, index: Symbol.Index, elf_file: *Elf) Elf.Ref { + const resolv = self.symbols_resolver.items[index]; + return elf_file.resolver.get(resolv).?; +} + +pub fn addSymbol(self: *LinkerDefined, allocator: Allocator) !Symbol.Index { + try self.symbols.ensureUnusedCapacity(allocator, 1); + const index: Symbol.Index = @intCast(self.symbols.items.len); + self.symbols.appendAssumeCapacity(.{ .file_index = self.index }); + return index; +} + +pub fn addSymbolExtra(self: *LinkerDefined, allocator: Allocator, extra: Symbol.Extra) !u32 { + const fields = @typeInfo(Symbol.Extra).Struct.fields; + try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len); + return self.addSymbolExtraAssumeCapacity(extra); +} + +pub fn addSymbolExtraAssumeCapacity(self: *LinkerDefined, extra: Symbol.Extra) u32 { + const index = @as(u32, @intCast(self.symbols_extra.items.len)); + const fields = @typeInfo(Symbol.Extra).Struct.fields; + inline for (fields) |field| { + self.symbols_extra.appendAssumeCapacity(switch (field.type) { + u32 => @field(extra, field.name), + else => @compileError("bad field type"), + }); + } + return index; +} + +pub fn symbolExtra(self: *LinkerDefined, index: u32) Symbol.Extra { + const fields = @typeInfo(Symbol.Extra).Struct.fields; + var i: usize = index; + var result: Symbol.Extra = undefined; + inline for (fields) |field| { + @field(result, field.name) = switch (field.type) { + u32 => self.symbols_extra.items[i], + else => @compileError("bad field type"), + }; + i += 1; + } + return result; +} + +pub fn setSymbolExtra(self: *LinkerDefined, index: u32, extra: Symbol.Extra) void { + const fields = @typeInfo(Symbol.Extra).Struct.fields; + inline for (fields, 0..) |field, i| { + self.symbols_extra.items[index + i] = switch (field.type) { + u32 => @field(extra, field.name), + else => @compileError("bad field type"), + }; + } +} + pub fn fmtSymtab(self: *LinkerDefined, elf_file: *Elf) std.fmt.Formatter(formatSymtab) { return .{ .data = .{ .self = self, diff --git a/src/link/Elf/SharedObject.zig b/src/link/Elf/SharedObject.zig index 00a64c3950..245805e59e 100644 --- a/src/link/Elf/SharedObject.zig +++ b/src/link/Elf/SharedObject.zig @@ -282,7 +282,7 @@ pub fn markLive(self: *SharedObject, elf_file: *Elf) void { } } -pub fn globals(self: SharedObject) []const Symbol.Index { +pub fn globals(self: *SharedObject) []Symbol { return self.symbols.items; } @@ -299,7 +299,7 @@ pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) void { } } -pub fn writeSymtab(self: SharedObject, elf_file: *Elf) void { +pub fn writeSymtab(self: *SharedObject, elf_file: *Elf) void { for (self.globals(), self.symbols_resolver.items) |global, resolv| { const ref = elf_file.resolver.get(resolv).?; const ref_sym = elf_file.symbol(ref) orelse continue;