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 {...@@ -3572,19 +3572,26 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
35723572
3573fn updateSectionSizes(self: *Elf) !void {3573fn updateSectionSizes(self: *Elf) !void {
3574 const slice = self.sections.slice();3574 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| {
3576 if (atom_list.atoms.items.len == 0) continue;3576 if (atom_list.atoms.items.len == 0) continue;
3577 if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue;
3577 atom_list.updateSize(self);3578 atom_list.updateSize(self);
3578 try atom_list.allocate(self);3579 try atom_list.allocate(self);
3579 }3580 }
35803581
3581 if (self.requiresThunks()) {3582 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| {
3583 if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue;3584 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
3586 // Create jump/branch range extenders if needed.3587 // 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;
3588 }3595 }
3589 }3596 }
35903597
...@@ -4066,7 +4073,7 @@ fn writeAtoms(self: *Elf) !void {...@@ -4066,7 +4073,7 @@ fn writeAtoms(self: *Elf) !void {
4066 for (self.thunks.items) |th| {4073 for (self.thunks.items) |th| {
4067 const thunk_size = th.size(self);4074 const thunk_size = th.size(self);
4068 try buffer.ensureUnusedCapacity(thunk_size);4075 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];
4070 const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset;4077 const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset;
4071 try th.write(self, buffer.writer());4078 try th.write(self, buffer.writer());
4072 assert(buffer.items.len == thunk_size);4079 assert(buffer.items.len == thunk_size);
...@@ -5613,9 +5620,10 @@ fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 {...@@ -5613,9 +5620,10 @@ fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 {
5613 };5620 };
5614}5621}
56155622
5616fn createThunks(elf_file: *Elf, shdr: *elf.Elf64_Shdr, shndx: u32) !void {5623fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {
5617 const gpa = elf_file.base.comp.gpa;5624 const gpa = elf_file.base.comp.gpa;
5618 const cpu_arch = elf_file.getTarget().cpu.arch;5625 const cpu_arch = elf_file.getTarget().cpu.arch;
5626
5619 // A branch will need an extender if its target is larger than5627 // A branch will need an extender if its target is larger than
5620 // `2^(jump_bits - 1) - margin` where margin is some arbitrary number.5628 // `2^(jump_bits - 1) - margin` where margin is some arbitrary number.
5621 const max_distance = switch (cpu_arch) {5629 const max_distance = switch (cpu_arch) {
...@@ -5623,36 +5631,44 @@ fn createThunks(elf_file: *Elf, shdr: *elf.Elf64_Shdr, shndx: u32) !void {...@@ -5623,36 +5631,44 @@ fn createThunks(elf_file: *Elf, shdr: *elf.Elf64_Shdr, shndx: u32) !void {
5623 .x86_64, .riscv64 => unreachable,5631 .x86_64, .riscv64 => unreachable,
5624 else => @panic("unhandled arch"),5632 else => @panic("unhandled arch"),
5625 };5633 };
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| {
5630 elf_file.atom(ref).?.value = -1;5646 elf_file.atom(ref).?.value = -1;
5631 }5647 }
56325648
5633 var i: usize = 0;5649 var i: usize = 0;
5634 while (i < atoms.len) {5650 while (i < atom_list.atoms.items.len) {
5635 const start = i;5651 const start = i;
5636 const start_atom = elf_file.atom(atoms[start]).?;5652 const start_atom = elf_file.atom(atom_list.atoms.items[start]).?;
5637 assert(start_atom.alive);5653 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);
5639 i += 1;5655 i += 1;
56405656
5641 while (i < atoms.len) : (i += 1) {5657 while (i < atom_list.atoms.items.len) : (i += 1) {
5642 const atom_ptr = elf_file.atom(atoms[i]).?;5658 const atom_ptr = elf_file.atom(atom_list.atoms.items[i]).?;
5643 assert(atom_ptr.alive);5659 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)
5645 break;5661 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);
5647 }5663 }
56485664
5649 // Insert a thunk at the group end5665 // Insert a thunk at the group end
5650 const thunk_index = try elf_file.addThunk();5666 const thunk_index = try elf_file.addThunk();
5651 const thunk_ptr = elf_file.thunk(thunk_index);5667 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
5654 // Scan relocs in the group and create trampolines for any unreachable callsite5670 // 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| {
5656 const atom_ptr = elf_file.atom(ref).?;5672 const atom_ptr = elf_file.atom(ref).?;
5657 const file_ptr = atom_ptr.file(elf_file).?;5673 const file_ptr = atom_ptr.file(elf_file).?;
5658 log.debug("atom({}) {s}", .{ ref, atom_ptr.name(elf_file) });5674 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 {...@@ -5682,18 +5698,11 @@ fn createThunks(elf_file: *Elf, shdr: *elf.Elf64_Shdr, shndx: u32) !void {
5682 atom_ptr.addExtra(.{ .thunk = thunk_index }, elf_file);5698 atom_ptr.addExtra(.{ .thunk = thunk_index }, elf_file);
5683 }5699 }
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
5687 log.debug("thunk({d}) : {}", .{ thunk_index, thunk_ptr.fmt(elf_file) });5703 log.debug("thunk({d}) : {}", .{ thunk_index, thunk_ptr.fmt(elf_file) });
5688 }5704 }
5689}5705}
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
5698const std = @import("std");5707const std = @import("std");
5699const build_options = @import("build_options");5708const build_options = @import("build_options");