authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-04 12:11:04+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-04 13:34:26+02:00
logf3d527c0822bd24bcd01fbcf3d670a7633a92468
tree98f8a2c01404e065d8553ca6531cf573a16b56e0
parentd302a1068effe4edcd36bd01f77ac2e1b1048e16

elf: migrate thunks to the new mechanism (AtomList)


1 files changed, 35 insertions(+), 26 deletions(-)

src/link/Elf.zig+35-26
......@@ -3572,19 +3572,26 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
35723572
35733573fn updateSectionSizes(self: *Elf) !void {
35743574 const slice = self.sections.slice();
3575 for (slice.items(.atom_list_2)) |*atom_list| {
3575 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {
35763576 if (atom_list.atoms.items.len == 0) continue;
3577 if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue;
35773578 atom_list.updateSize(self);
35783579 try atom_list.allocate(self);
35793580 }
35803581
35813582 if (self.requiresThunks()) {
3582 for (slice.items(.shdr), slice.items(.atom_list), 0..) |*shdr, atom_list, shndx| {
3583 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {
35833584 if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue;
3584 if (atom_list.items.len == 0) continue;
3585 if (atom_list.atoms.items.len == 0) continue;
35853586
35863587 // Create jump/branch range extenders if needed.
3587 try self.createThunks(shdr, @intCast(shndx));
3588 try self.createThunks(atom_list);
3589 try atom_list.allocate(self);
3590 }
3591
3592 // FIXME:JK this will hopefully not be needed once we create a link from Atom/Thunk to AtomList.
3593 for (self.thunks.items) |*th| {
3594 th.value += slice.items(.atom_list_2)[th.output_section_index].value;
35883595 }
35893596 }
35903597
......@@ -4066,7 +4073,7 @@ fn writeAtoms(self: *Elf) !void {
40664073 for (self.thunks.items) |th| {
40674074 const thunk_size = th.size(self);
40684075 try buffer.ensureUnusedCapacity(thunk_size);
4069 const shdr = self.sections.items(.shdr)[th.output_section_index];
4076 const shdr = slice.items(.shdr)[th.output_section_index];
40704077 const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset;
40714078 try th.write(self, buffer.writer());
40724079 assert(buffer.items.len == thunk_size);
......@@ -5613,9 +5620,10 @@ fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 {
56135620 };
56145621}
56155622
5616fn createThunks(elf_file: *Elf, shdr: *elf.Elf64_Shdr, shndx: u32) !void {
5623fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {
56175624 const gpa = elf_file.base.comp.gpa;
56185625 const cpu_arch = elf_file.getTarget().cpu.arch;
5626
56195627 // A branch will need an extender if its target is larger than
56205628 // `2^(jump_bits - 1) - margin` where margin is some arbitrary number.
56215629 const max_distance = switch (cpu_arch) {
......@@ -5623,36 +5631,44 @@ fn createThunks(elf_file: *Elf, shdr: *elf.Elf64_Shdr, shndx: u32) !void {
56235631 .x86_64, .riscv64 => unreachable,
56245632 else => @panic("unhandled arch"),
56255633 };
5626 const atoms = elf_file.sections.items(.atom_list)[shndx].items;
5627 assert(atoms.len > 0);
56285634
5629 for (atoms) |ref| {
5635 const advance = struct {
5636 fn advance(list: *AtomList, size: u64, alignment: Atom.Alignment) !i64 {
5637 const offset = alignment.forward(list.size);
5638 const padding = offset - list.size;
5639 list.size += padding + size;
5640 list.alignment = list.alignment.max(alignment);
5641 return @intCast(offset);
5642 }
5643 }.advance;
5644
5645 for (atom_list.atoms.items) |ref| {
56305646 elf_file.atom(ref).?.value = -1;
56315647 }
56325648
56335649 var i: usize = 0;
5634 while (i < atoms.len) {
5650 while (i < atom_list.atoms.items.len) {
56355651 const start = i;
5636 const start_atom = elf_file.atom(atoms[start]).?;
5652 const start_atom = elf_file.atom(atom_list.atoms.items[start]).?;
56375653 assert(start_atom.alive);
5638 start_atom.value = try advanceSection(shdr, start_atom.size, start_atom.alignment);
5654 start_atom.value = try advance(atom_list, start_atom.size, start_atom.alignment);
56395655 i += 1;
56405656
5641 while (i < atoms.len) : (i += 1) {
5642 const atom_ptr = elf_file.atom(atoms[i]).?;
5657 while (i < atom_list.atoms.items.len) : (i += 1) {
5658 const atom_ptr = elf_file.atom(atom_list.atoms.items[i]).?;
56435659 assert(atom_ptr.alive);
5644 if (@as(i64, @intCast(atom_ptr.alignment.forward(shdr.sh_size))) - start_atom.value >= max_distance)
5660 if (@as(i64, @intCast(atom_ptr.alignment.forward(atom_list.size))) - start_atom.value >= max_distance)
56455661 break;
5646 atom_ptr.value = try advanceSection(shdr, atom_ptr.size, atom_ptr.alignment);
5662 atom_ptr.value = try advance(atom_list, atom_ptr.size, atom_ptr.alignment);
56475663 }
56485664
56495665 // Insert a thunk at the group end
56505666 const thunk_index = try elf_file.addThunk();
56515667 const thunk_ptr = elf_file.thunk(thunk_index);
5652 thunk_ptr.output_section_index = shndx;
5668 thunk_ptr.output_section_index = atom_list.output_section_index;
56535669
56545670 // Scan relocs in the group and create trampolines for any unreachable callsite
5655 for (atoms[start..i]) |ref| {
5671 for (atom_list.atoms.items[start..i]) |ref| {
56565672 const atom_ptr = elf_file.atom(ref).?;
56575673 const file_ptr = atom_ptr.file(elf_file).?;
56585674 log.debug("atom({}) {s}", .{ ref, atom_ptr.name(elf_file) });
......@@ -5682,18 +5698,11 @@ fn createThunks(elf_file: *Elf, shdr: *elf.Elf64_Shdr, shndx: u32) !void {
56825698 atom_ptr.addExtra(.{ .thunk = thunk_index }, elf_file);
56835699 }
56845700
5685 thunk_ptr.value = try advanceSection(shdr, thunk_ptr.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2));
5701 thunk_ptr.value = try advance(atom_list, thunk_ptr.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2));
56865702
56875703 log.debug("thunk({d}) : {}", .{ thunk_index, thunk_ptr.fmt(elf_file) });
56885704 }
56895705}
5690fn advanceSection(shdr: *elf.Elf64_Shdr, adv_size: u64, alignment: Atom.Alignment) !i64 {
5691 const offset = alignment.forward(shdr.sh_size);
5692 const padding = offset - shdr.sh_size;
5693 shdr.sh_size += padding + adv_size;
5694 shdr.sh_addralign = @max(shdr.sh_addralign, alignment.toByteUnits() orelse 1);
5695 return @intCast(offset);
5696}
56975706
56985707const std = @import("std");
56995708const build_options = @import("build_options");