Merge pull request #21212 from ziglang/elf-incr

elf: cleanups, cleanups, cleanups
This commit is contained in:
Andrew Kelley 2024-08-26 19:25:23 -07:00 committed by GitHub
commit d9147b91a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 761 additions and 877 deletions

View file

@ -317,7 +317,7 @@ pub const Section = struct {
fn resize(sec: *Section, dwarf: *Dwarf, len: u64) UpdateError!void { fn resize(sec: *Section, dwarf: *Dwarf, len: u64) UpdateError!void {
if (dwarf.bin_file.cast(.elf)) |elf_file| { if (dwarf.bin_file.cast(.elf)) |elf_file| {
try elf_file.growNonAllocSection(sec.index, len, @intCast(sec.alignment.toByteUnits().?), true); try elf_file.growNonAllocSection(sec.index, len, @intCast(sec.alignment.toByteUnits().?), true);
const shdr = &elf_file.shdrs.items[sec.index]; const shdr = &elf_file.sections.items(.shdr)[sec.index];
sec.off = shdr.sh_offset; sec.off = shdr.sh_offset;
sec.len = shdr.sh_size; sec.len = shdr.sh_size;
} else if (dwarf.bin_file.cast(.macho)) |macho_file| { } else if (dwarf.bin_file.cast(.macho)) |macho_file| {
@ -340,7 +340,7 @@ pub const Section = struct {
sec.off += len; sec.off += len;
sec.len -= len; sec.len -= len;
if (dwarf.bin_file.cast(.elf)) |elf_file| { if (dwarf.bin_file.cast(.elf)) |elf_file| {
const shdr = &elf_file.shdrs.items[sec.index]; const shdr = &elf_file.sections.items(.shdr)[sec.index];
shdr.sh_offset = sec.off; shdr.sh_offset = sec.off;
shdr.sh_size = sec.len; shdr.sh_size = sec.len;
} else if (dwarf.bin_file.cast(.macho)) |macho_file| { } else if (dwarf.bin_file.cast(.macho)) |macho_file| {
@ -771,7 +771,7 @@ const Entry = struct {
log.err("missing {} from {s}", .{ log.err("missing {} from {s}", .{
@as(Entry.Index, @enumFromInt(entry - unit.entries.items.ptr)), @as(Entry.Index, @enumFromInt(entry - unit.entries.items.ptr)),
std.mem.sliceTo(if (dwarf.bin_file.cast(.elf)) |elf_file| std.mem.sliceTo(if (dwarf.bin_file.cast(.elf)) |elf_file|
elf_file.shstrtab.items[elf_file.shdrs.items[sec.index].sh_name..] elf_file.shstrtab.items[elf_file.sections.items(.shdr)[sec.index].sh_name..]
else if (dwarf.bin_file.cast(.macho)) |macho_file| else if (dwarf.bin_file.cast(.macho)) |macho_file|
if (macho_file.d_sym) |*d_sym| if (macho_file.d_sym) |*d_sym|
&d_sym.sections.items[sec.index].segname &d_sym.sections.items[sec.index].segname
@ -1529,7 +1529,7 @@ pub fn reloadSectionMetadata(dwarf: *Dwarf) void {
elf_file.debug_rnglists_section_index.?, elf_file.debug_rnglists_section_index.?,
elf_file.debug_str_section_index.?, elf_file.debug_str_section_index.?,
}) |sec, section_index| { }) |sec, section_index| {
const shdr = &elf_file.shdrs.items[section_index]; const shdr = &elf_file.sections.items(.shdr)[section_index];
sec.index = section_index; sec.index = section_index;
sec.off = shdr.sh_offset; sec.off = shdr.sh_offset;
sec.len = shdr.sh_size; sec.len = shdr.sh_size;

File diff suppressed because it is too large Load diff

View file

@ -25,10 +25,9 @@ relocs_section_index: u32 = 0,
/// Index of this atom in the linker's atoms table. /// Index of this atom in the linker's atoms table.
atom_index: Index = 0, atom_index: Index = 0,
/// Points to the previous and next neighbors, based on the `text_offset`. /// Points to the previous and next neighbors.
/// This can be used to find, for example, the capacity of this `TextBlock`. prev_atom_ref: Elf.Ref = .{},
prev_index: Index = 0, next_atom_ref: Elf.Ref = .{},
next_index: Index = 0,
/// Specifies whether this atom is alive or has been garbage collected. /// Specifies whether this atom is alive or has been garbage collected.
alive: bool = true, alive: bool = true,
@ -48,10 +47,22 @@ pub fn name(self: Atom, elf_file: *Elf) [:0]const u8 {
} }
pub fn address(self: Atom, elf_file: *Elf) i64 { pub fn address(self: Atom, elf_file: *Elf) i64 {
const shdr = elf_file.shdrs.items[self.output_section_index]; const shdr = elf_file.sections.items(.shdr)[self.output_section_index];
return @as(i64, @intCast(shdr.sh_addr)) + self.value; return @as(i64, @intCast(shdr.sh_addr)) + self.value;
} }
pub fn ref(self: Atom) Elf.Ref {
return .{ .index = self.atom_index, .file = self.file_index };
}
pub fn prevAtom(self: Atom, elf_file: *Elf) ?*Atom {
return elf_file.atom(self.prev_atom_ref);
}
pub fn nextAtom(self: Atom, elf_file: *Elf) ?*Atom {
return elf_file.atom(self.next_atom_ref);
}
pub fn debugTombstoneValue(self: Atom, target: Symbol, elf_file: *Elf) ?u64 { pub fn debugTombstoneValue(self: Atom, target: Symbol, elf_file: *Elf) ?u64 {
if (target.mergeSubsection(elf_file)) |msub| { if (target.mergeSubsection(elf_file)) |msub| {
if (msub.alive) return null; if (msub.alive) return null;
@ -95,18 +106,16 @@ pub fn priority(self: Atom, elf_file: *Elf) u64 {
/// File offset relocation happens transparently, so it is not included in /// File offset relocation happens transparently, so it is not included in
/// this calculation. /// this calculation.
pub fn capacity(self: Atom, elf_file: *Elf) u64 { pub fn capacity(self: Atom, elf_file: *Elf) u64 {
const zo = elf_file.zigObjectPtr().?; const next_addr = if (self.nextAtom(elf_file)) |next_atom|
const next_addr = if (zo.atom(self.next_index)) |next| next_atom.address(elf_file)
next.address(elf_file)
else else
std.math.maxInt(u32); std.math.maxInt(u32);
return @intCast(next_addr - self.address(elf_file)); return @intCast(next_addr - self.address(elf_file));
} }
pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
const zo = elf_file.zigObjectPtr().?;
// No need to keep a free list node for the last block. // No need to keep a free list node for the last block.
const next = zo.atom(self.next_index) orelse return false; const next = self.nextAtom(elf_file) orelse return false;
const cap: u64 = @intCast(next.address(elf_file) - self.address(elf_file)); const cap: u64 = @intCast(next.address(elf_file) - self.address(elf_file));
const ideal_cap = Elf.padToIdeal(self.size); const ideal_cap = Elf.padToIdeal(self.size);
if (cap <= ideal_cap) return false; if (cap <= ideal_cap) return false;
@ -115,11 +124,10 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
} }
pub fn allocate(self: *Atom, elf_file: *Elf) !void { pub fn allocate(self: *Atom, elf_file: *Elf) !void {
const zo = elf_file.zigObjectPtr().?; const slice = elf_file.sections.slice();
const shdr = &elf_file.shdrs.items[self.output_section_index]; const shdr = &slice.items(.shdr)[self.output_section_index];
const meta = elf_file.last_atom_and_free_list_table.getPtr(self.output_section_index).?; const free_list = &slice.items(.free_list)[self.output_section_index];
const free_list = &meta.free_list; const last_atom_ref = &slice.items(.last_atom)[self.output_section_index];
const last_atom_index = &meta.last_atom_index;
const new_atom_ideal_capacity = Elf.padToIdeal(self.size); const new_atom_ideal_capacity = Elf.padToIdeal(self.size);
// We use these to indicate our intention to update metadata, placing the new atom, // We use these to indicate our intention to update metadata, placing the new atom,
@ -127,7 +135,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
// It would be simpler to do it inside the for loop below, but that would cause a // It would be simpler to do it inside the for loop below, but that would cause a
// problem if an error was returned later in the function. So this action // problem if an error was returned later in the function. So this action
// is actually carried out at the end of the function, when errors are no longer possible. // is actually carried out at the end of the function, when errors are no longer possible.
var atom_placement: ?Atom.Index = null; var atom_placement: ?Elf.Ref = null;
var free_list_removal: ?usize = null; var free_list_removal: ?usize = null;
// First we look for an appropriately sized free list node. // First we look for an appropriately sized free list node.
@ -135,8 +143,8 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
self.value = blk: { self.value = blk: {
var i: usize = if (elf_file.base.child_pid == null) 0 else free_list.items.len; var i: usize = if (elf_file.base.child_pid == null) 0 else free_list.items.len;
while (i < free_list.items.len) { while (i < free_list.items.len) {
const big_atom_index = free_list.items[i]; const big_atom_ref = free_list.items[i];
const big_atom = zo.atom(big_atom_index).?; const big_atom = elf_file.atom(big_atom_ref).?;
// We now have a pointer to a live atom that has too much capacity. // We now have a pointer to a live atom that has too much capacity.
// Is it enough that we could fit this new atom? // Is it enough that we could fit this new atom?
const cap = big_atom.capacity(elf_file); const cap = big_atom.capacity(elf_file);
@ -163,50 +171,52 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
const keep_free_list_node = remaining_capacity >= Elf.min_text_capacity; const keep_free_list_node = remaining_capacity >= Elf.min_text_capacity;
// Set up the metadata to be updated, after errors are no longer possible. // Set up the metadata to be updated, after errors are no longer possible.
atom_placement = big_atom_index; atom_placement = big_atom_ref;
if (!keep_free_list_node) { if (!keep_free_list_node) {
free_list_removal = i; free_list_removal = i;
} }
break :blk @intCast(new_start_vaddr); break :blk @intCast(new_start_vaddr);
} else if (zo.atom(last_atom_index.*)) |last| { } else if (elf_file.atom(last_atom_ref.*)) |last_atom| {
const ideal_capacity = Elf.padToIdeal(last.size); const ideal_capacity = Elf.padToIdeal(last_atom.size);
const ideal_capacity_end_vaddr = @as(u64, @intCast(last.value)) + ideal_capacity; const ideal_capacity_end_vaddr = @as(u64, @intCast(last_atom.value)) + ideal_capacity;
const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr); const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr);
// Set up the metadata to be updated, after errors are no longer possible. // Set up the metadata to be updated, after errors are no longer possible.
atom_placement = last.atom_index; atom_placement = last_atom.ref();
break :blk @intCast(new_start_vaddr); break :blk @intCast(new_start_vaddr);
} else { } else {
break :blk 0; break :blk 0;
} }
}; };
log.debug("allocated atom({d}) : '{s}' at 0x{x} to 0x{x}", .{ log.debug("allocated atom({}) : '{s}' at 0x{x} to 0x{x}", .{
self.atom_index, self.ref(),
self.name(elf_file), self.name(elf_file),
self.address(elf_file), self.address(elf_file),
self.address(elf_file) + @as(i64, @intCast(self.size)), self.address(elf_file) + @as(i64, @intCast(self.size)),
}); });
const expand_section = if (atom_placement) |placement_index| const expand_section = if (atom_placement) |placement_ref|
zo.atom(placement_index).?.next_index == 0 elf_file.atom(placement_ref).?.nextAtom(elf_file) == null
else else
true; true;
if (expand_section) { if (expand_section) {
const needed_size: u64 = @intCast(self.value + @as(i64, @intCast(self.size))); const needed_size: u64 = @intCast(self.value + @as(i64, @intCast(self.size)));
try elf_file.growAllocSection(self.output_section_index, needed_size); try elf_file.growAllocSection(self.output_section_index, needed_size);
last_atom_index.* = self.atom_index; last_atom_ref.* = self.ref();
const zig_object = elf_file.zigObjectPtr().?; switch (self.file(elf_file).?) {
if (zig_object.dwarf) |_| { .zig_object => |zo| if (zo.dwarf) |_| {
// The .debug_info section has `low_pc` and `high_pc` values which is the virtual address // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address
// range of the compilation unit. When we expand the text section, this range changes, // range of the compilation unit. When we expand the text section, this range changes,
// so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty. // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty.
zig_object.debug_info_section_dirty = true; zo.debug_info_section_dirty = true;
// This becomes dirty for the same reason. We could potentially make this more // This becomes dirty for the same reason. We could potentially make this more
// fine-grained with the addition of support for more compilation units. It is planned to // fine-grained with the addition of support for more compilation units. It is planned to
// model each package as a different compilation unit. // model each package as a different compilation unit.
zig_object.debug_aranges_section_dirty = true; zo.debug_aranges_section_dirty = true;
zig_object.debug_rnglists_section_dirty = true; zo.debug_rnglists_section_dirty = true;
},
else => {},
} }
} }
shdr.sh_addralign = @max(shdr.sh_addralign, self.alignment.toByteUnits().?); shdr.sh_addralign = @max(shdr.sh_addralign, self.alignment.toByteUnits().?);
@ -214,21 +224,21 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
// This function can also reallocate an atom. // This function can also reallocate an atom.
// In this case we need to "unplug" it from its previous location before // In this case we need to "unplug" it from its previous location before
// plugging it in to its new location. // plugging it in to its new location.
if (zo.atom(self.prev_index)) |prev| { if (self.prevAtom(elf_file)) |prev| {
prev.next_index = self.next_index; prev.next_atom_ref = self.next_atom_ref;
} }
if (zo.atom(self.next_index)) |next| { if (self.nextAtom(elf_file)) |next| {
next.prev_index = self.prev_index; next.prev_atom_ref = self.prev_atom_ref;
} }
if (atom_placement) |big_atom_index| { if (atom_placement) |big_atom_ref| {
const big_atom = zo.atom(big_atom_index).?; const big_atom = elf_file.atom(big_atom_ref).?;
self.prev_index = big_atom_index; self.prev_atom_ref = big_atom_ref;
self.next_index = big_atom.next_index; self.next_atom_ref = big_atom.next_atom_ref;
big_atom.next_index = self.atom_index; big_atom.next_atom_ref = self.ref();
} else { } else {
self.prev_index = 0; self.prev_atom_ref = .{ .index = 0, .file = 0 };
self.next_index = 0; self.next_atom_ref = .{ .index = 0, .file = 0 };
} }
if (free_list_removal) |i| { if (free_list_removal) |i| {
_ = free_list.swapRemove(i); _ = free_list.swapRemove(i);
@ -248,64 +258,70 @@ pub fn grow(self: *Atom, elf_file: *Elf) !void {
} }
pub fn free(self: *Atom, elf_file: *Elf) void { pub fn free(self: *Atom, elf_file: *Elf) void {
log.debug("freeAtom {d} ({s})", .{ self.atom_index, self.name(elf_file) }); log.debug("freeAtom atom({}) ({s})", .{ self.ref(), self.name(elf_file) });
const zo = elf_file.zigObjectPtr().?;
const comp = elf_file.base.comp; const comp = elf_file.base.comp;
const gpa = comp.gpa; const gpa = comp.gpa;
const shndx = self.output_section_index; const shndx = self.output_section_index;
const meta = elf_file.last_atom_and_free_list_table.getPtr(shndx).?; const slice = elf_file.sections.slice();
const free_list = &meta.free_list; const free_list = &slice.items(.free_list)[shndx];
const last_atom_index = &meta.last_atom_index; const last_atom_ref = &slice.items(.last_atom)[shndx];
var already_have_free_list_node = false; var already_have_free_list_node = false;
{ {
var i: usize = 0; var i: usize = 0;
// TODO turn free_list into a hash map // TODO turn free_list into a hash map
while (i < free_list.items.len) { while (i < free_list.items.len) {
if (free_list.items[i] == self.atom_index) { if (free_list.items[i].eql(self.ref())) {
_ = free_list.swapRemove(i); _ = free_list.swapRemove(i);
continue; continue;
} }
if (free_list.items[i] == self.prev_index) { if (self.prevAtom(elf_file)) |prev_atom| {
already_have_free_list_node = true; if (free_list.items[i].eql(prev_atom.ref())) {
already_have_free_list_node = true;
}
} }
i += 1; i += 1;
} }
} }
if (zo.atom(last_atom_index.*)) |last_atom| { if (elf_file.atom(last_atom_ref.*)) |last_atom| {
if (last_atom.atom_index == self.atom_index) { if (last_atom.ref().eql(self.ref())) {
if (zo.atom(self.prev_index)) |_| { if (self.prevAtom(elf_file)) |prev_atom| {
// TODO shrink the section size here // TODO shrink the section size here
last_atom_index.* = self.prev_index; last_atom_ref.* = prev_atom.ref();
} else { } else {
last_atom_index.* = 0; last_atom_ref.* = .{};
} }
} }
} }
if (zo.atom(self.prev_index)) |prev| { if (self.prevAtom(elf_file)) |prev_atom| {
prev.next_index = self.next_index; prev_atom.next_atom_ref = self.next_atom_ref;
if (!already_have_free_list_node and prev.*.freeListEligible(elf_file)) { if (!already_have_free_list_node and prev_atom.*.freeListEligible(elf_file)) {
// The free list is heuristics, it doesn't have to be perfect, so we can // The free list is heuristics, it doesn't have to be perfect, so we can
// ignore the OOM here. // ignore the OOM here.
free_list.append(gpa, prev.atom_index) catch {}; free_list.append(gpa, prev_atom.ref()) catch {};
} }
} else { } else {
self.prev_index = 0; self.prev_atom_ref = .{};
} }
if (zo.atom(self.next_index)) |next| { if (self.nextAtom(elf_file)) |next_atom| {
next.prev_index = self.prev_index; next_atom.prev_atom_ref = self.prev_atom_ref;
} else { } else {
self.next_index = 0; self.next_atom_ref = .{};
} }
// TODO create relocs free list switch (self.file(elf_file).?) {
self.freeRelocs(zo); .zig_object => |zo| {
// TODO figure out how to free input section mappind in ZigModule // TODO create relocs free list
// const zig_object = elf_file.zigObjectPtr().? self.freeRelocs(zo);
// assert(zig_object.atoms.swapRemove(self.atom_index)); // TODO figure out how to free input section mappind in ZigModule
// const zig_object = elf_file.zigObjectPtr().?
// assert(zig_object.atoms.swapRemove(self.atom_index));
},
else => {},
}
self.* = .{}; self.* = .{};
} }
@ -336,10 +352,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El
switch (target.type(elf_file)) { switch (target.type(elf_file)) {
elf.STT_SECTION => { elf.STT_SECTION => {
r_addend += @intCast(target.address(.{}, elf_file)); r_addend += @intCast(target.address(.{}, elf_file));
r_sym = if (target.outputShndx(elf_file)) |osec| r_sym = target.outputShndx(elf_file) orelse 0;
elf_file.sectionSymbolOutputSymtabIndex(osec)
else
0;
}, },
else => { else => {
r_sym = target.outputSymtabIndex(elf_file) orelse 0; r_sym = target.outputSymtabIndex(elf_file) orelse 0;

View file

@ -129,9 +129,10 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void { pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
const gpa = elf_file.base.comp.gpa; const gpa = elf_file.base.comp.gpa;
const slice = elf_file.sections.slice();
var nsyms: usize = 0; var nsyms: usize = 0;
for (elf_file.shdrs.items) |shdr| { for (slice.items(.shdr)) |shdr| {
if (elf_file.getStartStopBasename(shdr)) |_| { if (elf_file.getStartStopBasename(shdr)) |_| {
nsyms += 2; // __start_, __stop_ nsyms += 2; // __start_, __stop_
} }
@ -143,7 +144,7 @@ pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
try self.symbols_extra.ensureUnusedCapacity(gpa, nsyms * @sizeOf(Symbol.Extra)); try self.symbols_extra.ensureUnusedCapacity(gpa, nsyms * @sizeOf(Symbol.Extra));
try self.symbols_resolver.ensureUnusedCapacity(gpa, nsyms); try self.symbols_resolver.ensureUnusedCapacity(gpa, nsyms);
for (elf_file.shdrs.items) |shdr| { for (slice.items(.shdr)) |shdr| {
if (elf_file.getStartStopBasename(shdr)) |name| { if (elf_file.getStartStopBasename(shdr)) |name| {
const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});
defer gpa.free(start_name); defer gpa.free(start_name);
@ -193,6 +194,7 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
const comp = elf_file.base.comp; const comp = elf_file.base.comp;
const link_mode = comp.config.link_mode; const link_mode = comp.config.link_mode;
const shdrs = elf_file.sections.items(.shdr);
const allocSymbol = struct { const allocSymbol = struct {
fn allocSymbol(ld: *LinkerDefined, index: Symbol.Index, value: u64, osec: u32, ef: *Elf) void { fn allocSymbol(ld: *LinkerDefined, index: Symbol.Index, value: u64, osec: u32, ef: *Elf) void {
@ -204,7 +206,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
// _DYNAMIC // _DYNAMIC
if (elf_file.dynamic_section_index) |shndx| { if (elf_file.dynamic_section_index) |shndx| {
const shdr = &elf_file.shdrs.items[shndx]; const shdr = shdrs[shndx];
allocSymbol(self, self.dynamic_index.?, shdr.sh_addr, shndx, elf_file); allocSymbol(self, self.dynamic_index.?, shdr.sh_addr, shndx, elf_file);
} }
@ -213,21 +215,21 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
// __init_array_start, __init_array_end // __init_array_start, __init_array_end
if (elf_file.sectionByName(".init_array")) |shndx| { if (elf_file.sectionByName(".init_array")) |shndx| {
const shdr = &elf_file.shdrs.items[shndx]; const shdr = shdrs[shndx];
allocSymbol(self, self.init_array_start_index.?, shdr.sh_addr, shndx, elf_file); 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); allocSymbol(self, self.init_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file);
} }
// __fini_array_start, __fini_array_end // __fini_array_start, __fini_array_end
if (elf_file.sectionByName(".fini_array")) |shndx| { if (elf_file.sectionByName(".fini_array")) |shndx| {
const shdr = &elf_file.shdrs.items[shndx]; const shdr = shdrs[shndx];
allocSymbol(self, self.fini_array_start_index.?, shdr.sh_addr, shndx, elf_file); 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); allocSymbol(self, self.fini_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file);
} }
// __preinit_array_start, __preinit_array_end // __preinit_array_start, __preinit_array_end
if (elf_file.sectionByName(".preinit_array")) |shndx| { if (elf_file.sectionByName(".preinit_array")) |shndx| {
const shdr = &elf_file.shdrs.items[shndx]; const shdr = shdrs[shndx];
allocSymbol(self, self.preinit_array_start_index.?, shdr.sh_addr, shndx, elf_file); 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); allocSymbol(self, self.preinit_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file);
} }
@ -235,38 +237,38 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
// _GLOBAL_OFFSET_TABLE_ // _GLOBAL_OFFSET_TABLE_
if (elf_file.getTarget().cpu.arch == .x86_64) { if (elf_file.getTarget().cpu.arch == .x86_64) {
if (elf_file.got_plt_section_index) |shndx| { if (elf_file.got_plt_section_index) |shndx| {
const shdr = elf_file.shdrs.items[shndx]; const shdr = shdrs[shndx];
allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file); allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file);
} }
} else { } else {
if (elf_file.got_section_index) |shndx| { if (elf_file.got_section_index) |shndx| {
const shdr = elf_file.shdrs.items[shndx]; const shdr = shdrs[shndx];
allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file); allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file);
} }
} }
// _PROCEDURE_LINKAGE_TABLE_ // _PROCEDURE_LINKAGE_TABLE_
if (elf_file.plt_section_index) |shndx| { if (elf_file.plt_section_index) |shndx| {
const shdr = &elf_file.shdrs.items[shndx]; const shdr = shdrs[shndx];
allocSymbol(self, self.plt_index.?, shdr.sh_addr, shndx, elf_file); allocSymbol(self, self.plt_index.?, shdr.sh_addr, shndx, elf_file);
} }
// __dso_handle // __dso_handle
if (self.dso_handle_index) |index| { if (self.dso_handle_index) |index| {
const shdr = &elf_file.shdrs.items[1]; const shdr = shdrs[1];
allocSymbol(self, index, shdr.sh_addr, 0, elf_file); allocSymbol(self, index, shdr.sh_addr, 0, elf_file);
} }
// __GNU_EH_FRAME_HDR // __GNU_EH_FRAME_HDR
if (elf_file.eh_frame_hdr_section_index) |shndx| { if (elf_file.eh_frame_hdr_section_index) |shndx| {
const shdr = &elf_file.shdrs.items[shndx]; const shdr = shdrs[shndx];
allocSymbol(self, self.gnu_eh_frame_hdr_index.?, shdr.sh_addr, shndx, elf_file); allocSymbol(self, self.gnu_eh_frame_hdr_index.?, shdr.sh_addr, shndx, elf_file);
} }
// __rela_iplt_start, __rela_iplt_end // __rela_iplt_start, __rela_iplt_end
if (elf_file.rela_dyn_section_index) |shndx| blk: { if (elf_file.rela_dyn_section_index) |shndx| blk: {
if (link_mode != .static or comp.config.pie) break :blk; if (link_mode != .static or comp.config.pie) break :blk;
const shdr = &elf_file.shdrs.items[shndx]; const shdr = shdrs[shndx];
const end_addr = shdr.sh_addr + shdr.sh_size; const end_addr = shdr.sh_addr + shdr.sh_size;
const start_addr = end_addr - elf_file.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela); const start_addr = end_addr - elf_file.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela);
allocSymbol(self, self.rela_iplt_start_index.?, start_addr, shndx, elf_file); allocSymbol(self, self.rela_iplt_start_index.?, start_addr, shndx, elf_file);
@ -277,7 +279,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
{ {
var value: u64 = 0; var value: u64 = 0;
var osec: u32 = 0; var osec: u32 = 0;
for (elf_file.shdrs.items, 0..) |shdr, shndx| { for (shdrs, 0..) |shdr, shndx| {
if (shdr.sh_flags & elf.SHF_ALLOC != 0) { if (shdr.sh_flags & elf.SHF_ALLOC != 0) {
value = shdr.sh_addr + shdr.sh_size; value = shdr.sh_addr + shdr.sh_size;
osec = @intCast(shndx); osec = @intCast(shndx);
@ -289,7 +291,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
// __global_pointer$ // __global_pointer$
if (self.global_pointer_index) |index| { if (self.global_pointer_index) |index| {
const value, const osec = if (elf_file.sectionByName(".sdata")) |shndx| .{ const value, const osec = if (elf_file.sectionByName(".sdata")) |shndx| .{
elf_file.shdrs.items[shndx].sh_addr + 0x800, shdrs[shndx].sh_addr + 0x800,
shndx, shndx,
} else .{ 0, 0 }; } else .{ 0, 0 };
allocSymbol(self, index, value, osec, elf_file); allocSymbol(self, index, value, osec, elf_file);
@ -305,7 +307,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
const stop_ref = self.resolveSymbol(self.start_stop_indexes.items[index + 1], elf_file); const stop_ref = self.resolveSymbol(self.start_stop_indexes.items[index + 1], elf_file);
const stop = elf_file.symbol(stop_ref).?; const stop = elf_file.symbol(stop_ref).?;
const shndx = elf_file.sectionByName(name["__start_".len..]).?; const shndx = elf_file.sectionByName(name["__start_".len..]).?;
const shdr = &elf_file.shdrs.items[shndx]; const shdr = shdrs[shndx];
start.value = @intCast(shdr.sh_addr); start.value = @intCast(shdr.sh_addr);
start.output_section_index = shndx; start.output_section_index = shndx;
stop.value = @intCast(shdr.sh_addr + shdr.sh_size); stop.value = @intCast(shdr.sh_addr + shdr.sh_size);

View file

@ -998,9 +998,8 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
const comp = elf_file.base.comp; const comp = elf_file.base.comp;
const gpa = comp.gpa; const gpa = comp.gpa;
const gop = try elf_file.output_sections.getOrPut(gpa, atom_ptr.output_section_index); const atom_list = &elf_file.sections.items(.atom_list)[atom_ptr.output_section_index];
if (!gop.found_existing) gop.value_ptr.* = .{}; try atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
try gop.value_ptr.append(gpa, .{ .index = atom_index, .file = self.index });
} }
} }
@ -1011,7 +1010,8 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void {
const shndx = atom_ptr.relocsShndx() orelse continue; const shndx = atom_ptr.relocsShndx() orelse continue;
const shdr = self.shdrs.items[shndx]; const shdr = self.shdrs.items[shndx];
const out_shndx = try self.initOutputSection(elf_file, shdr); const out_shndx = try self.initOutputSection(elf_file, shdr);
const out_shdr = &elf_file.shdrs.items[out_shndx]; const out_shdr = &elf_file.sections.items(.shdr)[out_shndx];
out_shdr.sh_type = elf.SHT_RELA;
out_shdr.sh_addralign = @alignOf(elf.Elf64_Rela); out_shdr.sh_addralign = @alignOf(elf.Elf64_Rela);
out_shdr.sh_entsize = @sizeOf(elf.Elf64_Rela); out_shdr.sh_entsize = @sizeOf(elf.Elf64_Rela);
out_shdr.sh_flags |= elf.SHF_INFO_LINK; out_shdr.sh_flags |= elf.SHF_INFO_LINK;
@ -1027,15 +1027,13 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {
const shdr = self.shdrs.items[shndx]; const shdr = self.shdrs.items[shndx];
break :blk self.initOutputSection(elf_file, shdr) catch unreachable; break :blk self.initOutputSection(elf_file, shdr) catch unreachable;
}; };
const shdr = &elf_file.shdrs.items[shndx]; const slice = elf_file.sections.slice();
const shdr = &slice.items(.shdr)[shndx];
shdr.sh_info = atom_ptr.output_section_index; shdr.sh_info = atom_ptr.output_section_index;
shdr.sh_link = elf_file.symtab_section_index.?; shdr.sh_link = elf_file.symtab_section_index.?;
const gpa = elf_file.base.comp.gpa;
const comp = elf_file.base.comp; const atom_list = &elf_file.sections.items(.atom_list)[shndx];
const gpa = comp.gpa; try atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
const gop = try elf_file.output_rela_sections.getOrPut(gpa, atom_ptr.output_section_index);
if (!gop.found_existing) gop.value_ptr.* = .{ .shndx = shndx };
try gop.value_ptr.atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
} }
} }

View file

@ -11,7 +11,7 @@ file_index: File.Index = 0,
/// Reference to Atom or merge subsection containing this symbol if any. /// Reference to Atom or merge subsection containing this symbol if any.
/// Use `atom` or `mergeSubsection` to get the pointer to the atom. /// Use `atom` or `mergeSubsection` to get the pointer to the atom.
ref: Elf.Ref = .{ .index = 0, .file = 0 }, ref: Elf.Ref = .{},
/// Assigned output section index for this symbol. /// Assigned output section index for this symbol.
output_section_index: u32 = 0, output_section_index: u32 = 0,
@ -126,7 +126,7 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true, trampoline: bool
const sym_name = symbol.name(elf_file); const sym_name = symbol.name(elf_file);
const sh_addr, const sh_size = blk: { const sh_addr, const sh_size = blk: {
const shndx = elf_file.eh_frame_section_index orelse break :blk .{ 0, 0 }; const shndx = elf_file.eh_frame_section_index orelse break :blk .{ 0, 0 };
const shdr = elf_file.shdrs.items[shndx]; const shdr = elf_file.sections.items(.shdr)[shndx];
break :blk .{ shdr.sh_addr, shdr.sh_size }; break :blk .{ shdr.sh_addr, shdr.sh_size };
}; };
if (mem.startsWith(u8, sym_name, "__EH_FRAME_BEGIN__") or if (mem.startsWith(u8, sym_name, "__EH_FRAME_BEGIN__") or
@ -173,7 +173,7 @@ pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 {
pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 { pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0; 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 shdr = elf_file.sections.items(.shdr)[elf_file.plt_got_section_index.?];
const cpu_arch = elf_file.getTarget().cpu.arch; const cpu_arch = elf_file.getTarget().cpu.arch;
return @intCast(shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch)); return @intCast(shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch));
} }
@ -181,7 +181,7 @@ pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 { pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 {
if (!symbol.flags.has_plt) return 0; 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 shdr = elf_file.sections.items(.shdr)[elf_file.plt_section_index.?];
const cpu_arch = elf_file.getTarget().cpu.arch; const cpu_arch = elf_file.getTarget().cpu.arch;
return @intCast(shdr.sh_addr + extras.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch)); return @intCast(shdr.sh_addr + extras.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch));
} }
@ -189,13 +189,13 @@ pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 {
pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) i64 { pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) i64 {
if (!symbol.flags.has_plt) return 0; 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.?]; const shdr = elf_file.sections.items(.shdr)[elf_file.got_plt_section_index.?];
return @intCast(shdr.sh_addr + extras.plt * 8 + GotPltSection.preamble_size); return @intCast(shdr.sh_addr + extras.plt * 8 + GotPltSection.preamble_size);
} }
pub fn copyRelAddress(symbol: Symbol, elf_file: *Elf) i64 { pub fn copyRelAddress(symbol: Symbol, elf_file: *Elf) i64 {
if (!symbol.flags.has_copy_rel) return 0; if (!symbol.flags.has_copy_rel) return 0;
const shdr = elf_file.shdrs.items[elf_file.copy_rel_section_index.?]; const shdr = elf_file.sections.items(.shdr)[elf_file.copy_rel_section_index.?];
return @as(i64, @intCast(shdr.sh_addr)) + symbol.value; return @as(i64, @intCast(shdr.sh_addr)) + symbol.value;
} }
@ -300,7 +300,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
break :blk 0; break :blk 0;
} }
if (st_shndx == elf.SHN_ABS or st_shndx == elf.SHN_COMMON) break :blk symbol.address(.{ .plt = false }, elf_file); if (st_shndx == elf.SHN_ABS or st_shndx == elf.SHN_COMMON) break :blk symbol.address(.{ .plt = false }, elf_file);
const shdr = elf_file.shdrs.items[st_shndx]; const shdr = elf_file.sections.items(.shdr)[st_shndx];
if (shdr.sh_flags & elf.SHF_TLS != 0 and file_ptr != .linker_defined) if (shdr.sh_flags & elf.SHF_TLS != 0 and file_ptr != .linker_defined)
break :blk symbol.address(.{ .plt = false }, elf_file) - elf_file.tlsAddress(); break :blk symbol.address(.{ .plt = false }, elf_file) - elf_file.tlsAddress();
break :blk symbol.address(.{ .plt = false, .trampoline = false }, elf_file); break :blk symbol.address(.{ .plt = false, .trampoline = false }, elf_file);

View file

@ -63,24 +63,300 @@ pub const global_symbol_bit: u32 = 0x80000000;
pub const symbol_mask: u32 = 0x7fffffff; pub const symbol_mask: u32 = 0x7fffffff;
pub const SHN_ATOM: u16 = 0x100; pub const SHN_ATOM: u16 = 0x100;
pub fn init(self: *ZigObject, elf_file: *Elf) !void { const InitOptions = struct {
symbol_count_hint: u64,
program_code_size_hint: u64,
};
pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
const comp = elf_file.base.comp; const comp = elf_file.base.comp;
const gpa = comp.gpa; const gpa = comp.gpa;
const ptr_size = elf_file.ptrWidthBytes();
const target = elf_file.getTarget();
const ptr_bit_width = target.ptrBitWidth();
try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); // null input section try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); // null input section
try self.relocs.append(gpa, .{}); // null relocs section try self.relocs.append(gpa, .{}); // null relocs section
try self.strtab.buffer.append(gpa, 0); try self.strtab.buffer.append(gpa, 0);
const name_off = try self.strtab.insert(gpa, self.path); {
const symbol_index = try self.newLocalSymbol(gpa, name_off); const name_off = try self.strtab.insert(gpa, self.path);
const sym = self.symbol(symbol_index); const symbol_index = try self.newLocalSymbol(gpa, name_off);
const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; const sym = self.symbol(symbol_index);
esym.st_info = elf.STT_FILE; const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
esym.st_shndx = elf.SHN_ABS; esym.st_info = elf.STT_FILE;
esym.st_shndx = elf.SHN_ABS;
}
const fillSection = struct {
fn fillSection(ef: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) !void {
if (ef.base.isRelocatable()) {
const off = try ef.findFreeSpace(size, shdr.sh_addralign);
shdr.sh_offset = off;
shdr.sh_size = size;
} else {
const phdr = ef.phdrs.items[phndx.?];
shdr.sh_addr = phdr.p_vaddr;
shdr.sh_offset = phdr.p_offset;
shdr.sh_size = phdr.p_memsz;
}
}
}.fillSection;
comptime assert(Elf.number_of_zig_segments == 4);
if (!elf_file.base.isRelocatable()) {
if (elf_file.phdr_zig_load_re_index == null) {
const filesz = options.program_code_size_hint;
const off = try elf_file.findFreeSpace(filesz, elf_file.page_size);
elf_file.phdr_zig_load_re_index = try elf_file.addPhdr(.{
.type = elf.PT_LOAD,
.offset = off,
.filesz = filesz,
.addr = if (ptr_bit_width >= 32) 0x4000000 else 0x4000,
.memsz = filesz,
.@"align" = elf_file.page_size,
.flags = elf.PF_X | elf.PF_R | elf.PF_W,
});
}
if (elf_file.phdr_zig_load_ro_index == null) {
const alignment = elf_file.page_size;
const filesz: u64 = 1024;
const off = try elf_file.findFreeSpace(filesz, alignment);
elf_file.phdr_zig_load_ro_index = try elf_file.addPhdr(.{
.type = elf.PT_LOAD,
.offset = off,
.filesz = filesz,
.addr = if (ptr_bit_width >= 32) 0xc000000 else 0xa000,
.memsz = filesz,
.@"align" = alignment,
.flags = elf.PF_R | elf.PF_W,
});
}
if (elf_file.phdr_zig_load_rw_index == null) {
const alignment = elf_file.page_size;
const filesz: u64 = 1024;
const off = try elf_file.findFreeSpace(filesz, alignment);
elf_file.phdr_zig_load_rw_index = try elf_file.addPhdr(.{
.type = elf.PT_LOAD,
.offset = off,
.filesz = filesz,
.addr = if (ptr_bit_width >= 32) 0x10000000 else 0xc000,
.memsz = filesz,
.@"align" = alignment,
.flags = elf.PF_R | elf.PF_W,
});
}
if (elf_file.phdr_zig_load_zerofill_index == null) {
const alignment = elf_file.page_size;
elf_file.phdr_zig_load_zerofill_index = try elf_file.addPhdr(.{
.type = elf.PT_LOAD,
.addr = if (ptr_bit_width >= 32) 0x14000000 else 0xf000,
.memsz = 1024,
.@"align" = alignment,
.flags = elf.PF_R | elf.PF_W,
});
}
}
if (elf_file.zig_text_section_index == null) {
elf_file.zig_text_section_index = try elf_file.addSection(.{
.name = try elf_file.insertShString(".text.zig"),
.type = elf.SHT_PROGBITS,
.flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
.addralign = 1,
.offset = std.math.maxInt(u64),
});
const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_text_section_index.?];
const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_text_section_index.?];
try fillSection(elf_file, shdr, options.program_code_size_hint, elf_file.phdr_zig_load_re_index);
if (elf_file.base.isRelocatable()) {
_ = try elf_file.addRelaShdr(
try elf_file.insertShString(".rela.text.zig"),
elf_file.zig_text_section_index.?,
);
} else {
phndx.* = elf_file.phdr_zig_load_re_index.?;
}
}
if (elf_file.zig_data_rel_ro_section_index == null) {
elf_file.zig_data_rel_ro_section_index = try elf_file.addSection(.{
.name = try elf_file.insertShString(".data.rel.ro.zig"),
.type = elf.SHT_PROGBITS,
.addralign = 1,
.flags = elf.SHF_ALLOC | elf.SHF_WRITE,
.offset = std.math.maxInt(u64),
});
const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_data_rel_ro_section_index.?];
const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_data_rel_ro_section_index.?];
try fillSection(elf_file, shdr, 1024, elf_file.phdr_zig_load_ro_index);
if (elf_file.base.isRelocatable()) {
_ = try elf_file.addRelaShdr(
try elf_file.insertShString(".rela.data.rel.ro.zig"),
elf_file.zig_data_rel_ro_section_index.?,
);
} else {
phndx.* = elf_file.phdr_zig_load_ro_index.?;
}
}
if (elf_file.zig_data_section_index == null) {
elf_file.zig_data_section_index = try elf_file.addSection(.{
.name = try elf_file.insertShString(".data.zig"),
.type = elf.SHT_PROGBITS,
.addralign = ptr_size,
.flags = elf.SHF_ALLOC | elf.SHF_WRITE,
.offset = std.math.maxInt(u64),
});
const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_data_section_index.?];
const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_data_section_index.?];
try fillSection(elf_file, shdr, 1024, elf_file.phdr_zig_load_rw_index);
if (elf_file.base.isRelocatable()) {
_ = try elf_file.addRelaShdr(
try elf_file.insertShString(".rela.data.zig"),
elf_file.zig_data_section_index.?,
);
} else {
phndx.* = elf_file.phdr_zig_load_rw_index.?;
}
}
if (elf_file.zig_bss_section_index == null) {
elf_file.zig_bss_section_index = try elf_file.addSection(.{
.name = try elf_file.insertShString(".bss.zig"),
.type = elf.SHT_NOBITS,
.addralign = ptr_size,
.flags = elf.SHF_ALLOC | elf.SHF_WRITE,
.offset = 0,
});
const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_bss_section_index.?];
const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_bss_section_index.?];
if (elf_file.base.isRelocatable()) {
shdr.sh_size = 1024;
} else {
phndx.* = elf_file.phdr_zig_load_zerofill_index.?;
const phdr = elf_file.phdrs.items[phndx.*.?];
shdr.sh_addr = phdr.p_vaddr;
shdr.sh_size = phdr.p_memsz;
}
}
switch (comp.config.debug_format) { switch (comp.config.debug_format) {
.strip => {}, .strip => {},
.dwarf => |v| self.dwarf = Dwarf.init(&elf_file.base, v), .dwarf => |v| {
var dwarf = Dwarf.init(&elf_file.base, v);
const addSectionSymbol = struct {
fn addSectionSymbol(
zig_object: *ZigObject,
alloc: Allocator,
name: [:0]const u8,
alignment: Atom.Alignment,
shndx: u32,
) !Symbol.Index {
const name_off = try zig_object.addString(alloc, name);
const index = try zig_object.newSymbolWithAtom(alloc, name_off);
const sym = zig_object.symbol(index);
const esym = &zig_object.symtab.items(.elf_sym)[sym.esym_index];
esym.st_info |= elf.STT_SECTION;
const atom_ptr = zig_object.atom(sym.ref.index).?;
atom_ptr.alignment = alignment;
atom_ptr.output_section_index = shndx;
return index;
}
}.addSectionSymbol;
if (elf_file.debug_str_section_index == null) {
elf_file.debug_str_section_index = try elf_file.addSection(.{
.name = try elf_file.insertShString(".debug_str"),
.flags = elf.SHF_MERGE | elf.SHF_STRINGS,
.entsize = 1,
.type = elf.SHT_PROGBITS,
.addralign = 1,
});
self.debug_str_section_dirty = true;
self.debug_str_index = try addSectionSymbol(self, gpa, ".debug_str", .@"1", elf_file.debug_str_section_index.?);
}
if (elf_file.debug_info_section_index == null) {
elf_file.debug_info_section_index = try elf_file.addSection(.{
.name = try elf_file.insertShString(".debug_info"),
.type = elf.SHT_PROGBITS,
.addralign = 1,
});
self.debug_info_section_dirty = true;
self.debug_info_index = try addSectionSymbol(self, gpa, ".debug_info", .@"1", elf_file.debug_info_section_index.?);
}
if (elf_file.debug_abbrev_section_index == null) {
elf_file.debug_abbrev_section_index = try elf_file.addSection(.{
.name = try elf_file.insertShString(".debug_abbrev"),
.type = elf.SHT_PROGBITS,
.addralign = 1,
});
self.debug_abbrev_section_dirty = true;
self.debug_abbrev_index = try addSectionSymbol(self, gpa, ".debug_abbrev", .@"1", elf_file.debug_abbrev_section_index.?);
}
if (elf_file.debug_aranges_section_index == null) {
elf_file.debug_aranges_section_index = try elf_file.addSection(.{
.name = try elf_file.insertShString(".debug_aranges"),
.type = elf.SHT_PROGBITS,
.addralign = 16,
});
self.debug_aranges_section_dirty = true;
self.debug_aranges_index = try addSectionSymbol(self, gpa, ".debug_aranges", .@"16", elf_file.debug_aranges_section_index.?);
}
if (elf_file.debug_line_section_index == null) {
elf_file.debug_line_section_index = try elf_file.addSection(.{
.name = try elf_file.insertShString(".debug_line"),
.type = elf.SHT_PROGBITS,
.addralign = 1,
});
self.debug_line_section_dirty = true;
self.debug_line_index = try addSectionSymbol(self, gpa, ".debug_line", .@"1", elf_file.debug_line_section_index.?);
}
if (elf_file.debug_line_str_section_index == null) {
elf_file.debug_line_str_section_index = try elf_file.addSection(.{
.name = try elf_file.insertShString(".debug_line_str"),
.flags = elf.SHF_MERGE | elf.SHF_STRINGS,
.entsize = 1,
.type = elf.SHT_PROGBITS,
.addralign = 1,
});
self.debug_line_str_section_dirty = true;
self.debug_line_str_index = try addSectionSymbol(self, gpa, ".debug_line_str", .@"1", elf_file.debug_line_str_section_index.?);
}
if (elf_file.debug_loclists_section_index == null) {
elf_file.debug_loclists_section_index = try elf_file.addSection(.{
.name = try elf_file.insertShString(".debug_loclists"),
.type = elf.SHT_PROGBITS,
.addralign = 1,
});
self.debug_loclists_section_dirty = true;
self.debug_loclists_index = try addSectionSymbol(self, gpa, ".debug_loclists", .@"1", elf_file.debug_loclists_section_index.?);
}
if (elf_file.debug_rnglists_section_index == null) {
elf_file.debug_rnglists_section_index = try elf_file.addSection(.{
.name = try elf_file.insertShString(".debug_rnglists"),
.type = elf.SHT_PROGBITS,
.addralign = 1,
});
self.debug_rnglists_section_dirty = true;
self.debug_rnglists_index = try addSectionSymbol(self, gpa, ".debug_rnglists", .@"1", elf_file.debug_rnglists_section_index.?);
}
try dwarf.initMetadata();
self.dwarf = dwarf;
},
.code_view => unreachable, .code_view => unreachable,
} }
} }
@ -198,7 +474,7 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
const atom_ptr = self.atom(sym.ref.index).?; const atom_ptr = self.atom(sym.ref.index).?;
if (!atom_ptr.alive) continue; if (!atom_ptr.alive) continue;
const shndx = sym.outputShndx(elf_file).?; const shndx = sym.outputShndx(elf_file).?;
const shdr = elf_file.shdrs.items[shndx]; const shdr = elf_file.sections.items(.shdr)[shndx];
const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
esym.st_size = shdr.sh_size; esym.st_size = shdr.sh_size;
atom_ptr.size = shdr.sh_size; atom_ptr.size = shdr.sh_size;
@ -358,13 +634,10 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
} }
if (elf_file.base.isRelocatable() and relocs.items.len > 0) { if (elf_file.base.isRelocatable() and relocs.items.len > 0) {
const gop = try elf_file.output_rela_sections.getOrPut(gpa, shndx); const rela_sect_name = try std.fmt.allocPrintZ(gpa, ".rela{s}", .{elf_file.getShString(shdr.sh_name)});
if (!gop.found_existing) { defer gpa.free(rela_sect_name);
const rela_sect_name = try std.fmt.allocPrintZ(gpa, ".rela{s}", .{elf_file.getShString(shdr.sh_name)}); if (elf_file.sectionByName(rela_sect_name) == null) {
defer gpa.free(rela_sect_name); _ = try elf_file.addRelaShdr(try elf_file.insertShString(rela_sect_name), shndx);
const rela_sh_name = try elf_file.insertShString(rela_sect_name);
const rela_shndx = try elf_file.addRelaShdr(rela_sh_name, shndx);
gop.value_ptr.* = .{ .shndx = rela_shndx };
} }
} }
} }
@ -446,7 +719,7 @@ fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index {
return index; return index;
} }
pub fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index { fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {
const atom_index = try self.newAtom(allocator, name_off); const atom_index = try self.newAtom(allocator, name_off);
const sym_index = try self.newLocalSymbol(allocator, name_off); const sym_index = try self.newLocalSymbol(allocator, name_off);
const sym = self.symbol(sym_index); const sym = self.symbol(sym_index);
@ -460,7 +733,7 @@ pub fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32)
pub fn inputShdr(self: *ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.Elf64_Shdr { pub fn inputShdr(self: *ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.Elf64_Shdr {
const atom_ptr = self.atom(atom_index) orelse return Elf.null_shdr; const atom_ptr = self.atom(atom_index) orelse return Elf.null_shdr;
const shndx = atom_ptr.output_section_index; const shndx = atom_ptr.output_section_index;
var shdr = elf_file.shdrs.items[shndx]; var shdr = elf_file.sections.items(.shdr)[shndx];
shdr.sh_addr = 0; shdr.sh_addr = 0;
shdr.sh_offset = 0; shdr.sh_offset = 0;
shdr.sh_size = atom_ptr.size; shdr.sh_size = atom_ptr.size;
@ -638,8 +911,8 @@ pub fn readFileContents(self: *ZigObject, elf_file: *Elf) !void {
.p32 => @sizeOf(elf.Elf32_Shdr), .p32 => @sizeOf(elf.Elf32_Shdr),
.p64 => @sizeOf(elf.Elf64_Shdr), .p64 => @sizeOf(elf.Elf64_Shdr),
}; };
var end_pos: u64 = elf_file.shdr_table_offset.? + elf_file.shdrs.items.len * shsize; var end_pos: u64 = elf_file.shdr_table_offset.? + elf_file.sections.items(.shdr).len * shsize;
for (elf_file.shdrs.items) |shdr| { for (elf_file.sections.items(.shdr)) |shdr| {
if (shdr.sh_type == elf.SHT_NOBITS) continue; if (shdr.sh_type == elf.SHT_NOBITS) continue;
end_pos = @max(end_pos, shdr.sh_offset + shdr.sh_size); end_pos = @max(end_pos, shdr.sh_offset + shdr.sh_size);
} }
@ -692,12 +965,14 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {
// TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level
if (self.relocs.items[rela_shndx].items.len == 0) continue; if (self.relocs.items[rela_shndx].items.len == 0) continue;
const out_shndx = atom_ptr.output_section_index; const out_shndx = atom_ptr.output_section_index;
const out_shdr = elf_file.shdrs.items[out_shndx]; const out_shdr = elf_file.sections.items(.shdr)[out_shndx];
if (out_shdr.sh_type == elf.SHT_NOBITS) continue; if (out_shdr.sh_type == elf.SHT_NOBITS) continue;
const out_rela_shndx = for (elf_file.sections.items(.shdr), 0..) |out_rela_shdr, out_rela_shndx| {
if (out_rela_shdr.sh_type == elf.SHT_RELA and out_rela_shdr.sh_info == out_shndx) break out_rela_shndx;
} else unreachable;
const atom_list = &elf_file.sections.items(.atom_list)[out_rela_shndx];
const gpa = elf_file.base.comp.gpa; const gpa = elf_file.base.comp.gpa;
const sec = elf_file.output_rela_sections.getPtr(out_shndx).?; try atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
try sec.atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
} }
} }
@ -767,7 +1042,7 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void {
pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
const gpa = elf_file.base.comp.gpa; const gpa = elf_file.base.comp.gpa;
const atom_ptr = self.atom(atom_index).?; const atom_ptr = self.atom(atom_index).?;
const shdr = &elf_file.shdrs.items[atom_ptr.output_section_index]; const shdr = &elf_file.sections.items(.shdr)[atom_ptr.output_section_index];
if (shdr.sh_flags & elf.SHF_TLS != 0) { if (shdr.sh_flags & elf.SHF_TLS != 0) {
const tlv = self.tls_variables.get(atom_index).?; const tlv = self.tls_variables.get(atom_index).?;
@ -1094,7 +1369,7 @@ fn updateNavCode(
} }
} }
const shdr = elf_file.shdrs.items[shdr_index]; const shdr = elf_file.sections.items(.shdr)[shdr_index];
if (shdr.sh_type != elf.SHT_NOBITS) { if (shdr.sh_type != elf.SHT_NOBITS) {
const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
try elf_file.base.file.?.pwriteAll(code, file_offset); try elf_file.base.file.?.pwriteAll(code, file_offset);
@ -1149,16 +1424,13 @@ fn updateTlv(
gop.value_ptr.* = .{ .symbol_index = sym_index }; gop.value_ptr.* = .{ .symbol_index = sym_index };
// We only store the data for the TLV if it's non-zerofill. // We only store the data for the TLV if it's non-zerofill.
if (elf_file.shdrs.items[shndx].sh_type != elf.SHT_NOBITS) { if (elf_file.sections.items(.shdr)[shndx].sh_type != elf.SHT_NOBITS) {
gop.value_ptr.code = try gpa.dupe(u8, code); gop.value_ptr.code = try gpa.dupe(u8, code);
} }
} }
{ const atom_list = &elf_file.sections.items(.atom_list)[atom_ptr.output_section_index];
const gop = try elf_file.output_sections.getOrPut(gpa, atom_ptr.output_section_index); try atom_list.append(gpa, .{ .index = atom_ptr.atom_index, .file = self.index });
if (!gop.found_existing) gop.value_ptr.* = .{};
try gop.value_ptr.append(gpa, .{ .index = atom_ptr.atom_index, .file = self.index });
}
} }
pub fn updateFunc( pub fn updateFunc(
@ -1210,7 +1482,7 @@ pub fn updateFunc(
const shndx = try self.getNavShdrIndex(elf_file, zcu, func.owner_nav, sym_index, code); const shndx = try self.getNavShdrIndex(elf_file, zcu, func.owner_nav, sym_index, code);
log.debug("setting shdr({x},{s}) for {}", .{ log.debug("setting shdr({x},{s}) for {}", .{
shndx, shndx,
elf_file.getShString(elf_file.shdrs.items[shndx].sh_name), elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name),
ip.getNav(func.owner_nav).fqn.fmt(ip), ip.getNav(func.owner_nav).fqn.fmt(ip),
}); });
const old_rva, const old_alignment = blk: { const old_rva, const old_alignment = blk: {
@ -1338,10 +1610,10 @@ pub fn updateNav(
const shndx = try self.getNavShdrIndex(elf_file, zcu, nav_index, sym_index, code); const shndx = try self.getNavShdrIndex(elf_file, zcu, nav_index, sym_index, code);
log.debug("setting shdr({x},{s}) for {}", .{ log.debug("setting shdr({x},{s}) for {}", .{
shndx, shndx,
elf_file.getShString(elf_file.shdrs.items[shndx].sh_name), elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name),
nav.fqn.fmt(ip), nav.fqn.fmt(ip),
}); });
if (elf_file.shdrs.items[shndx].sh_flags & elf.SHF_TLS != 0) if (elf_file.sections.items(.shdr)[shndx].sh_flags & elf.SHF_TLS != 0)
try self.updateTlv(elf_file, pt, nav_index, sym_index, shndx, code) try self.updateTlv(elf_file, pt, nav_index, sym_index, shndx, code)
else else
try self.updateNavCode(elf_file, pt, nav_index, sym_index, shndx, code, elf.STT_OBJECT); try self.updateNavCode(elf_file, pt, nav_index, sym_index, shndx, code, elf.STT_OBJECT);
@ -1440,7 +1712,7 @@ fn updateLazySymbol(
local_sym.value = 0; local_sym.value = 0;
local_esym.st_value = 0; local_esym.st_value = 0;
const shdr = elf_file.shdrs.items[output_section_index]; const shdr = elf_file.sections.items(.shdr)[output_section_index];
const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
try elf_file.base.file.?.pwriteAll(code, file_offset); try elf_file.base.file.?.pwriteAll(code, file_offset);
} }
@ -1496,7 +1768,7 @@ fn lowerConst(
// TODO rename and re-audit this method // TODO rename and re-audit this method
errdefer self.freeNavMetadata(elf_file, sym_index); errdefer self.freeNavMetadata(elf_file, sym_index);
const shdr = elf_file.shdrs.items[output_section_index]; const shdr = elf_file.sections.items(.shdr)[output_section_index];
const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
try elf_file.base.file.?.pwriteAll(code, file_offset); try elf_file.base.file.?.pwriteAll(code, file_offset);
@ -1660,7 +1932,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 {
fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void { fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {
const atom_ptr = tr_sym.atom(elf_file).?; const atom_ptr = tr_sym.atom(elf_file).?;
const shdr = elf_file.shdrs.items[atom_ptr.output_section_index]; const shdr = elf_file.sections.items(.shdr)[atom_ptr.output_section_index];
const fileoff = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); const fileoff = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
const source_addr = tr_sym.address(.{}, elf_file); const source_addr = tr_sym.address(.{}, elf_file);
const target_addr = target.address(.{ .trampoline = false }, elf_file); const target_addr = target.address(.{ .trampoline = false }, elf_file);

View file

@ -13,7 +13,7 @@ pub const Fde = struct {
pub fn address(fde: Fde, elf_file: *Elf) u64 { pub fn address(fde: Fde, elf_file: *Elf) u64 {
const base: u64 = if (elf_file.eh_frame_section_index) |shndx| const base: u64 = if (elf_file.eh_frame_section_index) |shndx|
elf_file.shdrs.items[shndx].sh_addr elf_file.sections.items(.shdr)[shndx].sh_addr
else else
0; 0;
return base + fde.out_offset; return base + fde.out_offset;
@ -112,7 +112,7 @@ pub const Cie = struct {
pub fn address(cie: Cie, elf_file: *Elf) u64 { pub fn address(cie: Cie, elf_file: *Elf) u64 {
const base: u64 = if (elf_file.eh_frame_section_index) |shndx| const base: u64 = if (elf_file.eh_frame_section_index) |shndx|
elf_file.shdrs.items[shndx].sh_addr elf_file.sections.items(.shdr)[shndx].sh_addr
else else
0; 0;
return base + cie.out_offset; return base + cie.out_offset;
@ -326,7 +326,9 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:
} }
pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
relocs_log.debug("{x}: .eh_frame", .{elf_file.shdrs.items[elf_file.eh_frame_section_index.?].sh_addr}); relocs_log.debug("{x}: .eh_frame", .{
elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr,
});
var has_reloc_errors = false; var has_reloc_errors = false;
@ -423,7 +425,7 @@ fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Re
switch (sym.type(elf_file)) { switch (sym.type(elf_file)) {
elf.STT_SECTION => { elf.STT_SECTION => {
r_addend += @intCast(sym.address(.{}, elf_file)); r_addend += @intCast(sym.address(.{}, elf_file));
r_sym = elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx(elf_file).?); r_sym = sym.outputShndx(elf_file).?;
}, },
else => { else => {
r_sym = sym.outputSymtabIndex(elf_file) orelse 0; r_sym = sym.outputSymtabIndex(elf_file) orelse 0;
@ -446,7 +448,9 @@ fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Re
} }
pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
relocs_log.debug("{x}: .eh_frame", .{elf_file.shdrs.items[elf_file.eh_frame_section_index.?].sh_addr}); relocs_log.debug("{x}: .eh_frame", .{
elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr,
});
for (elf_file.objects.items) |index| { for (elf_file.objects.items) |index| {
const object = elf_file.file(index).?.object; const object = elf_file.file(index).?.object;
@ -482,8 +486,9 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
try writer.writeByte(EH_PE.udata4); try writer.writeByte(EH_PE.udata4);
try writer.writeByte(EH_PE.datarel | EH_PE.sdata4); try writer.writeByte(EH_PE.datarel | EH_PE.sdata4);
const eh_frame_shdr = elf_file.shdrs.items[elf_file.eh_frame_section_index.?]; const shdrs = elf_file.sections.items(.shdr);
const eh_frame_hdr_shdr = elf_file.shdrs.items[elf_file.eh_frame_hdr_section_index.?]; const eh_frame_shdr = shdrs[elf_file.eh_frame_section_index.?];
const eh_frame_hdr_shdr = shdrs[elf_file.eh_frame_hdr_section_index.?];
const num_fdes = @as(u32, @intCast(@divExact(eh_frame_hdr_shdr.sh_size - eh_frame_hdr_header_size, 8))); const num_fdes = @as(u32, @intCast(@divExact(eh_frame_hdr_shdr.sh_size - eh_frame_hdr_header_size, 8)));
try writer.writeInt( try writer.writeInt(
u32, u32,

View file

@ -29,7 +29,7 @@ pub const MergeSection = struct {
} }
pub fn address(msec: MergeSection, elf_file: *Elf) i64 { pub fn address(msec: MergeSection, elf_file: *Elf) i64 {
const shdr = elf_file.shdrs.items[msec.output_section_index]; const shdr = elf_file.sections.items(.shdr)[msec.output_section_index];
return @intCast(shdr.sh_addr + msec.value); return @intCast(shdr.sh_addr + msec.value);
} }
@ -108,13 +108,11 @@ pub const MergeSection = struct {
} }
pub fn initOutputSection(msec: *MergeSection, elf_file: *Elf) !void { pub fn initOutputSection(msec: *MergeSection, elf_file: *Elf) !void {
const shndx = elf_file.sectionByName(msec.name(elf_file)) orelse try elf_file.addSection(.{ msec.output_section_index = elf_file.sectionByName(msec.name(elf_file)) orelse try elf_file.addSection(.{
.name = msec.name_offset, .name = msec.name_offset,
.type = msec.type, .type = msec.type,
.flags = msec.flags, .flags = msec.flags,
}); });
try elf_file.output_sections.put(elf_file.base.comp.gpa, shndx, .{});
msec.output_section_index = shndx;
} }
pub fn addMergeSubsection(msec: *MergeSection, allocator: Allocator) !MergeSubsection.Index { pub fn addMergeSubsection(msec: *MergeSection, allocator: Allocator) !MergeSubsection.Index {

View file

@ -347,36 +347,36 @@ fn initComdatGroups(elf_file: *Elf) !void {
} }
fn updateSectionSizes(elf_file: *Elf) !void { fn updateSectionSizes(elf_file: *Elf) !void {
for (elf_file.output_sections.keys(), elf_file.output_sections.values()) |shndx, atom_list| { const slice = elf_file.sections.slice();
const shdr = &elf_file.shdrs.items[shndx]; for (slice.items(.shdr), 0..) |*shdr, shndx| {
for (atom_list.items) |ref| { const atom_list = slice.items(.atom_list)[shndx];
const atom_ptr = elf_file.atom(ref) orelse continue; if (shdr.sh_type != elf.SHT_RELA) {
if (!atom_ptr.alive) continue; for (atom_list.items) |ref| {
const offset = atom_ptr.alignment.forward(shdr.sh_size); const atom_ptr = elf_file.atom(ref) orelse continue;
const padding = offset - shdr.sh_size; if (!atom_ptr.alive) continue;
atom_ptr.value = @intCast(offset); const offset = atom_ptr.alignment.forward(shdr.sh_size);
shdr.sh_size += padding + atom_ptr.size; const padding = offset - shdr.sh_size;
shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1); atom_ptr.value = @intCast(offset);
} shdr.sh_size += padding + atom_ptr.size;
} shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1);
}
} else {
for (atom_list.items) |ref| {
const atom_ptr = elf_file.atom(ref) orelse continue;
if (!atom_ptr.alive) continue;
const relocs = atom_ptr.relocs(elf_file);
shdr.sh_size += shdr.sh_entsize * relocs.len;
}
for (elf_file.output_rela_sections.values()) |sec| { if (shdr.sh_size == 0) shdr.sh_offset = 0;
const shdr = &elf_file.shdrs.items[sec.shndx];
for (sec.atom_list.items) |ref| {
const atom_ptr = elf_file.atom(ref) orelse continue;
if (!atom_ptr.alive) continue;
const relocs = atom_ptr.relocs(elf_file);
shdr.sh_size += shdr.sh_entsize * relocs.len;
} }
if (shdr.sh_size == 0) shdr.sh_offset = 0;
} }
if (elf_file.eh_frame_section_index) |index| { if (elf_file.eh_frame_section_index) |index| {
elf_file.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(elf_file); slice.items(.shdr)[index].sh_size = try eh_frame.calcEhFrameSize(elf_file);
} }
if (elf_file.eh_frame_rela_section_index) |index| { if (elf_file.eh_frame_rela_section_index) |index| {
const shdr = &elf_file.shdrs.items[index]; const shdr = &slice.items(.shdr)[index];
shdr.sh_size = eh_frame.calcEhFrameRelocs(elf_file) * shdr.sh_entsize; shdr.sh_size = eh_frame.calcEhFrameRelocs(elf_file) * shdr.sh_entsize;
} }
@ -387,19 +387,18 @@ fn updateSectionSizes(elf_file: *Elf) !void {
fn updateComdatGroupsSizes(elf_file: *Elf) void { fn updateComdatGroupsSizes(elf_file: *Elf) void {
for (elf_file.comdat_group_sections.items) |cg| { for (elf_file.comdat_group_sections.items) |cg| {
const shdr = &elf_file.shdrs.items[cg.shndx]; const shdr = &elf_file.sections.items(.shdr)[cg.shndx];
shdr.sh_size = cg.size(elf_file); shdr.sh_size = cg.size(elf_file);
shdr.sh_link = elf_file.symtab_section_index.?; shdr.sh_link = elf_file.symtab_section_index.?;
const sym = cg.symbol(elf_file); const sym = cg.symbol(elf_file);
shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse sym.outputShndx(elf_file).?;
elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx(elf_file).?);
} }
} }
/// Allocates alloc sections when merging relocatable objects files together. /// Allocates alloc sections when merging relocatable objects files together.
fn allocateAllocSections(elf_file: *Elf) !void { fn allocateAllocSections(elf_file: *Elf) !void {
for (elf_file.shdrs.items) |*shdr| { for (elf_file.sections.items(.shdr)) |*shdr| {
if (shdr.sh_type == elf.SHT_NULL) continue; if (shdr.sh_type == elf.SHT_NULL) continue;
if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
if (shdr.sh_type == elf.SHT_NOBITS) { if (shdr.sh_type == elf.SHT_NOBITS) {
@ -418,13 +417,13 @@ fn allocateAllocSections(elf_file: *Elf) !void {
fn writeAtoms(elf_file: *Elf) !void { fn writeAtoms(elf_file: *Elf) !void {
const gpa = elf_file.base.comp.gpa; const gpa = elf_file.base.comp.gpa;
const slice = elf_file.sections.slice();
// TODO iterate over `output_sections` directly // TODO iterate over `output_sections` directly
for (elf_file.shdrs.items, 0..) |shdr, shndx| { for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| {
if (shdr.sh_type == elf.SHT_NULL) continue; if (shdr.sh_type == elf.SHT_NULL) continue;
if (shdr.sh_type == elf.SHT_NOBITS) continue; if (shdr.sh_type == elf.SHT_NOBITS) continue;
if (shdr.sh_type == elf.SHT_RELA) continue;
const atom_list = elf_file.output_sections.get(@intCast(shndx)) orelse continue;
if (atom_list.items.len == 0) continue; if (atom_list.items.len == 0) continue;
log.debug("writing atoms in '{s}' section", .{elf_file.getShString(shdr.sh_name)}); log.debug("writing atoms in '{s}' section", .{elf_file.getShString(shdr.sh_name)});
@ -490,18 +489,18 @@ fn writeAtoms(elf_file: *Elf) !void {
fn writeSyntheticSections(elf_file: *Elf) !void { fn writeSyntheticSections(elf_file: *Elf) !void {
const gpa = elf_file.base.comp.gpa; const gpa = elf_file.base.comp.gpa;
const slice = elf_file.sections.slice();
for (elf_file.output_rela_sections.values()) |sec| { for (slice.items(.shdr), slice.items(.atom_list)) |shdr, atom_list| {
if (sec.atom_list.items.len == 0) continue; if (shdr.sh_type != elf.SHT_RELA) continue;
if (atom_list.items.len == 0) continue;
const shdr = elf_file.shdrs.items[sec.shndx];
const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse
return error.Overflow; return error.Overflow;
var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs); var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs);
defer relocs.deinit(); defer relocs.deinit();
for (sec.atom_list.items) |ref| { for (atom_list.items) |ref| {
const atom_ptr = elf_file.atom(ref) orelse continue; const atom_ptr = elf_file.atom(ref) orelse continue;
if (!atom_ptr.alive) continue; if (!atom_ptr.alive) continue;
try atom_ptr.writeRelocs(elf_file, &relocs); try atom_ptr.writeRelocs(elf_file, &relocs);
@ -527,7 +526,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
} }
if (elf_file.eh_frame_section_index) |shndx| { if (elf_file.eh_frame_section_index) |shndx| {
const shdr = elf_file.shdrs.items[shndx]; const shdr = slice.items(.shdr)[shndx];
const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
defer buffer.deinit(); defer buffer.deinit();
@ -540,7 +539,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
} }
if (elf_file.eh_frame_rela_section_index) |shndx| { if (elf_file.eh_frame_rela_section_index) |shndx| {
const shdr = elf_file.shdrs.items[shndx]; const shdr = slice.items(.shdr)[shndx];
const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
defer buffer.deinit(); defer buffer.deinit();
@ -561,7 +560,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
fn writeComdatGroups(elf_file: *Elf) !void { fn writeComdatGroups(elf_file: *Elf) !void {
const gpa = elf_file.base.comp.gpa; const gpa = elf_file.base.comp.gpa;
for (elf_file.comdat_group_sections.items) |cgs| { for (elf_file.comdat_group_sections.items) |cgs| {
const shdr = elf_file.shdrs.items[cgs.shndx]; const shdr = elf_file.sections.items(.shdr)[cgs.shndx];
const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
defer buffer.deinit(); defer buffer.deinit();

View file

@ -95,6 +95,8 @@ pub const DynamicSection = struct {
} }
pub fn write(dt: DynamicSection, elf_file: *Elf, writer: anytype) !void { pub fn write(dt: DynamicSection, elf_file: *Elf, writer: anytype) !void {
const shdrs = elf_file.sections.items(.shdr);
// NEEDED // NEEDED
for (dt.needed.items) |off| { for (dt.needed.items) |off| {
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NEEDED, .d_val = off }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NEEDED, .d_val = off });
@ -112,33 +114,33 @@ pub const DynamicSection = struct {
// INIT // INIT
if (elf_file.sectionByName(".init")) |shndx| { if (elf_file.sectionByName(".init")) |shndx| {
const addr = elf_file.shdrs.items[shndx].sh_addr; const addr = shdrs[shndx].sh_addr;
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT, .d_val = addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT, .d_val = addr });
} }
// FINI // FINI
if (elf_file.sectionByName(".fini")) |shndx| { if (elf_file.sectionByName(".fini")) |shndx| {
const addr = elf_file.shdrs.items[shndx].sh_addr; const addr = shdrs[shndx].sh_addr;
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI, .d_val = addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI, .d_val = addr });
} }
// INIT_ARRAY // INIT_ARRAY
if (elf_file.sectionByName(".init_array")) |shndx| { if (elf_file.sectionByName(".init_array")) |shndx| {
const shdr = elf_file.shdrs.items[shndx]; const shdr = shdrs[shndx];
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr });
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size });
} }
// FINI_ARRAY // FINI_ARRAY
if (elf_file.sectionByName(".fini_array")) |shndx| { if (elf_file.sectionByName(".fini_array")) |shndx| {
const shdr = elf_file.shdrs.items[shndx]; const shdr = shdrs[shndx];
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr });
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size });
} }
// RELA // RELA
if (elf_file.rela_dyn_section_index) |shndx| { if (elf_file.rela_dyn_section_index) |shndx| {
const shdr = elf_file.shdrs.items[shndx]; const shdr = shdrs[shndx];
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr });
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size });
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize });
@ -146,7 +148,7 @@ pub const DynamicSection = struct {
// JMPREL // JMPREL
if (elf_file.rela_plt_section_index) |shndx| { if (elf_file.rela_plt_section_index) |shndx| {
const shdr = elf_file.shdrs.items[shndx]; const shdr = shdrs[shndx];
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr });
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size });
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA });
@ -154,18 +156,18 @@ pub const DynamicSection = struct {
// PLTGOT // PLTGOT
if (elf_file.got_plt_section_index) |shndx| { if (elf_file.got_plt_section_index) |shndx| {
const addr = elf_file.shdrs.items[shndx].sh_addr; const addr = shdrs[shndx].sh_addr;
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr });
} }
{ {
assert(elf_file.hash_section_index != null); assert(elf_file.hash_section_index != null);
const addr = elf_file.shdrs.items[elf_file.hash_section_index.?].sh_addr; const addr = shdrs[elf_file.hash_section_index.?].sh_addr;
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr });
} }
if (elf_file.gnu_hash_section_index) |shndx| { if (elf_file.gnu_hash_section_index) |shndx| {
const addr = elf_file.shdrs.items[shndx].sh_addr; const addr = shdrs[shndx].sh_addr;
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr });
} }
@ -177,7 +179,7 @@ pub const DynamicSection = struct {
// SYMTAB + SYMENT // SYMTAB + SYMENT
{ {
assert(elf_file.dynsymtab_section_index != null); assert(elf_file.dynsymtab_section_index != null);
const shdr = elf_file.shdrs.items[elf_file.dynsymtab_section_index.?]; const shdr = shdrs[elf_file.dynsymtab_section_index.?];
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr });
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize });
} }
@ -185,20 +187,20 @@ pub const DynamicSection = struct {
// STRTAB + STRSZ // STRTAB + STRSZ
{ {
assert(elf_file.dynstrtab_section_index != null); assert(elf_file.dynstrtab_section_index != null);
const shdr = elf_file.shdrs.items[elf_file.dynstrtab_section_index.?]; const shdr = shdrs[elf_file.dynstrtab_section_index.?];
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr });
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size });
} }
// VERSYM // VERSYM
if (elf_file.versym_section_index) |shndx| { if (elf_file.versym_section_index) |shndx| {
const addr = elf_file.shdrs.items[shndx].sh_addr; const addr = shdrs[shndx].sh_addr;
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr });
} }
// VERNEED + VERNEEDNUM // VERNEED + VERNEEDNUM
if (elf_file.verneed_section_index) |shndx| { if (elf_file.verneed_section_index) |shndx| {
const addr = elf_file.shdrs.items[shndx].sh_addr; const addr = shdrs[shndx].sh_addr;
try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr });
try writer.writeStruct(elf.Elf64_Dyn{ try writer.writeStruct(elf.Elf64_Dyn{
.d_tag = elf.DT_VERNEEDNUM, .d_tag = elf.DT_VERNEEDNUM,
@ -259,7 +261,7 @@ pub const GotSection = struct {
pub fn address(entry: Entry, elf_file: *Elf) i64 { pub fn address(entry: Entry, elf_file: *Elf) i64 {
const ptr_bytes = elf_file.archPtrWidthBytes(); const ptr_bytes = elf_file.archPtrWidthBytes();
const shdr = &elf_file.shdrs.items[elf_file.got_section_index.?]; const shdr = &elf_file.sections.items(.shdr)[elf_file.got_section_index.?];
return @as(i64, @intCast(shdr.sh_addr)) + entry.cell_index * ptr_bytes; return @as(i64, @intCast(shdr.sh_addr)) + entry.cell_index * ptr_bytes;
} }
}; };
@ -759,8 +761,9 @@ pub const PltSection = struct {
const x86_64 = struct { const x86_64 = struct {
fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {
const plt_addr = elf_file.shdrs.items[elf_file.plt_section_index.?].sh_addr; const shdrs = elf_file.sections.items(.shdr);
const got_plt_addr = elf_file.shdrs.items[elf_file.got_plt_section_index.?].sh_addr; const plt_addr = shdrs[elf_file.plt_section_index.?].sh_addr;
const got_plt_addr = shdrs[elf_file.got_plt_section_index.?].sh_addr;
var preamble = [_]u8{ var preamble = [_]u8{
0xf3, 0x0f, 0x1e, 0xfa, // endbr64 0xf3, 0x0f, 0x1e, 0xfa, // endbr64
0x41, 0x53, // push r11 0x41, 0x53, // push r11
@ -794,8 +797,9 @@ pub const PltSection = struct {
const aarch64 = struct { const aarch64 = struct {
fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {
{ {
const plt_addr: i64 = @intCast(elf_file.shdrs.items[elf_file.plt_section_index.?].sh_addr); const shdrs = elf_file.sections.items(.shdr);
const got_plt_addr: i64 = @intCast(elf_file.shdrs.items[elf_file.got_plt_section_index.?].sh_addr); const plt_addr: i64 = @intCast(shdrs[elf_file.plt_section_index.?].sh_addr);
const got_plt_addr: i64 = @intCast(shdrs[elf_file.got_plt_section_index.?].sh_addr);
// TODO: relax if possible // TODO: relax if possible
// .got.plt[2] // .got.plt[2]
const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16); const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16);
@ -869,7 +873,7 @@ pub const GotPltSection = struct {
try writer.writeInt(u64, 0x0, .little); try writer.writeInt(u64, 0x0, .little);
try writer.writeInt(u64, 0x0, .little); try writer.writeInt(u64, 0x0, .little);
if (elf_file.plt_section_index) |shndx| { if (elf_file.plt_section_index) |shndx| {
const plt_addr = elf_file.shdrs.items[shndx].sh_addr; const plt_addr = elf_file.sections.items(.shdr)[shndx].sh_addr;
for (0..elf_file.plt.symbols.items.len) |_| { for (0..elf_file.plt.symbols.items.len) |_| {
// [N]: .plt // [N]: .plt
try writer.writeInt(u64, plt_addr, .little); try writer.writeInt(u64, plt_addr, .little);
@ -1027,7 +1031,7 @@ pub const CopyRelSection = struct {
} }
pub fn updateSectionSize(copy_rel: CopyRelSection, shndx: u32, elf_file: *Elf) !void { pub fn updateSectionSize(copy_rel: CopyRelSection, shndx: u32, elf_file: *Elf) !void {
const shdr = &elf_file.shdrs.items[shndx]; const shdr = &elf_file.sections.items(.shdr)[shndx];
for (copy_rel.symbols.items) |ref| { for (copy_rel.symbols.items) |ref| {
const symbol = elf_file.symbol(ref).?; const symbol = elf_file.symbol(ref).?;
const shared_object = symbol.file(elf_file).?.shared_object; const shared_object = symbol.file(elf_file).?.shared_object;
@ -1487,8 +1491,12 @@ pub const ComdatGroupSection = struct {
elf.SHT_RELA => { elf.SHT_RELA => {
const atom_index = object.atoms_indexes.items[shdr.sh_info]; const atom_index = object.atoms_indexes.items[shdr.sh_info];
const atom = object.atom(atom_index).?; const atom = object.atom(atom_index).?;
const rela = elf_file.output_rela_sections.get(atom.output_section_index).?; const rela_shndx = for (elf_file.sections.items(.shdr), 0..) |rela_shdr, rela_shndx| {
try writer.writeInt(u32, rela.shndx, .little); if (rela_shdr.sh_type == elf.SHT_RELA and
atom.output_section_index == rela_shdr.sh_info)
break rela_shndx;
} else unreachable;
try writer.writeInt(u32, @intCast(rela_shndx), .little);
}, },
else => { else => {
const atom_index = object.atoms_indexes.items[shndx]; const atom_index = object.atoms_indexes.items[shndx];

View file

@ -1,9 +1,8 @@
pub fn createThunks(shndx: u32, elf_file: *Elf) !void { pub fn createThunks(shdr: *elf.Elf64_Shdr, shndx: u32, elf_file: *Elf) !void {
const gpa = elf_file.base.comp.gpa; const gpa = elf_file.base.comp.gpa;
const cpu_arch = elf_file.getTarget().cpu.arch; const cpu_arch = elf_file.getTarget().cpu.arch;
const max_distance = maxAllowedDistance(cpu_arch); const max_distance = maxAllowedDistance(cpu_arch);
const shdr = &elf_file.shdrs.items[shndx]; const atoms = elf_file.sections.items(.atom_list)[shndx].items;
const atoms = elf_file.output_sections.get(shndx).?.items;
assert(atoms.len > 0); assert(atoms.len > 0);
for (atoms) |ref| { for (atoms) |ref| {
@ -89,7 +88,7 @@ pub const Thunk = struct {
} }
pub fn address(thunk: Thunk, elf_file: *Elf) i64 { pub fn address(thunk: Thunk, elf_file: *Elf) i64 {
const shdr = elf_file.shdrs.items[thunk.output_section_index]; const shdr = elf_file.sections.items(.shdr)[thunk.output_section_index];
return @as(i64, @intCast(shdr.sh_addr)) + thunk.value; return @as(i64, @intCast(shdr.sh_addr)) + thunk.value;
} }