[lld] r176415 - [ELF][Hexagon] add initial changes to add GOT/PLT

Shankar Easwaran shankare at codeaurora.org
Sat Mar 2 23:34:56 PST 2013


Author: shankare
Date: Sun Mar  3 01:34:56 2013
New Revision: 176415

URL: http://llvm.org/viewvc/llvm-project?rev=176415&view=rev
Log:
[ELF][Hexagon] add initial changes to add GOT/PLT

Added:
    lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicAtoms.h
    lld/trunk/test/elf/Hexagon/Inputs/use-shared.hexagon   (with props)
    lld/trunk/test/elf/Hexagon/hexagon-plt-setup.test
Modified:
    lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp
    lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h

Added: lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicAtoms.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicAtoms.h?rev=176415&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicAtoms.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicAtoms.h Sun Mar  3 01:34:56 2013
@@ -0,0 +1,82 @@
+//===- lib/ReaderWriter/ELF/Hexagon/HexagonDynamicAtoms.h -----------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_ELF_HEXAGON_DYNAMIC_ATOMS_H
+#define LLD_READER_WRITER_ELF_HEXAGON_DYNAMIC_ATOMS_H
+
+#include "Atoms.h"
+#include "HexagonTargetInfo.h"
+
+namespace lld {
+namespace elf {
+
+class HexagonGOTAtom : public GOTAtom {
+  static const uint8_t _defaultContent[8];
+
+public:
+  HexagonGOTAtom(const File &f, StringRef secName)
+      : GOTAtom(f, secName) {
+  }
+
+  virtual ArrayRef<uint8_t> rawContent() const {
+    return ArrayRef<uint8_t>(_defaultContent, 8);
+  }
+};
+
+const uint8_t HexagonGOTAtom::_defaultContent[8] = { 0 };
+
+class HexagonPLTAtom : public PLTAtom {
+  static const uint8_t _defaultContent[16];
+
+public:
+  HexagonPLTAtom(const File &f, StringRef secName)
+      : PLTAtom(f, secName) {
+  }
+
+  virtual ArrayRef<uint8_t> rawContent() const {
+    return ArrayRef<uint8_t>(_defaultContent, 16);
+  }
+};
+
+const uint8_t HexagonPLTAtom::_defaultContent[16] = {
+  0x00, 0x40, 0x00, 0x00, // { immext (#0)                                     
+  0x0e, 0xc0, 0x49, 0x6a, //   r14 = add (pc, ##GOTn at PCREL) } # address of GOTn
+  0x1c, 0xc0, 0x8e, 0x91, // r28 = memw (r14)                 # contents of GOTn
+  0x00, 0xc0, 0x9c, 0x52, // jumpr r28                        # call it        
+};
+
+class HexagonPLT0Atom : public PLT0Atom {
+  static const uint8_t _plt0Content[28];
+
+public:
+  HexagonPLT0Atom(const File &f) : PLT0Atom(f) {
+#ifndef NDEBUG
+    _name = ".PLT0";
+#endif
+  }
+
+  virtual ArrayRef<uint8_t> rawContent() const {
+    return ArrayRef<uint8_t>(_plt0Content, 28);
+  }
+};
+
+const uint8_t HexagonPLT0Atom::_plt0Content[28] = {
+ 0x00, 0x40, 0x00, 0x00,  // { immext (#0)                                      
+ 0x1c, 0xc0, 0x49, 0x6a,  //   r28 = add (pc, ##GOT0 at PCREL) } # address of GOT0
+ 0x0e, 0x42, 0x9c, 0xe2,  // { r14 -= add (r28, #16)  # offset of GOTn from GOTa
+ 0x4f, 0x40, 0x9c, 0x91,  //   r15 = memw (r28 + #8)  # object ID at GOT2      
+ 0x3c, 0xc0, 0x9c, 0x91,  //   r28 = memw (r28 + #4) }# dynamic link at GOT1  
+ 0x0e, 0x42, 0x0e, 0x8c,  // { r14 = asr (r14, #2)    # index of PLTn         
+ 0x00, 0xc0, 0x9c, 0x52,  //   jumpr r28 }            # call dynamic linker  
+};
+
+} // elf 
+} // lld
+
+#endif // LLD_READER_WRITER_ELF_HEXAGON_DYNAMIC_ATOMS_H

Modified: lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp?rev=176415&r1=176414&r2=176415&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp Sun Mar  3 01:34:56 2013
@@ -97,6 +97,16 @@ int relocHexBNPCRELX(uint8_t *location,
   return 1;
 }
 
+// R_HEX_6_PCREL_X
+int relocHex6PCRELX(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
+  int32_t result = (S + A - P);
+  result = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
+  *reinterpret_cast<llvm::support::ulittle32_t *>(location) =
+      result |
+      (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location);
+  return 0;
+}
+
 // R_HEX_N_X : Word32_U6 : (S + A) : Unsigned Truncate
 int relocHex_N_X(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
   uint32_t result = (S + A);
@@ -197,6 +207,11 @@ ErrorOr<void> HexagonTargetRelocationHan
   case R_HEX_6_X:
     relocHex_N_X(location, relocVAddress, targetVAddress, ref.addend());
     break;
+  case R_HEX_6_PCREL_X:
+    relocHex6PCRELX(location, relocVAddress, targetVAddress, ref.addend());
+    break;
+  case R_HEX_JMP_SLOT:
+    break;
   case lld::Reference::kindLayoutAfter:
   case lld::Reference::kindLayoutBefore:
   case lld::Reference::kindInGroup:

Modified: lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp?rev=176415&r1=176414&r2=176415&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp Sun Mar  3 01:34:56 2013
@@ -7,6 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "HexagonDynamicAtoms.h"
 #include "HexagonTargetHandler.h"
 #include "HexagonTargetInfo.h"
 
@@ -19,3 +20,158 @@ HexagonTargetHandler::HexagonTargetHandl
     : DefaultTargetHandler(targetInfo), _targetLayout(targetInfo),
       _relocationHandler(targetInfo, _targetLayout),
       _hexagonRuntimeFile(targetInfo) {}
+
+namespace {
+
+using namespace llvm::ELF;
+
+class ELFPassFile : public SimpleFile {
+public:
+  ELFPassFile(const ELFTargetInfo &eti) : SimpleFile(eti, "ELFPassFile") {}
+
+  llvm::BumpPtrAllocator _alloc;
+};
+
+/// \brief Create GOT and PLT entries for relocations. Handles standard GOT/PLT
+template <class Derived> class GOTPLTPass : public Pass {
+  /// \brief Handle a specific reference.
+  void handleReference(const DefinedAtom &atom, const Reference &ref) {
+    switch (ref.kind()) {
+    case R_HEX_PLT_B22_PCREL:
+      static_cast<Derived *>(this)->handlePLT32(ref);
+      break;
+    }
+  }
+
+protected:
+  /// \brief Create a GOT entry containing 0.
+  const GOTAtom *getNullGOT() {
+    if (!_null) {
+      _null = new (_file._alloc) HexagonGOTAtom(_file, ".got.plt");
+#ifndef NDEBUG
+      _null->_name = "__got_null";
+#endif
+    }
+    return _null;
+  }
+
+public:
+  GOTPLTPass(const ELFTargetInfo &ti)
+      : _file(ti), _null(nullptr), _PLT0(nullptr), _got0(nullptr) {}
+
+  /// \brief Do the pass.
+  ///
+  /// The goal here is to first process each reference individually. Each call
+  /// to handleReference may modify the reference itself and/or create new
+  /// atoms which must be stored in one of the maps below.
+  ///
+  /// After all references are handled, the atoms created during that are all
+  /// added to mf.
+  virtual void perform(MutableFile &mf) {
+    // Process all references.
+    for (const auto &atom : mf.defined())
+      for (const auto &ref : *atom)
+        handleReference(*atom, *ref);
+
+    // Add all created atoms to the link.
+    uint64_t ordinal = 0;
+    if (_PLT0) {
+      _PLT0->setOrdinal(ordinal++);
+      mf.addAtom(*_PLT0);
+    }
+    for (const auto &plt : _pltMap) {
+      plt.second->setOrdinal(ordinal++);
+      mf.addAtom(*plt.second);
+    }
+    if (_null) {
+      _null->setOrdinal(ordinal++);
+      mf.addAtom(*_null);
+    }
+    if (_PLT0) {
+      _got0->setOrdinal(ordinal++);
+      mf.addAtom(*_got0);
+    }
+    for (const auto &got : _gotMap) {
+      got.second->setOrdinal(ordinal++);
+      mf.addAtom(*got.second);
+    }
+  }
+
+protected:
+  /// \brief Owner of all the Atoms created by this pass.
+  ELFPassFile _file;
+  
+  /// \brief Map Atoms to their GOT entries.
+  llvm::DenseMap<const Atom *, GOTAtom *> _gotMap;
+
+  /// \brief Map Atoms to their PLT entries.
+  llvm::DenseMap<const Atom *, PLTAtom *> _pltMap;
+
+  /// \brief GOT entry that is always 0. Used for undefined weaks.
+  GOTAtom *_null;
+
+  /// \brief The got and plt entries for .PLT0. This is used to call into the
+  /// dynamic linker for symbol resolution.
+  /// @{
+  PLT0Atom *_PLT0;
+  GOTAtom *_got0;
+  /// @}
+};
+
+class DynamicGOTPLTPass LLVM_FINAL : public GOTPLTPass<DynamicGOTPLTPass> {
+public:
+  DynamicGOTPLTPass(const elf::HexagonTargetInfo &ti) : GOTPLTPass(ti) {}
+
+  const PLT0Atom *getPLT0() {
+    if (_PLT0)
+      return _PLT0;
+    // Fill in the null entry.
+    getNullGOT();
+    _PLT0 = new (_file._alloc) HexagonPLT0Atom(_file);
+    _got0 = new (_file._alloc) HexagonGOTAtom(_file, ".got.plt");
+    _PLT0->addReference(R_HEX_B32_PCREL_X, 0, _got0, 0);
+    _PLT0->addReference(R_HEX_6_PCREL_X, 4, _got0, 0);
+#ifndef NDEBUG
+    _got0->_name = "__got0";
+#endif
+    return _PLT0;
+  }
+
+  const PLTAtom *getPLTEntry(const Atom *a) {
+    auto plt = _pltMap.find(a);
+    if (plt != _pltMap.end())
+      return plt->second;
+    auto ga = new (_file._alloc) HexagonGOTAtom(_file, ".got.plt");
+    ga->addReference(R_HEX_JMP_SLOT, 0, a, 0);
+    auto pa = new (_file._alloc) HexagonPLTAtom(_file, ".plt");
+    pa->addReference(R_HEX_B32_PCREL_X, 0, ga, 0);
+    pa->addReference(R_HEX_6_PCREL_X, 4, ga, 4);
+
+    // Point the got entry to the PLT0 atom initially
+    ga->addReference(R_HEX_32, 0, getPLT0(), 0);
+#ifndef NDEBUG
+    ga->_name = "__got_";
+    ga->_name += a->name();
+    pa->_name = "__plt_";
+    pa->_name += a->name();
+#endif
+    _gotMap[a] = ga;
+    _pltMap[a] = pa;
+    return pa;
+  }
+
+  ErrorOr<void> handlePLT32(const Reference &ref) {
+    // Turn this into a PC32 to the PLT entry.
+    const_cast<Reference &>(ref).setKind(R_HEX_B22_PCREL);
+    const_cast<Reference &>(ref).setTarget(getPLTEntry(ref.target()));
+    return error_code::success();
+  }
+};
+} // end anonymous namespace
+
+void elf::HexagonTargetInfo::addPasses(PassManager &pm) const {
+  if (_options._outputKind == OutputKind::DynamicExecutable ||
+           _options._outputKind == OutputKind::Shared)
+    pm.add(std::unique_ptr<Pass>(new DynamicGOTPLTPass(*this)));
+  ELFTargetInfo::addPasses(pm);
+}

Modified: lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp?rev=176415&r1=176414&r2=176415&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp Sun Mar  3 01:34:56 2013
@@ -215,3 +215,4 @@ ErrorOr<std::string> elf::HexagonTargetI
 
   return make_error_code(yaml_reader_error::illegal_value);
 }
+

Modified: lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h?rev=176415&r1=176414&r2=176415&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h Sun Mar  3 01:34:56 2013
@@ -32,6 +32,29 @@ public:
 
   virtual ErrorOr<int32_t> relocKindFromString(StringRef str) const;
   virtual ErrorOr<std::string> stringFromRelocKind(int32_t kind) const;
+
+  virtual void addPasses(PassManager &) const;
+
+  virtual bool isDynamicRelocation(const DefinedAtom &,
+                                   const Reference &r) const {
+    switch (r.kind()){
+    case llvm::ELF::R_HEX_RELATIVE:
+    case llvm::ELF::R_HEX_GLOB_DAT:
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  virtual bool isPLTRelocation(const DefinedAtom &,
+                               const Reference &r) const {
+    switch (r.kind()){
+    case llvm::ELF::R_HEX_JMP_SLOT:
+      return true;
+    default:
+      return false;
+    }
+  }
 };
 
 } // elf

Added: lld/trunk/test/elf/Hexagon/Inputs/use-shared.hexagon
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Hexagon/Inputs/use-shared.hexagon?rev=176415&view=auto
==============================================================================
Binary file - no diff available.

Propchange: lld/trunk/test/elf/Hexagon/Inputs/use-shared.hexagon
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: lld/trunk/test/elf/Hexagon/hexagon-plt-setup.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Hexagon/hexagon-plt-setup.test?rev=176415&view=auto
==============================================================================
--- lld/trunk/test/elf/Hexagon/hexagon-plt-setup.test (added)
+++ lld/trunk/test/elf/Hexagon/hexagon-plt-setup.test Sun Mar  3 01:34:56 2013
@@ -0,0 +1,15 @@
+RUN: lld -core -target hexagon %p/Inputs/use-shared.hexagon \
+RUN: -emit-yaml -output=%t2 -noinhibit-exec -output-type=dynamic
+RUN: FileCheck %s < %t2
+
+CHECK:  - name:            fn3
+CHECK:    references:      
+CHECK:      - kind:            R_HEX_B22_PCREL
+CHECK:        offset:          4
+              target:          __plt_fn1
+CHECK:      - kind:            R_HEX_B22_PCREL
+CHECK:        offset:          8
+              target:          __plt_fn2
+CHECK:      - kind:            <unknown>
+CHECK:        offset:          0
+CHECK:        target:          fn1





More information about the llvm-commits mailing list