[lld] r233383 - [ARM] Handle GOT relocations

Denis Protivensky dprotivensky at accesssoftek.com
Fri Mar 27 09:29:09 PDT 2015


Author: denis-protivensky
Date: Fri Mar 27 11:29:08 2015
New Revision: 233383

URL: http://llvm.org/viewvc/llvm-project?rev=233383&view=rev
Log:
[ARM] Handle GOT relocations

This includes relocs needed to link against glibc:
R_ARM_BASE_PREL
R_ARM_GOT_BREL

Every reloc is accompanied with a test case.

Added:
    lld/trunk/test/elf/ARM/rel-base-prel.test
    lld/trunk/test/elf/ARM/rel-got-brel.test
Modified:
    lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
    lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h

Modified: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp?rev=233383&r1=233382&r2=233383&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp Fri Mar 27 11:29:08 2015
@@ -82,6 +82,8 @@ static Reference::Addend readAddend(cons
   switch (kindValue) {
   case R_ARM_ABS32:
   case R_ARM_REL32:
+  case R_ARM_GOT_BREL:
+  case R_ARM_BASE_PREL:
   case R_ARM_TLS_IE32:
   case R_ARM_TLS_LE32:
     return (int32_t)read32le(location);
@@ -257,6 +259,32 @@ static void relocR_ARM_THM_JUMP11(uint8_
   applyThumb16Reloc(location, result, 0x7FF);
 }
 
+/// \brief R_ARM_BASE_PREL - B(S) + A - P => S + A - P
+static void relocR_ARM_BASE_PREL(uint8_t *location, uint64_t P, uint64_t S,
+                                 int64_t A) {
+  uint32_t result = (uint32_t)(S + A - P);
+  DEBUG_WITH_TYPE(
+      "ARM", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
+      llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
+      llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
+      llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
+      llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
+  applyArmReloc(location, result);
+}
+
+/// \brief R_ARM_GOT_BREL - GOT(S) + A - GOT_ORG => S + A - GOT_ORG
+static void relocR_ARM_GOT_BREL(uint8_t *location, uint64_t P, uint64_t S,
+                                int64_t A, uint64_t GOT_ORG) {
+  uint32_t result = (uint32_t)(S + A - GOT_ORG);
+  DEBUG_WITH_TYPE(
+      "ARM", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
+      llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
+      llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
+      llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
+      llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
+  applyArmReloc(location, result);
+}
+
 /// \brief R_ARM_CALL - ((S + A) | T) - P
 static void relocR_ARM_CALL(uint8_t *location, uint64_t P, uint64_t S,
                             int64_t A, bool addressesThumb) {
@@ -561,6 +589,20 @@ std::error_code ARMTargetRelocationHandl
     relocR_ARM_TLS_LE32(location, relocVAddress, targetVAddress, addend,
                         _armLayout.getTPOffset());
     break;
+  case R_ARM_GOT_BREL:
+    relocR_ARM_GOT_BREL(location, relocVAddress, targetVAddress, addend,
+                        _armLayout.getGOTSymAddr());
+    break;
+  case R_ARM_BASE_PREL:
+    // GOT origin is used for NULL symbol and when explicitly specified
+    if (!targetVAddress ||
+        ref.target()->name().equals("_GLOBAL_OFFSET_TABLE_")) {
+      targetVAddress = _armLayout.getGOTSymAddr();
+    } else {
+      llvm_unreachable("Segment-base relative addressing is not supported");
+    }
+    relocR_ARM_BASE_PREL(location, relocVAddress, targetVAddress, addend);
+    break;
   case R_ARM_ALU_PC_G0_NC:
     relocR_ARM_ALU_PC_G0_NC(location, relocVAddress, targetVAddress, addend);
     break;

Modified: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp?rev=233383&r1=233382&r2=233383&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp Fri Mar 27 11:29:08 2015
@@ -178,6 +178,11 @@ template <class Derived> class ARMReloca
     case R_ARM_TLS_IE32:
       static_cast<Derived *>(this)->handleTLSIE32(ref);
       break;
+    case R_ARM_GOT_BREL:
+      static_cast<Derived *>(this)->handleGOT(ref);
+      break;
+    default:
+      break;
     }
   }
 
@@ -314,8 +319,35 @@ protected:
     return std::error_code();
   }
 
+  /// \brief Create a GOT entry containing 0.
+  const GOTAtom *getNullGOT() {
+    if (!_null) {
+      _null = new (_file._alloc) ARMGOTAtom(_file, ".got.plt");
+#ifndef NDEBUG
+      _null->_name = "__got_null";
+#endif
+    }
+    return _null;
+  }
+
+  const GOTAtom *getGOT(const DefinedAtom *da) {
+    auto got = _gotMap.find(da);
+    if (got != _gotMap.end())
+      return got->second;
+    auto g = new (_file._alloc) ARMGOTAtom(_file, ".got");
+    g->addReferenceELF_ARM(R_ARM_ABS32, 0, da, 0);
+#ifndef NDEBUG
+    g->_name = "__got_";
+    g->_name += da->name();
+#endif
+    _gotMap[da] = g;
+    _gotVector.push_back(g);
+    return g;
+  }
+
 public:
-  ARMRelocationPass(const ELFLinkingContext &ctx) : _file(ctx), _ctx(ctx) {}
+  ARMRelocationPass(const ELFLinkingContext &ctx)
+      : _file(ctx), _ctx(ctx), _null(nullptr) {}
 
   /// \brief Do the pass.
   ///
@@ -361,14 +393,18 @@ public:
 
     // Add all created atoms to the link.
     uint64_t ordinal = 0;
-    for (auto &got : _gotVector) {
-      got->setOrdinal(ordinal++);
-      mf->addAtom(*got);
-    }
     for (auto &plt : _pltVector) {
       plt->setOrdinal(ordinal++);
       mf->addAtom(*plt);
     }
+    if (_null) {
+      _null->setOrdinal(ordinal++);
+      mf->addAtom(*_null);
+    }
+    for (auto &got : _gotVector) {
+      got->setOrdinal(ordinal++);
+      mf->addAtom(*got);
+    }
     for (auto &veneer : _veneerVector) {
       veneer->setOrdinal(ordinal++);
       mf->addAtom(*veneer);
@@ -395,6 +431,9 @@ protected:
 
   /// \brief the list of veneer atoms.
   std::vector<VeneerAtom *> _veneerVector;
+
+  /// \brief GOT entry that is always 0. Used for undefined weaks.
+  GOTAtom *_null;
 };
 
 /// This implements the static relocation model. Meaning GOT and PLT entries are
@@ -451,6 +490,14 @@ public:
   const GOTAtom *getTLSTPOFF32(const DefinedAtom *da) {
     return getGOTTLSEntry<R_ARM_TLS_LE32>(da);
   }
+
+  std::error_code handleGOT(const Reference &ref) {
+    if (isa<UndefinedAtom>(ref.target()))
+      const_cast<Reference &>(ref).setTarget(getNullGOT());
+    else if (const auto *da = dyn_cast<DefinedAtom>(ref.target()))
+      const_cast<Reference &>(ref).setTarget(getGOT(da));
+    return std::error_code();
+  }
 };
 
 } // end of anon namespace

Modified: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h?rev=233383&r1=233382&r2=233383&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h Fri Mar 27 11:29:08 2015
@@ -15,20 +15,26 @@
 #include "ARMRelocationHandler.h"
 #include "DefaultTargetHandler.h"
 #include "TargetLayout.h"
-
-#include "lld/Core/Simple.h"
 #include "llvm/ADT/Optional.h"
-#include <map>
 
 namespace lld {
 namespace elf {
-typedef llvm::object::ELFType<llvm::support::little, 2, false> ARMELFType;
 class ARMLinkingContext;
 
 template <class ELFT> class ARMTargetLayout : public TargetLayout<ELFT> {
 public:
   ARMTargetLayout(ARMLinkingContext &ctx) : TargetLayout<ELFT>(ctx) {}
 
+  uint64_t getGOTSymAddr() {
+    if (!_gotSymAddr.hasValue()) {
+      auto gotAtomIter = this->findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
+      _gotSymAddr = (gotAtomIter != this->absoluteAtoms().end())
+                        ? (*gotAtomIter)->_virtualAddr
+                        : 0;
+    }
+    return *_gotSymAddr;
+  }
+
   uint64_t getTPOffset() {
     if (_tpOff.hasValue())
       return *_tpOff;
@@ -46,6 +52,10 @@ private:
   // TCB block size of the TLS.
   enum { TCB_SIZE = 0x8 };
 
+private:
+  // Cached value of the GOT origin symbol address.
+  llvm::Optional<uint64_t> _gotSymAddr;
+
   // Cached value of the TLS offset from the $tp pointer.
   llvm::Optional<uint64_t> _tpOff;
 };

Added: lld/trunk/test/elf/ARM/rel-base-prel.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/ARM/rel-base-prel.test?rev=233383&view=auto
==============================================================================
--- lld/trunk/test/elf/ARM/rel-base-prel.test (added)
+++ lld/trunk/test/elf/ARM/rel-base-prel.test Fri Mar 27 11:29:08 2015
@@ -0,0 +1,62 @@
+# Check handling of R_ARM_BASE_PREL relocation.
+# It only works for _GLOBAL_OFFSET_TABLE_ symbol, and returns error
+# for other cases.
+
+# RUN: yaml2obj -format=elf %s > %t-o.o
+# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi -Bstatic \
+# RUN: --noinhibit-exec %t-o.o -o %t
+# RUN: llvm-objdump -s -t %t | FileCheck %s
+
+# CHECK: Contents of section .data:
+# CHECK-NEXT: 401004 fcffffff
+#           offset = -0x4 ^^
+#               addr site   offset    _GOT_
+#               0x401004  + (-0x4) = 0x401000
+# CHECK: SYMBOL TABLE:
+# CHECK: 00401000 g       *ABS* {{[0-9a-f]+}} _GLOBAL_OFFSET_TABLE_
+
+---
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_ARM
+  Flags:           [ EF_ARM_EABI_VER5 ]
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000004
+    Content:         80B400AF00231846BD465DF8047B7047
+  - Name:            .got
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000004
+    Content:         '00000000'
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000004
+    Content:         '00000000'
+  - Name:            .rel.data
+    Type:            SHT_REL
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .data
+    Relocations:
+      - Offset:          0x0000000000000000
+        Symbol:          _GLOBAL_OFFSET_TABLE_
+        Type:            R_ARM_BASE_PREL
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+Symbols:
+  Global:
+    - Name:            main
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000001
+    - Name:            _GLOBAL_OFFSET_TABLE_
+...

Added: lld/trunk/test/elf/ARM/rel-got-brel.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/ARM/rel-got-brel.test?rev=233383&view=auto
==============================================================================
--- lld/trunk/test/elf/ARM/rel-got-brel.test (added)
+++ lld/trunk/test/elf/ARM/rel-got-brel.test Fri Mar 27 11:29:08 2015
@@ -0,0 +1,64 @@
+# Check handling of R_ARM_GOT_BREL relocation.
+
+# RUN: yaml2obj -format=elf %s > %t-o.o
+# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi -Bstatic \
+# RUN: --noinhibit-exec %t-o.o -o %t
+# RUN: llvm-objdump -s -t %t | FileCheck %s
+
+# CHECK: Contents of section .got:
+# CHECK-NEXT: 401000 75004000 81004000
+#    f_thumb = 0x400075 ^^       ^^ main_thumb = 0x400081
+# CHECK: Contents of section .data:
+# CHECK-NEXT: 401008 00000000 04000000
+#   GOT[0] offset = 0x0 ^^       ^^ GOT[1] offset = 0x4
+# CHECK: SYMBOL TABLE:
+# CHECK: 00400074 g     F .text {{[0-9a-f]+}} f
+# CHECK: 00400080 g     F .text	{{[0-9a-f]+}} main
+
+---
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_ARM
+  Flags:           [ EF_ARM_EABI_VER5 ]
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000004
+    Content:         80B400AFBD465DF8047B704780B400AF00231846BD465DF8047B7047
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000004
+    Content:         '0000000000000000'
+  - Name:            .rel.data
+    Type:            SHT_REL
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .data
+    Relocations:
+      - Offset:          0x0000000000000000
+        Symbol:          f
+        Type:            R_ARM_GOT_BREL
+      - Offset:          0x0000000000000004
+        Symbol:          main
+        Type:            R_ARM_GOT_BREL
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+Symbols:
+  Global:
+    - Name:            f
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000001
+    - Name:            main
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x000000000000000D
+    - Name:            _GLOBAL_OFFSET_TABLE_
+...





More information about the llvm-commits mailing list