aboutsummaryrefslogtreecommitdiff
path: root/lld/MachO/Arch/ARM64Common.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-03 14:10:23 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-07-03 14:10:23 +0000
commit145449b1e420787bb99721a429341fa6be3adfb6 (patch)
tree1d56ae694a6de602e348dd80165cf881a36600ed /lld/MachO/Arch/ARM64Common.cpp
parentecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (diff)
Diffstat (limited to 'lld/MachO/Arch/ARM64Common.cpp')
-rw-r--r--lld/MachO/Arch/ARM64Common.cpp41
1 files changed, 21 insertions, 20 deletions
diff --git a/lld/MachO/Arch/ARM64Common.cpp b/lld/MachO/Arch/ARM64Common.cpp
index 67e7292fd6fd..f55258ce8ec9 100644
--- a/lld/MachO/Arch/ARM64Common.cpp
+++ b/lld/MachO/Arch/ARM64Common.cpp
@@ -38,56 +38,57 @@ int64_t ARM64Common::getEmbeddedAddend(MemoryBufferRef mb, uint64_t offset,
}
}
+static void writeValue(uint8_t *loc, const Reloc &r, uint64_t value) {
+ switch (r.length) {
+ case 2:
+ checkInt(loc, r, value, 32);
+ write32le(loc, value);
+ break;
+ case 3:
+ write64le(loc, value);
+ break;
+ default:
+ llvm_unreachable("invalid r_length");
+ }
+}
+
// For instruction relocations (load, store, add), the base
// instruction is pre-populated in the text section. A pre-populated
// instruction has opcode & register-operand bits set, with immediate
// operands zeroed. We read it from text, OR-in the immediate
// operands, then write-back the completed instruction.
-
void ARM64Common::relocateOne(uint8_t *loc, const Reloc &r, uint64_t value,
uint64_t pc) const {
+ auto loc32 = reinterpret_cast<uint32_t *>(loc);
uint32_t base = ((r.length == 2) ? read32le(loc) : 0);
switch (r.type) {
case ARM64_RELOC_BRANCH26:
- value = encodeBranch26(r, base, value - pc);
+ encodeBranch26(loc32, r, base, value - pc);
break;
case ARM64_RELOC_SUBTRACTOR:
case ARM64_RELOC_UNSIGNED:
- if (r.length == 2)
- checkInt(r, value, 32);
+ writeValue(loc, r, value);
break;
case ARM64_RELOC_POINTER_TO_GOT:
if (r.pcrel)
value -= pc;
- checkInt(r, value, 32);
+ writeValue(loc, r, value);
break;
case ARM64_RELOC_PAGE21:
case ARM64_RELOC_GOT_LOAD_PAGE21:
- case ARM64_RELOC_TLVP_LOAD_PAGE21: {
+ case ARM64_RELOC_TLVP_LOAD_PAGE21:
assert(r.pcrel);
- value = encodePage21(r, base, pageBits(value) - pageBits(pc));
+ encodePage21(loc32, r, base, pageBits(value) - pageBits(pc));
break;
- }
case ARM64_RELOC_PAGEOFF12:
case ARM64_RELOC_GOT_LOAD_PAGEOFF12:
case ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
assert(!r.pcrel);
- value = encodePageOff12(base, value);
+ encodePageOff12(loc32, base, value);
break;
default:
llvm_unreachable("unexpected relocation type");
}
-
- switch (r.length) {
- case 2:
- write32le(loc, value);
- break;
- case 3:
- write64le(loc, value);
- break;
- default:
- llvm_unreachable("invalid r_length");
- }
}
void ARM64Common::relaxGotLoad(uint8_t *loc, uint8_t type) const {