| ... | @@ -3572,19 +3572,26 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { | ... | @@ -3572,19 +3572,26 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { |
| 3572 | | 3572 | |
| 3573 | fn updateSectionSizes(self: *Elf) !void { | 3573 | fn 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 | } |
| 3580 | | 3581 | |
| 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; |
| 3585 | | 3586 | |
| 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 | } |
| 3590 | | 3597 | |
| ... | @@ -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 | } |
| 5615 | | 5622 | |
| 5616 | fn createThunks(elf_file: *Elf, shdr: *elf.Elf64_Shdr, shndx: u32) !void { | 5623 | fn 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 than | 5627 | // 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); | | |
| 5628 | | 5634 | |
| 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 | } |
| 5632 | | 5648 | |
| 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; |
| 5640 | | 5656 | |
| 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 | } |
| 5648 | | 5664 | |
| 5649 | // Insert a thunk at the group end | 5665 | // 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; |
| 5653 | | 5669 | |
| 5654 | // Scan relocs in the group and create trampolines for any unreachable callsite | 5670 | // 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 | } |
| 5684 | | 5700 | |
| 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)); |
| 5686 | | 5702 | |
| 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 | } |
| 5690 | fn 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 | } | | |
| 5697 | | 5706 | |
| 5698 | const std = @import("std"); | 5707 | const std = @import("std"); |
| 5699 | const build_options = @import("build_options"); | 5708 | const build_options = @import("build_options"); |