[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