aboutsummaryrefslogtreecommitdiff
path: root/src/link/Elf/Atom.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2024-03-08 22:44:37 +0100
committerJakub Konka <kubkon@jakubkonka.com>2024-03-08 22:46:18 +0100
commit859f9a22c4ac28a4e6b003b6e07c2c9912fcb074 (patch)
tree1020151bec8fb6c54eb15334d7095a8b4b16605b /src/link/Elf/Atom.zig
parent7c5ddb6ae410a861e139ce36dec94434392bfdad (diff)
downloadzig-859f9a22c4ac28a4e6b003b6e07c2c9912fcb074.tar.gz
zig-859f9a22c4ac28a4e6b003b6e07c2c9912fcb074.zip
elf+aarch64: implement basic thunk support
Diffstat (limited to 'src/link/Elf/Atom.zig')
-rw-r--r--src/link/Elf/Atom.zig30
1 files changed, 18 insertions, 12 deletions
diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig
index 34c5602b0d..4841501aa6 100644
--- a/src/link/Elf/Atom.zig
+++ b/src/link/Elf/Atom.zig
@@ -31,6 +31,9 @@ rel_num: u32 = 0,
/// Index of this atom in the linker's atoms table.
atom_index: Index = 0,
+/// Index of the thunk for this atom.
+thunk_index: Thunk.Index = 0,
+
/// Flags we use for state tracking.
flags: Flags = .{},
@@ -64,6 +67,10 @@ pub fn file(self: Atom, elf_file: *Elf) ?File {
return elf_file.file(self.file_index);
}
+pub fn thunk(self: Atom, elf_file: *Elf) *Thunk {
+ return elf_file.thunk(self.thunk_index);
+}
+
pub fn inputShdr(self: Atom, elf_file: *Elf) elf.Elf64_Shdr {
return switch (self.file(elf_file).?) {
.object => |x| x.shdrs.items[self.input_section_index],
@@ -1681,6 +1688,7 @@ const aarch64 = struct {
const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
const cwriter = stream.writer();
const code = code_buffer[rel.r_offset..][0..4];
+ const file_ptr = atom.file(elf_file).?;
const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args;
_ = DTP;
@@ -1701,18 +1709,15 @@ const aarch64 = struct {
.CALL26,
.JUMP26,
=> {
- // TODO: add thunk support
- const disp: i28 = math.cast(i28, S + A - P) orelse {
- var err = try elf_file.addErrorWithNotes(1);
- try err.addMsg(elf_file, "TODO: branch relocation target ({s}) exceeds max jump distance", .{
- target.name(elf_file),
- });
- try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{
- atom.file(elf_file).?.fmtPath(),
- atom.name(elf_file),
- r_offset,
- });
- return;
+ const disp: i28 = math.cast(i28, S + A - P) orelse blk: {
+ const th = atom.thunk(elf_file);
+ const target_index = switch (file_ptr) {
+ .zig_object => |x| x.symbol(rel.r_sym()),
+ .object => |x| x.symbols.items[rel.r_sym()],
+ else => unreachable,
+ };
+ const S_: i64 = @intCast(th.targetAddress(target_index, elf_file));
+ break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;
};
aarch64_util.writeBranchImm(disp, code);
},
@@ -2173,3 +2178,4 @@ const Fde = eh_frame.Fde;
const File = @import("file.zig").File;
const Object = @import("Object.zig");
const Symbol = @import("Symbol.zig");
+const Thunk = @import("thunks.zig").Thunk;