[lld] r303337 - [ELF] Support R_ARM_SBREL32 Relocation

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Thu May 18 02:12:23 PDT 2017


Author: psmith
Date: Thu May 18 04:12:21 2017
New Revision: 303337

URL: http://llvm.org/viewvc/llvm-project?rev=303337&view=rev
Log:
[ELF] Support R_ARM_SBREL32 Relocation

This change adds support for the R_ARM_SBREL32 relocation. The relocation
is a base relative relocation that is produced by clang/llvm when -frwpi
is used. The use case for the -frwpi option is position independent data
for embedded systems that do not have a GOT. With -frwpi all data is
accessed via an offset from a base register (usually r9), where r9 is set
at run time to where the data has been loaded. The base of the data is
known as the static base.

The ARM ABI defines the static base as:
B(S) is the addressing origin of the output segment defining the symbol S.
The origin is not required to be the base address of the segment. For
simplicity we choose to use the base address of the segment.

The ARM procedure call standard only defines a read write variant using
R_ARM_SBREL32 relocations. The read-only data is accessed via pc-relative
offsets from the code, this is implemented in clang as -fropi.

Fixes PR32924

Differential Revision: https://reviews.llvm.org/D33280


Added:
    lld/trunk/test/ELF/arm-sbrel32.s
Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/Relocations.h
    lld/trunk/ELF/Target.cpp

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=303337&r1=303336&r2=303337&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Thu May 18 04:12:21 2017
@@ -390,6 +390,20 @@ static uint64_t getAArch64UndefinedRelat
   }
 }
 
+// ARM SBREL relocations are of the form S + A - B where B is the static base
+// The ARM ABI defines base to be "addressing origin of the output segment
+// defining the symbol S". We defined the "addressing origin"/static base to be
+// the base of the PT_LOAD segment containing the Body.
+// The procedure call standard only defines a Read Write Position Independent
+// RWPI variant so in practice we should expect the static base to be the base
+// of the RW segment.
+static uint64_t getARMStaticBase(const SymbolBody &Body) {
+  OutputSection *OS = Body.getOutputSection();
+  if (!OS || !OS->FirstInPtLoad)
+    fatal("SBREL relocation to " + Body.getName() + " without static base\n");
+  return OS->FirstInPtLoad->Addr;
+}
+
 template <class ELFT>
 static typename ELFT::uint
 getRelocTargetVA(uint32_t Type, int64_t A, typename ELFT::uint P,
@@ -398,6 +412,8 @@ getRelocTargetVA(uint32_t Type, int64_t
   case R_ABS:
   case R_RELAX_GOT_PC_NOPIC:
     return Body.getVA(A);
+  case R_ARM_SBREL:
+    return Body.getVA(A) - getARMStaticBase(Body);
   case R_GOT:
   case R_RELAX_TLS_GD_TO_IE_ABS:
     return Body.getGotVA() + A;

Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=303337&r1=303336&r2=303337&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Thu May 18 04:12:21 2017
@@ -27,6 +27,7 @@ class OutputSection;
 // doesn't have to know about architecture-specific details.
 enum RelExpr {
   R_ABS,
+  R_ARM_SBREL,
   R_GOT,
   R_GOTONLY_PC,
   R_GOTONLY_PC_FROM_END,

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=303337&r1=303336&r2=303337&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Thu May 18 04:12:21 2017
@@ -1693,6 +1693,8 @@ RelExpr ARMTargetInfo::getRelExpr(uint32
   case R_ARM_TLS_IE32:
     // GOT(S) + A - P
     return R_GOT_PC;
+  case R_ARM_SBREL32:
+    return R_ARM_SBREL;
   case R_ARM_TARGET1:
     return Config->Target1Rel ? R_PC : R_ABS;
   case R_ARM_TARGET2:
@@ -1832,6 +1834,7 @@ void ARMTargetInfo::relocateOne(uint8_t
   case R_ARM_GOT_PREL:
   case R_ARM_REL32:
   case R_ARM_RELATIVE:
+  case R_ARM_SBREL32:
   case R_ARM_TARGET1:
   case R_ARM_TARGET2:
   case R_ARM_TLS_GD32:

Added: lld/trunk/test/ELF/arm-sbrel32.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-sbrel32.s?rev=303337&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-sbrel32.s (added)
+++ lld/trunk/test/ELF/arm-sbrel32.s Thu May 18 04:12:21 2017
@@ -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 -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
+// REQUIRES: arm
+
+// Test the R_ARM_SBREL32 relocation which calculates the offset of the Symbol
+// from the static base. We define the static base to be the address of the
+// segment containing the symbol
+ .text
+ .syntax unified
+
+ .globl _start
+ .p2align       2
+ .type  _start,%function
+_start:
+        .fnstart
+        bx lr
+
+        .long   foo(sbrel)
+        .long   foo2(sbrel)
+        .long   foo3(sbrel)
+        .long   foo4(sbrel)
+// RW segment starts here
+        .data
+        .p2align 4
+foo:    .word 10
+foo2:   .word 20
+
+        .bss
+foo3:   .space 4
+foo4:   .space 4
+
+// CHECK: Disassembly of section .text:
+// CHECK-NEXT: _start:
+// CHECK-NEXT:    11000:        1e ff 2f e1     bx      lr
+// CHECK:         11004:        00 00 00 00     .word   0x00000000
+// CHECK-NEXT:    11008:        04 00 00 00     .word   0x00000004
+// CHECK-NEXT:    1100c:        08 00 00 00     .word   0x00000008
+// CHECK-NEXT:    11010:        0c 00 00 00     .word   0x0000000c




More information about the llvm-commits mailing list