[lld] r286353 - [ELF] ARM and AArch64 undefined weak reference values

Rafael EspĂ­ndola via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 9 06:22:59 PST 2016


This is quite interesting. How are these references produced? Directly
writing assembly? I wonder if
AArch64Subtarget::ClassifyGlobalReference should be changed in any
way:

  // The small code mode's direct accesses use ADRP, which cannot necessarily
  // produce the value 0 (if the code is above 4GB).
  if (TM.getCodeModel() == CodeModel::Small && GV->hasExternalWeakLinkage())
    return AArch64II::MO_GOT;

Cheers,
Rafael



On 9 November 2016 at 05:22, Peter Smith via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> Author: psmith
> Date: Wed Nov  9 04:22:29 2016
> New Revision: 286353
>
> URL: http://llvm.org/viewvc/llvm-project?rev=286353&view=rev
> Log:
> [ELF] ARM and AArch64 undefined weak reference values
>
> The ARM 32 and 64-bit ABI does not use 0 for undefined weak references
> that are used in PC relative relocations. In particular:
> - A branch relocation to an undefined weak resolves to the next
>   instruction. Effectively making the branch a no-op
> - In all other cases the symbol resolves to the place so that S + A - P
>   resolves to A.
>
> Differential Revision: https://reviews.llvm.org/D26240
>
>
> Added:
>     lld/trunk/test/ELF/aarch64-undefined-weak.s   (with props)
>     lld/trunk/test/ELF/arm-thumb-undefined-weak.s   (with props)
>     lld/trunk/test/ELF/arm-undefined-weak.s   (with props)
> Modified:
>     lld/trunk/ELF/InputSection.cpp
>     lld/trunk/test/ELF/arm-thumb-no-undefined-thunk.s
>
> Modified: lld/trunk/ELF/InputSection.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=286353&r1=286352&r2=286353&view=diff
> ==============================================================================
> --- lld/trunk/ELF/InputSection.cpp (original)
> +++ lld/trunk/ELF/InputSection.cpp Wed Nov  9 04:22:29 2016
> @@ -258,6 +258,42 @@ static uint64_t getAArch64Page(uint64_t
>    return Expr & (~static_cast<uint64_t>(0xFFF));
>  }
>
> +static uint32_t getARMUndefinedRelativeWeakVA(uint32_t Type,
> +                                              uint32_t A,
> +                                              uint32_t P) {
> +  switch (Type) {
> +  case R_ARM_THM_JUMP11:
> +    return P + 2;
> +  case R_ARM_CALL:
> +  case R_ARM_JUMP24:
> +  case R_ARM_PC24:
> +  case R_ARM_PLT32:
> +  case R_ARM_PREL31:
> +  case R_ARM_THM_JUMP19:
> +  case R_ARM_THM_JUMP24:
> +    return P + 4;
> +  case R_ARM_THM_CALL:
> +    // We don't want an interworking BLX to ARM
> +    return P + 5;
> +  default:
> +    return A;
> +  }
> +}
> +
> +static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t Type,
> +                                                  uint64_t A,
> +                                                  uint64_t P) {
> +  switch (Type) {
> +  case R_AARCH64_CALL26:
> +  case R_AARCH64_CONDBR19:
> +  case R_AARCH64_JUMP26:
> +  case R_AARCH64_TSTBR14:
> +    return P + 4;
> +  default:
> +    return A;
> +  }
> +}
> +
>  template <class ELFT>
>  static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A,
>                                      typename ELFT::uint P,
> @@ -373,10 +409,20 @@ static typename ELFT::uint getSymVA(uint
>      return SymVA - P;
>    }
>    case R_PC:
> +    if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak()) {
> +      // On ARM and AArch64 a branch to an undefined weak resolves to the
> +      // next instruction, otherwise the place.
> +      if (Config->EMachine == EM_ARM)
> +        return getARMUndefinedRelativeWeakVA(Type, A, P);
> +      if (Config->EMachine == EM_AARCH64)
> +        return getAArch64UndefinedRelativeWeakVA(Type, A, P);
> +    }
>    case R_RELAX_GOT_PC:
>      return Body.getVA<ELFT>(A) - P;
>    case R_PLT_PAGE_PC:
>    case R_PAGE_PC:
> +    if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak())
> +      return getAArch64Page(A);
>      return getAArch64Page(Body.getVA<ELFT>(A)) - getAArch64Page(P);
>    }
>    llvm_unreachable("Invalid expression");
>
> Added: lld/trunk/test/ELF/aarch64-undefined-weak.s
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-undefined-weak.s?rev=286353&view=auto
> ==============================================================================
> --- lld/trunk/test/ELF/aarch64-undefined-weak.s (added)
> +++ lld/trunk/test/ELF/aarch64-undefined-weak.s Wed Nov  9 04:22:29 2016
> @@ -0,0 +1,45 @@
> +// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t
> +// RUN: ld.lld %t -o %t2 2>&1
> +// RUN: llvm-objdump -triple=aarch64-none-linux -d %t2 | FileCheck %s
> +// REQUIRES: aarch64
> +
> +// Check that the ARM 64-bit ABI rules for undefined weak symbols are applied.
> +// Branch instructions are resolved to the next instruction. Undefined
> +// Symbols in relative are resolved to the place so S - P + A = A.
> +
> + .weak target
> +
> + .text
> + .global _start
> +_start:
> +// R_AARCH64_JUMP26
> + b target
> +// R_AARCH64_CALL26
> + bl target
> +// R_AARCH64_CONDBR19
> + b.eq target
> +// R_AARCH64_TSTBR14
> + cbz x1, target
> +// R_AARCH64_ADR_PREL_LO21
> + adr x0, target
> +// R_AARCH64_ADR_PREL_PG_HI21
> + adrp x0, target
> +// R_AARCH64_PREL32
> + .word target - .
> +// R_AARCH64_PREL64
> + .xword target - .
> +// R_AARCH64_PREL16
> + .hword target - .
> +
> +// CHECK: Disassembly of section .text:
> +// 131076 = 0x20004
> +// CHECK:         20000:       01 80 00 14     b       #131076
> +// CHECK-NEXT:    20004:       02 80 00 94     bl      #131080
> +// CHECK-NEXT:    20008:       60 00 10 54     b.eq    #131084
> +// CHECK-NEXT:    2000c:       81 00 10 b4     cbz     x1, #131088
> +// CHECK-NEXT:    20010:       00 00 00 10     adr     x0, #0
> +// CHECK-NEXT:    20014:       00 00 00 90     adrp    x0, #0
> +// CHECK:         20018:       00 00 00 00     .word   0x00000000
> +// CHECK-NEXT:    2001c:       00 00 00 00     .word   0x00000000
> +// CHECK-NEXT:    20020:       00 00 00 00     .word   0x00000000
> +// CHECK-NEXT:    20024:       00 00           .short  0x0000
>
> Propchange: lld/trunk/test/ELF/aarch64-undefined-weak.s
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Propchange: lld/trunk/test/ELF/aarch64-undefined-weak.s
> ------------------------------------------------------------------------------
>     svn:keywords = Rev Date Author URL Id
>
> Modified: lld/trunk/test/ELF/arm-thumb-no-undefined-thunk.s
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thumb-no-undefined-thunk.s?rev=286353&r1=286352&r2=286353&view=diff
> ==============================================================================
> --- lld/trunk/test/ELF/arm-thumb-no-undefined-thunk.s (original)
> +++ lld/trunk/test/ELF/arm-thumb-no-undefined-thunk.s Wed Nov  9 04:22:29 2016
> @@ -18,6 +18,7 @@ _start:
>
>  // CHECK: Disassembly of section .text:
>  // CHECK-NEXT: _start:
> -// CHECK-NEXT:    11000:        ee f7 fe ef     blx     #-69636
> -// CHECK-NEXT:    11004:        ee f7 fc bf     b.w     #-69640
> -// CHECK-NEXT:    11008:        ee f7 fa bf     b.w     #-69644
> +// 69636 = 0x11004 = next instruction
> +// CHECK:         11000:        11 f0 02 f8     bl      #69636
> +// CHECK-NEXT:    11004:        11 f0 04 b8     b.w     #69640
> +// CHECK-NEXT:    11008:        11 f0 06 b8     b.w     #69644
>
> Added: lld/trunk/test/ELF/arm-thumb-undefined-weak.s
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thumb-undefined-weak.s?rev=286353&view=auto
> ==============================================================================
> --- lld/trunk/test/ELF/arm-thumb-undefined-weak.s (added)
> +++ lld/trunk/test/ELF/arm-thumb-undefined-weak.s Wed Nov  9 04:22:29 2016
> @@ -0,0 +1,38 @@
> +// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
> +// RUN: ld.lld %t -o %t2 2>&1
> +// RUN: llvm-objdump -triple=thumbv7a-none-linux-gnueabi -d %t2 | FileCheck %s
> +// REQUIRES: arm
> +
> +// Check that the ARM ABI rules for undefined weak symbols are applied.
> +// Branch instructions are resolved to the next instruction. Relative
> +// relocations are resolved to the place.
> +
> + .syntax unified
> +
> + .weak target
> +
> + .text
> + .global _start
> +_start:
> +// R_ARM_THM_JUMP19
> + beq.w target
> +// R_ARM_THM_JUMP24
> + b.w target
> +// R_ARM_THM_CALL
> + bl target
> +// R_ARM_THM_CALL with exchange
> + blx target
> +// R_ARM_THM_MOVT_PREL
> + movt r0, :upper16:target - .
> +// R_ARM_THM_MOVW_PREL_NC
> + movw r0, :lower16:target - .
> +
> +// CHECK: Disassembly of section .text:
> +// 69636 = 0x11004
> +// CHECK:         11000:       11 f0 02 80     beq.w   #69636
> +// CHECK-NEXT:    11004:       11 f0 04 b8     b.w     #69640
> +// CHECK-NEXT:    11008:       11 f0 06 f8     bl      #69644
> +// blx is transformed into bl so we don't change state
> +// CHECK-NEXT:    1100c:       11 f0 08 f8     bl      #69648
> +// CHECK-NEXT:    11010:       c0 f2 00 00     movt    r0, #0
> +// CHECK-NEXT:    11014:       40 f2 00 00     movw    r0, #0
>
> Propchange: lld/trunk/test/ELF/arm-thumb-undefined-weak.s
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Propchange: lld/trunk/test/ELF/arm-thumb-undefined-weak.s
> ------------------------------------------------------------------------------
>     svn:keywords = Rev Date Author URL Id
>
> Added: lld/trunk/test/ELF/arm-undefined-weak.s
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-undefined-weak.s?rev=286353&view=auto
> ==============================================================================
> --- lld/trunk/test/ELF/arm-undefined-weak.s (added)
> +++ lld/trunk/test/ELF/arm-undefined-weak.s Wed Nov  9 04:22:29 2016
> @@ -0,0 +1,39 @@
> +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
> +// RUN: ld.lld %t -o %t2 2>&1
> +// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t2 | FileCheck %s
> +// REQUIRES: arm
> +
> +// Check that the ARM ABI rules for undefined weak symbols are applied.
> +// Branch instructions are resolved to the next instruction. Undefined
> +// Symbols in relative are resolved to the place so S - P + A = A.
> +
> + .syntax unified
> +
> + .weak target
> +
> + .text
> + .global _start
> +_start:
> +// R_ARM_JUMP24
> + b target
> +// R_ARM_CALL
> + bl target
> +// R_ARM_CALL with exchange
> + blx target
> +// R_ARM_MOVT_PREL
> + movt r0, :upper16:target - .
> +// R_ARM_MOVW_PREL_NC
> + movw r0, :lower16:target - .
> +// R_ARM_REL32
> + .word target - .
> +
> +// CHECK: Disassembly of section .text:
> +// 69636 = 0x11004
> +// CHECK:         11000:       01 44 00 ea     b       #69636
> +// CHECK-NEXT:    11004:       02 44 00 eb     bl      #69640
> +// blx is transformed into bl so we don't change state
> +// CHECK-NEXT:    11008:       03 44 00 eb     bl      #69644
> +// CHECK-NEXT:    1100c:       00 00 40 e3     movt    r0, #0
> +// CHECK-NEXT:    11010:       00 00 00 e3     movw    r0, #0
> +// CHECK:         11014:       00 00 00 00     .word   0x00000000
> +
>
> Propchange: lld/trunk/test/ELF/arm-undefined-weak.s
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Propchange: lld/trunk/test/ELF/arm-undefined-weak.s
> ------------------------------------------------------------------------------
>     svn:keywords = Rev Date Author URL Id
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list