case ARM64_RELOC_GOT_LOAD_PAGEOFF12:
case ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
assert(!r.pcrel);
- encodePageOff12(loc32, base, value);
+ encodePageOff12(loc32, r, base, value);
break;
default:
llvm_unreachable("unexpected relocation type");
error("Unrecognized dtrace symbol prefix: " + toString(*sym));
}
}
+
+static void reportUnalignedLdrStr(Twine loc, uint64_t va, int align,
+ const Symbol *sym) {
+ std::string symbolHint;
+ if (sym)
+ symbolHint = " (" + toString(*sym) + ")";
+ error(loc + ": " + Twine(8 * align) + "-bit LDR/STR to 0x" +
+ llvm::utohexstr(va) + symbolHint + " is not " + Twine(align) +
+ "-byte aligned");
+}
+
+void macho::reportUnalignedLdrStr(void *loc, const lld::macho::Reloc &r,
+ uint64_t va, int align) {
+ uint64_t off = reinterpret_cast<const uint8_t *>(loc) - in.bufferStart;
+ const InputSection *isec = offsetToInputSection(&off);
+ std::string locStr = isec ? isec->getLocation(off) : "(invalid location)";
+ ::reportUnalignedLdrStr(locStr, va, align, r.referent.dyn_cast<Symbol *>());
+}
+
+void macho::reportUnalignedLdrStr(void *loc, lld::macho::SymbolDiagnostic d,
+ uint64_t va, int align) {
+ ::reportUnalignedLdrStr(d.reason, va, align, d.symbol);
+}
bitField(va, 14, 19, 5));
}
+void reportUnalignedLdrStr(void *loc, const Reloc &, uint64_t va, int align);
+void reportUnalignedLdrStr(void *loc, SymbolDiagnostic, uint64_t va, int align);
+
// 21 10
// +-------------------+-----------------------+-------------------+
// | | imm12 | |
// +-------------------+-----------------------+-------------------+
-inline void encodePageOff12(uint32_t *loc, uint32_t base, uint64_t va) {
+template <typename Target>
+inline void encodePageOff12(uint32_t *loc, Target t, uint32_t base,
+ uint64_t va) {
int scale = 0;
if ((base & 0x3b00'0000) == 0x3900'0000) { // load/store
scale = base >> 30;
if (scale == 0 && (base & 0x0480'0000) == 0x0480'0000) // 128-bit variant
scale = 4;
}
+ const int size = 1 << scale;
+ if ((va & (size - 1)) != 0)
+ reportUnalignedLdrStr(loc, t, va, size);
// TODO(gkm): extract embedded addend and warn if != 0
// uint64_t addend = ((base & 0x003FFC00) >> 10);
const macho::Symbol &sym) {
auto *buf32 = reinterpret_cast<uint32_t *>(buf8);
constexpr size_t stubCodeSize = 3 * sizeof(uint32_t);
+ SymbolDiagnostic d = {&sym, "stub"};
uint64_t pcPageBits =
pageBits(in.stubs->addr + sym.stubsIndex * stubCodeSize);
uint64_t lazyPointerVA =
in.lazyPointers->addr + sym.stubsIndex * LP::wordSize;
- encodePage21(&buf32[0], {&sym, "stub"}, stubCode[0],
- pageBits(lazyPointerVA) - pcPageBits);
- encodePageOff12(&buf32[1], stubCode[1], lazyPointerVA);
+ encodePage21(&buf32[0], d, stubCode[0], pageBits(lazyPointerVA) - pcPageBits);
+ encodePageOff12(&buf32[1], d, stubCode[1], lazyPointerVA);
buf32[2] = stubCode[2];
}
SymbolDiagnostic d = {nullptr, "stub header helper"};
encodePage21(&buf32[0], d, stubHelperHeaderCode[0],
pageBits(loaderVA) - pcPageBits(0));
- encodePageOff12(&buf32[1], stubHelperHeaderCode[1], loaderVA);
+ encodePageOff12(&buf32[1], d, stubHelperHeaderCode[1], loaderVA);
buf32[2] = stubHelperHeaderCode[2];
uint64_t binderVA =
in.got->addr + in.stubHelper->stubBinder->gotIndex * LP::wordSize;
encodePage21(&buf32[3], d, stubHelperHeaderCode[3],
pageBits(binderVA) - pcPageBits(3));
- encodePageOff12(&buf32[4], stubHelperHeaderCode[4], binderVA);
+ encodePageOff12(&buf32[4], d, stubHelperHeaderCode[4], binderVA);
buf32[5] = stubHelperHeaderCode[5];
}
uint64_t selectorOffset = selectorIndex * LP::wordSize;
encodePage21(&buf32[0], d, objcStubsFastCode[0],
pageBits(selrefsVA + selectorOffset) - pcPageBits(0));
- encodePageOff12(&buf32[1], objcStubsFastCode[1], selrefsVA + selectorOffset);
+ encodePageOff12(&buf32[1], d, objcStubsFastCode[1],
+ selrefsVA + selectorOffset);
encodePage21(&buf32[2], d, objcStubsFastCode[2],
pageBits(gotAddr) - pcPageBits(2));
encodePage21(&buf32[3], d, objcStubsFastCode[3], msgSendIndex * LP::wordSize);
--- /dev/null
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %s -o %t.o
+# RUN: not %lld -arch arm64 %t.o -o %t 2>&1 | FileCheck %s --implicit-check-not=_byte \
+# RUN: --implicit-check-not=_correct
+
+# CHECK-DAG: error: {{.*}}:(symbol _main+0x4): 16-bit LDR/STR to 0x[[#%X,]] (_half) is not 2-byte aligned
+# CHECK-DAG: error: {{.*}}:(symbol _main+0xc): 32-bit LDR/STR to 0x[[#%X,]] (_word) is not 4-byte aligned
+# CHECK-DAG: error: {{.*}}:(symbol _main+0x14): 64-bit LDR/STR to 0x[[#%X,]] (_double) is not 8-byte aligned
+# CHECK-DAG: error: {{.*}}:(symbol _main+0x1c): 128-bit LDR/STR to 0x[[#%X,]] (_quad) is not 16-byte aligned
+
+.globl _main
+_main:
+ adrp x0, _half@PAGE
+ ldrh w0, [x0, _half@PAGEOFF]
+
+ adrp x1, _word@PAGE
+ ldr w1, [x1, _word@PAGEOFF]
+
+ adrp x2, _double@PAGE
+ ldr x2, [x2, _double@PAGEOFF]
+
+ adrp x3, _quad@PAGE
+ ldr q0, [x3, _quad@PAGEOFF]
+
+ adrp x4, _byte@PAGE
+ ldrb w4, [x4, _byte@PAGEOFF]
+
+ adrp x5, _correct@PAGE
+ ldr x5, [x5, _correct@PAGEOFF]
+
+.data
+.p2align 4
+_correct:
+.8byte 0
+.byte 0
+_half:
+.2byte 0
+_word:
+.4byte 0
+_double:
+.8byte 0
+_quad:
+.8byte 0
+.8byte 0
+_byte:
+.byte 0