[llvm] r213689 - [RuntimeDyld][MachO][AArch64] Add a helper function for encoding addends in instructions.
Lang Hames
lhames at gmail.com
Tue Jul 22 16:18:40 PDT 2014
Nice!
Thanks very much for working on this Juergen.
- Lang.
On Tue, Jul 22, 2014 at 2:42 PM, Juergen Ributzka <juergen at apple.com> wrote:
> Author: ributzka
> Date: Tue Jul 22 16:42:55 2014
> New Revision: 213689
>
> URL: http://llvm.org/viewvc/llvm-project?rev=213689&view=rev
> Log:
> [RuntimeDyld][MachO][AArch64] Add a helper function for encoding addends
> in instructions.
>
> Factor out the addend encoding into a helper function and simplify the
> processRelocationRef.
>
> Also add a few simple rtdyld tests. More tests to come once GOTs can be
> tested too.
>
> Related to <rdar://problem/17768539>
>
> Added:
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/
>
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/lit.local.cfg
> Modified:
>
> llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h
>
> Modified:
> llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h?rev=213689&r1=213688&r2=213689&view=diff
>
> ==============================================================================
> ---
> llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h
> (original)
> +++
> llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h
> Tue Jul 22 16:42:55 2014
> @@ -118,6 +118,109 @@ public:
> return Addend;
> }
>
> + /// Extract the addend encoded in the instruction.
> + void encodeAddend(uint8_t *LocalAddress, uint32_t RelType,
> + int64_t Addend) const {
> + // Verify that the relocation has the correct alignment.
> + switch (RelType) {
> + default:
> + llvm_unreachable("Unsupported relocation type!");
> + case MachO::ARM64_RELOC_UNSIGNED:
> + llvm_unreachable("Invalid relocation type for instruction.");
> + case MachO::ARM64_RELOC_BRANCH26:
> + case MachO::ARM64_RELOC_PAGE21:
> + case MachO::ARM64_RELOC_PAGEOFF12:
> + case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
> + case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
> + assert((((uintptr_t)LocalAddress & 0x3) == 0) &&
> + "Instruction address is not aligned to 4 bytes.");
> + break;
> + }
> +
> + switch (RelType) {
> + default:
> + llvm_unreachable("Unsupported relocation type!");
> + case MachO::ARM64_RELOC_BRANCH26: {
> + // Verify that the relocation points to the expected branch
> instruction.
> + uint32_t *p = (uint32_t *)LocalAddress;
> + assert((*p & 0xFC000000) == 0x14000000 && "Expected branch
> instruction.");
> +
> + // Verify addend value.
> + assert((Addend & 0x3) == 0 && "Branch target is not aligned");
> + assert(isInt<28>(Addend) && "Branch target is out of range.");
> +
> + // Encode the addend as 26 bit immediate in the branch instruction.
> + *p = (*p & 0xFC000000) | ((uint32_t)(Addend >> 2) & 0x03FFFFFF);
> + break;
> + }
> + case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
> + case MachO::ARM64_RELOC_PAGE21: {
> + // Verify that the relocation points to the expected adrp
> instruction.
> + uint32_t *p = (uint32_t *)LocalAddress;
> + assert((*p & 0x9F000000) == 0x90000000 && "Expected adrp
> instruction.");
> +
> + // Check that the addend fits into 21 bits (+ 12 lower bits).
> + assert((Addend & 0xFFF) == 0 && "ADRP target is not page aligned.");
> + assert(isInt<33>(Addend) && "Invalid page reloc value.");
> +
> + // Encode the addend into the instruction.
> + uint32_t ImmLoValue = (uint32_t)(Addend << 17) & 0x60000000;
> + uint32_t ImmHiValue = (uint32_t)(Addend >> 9) & 0x00FFFFE0;
> + *p = (*p & 0x9F00001F) | ImmHiValue | ImmLoValue;
> + break;
> + }
> + case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: {
> + // Verify that the relocation points to one of the expected load /
> store
> + // instructions.
> + uint32_t *p = (uint32_t *)LocalAddress;
> + assert((*p & 0x3B000000) == 0x39000000 &&
> + "Only expected load / store instructions.");
> + } // fall-through
> + case MachO::ARM64_RELOC_PAGEOFF12: {
> + // Verify that the relocation points to one of the expected load /
> store
> + // or add / sub instructions.
> + uint32_t *p = (uint32_t *)LocalAddress;
> + assert((((*p & 0x3B000000) == 0x39000000) ||
> + ((*p & 0x11C00000) == 0x11000000) ) &&
> + "Expected load / store or add/sub instruction.");
> +
> + // Check which instruction we are decoding to obtain the implicit
> shift
> + // factor of the instruction and verify alignment.
> + int ImplicitShift = 0;
> + if ((*p & 0x3B000000) == 0x39000000) { // << load / store
> + // For load / store instructions the size is encoded in bits
> 31:30.
> + ImplicitShift = ((*p >> 30) & 0x3);
> + switch (ImplicitShift) {
> + case 0:
> + // Check if this a vector op to get the correct shift value.
> + if ((*p & 0x04800000) == 0x04800000) {
> + ImplicitShift = 4;
> + assert(((Addend & 0xF) == 0) &&
> + "128-bit LDR/STR not 16-byte aligned.");
> + }
> + break;
> + case 1:
> + assert(((Addend & 0x1) == 0) && "16-bit LDR/STR not 2-byte
> aligned.");
> + break;
> + case 2:
> + assert(((Addend & 0x3) == 0) && "32-bit LDR/STR not 4-byte
> aligned.");
> + break;
> + case 3:
> + assert(((Addend & 0x7) == 0) && "64-bit LDR/STR not 8-byte
> aligned.");
> + break;
> + }
> + }
> + // Compensate for implicit shift.
> + Addend >>= ImplicitShift;
> + assert(isUInt<12>(Addend) && "Addend cannot be encoded.");
> +
> + // Encode the addend into the instruction.
> + *p = (*p & 0xFFC003FF) | ((uint32_t)(Addend << 10) & 0x003FFC00);
> + break;
> + }
> + }
> + }
> +
> relocation_iterator
> processRelocationRef(unsigned SectionID, relocation_iterator RelI,
> ObjectImage &ObjImg, ObjSectionToIDMap
> &ObjSectionToID,
> @@ -196,105 +299,37 @@ public:
> }
> case MachO::ARM64_RELOC_BRANCH26: {
> assert(RE.IsPCRel && "not PCRel and ARM64_RELOC_BRANCH26 not
> supported");
> - // Mask the value into the target address. We know instructions are
> - // 32-bit aligned, so we can do it all at once.
> - uint32_t *p = (uint32_t *)LocalAddress;
> - // Check if the addend is encoded in the instruction.
> - uint32_t EncodedAddend = *p & 0x03FFFFFF;
> - if (EncodedAddend != 0) {
> - if (RE.Addend == 0)
> - llvm_unreachable("branch26 instruction has embedded addend.");
> - else
> - llvm_unreachable("branch26 instruction has embedded addend and"
> - "ARM64_RELOC_ADDEND.");
> - }
> // Check if branch is in range.
> uint64_t FinalAddress = Section.LoadAddress + RE.Offset;
> - uint64_t PCRelVal = Value - FinalAddress + RE.Addend;
> - assert(isInt<26>(PCRelVal) && "Branch target out of range!");
> - // Insert the value into the instruction.
> - *p = (*p & 0xFC000000) | ((uint32_t)(PCRelVal >> 2) & 0x03FFFFFF);
> + int64_t PCRelVal = Value - FinalAddress + RE.Addend;
> + encodeAddend(LocalAddress, RE.RelType, PCRelVal);
> break;
> }
> case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
> case MachO::ARM64_RELOC_PAGE21: {
> assert(RE.IsPCRel && "not PCRel and ARM64_RELOC_PAGE21 not
> supported");
> - // Mask the value into the target address. We know instructions are
> - // 32-bit aligned, so we can do it all at once.
> - uint32_t *p = (uint32_t *)LocalAddress;
> - // Check if the addend is encoded in the instruction.
> - uint32_t EncodedAddend =
> - ((*p & 0x60000000) >> 29) | ((*p & 0x01FFFFE0) >> 3);
> - if (EncodedAddend != 0) {
> - if (RE.Addend == 0)
> - llvm_unreachable("adrp instruction has embedded addend.");
> - else
> - llvm_unreachable("adrp instruction has embedded addend and"
> - "ARM64_RELOC_ADDEND.");
> - }
> // Adjust for PC-relative relocation and offset.
> uint64_t FinalAddress = Section.LoadAddress + RE.Offset;
> - uint64_t PCRelVal =
> - ((Value + RE.Addend) & (-4096)) - (FinalAddress & (-4096));
> - // Check that the value fits into 21 bits (+ 12 lower bits).
> - assert(isInt<33>(PCRelVal) && "Invalid page reloc value!");
> - // Insert the value into the instruction.
> - uint32_t ImmLoValue = (uint32_t)(PCRelVal << 17) & 0x60000000;
> - uint32_t ImmHiValue = (uint32_t)(PCRelVal >> 9) & 0x00FFFFE0;
> - *p = (*p & 0x9F00001F) | ImmHiValue | ImmLoValue;
> + int64_t PCRelVal =
> + ((Value + RE.Addend) & (-4096)) - (FinalAddress & (-4096));
> + encodeAddend(LocalAddress, RE.RelType, PCRelVal);
> break;
> }
> case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
> case MachO::ARM64_RELOC_PAGEOFF12: {
> assert(!RE.IsPCRel && "PCRel and ARM64_RELOC_PAGEOFF21 not
> supported");
> - // Mask the value into the target address. We know instructions are
> - // 32-bit aligned, so we can do it all at once.
> - uint32_t *p = (uint32_t *)LocalAddress;
> - // Check if the addend is encoded in the instruction.
> - uint32_t EncodedAddend = *p & 0x003FFC00;
> - if (EncodedAddend != 0) {
> - if (RE.Addend == 0)
> - llvm_unreachable("adrp instruction has embedded addend.");
> - else
> - llvm_unreachable("adrp instruction has embedded addend and"
> - "ARM64_RELOC_ADDEND.");
> - }
> // Add the offset from the symbol.
> Value += RE.Addend;
> // Mask out the page address and only use the lower 12 bits.
> Value &= 0xFFF;
> - // Check which instruction we are updating to obtain the implicit
> shift
> - // factor from LDR/STR instructions.
> - if (*p & 0x08000000) {
> - uint32_t ImplicitShift = ((*p >> 30) & 0x3);
> - switch (ImplicitShift) {
> - case 0:
> - // Check if this a vector op.
> - if ((*p & 0x04800000) == 0x04800000) {
> - ImplicitShift = 4;
> - assert(((Value & 0xF) == 0) &&
> - "128-bit LDR/STR not 16-byte aligned.");
> - }
> - break;
> - case 1:
> - assert(((Value & 0x1) == 0) && "16-bit LDR/STR not 2-byte
> aligned.");
> - case 2:
> - assert(((Value & 0x3) == 0) && "32-bit LDR/STR not 4-byte
> aligned.");
> - case 3:
> - assert(((Value & 0x7) == 0) && "64-bit LDR/STR not 8-byte
> aligned.");
> - }
> - // Compensate for implicit shift.
> - Value >>= ImplicitShift;
> - }
> - // Insert the value into the instruction.
> - *p = (*p & 0xFFC003FF) | ((uint32_t)(Value << 10) & 0x003FFC00);
> + encodeAddend(LocalAddress, RE.RelType, Value);
> break;
> }
> case MachO::ARM64_RELOC_SUBTRACTOR:
> case MachO::ARM64_RELOC_POINTER_TO_GOT:
> case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
> case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
> - llvm_unreachable("Relocation type not implemented yet!");
> + llvm_unreachable("Relocation type not yet implemented!");
> case MachO::ARM64_RELOC_ADDEND:
> llvm_unreachable("ARM64_RELOC_ADDEND should have been handeled by "
> "processRelocationRef!");
>
> Added:
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s?rev=213689&view=auto
>
> ==============================================================================
> ---
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s
> (added)
> +++
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s
> Tue Jul 22 16:42:55 2014
> @@ -0,0 +1,54 @@
> +# RUN: llvm-mc -triple=arm64-apple-ios7.0.0 -code-model=small
> -relocation-model=pic -filetype=obj -o %t.o %s
> +# RUN: llvm-rtdyld -triple=arm64-apple-ios7.0.0 -verify -check=%s %t.o
> +# RUN: rm %t.o
> +
> +# FIXME: Add GOT relocation tests once GOT testing is supported.
> +
> + .section __TEXT,__text,regular,pure_instructions
> + .ios_version_min 7, 0
> + .globl foo
> + .align 2
> +foo:
> + movz w0, #0
> + ret
> +
> + .globl _test_branch_reloc
> + .align 2
> +
> +
> +# Test ARM64_RELOC_BRANCH26 relocation. The branch instruction only
> encodes 26
> +# bits of the 28-bit possible branch range. The lower two bits are always
> zero
> +# and therefore ignored.
> +# rtdyld-check: decode_operand(br1, 0)[25:0] = (foo-br1)[27:2]
> +_test_branch_reloc:
> +br1:
> + b foo
> + ret
> +
> +
> +# Test ARM64_RELOC_UNSIGNED relocation. The absolute 64-bit address of the
> +# function should be stored at the 8-byte memory location.
> +# rtdyld-check: *{8}ptr = foo
> + .section __DATA,__data
> + .globl ptr
> + .align 3
> + .fill 8192, 1, 0
> +ptr:
> + .quad foo
> +
> +
> +# Test ARM64_RELOC_PAGE21 and ARM64_RELOC_PAGEOFF12 relocation. adrp
> encodes
> +# the PC-relative page (4 KiB) difference between the adrp instruction
> and the
> +# variable ptr. ldr encodes the offset of the variable within the page.
> The ldr
> +# instruction perfroms an implicit shift on the encoded immediate
> (imm<<3).
> +# rtdyld-check: decode_operand(adrp1, 1) = (ptr[32:12]-adrp1[32:12])
> +# rtdyld-check: decode_operand(ldr1, 2) = (ptr[11:3])
> + .globl _test_adrp_ldr
> + .align 2
> +_test_adrp_ldr:
> +adrp1:
> + adrp x0, ptr at PAGE
> +ldr1:
> + ldr x0, [x0, ptr at PAGEOFF]
> + ret
> + .fill 8192, 1, 0
>
> Added: llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/lit.local.cfg
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/lit.local.cfg?rev=213689&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/lit.local.cfg
> (added)
> +++ llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/lit.local.cfg Tue
> Jul 22 16:42:55 2014
> @@ -0,0 +1,3 @@
> +if not 'AArch64' in config.root.targets:
> + config.unsupported = True
> +
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140722/02cc4225/attachment.html>
More information about the llvm-commits
mailing list