[ELF][x86-64] Add X86_64TargetRelocationHandler and friends.
authorMichael J. Spencer <bigcheesegs@gmail.com>
Wed, 30 Jan 2013 05:26:03 +0000 (05:26 +0000)
committerMichael J. Spencer <bigcheesegs@gmail.com>
Wed, 30 Jan 2013 05:26:03 +0000 (05:26 +0000)
llvm-svn: 173897

lld/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt
lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp [new file with mode: 0644]
lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h [new file with mode: 0644]
lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h

index c32b5eb..1833673 100644 (file)
@@ -1,5 +1,6 @@
 add_lld_library(lldX86_64ELFTarget
   X86_64TargetInfo.cpp
+  X86_64TargetHandler.cpp
   )
 
 target_link_libraries(lldX86_64ELFTarget
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp
new file mode 100644 (file)
index 0000000..d9adc89
--- /dev/null
@@ -0,0 +1,90 @@
+//===- lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp ----------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86_64TargetHandler.h"
+#include "X86_64TargetInfo.h"
+
+using namespace lld;
+using namespace elf;
+
+using namespace llvm::ELF;
+
+namespace {
+/// \brief R_X86_64_64 - word64: S + A
+void reloc64(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
+  uint64_t result = S + A;
+  *reinterpret_cast<llvm::support::ulittle64_t *>(location) = result |
+            (uint64_t)*reinterpret_cast<llvm::support::ulittle64_t *>(location);
+}
+
+/// \brief R_X86_64_PC32 - word32: S + A - P
+void relocPC32(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
+  uint32_t result = (uint32_t)((S + A) - P);
+  *reinterpret_cast<llvm::support::ulittle32_t *>(location) = result +
+            (uint32_t)*reinterpret_cast<llvm::support::ulittle32_t *>(location);
+}
+
+/// \brief R_X86_64_32 - word32:  S + A
+void reloc32(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
+  int32_t result = (uint32_t)(S + A);
+  *reinterpret_cast<llvm::support::ulittle32_t *>(location) = result |
+            (uint32_t)*reinterpret_cast<llvm::support::ulittle32_t *>(location);
+  // TODO: Make sure that the result zero extends to the 64bit value.
+}
+
+/// \brief R_X86_64_32S - word32:  S + A
+void reloc32S(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
+  int32_t result = (int32_t)(S + A);
+  *reinterpret_cast<llvm::support::little32_t *>(location) = result |
+            (int32_t)*reinterpret_cast<llvm::support::little32_t *>(location);
+  // TODO: Make sure that the result sign extends to the 64bit value.
+}
+} // end anon namespace
+
+ErrorOr<void> X86_64TargetRelocationHandler::applyRelocation(
+    ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
+    const Reference &ref) const {
+  uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
+  uint8_t *location = atomContent + ref.offsetInAtom();
+  uint64_t targetVAddress = writer.addressOfAtom(ref.target());
+  uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom();
+
+  switch (ref.kind()) {
+  case R_X86_64_64:
+    reloc64(location, relocVAddress, targetVAddress, ref.addend());
+    break;
+  case R_X86_64_PC32:
+    relocPC32(location, relocVAddress, targetVAddress, ref.addend());
+    break;
+  case R_X86_64_32:
+    reloc32(location, relocVAddress, targetVAddress, ref.addend());
+    break;
+  case R_X86_64_32S:
+    reloc32S(location, relocVAddress, targetVAddress, ref.addend());
+    break;
+  // Runtime only relocations. Ignore here.
+  case R_X86_64_IRELATIVE:
+    break;
+  default: {
+    std::string str;
+    llvm::raw_string_ostream s(str);
+    auto name = _targetInfo.stringFromRelocKind(ref.kind());
+    s << "Unhandled relocation: "
+      << (name ? *name : "<unknown>" ) << " (" << ref.kind() << ")";
+    s.flush();
+    llvm_unreachable(str.c_str());
+  }
+  }
+
+  return error_code::success();
+}
+
+X86_64TargetHandler::X86_64TargetHandler(X86_64TargetInfo &targetInfo)
+    : DefaultTargetHandler(targetInfo), _relocationHandler(targetInfo) {
+}
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
new file mode 100644 (file)
index 0000000..91294e9
--- /dev/null
@@ -0,0 +1,48 @@
+//===- lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.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_X86_64_TARGET_HANDLER_H
+#define LLD_READER_WRITER_ELF_X86_64_TARGET_HANDLER_H
+
+#include "DefaultTargetHandler.h"
+
+namespace lld {
+namespace elf {
+typedef llvm::object::ELFType<llvm::support::little, 8, false> X86_64ELFType;
+class X86_64TargetInfo;
+
+class X86_64TargetRelocationHandler LLVM_FINAL
+    : public TargetRelocationHandler<X86_64ELFType> {
+public:
+  X86_64TargetRelocationHandler(const X86_64TargetInfo &ti) : _targetInfo(ti) {}
+
+  virtual ErrorOr<void> applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
+                                        const AtomLayout &,
+                                        const Reference &)const;
+
+private:
+  const X86_64TargetInfo &_targetInfo;
+};
+
+class X86_64TargetHandler LLVM_FINAL
+    : public DefaultTargetHandler<X86_64ELFType> {
+public:
+  X86_64TargetHandler(X86_64TargetInfo &targetInfo);
+
+  virtual const X86_64TargetRelocationHandler &getRelocationHandler() const {
+    return _relocationHandler;
+  }
+
+private:
+  X86_64TargetRelocationHandler _relocationHandler;
+};
+} // end namespace elf
+} // end namespace lld
+
+#endif
index dccc750..d867424 100644 (file)
@@ -10,7 +10,7 @@
 #ifndef LLD_READER_WRITER_ELF_X86_64_TARGETINFO_H
 #define LLD_READER_WRITER_ELF_X86_64_TARGETINFO_H
 
-#include "DefaultTargetHandler.h"
+#include "X86_64TargetHandler.h"
 
 #include "lld/Core/LinkerOptions.h"
 #include "lld/ReaderWriter/ELFTargetInfo.h"
 
 namespace lld {
 namespace elf {
+typedef llvm::object::ELFType<llvm::support::little, 8, false> X86_64ELFType;
+
 class X86_64TargetInfo LLVM_FINAL : public ELFTargetInfo {
 public:
   X86_64TargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {
-    _targetHandler = std::unique_ptr<TargetHandlerBase>(
-        new DefaultTargetHandler<llvm::object::ELFType<llvm::support::little,
-                                                          8, false> >(*this));
+    _targetHandler =
+        std::unique_ptr<TargetHandlerBase>(new X86_64TargetHandler(*this));
   }
 
   virtual uint64_t getPageSize() const { return 0x1000; }
@@ -47,7 +48,7 @@ public:
   virtual ErrorOr<std::string> stringFromRelocKind(int32_t kind) const;
 
 };
-} // elf
-} // lld
+} // end namespace elf
+} // end namespace lld
 
-#endif // LLD_READER_WRITER_ELF_X86_64_TARGETINFO_H
+#endif