mirror of
https://github.com/ziglang/zig.git
synced 2026-02-07 15:07:12 +00:00
171 lines
5.5 KiB
Zig
171 lines
5.5 KiB
Zig
tag: Tag,
|
|
offset: u32,
|
|
target: u32,
|
|
addend: i64,
|
|
type: Type,
|
|
meta: packed struct {
|
|
pcrel: bool,
|
|
has_subtractor: bool,
|
|
length: u2,
|
|
symbolnum: u24,
|
|
},
|
|
|
|
pub fn getTargetSymbolRef(rel: Relocation, atom: Atom, macho_file: *MachO) MachO.Ref {
|
|
assert(rel.tag == .@"extern");
|
|
return atom.getFile(macho_file).getSymbolRef(rel.target, macho_file);
|
|
}
|
|
|
|
pub fn getTargetSymbol(rel: Relocation, atom: Atom, macho_file: *MachO) *Symbol {
|
|
assert(rel.tag == .@"extern");
|
|
const ref = atom.getFile(macho_file).getSymbolRef(rel.target, macho_file);
|
|
return ref.getSymbol(macho_file).?;
|
|
}
|
|
|
|
pub fn getTargetAtom(rel: Relocation, atom: Atom, macho_file: *MachO) *Atom {
|
|
assert(rel.tag == .local);
|
|
return atom.getFile(macho_file).getAtom(rel.target).?;
|
|
}
|
|
|
|
pub fn getTargetAddress(rel: Relocation, atom: Atom, macho_file: *MachO) u64 {
|
|
return switch (rel.tag) {
|
|
.local => rel.getTargetAtom(atom, macho_file).getAddress(macho_file),
|
|
.@"extern" => rel.getTargetSymbol(atom, macho_file).getAddress(.{}, macho_file),
|
|
};
|
|
}
|
|
|
|
pub fn getGotTargetAddress(rel: Relocation, atom: Atom, macho_file: *MachO) u64 {
|
|
return switch (rel.tag) {
|
|
.local => 0,
|
|
.@"extern" => rel.getTargetSymbol(atom, macho_file).getGotAddress(macho_file),
|
|
};
|
|
}
|
|
|
|
pub fn getZigGotTargetAddress(rel: Relocation, macho_file: *MachO) u64 {
|
|
const zo = macho_file.getZigObject() orelse return 0;
|
|
return switch (rel.tag) {
|
|
.local => 0,
|
|
.@"extern" => {
|
|
const ref = zo.getSymbolRef(rel.target, macho_file);
|
|
return ref.getSymbol(macho_file).?.getZigGotAddress(macho_file);
|
|
},
|
|
};
|
|
}
|
|
|
|
pub fn getRelocAddend(rel: Relocation, cpu_arch: std.Target.Cpu.Arch) i64 {
|
|
const addend: i64 = switch (rel.type) {
|
|
.signed => 0,
|
|
.signed1 => -1,
|
|
.signed2 => -2,
|
|
.signed4 => -4,
|
|
else => 0,
|
|
};
|
|
return switch (cpu_arch) {
|
|
.x86_64 => if (rel.meta.pcrel) addend - 4 else addend,
|
|
else => addend,
|
|
};
|
|
}
|
|
|
|
pub fn lessThan(ctx: void, lhs: Relocation, rhs: Relocation) bool {
|
|
_ = ctx;
|
|
return lhs.offset < rhs.offset;
|
|
}
|
|
|
|
pub fn fmtPretty(rel: Relocation, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatter(Format, Format.pretty) {
|
|
return .{ .data = .{ .relocation = rel, .arch = cpu_arch } };
|
|
}
|
|
|
|
const Format = struct {
|
|
relocation: Relocation,
|
|
arch: std.Target.Cpu.Arch,
|
|
|
|
fn pretty(f: Format, w: *Writer) Writer.Error!void {
|
|
try w.writeAll(switch (f.relocation.type) {
|
|
.signed => "X86_64_RELOC_SIGNED",
|
|
.signed1 => "X86_64_RELOC_SIGNED_1",
|
|
.signed2 => "X86_64_RELOC_SIGNED_2",
|
|
.signed4 => "X86_64_RELOC_SIGNED_4",
|
|
.got_load => "X86_64_RELOC_GOT_LOAD",
|
|
.tlv => "X86_64_RELOC_TLV",
|
|
.page => "ARM64_RELOC_PAGE21",
|
|
.pageoff => "ARM64_RELOC_PAGEOFF12",
|
|
.got_load_page => "ARM64_RELOC_GOT_LOAD_PAGE21",
|
|
.got_load_pageoff => "ARM64_RELOC_GOT_LOAD_PAGEOFF12",
|
|
.tlvp_page => "ARM64_RELOC_TLVP_LOAD_PAGE21",
|
|
.tlvp_pageoff => "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
|
|
.branch => switch (f.arch) {
|
|
.x86_64 => "X86_64_RELOC_BRANCH",
|
|
.aarch64 => "ARM64_RELOC_BRANCH26",
|
|
else => unreachable,
|
|
},
|
|
.got => switch (f.arch) {
|
|
.x86_64 => "X86_64_RELOC_GOT",
|
|
.aarch64 => "ARM64_RELOC_POINTER_TO_GOT",
|
|
else => unreachable,
|
|
},
|
|
.subtractor => switch (f.arch) {
|
|
.x86_64 => "X86_64_RELOC_SUBTRACTOR",
|
|
.aarch64 => "ARM64_RELOC_SUBTRACTOR",
|
|
else => unreachable,
|
|
},
|
|
.unsigned => switch (f.arch) {
|
|
.x86_64 => "X86_64_RELOC_UNSIGNED",
|
|
.aarch64 => "ARM64_RELOC_UNSIGNED",
|
|
else => unreachable,
|
|
},
|
|
});
|
|
}
|
|
};
|
|
|
|
pub const Type = enum {
|
|
// x86_64
|
|
/// RIP-relative displacement (X86_64_RELOC_SIGNED)
|
|
signed,
|
|
/// RIP-relative displacement (X86_64_RELOC_SIGNED_1)
|
|
signed1,
|
|
/// RIP-relative displacement (X86_64_RELOC_SIGNED_2)
|
|
signed2,
|
|
/// RIP-relative displacement (X86_64_RELOC_SIGNED_4)
|
|
signed4,
|
|
/// RIP-relative GOT load (X86_64_RELOC_GOT_LOAD)
|
|
got_load,
|
|
/// RIP-relative TLV load (X86_64_RELOC_TLV)
|
|
tlv,
|
|
|
|
// arm64
|
|
/// PC-relative load (distance to page, ARM64_RELOC_PAGE21)
|
|
page,
|
|
/// Non-PC-relative offset to symbol (ARM64_RELOC_PAGEOFF12)
|
|
pageoff,
|
|
/// PC-relative GOT load (distance to page, ARM64_RELOC_GOT_LOAD_PAGE21)
|
|
got_load_page,
|
|
/// Non-PC-relative offset to GOT slot (ARM64_RELOC_GOT_LOAD_PAGEOFF12)
|
|
got_load_pageoff,
|
|
/// PC-relative TLV load (distance to page, ARM64_RELOC_TLVP_LOAD_PAGE21)
|
|
tlvp_page,
|
|
/// Non-PC-relative offset to TLV slot (ARM64_RELOC_TLVP_LOAD_PAGEOFF12)
|
|
tlvp_pageoff,
|
|
|
|
// common
|
|
/// PC-relative call/bl/b (X86_64_RELOC_BRANCH or ARM64_RELOC_BRANCH26)
|
|
branch,
|
|
/// PC-relative displacement to GOT pointer (X86_64_RELOC_GOT or ARM64_RELOC_POINTER_TO_GOT)
|
|
got,
|
|
/// Absolute subtractor value (X86_64_RELOC_SUBTRACTOR or ARM64_RELOC_SUBTRACTOR)
|
|
subtractor,
|
|
/// Absolute relocation (X86_64_RELOC_UNSIGNED or ARM64_RELOC_UNSIGNED)
|
|
unsigned,
|
|
};
|
|
|
|
const Tag = enum { local, @"extern" };
|
|
|
|
const std = @import("std");
|
|
const assert = std.debug.assert;
|
|
const macho = std.macho;
|
|
const math = std.math;
|
|
const Writer = std.io.Writer;
|
|
|
|
const Atom = @import("Atom.zig");
|
|
const MachO = @import("../MachO.zig");
|
|
const Relocation = @This();
|
|
const Symbol = @import("Symbol.zig");
|