Reverting r222828 and r222810-r222812 as they broke the build on Windows.
[oota-llvm.git] / lib / ExecutionEngine / RuntimeDyld / RuntimeDyldELF.cpp
index d213cc9379317bd2b5c5b7e72f2dbd5a2dd876d7..d95cffef03fff21c8b41ab1b16cb26e43fd52a77 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "RuntimeDyldELF.h"
+#include "JITRegistrar.h"
+#include "ObjectImageCommon.h"
 #include "llvm/ADT/IntervalMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Triple.h"
-#include "llvm/MC/MCStreamer.h"
+#include "llvm/ExecutionEngine/ObjectBuffer.h"
+#include "llvm/ExecutionEngine/ObjectImage.h"
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/ELF.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/TargetRegistry.h"
 
 using namespace llvm;
 using namespace llvm::object;
 
 #define DEBUG_TYPE "dyld"
 
+namespace {
+
 static inline std::error_code check(std::error_code Err) {
   if (Err) {
     report_fatal_error(Err.message());
@@ -36,8 +40,6 @@ static inline std::error_code check(std::error_code Err) {
   return Err;
 }
 
-namespace {
-
 template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> {
   LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
 
@@ -50,12 +52,16 @@ template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> {
 
   typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type;
 
+  std::unique_ptr<ObjectFile> UnderlyingFile;
+
 public:
+  DyldELFObject(std::unique_ptr<ObjectFile> UnderlyingFile,
+                MemoryBufferRef Wrapper, std::error_code &ec);
+
   DyldELFObject(MemoryBufferRef Wrapper, std::error_code &ec);
 
   void updateSectionAddress(const SectionRef &Sec, uint64_t Addr);
-
-  void updateSymbolAddress(const SymbolRef &SymRef, uint64_t Addr);
+  void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr);
 
   // Methods for type inquiry through isa, cast and dyn_cast
   static inline bool classof(const Binary *v) {
@@ -65,10 +71,42 @@ public:
   static inline bool classof(const ELFObjectFile<ELFT> *v) {
     return v->isDyldType();
   }
-
 };
 
+template <class ELFT> class ELFObjectImage : public ObjectImageCommon {
+  bool Registered;
+
+public:
+  ELFObjectImage(std::unique_ptr<ObjectBuffer> Input,
+                 std::unique_ptr<DyldELFObject<ELFT>> Obj)
+      : ObjectImageCommon(std::move(Input), std::move(Obj)), Registered(false) {
+  }
+
+  virtual ~ELFObjectImage() {
+    if (Registered)
+      deregisterWithDebugger();
+  }
+
+  // Subclasses can override these methods to update the image with loaded
+  // addresses for sections and common symbols
+  void updateSectionAddress(const SectionRef &Sec, uint64_t Addr) override {
+    static_cast<DyldELFObject<ELFT>*>(getObjectFile())
+        ->updateSectionAddress(Sec, Addr);
+  }
+
+  void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr) override {
+    static_cast<DyldELFObject<ELFT>*>(getObjectFile())
+        ->updateSymbolAddress(Sym, Addr);
+  }
 
+  void registerWithDebugger() override {
+    JITRegistrar::getGDBRegistrar().registerObject(*Buffer);
+    Registered = true;
+  }
+  void deregisterWithDebugger() override {
+    JITRegistrar::getGDBRegistrar().deregisterObject(*Buffer);
+  }
+};
 
 // The MemoryBuffer passed into this constructor is just a wrapper around the
 // actual memory.  Ultimately, the Binary parent class will take ownership of
@@ -79,6 +117,14 @@ DyldELFObject<ELFT>::DyldELFObject(MemoryBufferRef Wrapper, std::error_code &EC)
   this->isDyldELFObject = true;
 }
 
+template <class ELFT>
+DyldELFObject<ELFT>::DyldELFObject(std::unique_ptr<ObjectFile> UnderlyingFile,
+                                   MemoryBufferRef Wrapper, std::error_code &EC)
+    : ELFObjectFile<ELFT>(Wrapper, EC),
+      UnderlyingFile(std::move(UnderlyingFile)) {
+  this->isDyldELFObject = true;
+}
+
 template <class ELFT>
 void DyldELFObject<ELFT>::updateSectionAddress(const SectionRef &Sec,
                                                uint64_t Addr) {
@@ -103,89 +149,10 @@ void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef,
   sym->st_value = static_cast<addr_type>(Addr);
 }
 
-class LoadedELFObjectInfo : public RuntimeDyld::LoadedObjectInfo {
-public:
-  LoadedELFObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
-                      unsigned EndIdx)
-    : RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {}
-
-  OwningBinary<ObjectFile>
-  getObjectForDebug(const ObjectFile &Obj) const override;
-};
-
-template <typename ELFT>
-std::unique_ptr<DyldELFObject<ELFT>>
-createRTDyldELFObject(MemoryBufferRef Buffer,
-                      const LoadedELFObjectInfo &L,
-                      std::error_code &ec) {
-  typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
-  typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type;
-
-  std::unique_ptr<DyldELFObject<ELFT>> Obj =
-    llvm::make_unique<DyldELFObject<ELFT>>(Buffer, ec);
-
-  // Iterate over all sections in the object.
-  for (const auto &Sec : Obj->sections()) {
-    StringRef SectionName;
-    Sec.getName(SectionName);
-    if (SectionName != "") {
-      DataRefImpl ShdrRef = Sec.getRawDataRefImpl();
-      Elf_Shdr *shdr = const_cast<Elf_Shdr *>(
-          reinterpret_cast<const Elf_Shdr *>(ShdrRef.p));
-
-      if (uint64_t SecLoadAddr = L.getSectionLoadAddress(SectionName)) {
-        // This assumes that the address passed in matches the target address
-        // bitness. The template-based type cast handles everything else.
-        shdr->sh_addr = static_cast<addr_type>(SecLoadAddr);
-      }
-    }
-  }
-
-  return Obj;
-}
-
-OwningBinary<ObjectFile> createELFDebugObject(const ObjectFile &Obj,
-                                              const LoadedELFObjectInfo &L) {
-  assert(Obj.isELF() && "Not an ELF object file.");
-
-  std::unique_ptr<MemoryBuffer> Buffer =
-    MemoryBuffer::getMemBufferCopy(Obj.getData(), Obj.getFileName());
-
-  std::error_code ec;
-
-  std::unique_ptr<ObjectFile> DebugObj;
-  if (Obj.getBytesInAddress() == 4 && Obj.isLittleEndian()) {
-    typedef ELFType<support::little, 2, false> ELF32LE;
-    DebugObj = createRTDyldELFObject<ELF32LE>(Buffer->getMemBufferRef(), L, ec);
-  } else if (Obj.getBytesInAddress() == 4 && !Obj.isLittleEndian()) {
-    typedef ELFType<support::big, 2, false> ELF32BE;
-    DebugObj = createRTDyldELFObject<ELF32BE>(Buffer->getMemBufferRef(), L, ec);
-  } else if (Obj.getBytesInAddress() == 8 && !Obj.isLittleEndian()) {
-    typedef ELFType<support::big, 2, true> ELF64BE;
-    DebugObj = createRTDyldELFObject<ELF64BE>(Buffer->getMemBufferRef(), L, ec);
-  } else if (Obj.getBytesInAddress() == 8 && Obj.isLittleEndian()) {
-    typedef ELFType<support::little, 2, true> ELF64LE;
-    DebugObj = createRTDyldELFObject<ELF64LE>(Buffer->getMemBufferRef(), L, ec);
-  } else
-    llvm_unreachable("Unexpected ELF format");
-
-  assert(!ec && "Could not construct copy ELF object file");
-
-  return OwningBinary<ObjectFile>(std::move(DebugObj), std::move(Buffer));
-}
-
-OwningBinary<ObjectFile>
-LoadedELFObjectInfo::getObjectForDebug(const ObjectFile &Obj) const {
-  return createELFDebugObject(Obj, *this);
-}
-
 } // namespace
 
 namespace llvm {
 
-RuntimeDyldELF::RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
-RuntimeDyldELF::~RuntimeDyldELF() {}
-
 void RuntimeDyldELF::registerEHFrames() {
   if (!MemMgr)
     return;
@@ -213,14 +180,83 @@ void RuntimeDyldELF::deregisterEHFrames() {
   RegisteredEHFrameSections.clear();
 }
 
-std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
-RuntimeDyldELF::loadObject(const object::ObjectFile &O) {
-  unsigned SectionStartIdx, SectionEndIdx;
-  std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O);
-  return llvm::make_unique<LoadedELFObjectInfo>(*this, SectionStartIdx,
-                                                SectionEndIdx);
+ObjectImage *
+RuntimeDyldELF::createObjectImageFromFile(std::unique_ptr<object::ObjectFile> ObjFile) {
+  if (!ObjFile)
+    return nullptr;
+
+  std::error_code ec;
+  MemoryBufferRef Buffer = ObjFile->getMemoryBufferRef();
+
+  if (ObjFile->getBytesInAddress() == 4 && ObjFile->isLittleEndian()) {
+    auto Obj =
+        llvm::make_unique<DyldELFObject<ELFType<support::little, 2, false>>>(
+            std::move(ObjFile), Buffer, ec);
+    return new ELFObjectImage<ELFType<support::little, 2, false>>(
+        nullptr, std::move(Obj));
+  } else if (ObjFile->getBytesInAddress() == 4 && !ObjFile->isLittleEndian()) {
+    auto Obj =
+        llvm::make_unique<DyldELFObject<ELFType<support::big, 2, false>>>(
+            std::move(ObjFile), Buffer, ec);
+    return new ELFObjectImage<ELFType<support::big, 2, false>>(nullptr, std::move(Obj));
+  } else if (ObjFile->getBytesInAddress() == 8 && !ObjFile->isLittleEndian()) {
+    auto Obj = llvm::make_unique<DyldELFObject<ELFType<support::big, 2, true>>>(
+        std::move(ObjFile), Buffer, ec);
+    return new ELFObjectImage<ELFType<support::big, 2, true>>(nullptr,
+                                                              std::move(Obj));
+  } else if (ObjFile->getBytesInAddress() == 8 && ObjFile->isLittleEndian()) {
+    auto Obj =
+        llvm::make_unique<DyldELFObject<ELFType<support::little, 2, true>>>(
+            std::move(ObjFile), Buffer, ec);
+    return new ELFObjectImage<ELFType<support::little, 2, true>>(
+        nullptr, std::move(Obj));
+  } else
+    llvm_unreachable("Unexpected ELF format");
 }
 
+std::unique_ptr<ObjectImage>
+RuntimeDyldELF::createObjectImage(std::unique_ptr<ObjectBuffer> Buffer) {
+  if (Buffer->getBufferSize() < ELF::EI_NIDENT)
+    llvm_unreachable("Unexpected ELF object size");
+  std::pair<unsigned char, unsigned char> Ident =
+      std::make_pair((uint8_t)Buffer->getBufferStart()[ELF::EI_CLASS],
+                     (uint8_t)Buffer->getBufferStart()[ELF::EI_DATA]);
+  std::error_code ec;
+
+  MemoryBufferRef Buf = Buffer->getMemBuffer();
+
+  if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) {
+    auto Obj =
+        llvm::make_unique<DyldELFObject<ELFType<support::little, 4, false>>>(
+            Buf, ec);
+    return llvm::make_unique<
+        ELFObjectImage<ELFType<support::little, 4, false>>>(std::move(Buffer),
+                                                            std::move(Obj));
+  }
+  if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) {
+    auto Obj =
+        llvm::make_unique<DyldELFObject<ELFType<support::big, 4, false>>>(Buf,
+                                                                          ec);
+    return llvm::make_unique<ELFObjectImage<ELFType<support::big, 4, false>>>(
+        std::move(Buffer), std::move(Obj));
+  }
+  if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) {
+    auto Obj = llvm::make_unique<DyldELFObject<ELFType<support::big, 8, true>>>(
+        Buf, ec);
+    return llvm::make_unique<ELFObjectImage<ELFType<support::big, 8, true>>>(
+        std::move(Buffer), std::move(Obj));
+  }
+  assert(Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB &&
+         "Unexpected ELF format");
+  auto Obj =
+      llvm::make_unique<DyldELFObject<ELFType<support::little, 8, true>>>(Buf,
+                                                                          ec);
+  return llvm::make_unique<ELFObjectImage<ELFType<support::little, 8, true>>>(
+      std::move(Buffer), std::move(Obj));
+}
+
+RuntimeDyldELF::~RuntimeDyldELF() {}
+
 void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
                                              uint64_t Offset, uint64_t Value,
                                              uint32_t Type, int64_t Addend,
@@ -579,7 +615,7 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section,
 }
 
 // Return the .TOC. section and offset.
-void RuntimeDyldELF::findPPC64TOCSection(const ObjectFile &Obj,
+void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj,
                                          ObjSectionToIDMap &LocalSections,
                                          RelocationValueRef &Rel) {
   // Set a default SectionID in case we do not find a TOC section below.
@@ -592,7 +628,7 @@ void RuntimeDyldELF::findPPC64TOCSection(const ObjectFile &Obj,
 
   // The TOC consists of sections .got, .toc, .tocbss, .plt in that
   // order. The TOC starts where the first of these sections starts.
-  for (section_iterator si = Obj.section_begin(), se = Obj.section_end();
+  for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections();
        si != se; ++si) {
 
     StringRef SectionName;
@@ -614,15 +650,15 @@ void RuntimeDyldELF::findPPC64TOCSection(const ObjectFile &Obj,
 
 // Returns the sections and offset associated with the ODP entry referenced
 // by Symbol.
-void RuntimeDyldELF::findOPDEntrySection(const ObjectFile &Obj,
+void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj,
                                          ObjSectionToIDMap &LocalSections,
                                          RelocationValueRef &Rel) {
   // Get the ELF symbol value (st_value) to compare with Relocation offset in
   // .opd entries
-  for (section_iterator si = Obj.section_begin(), se = Obj.section_end();
+  for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections();
        si != se; ++si) {
     section_iterator RelSecI = si->getRelocatedSection();
-    if (RelSecI == Obj.section_end())
+    if (RelSecI == Obj.end_sections())
       continue;
 
     StringRef RelSectionName;
@@ -664,7 +700,7 @@ void RuntimeDyldELF::findOPDEntrySection(const ObjectFile &Obj,
       if (Rel.Addend != (int64_t)TargetSymbolOffset)
         continue;
 
-      section_iterator tsi(Obj.section_end());
+      section_iterator tsi(Obj.end_sections());
       check(TargetSymbol->getSection(tsi));
       bool IsCode = tsi->isText();
       Rel.SectionID = findOrEmitSection(Obj, (*tsi), IsCode, LocalSections);
@@ -899,8 +935,7 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
 }
 
 relocation_iterator RuntimeDyldELF::processRelocationRef(
-    unsigned SectionID, relocation_iterator RelI,
-    const ObjectFile &Obj,
+    unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj,
     ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols,
     StubMap &Stubs) {
   uint64_t RelType;
@@ -911,7 +946,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
 
   // Obtain the symbol name which is referenced in the relocation
   StringRef TargetName;
-  if (Symbol != Obj.symbol_end())
+  if (Symbol != Obj.end_symbols())
     Symbol->getName(TargetName);
   DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend
                << " TargetName: " << TargetName << "\n");
@@ -919,7 +954,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
   // First search for the symbol in the local symbol table
   SymbolTableMap::const_iterator lsi = Symbols.end();
   SymbolRef::Type SymType = SymbolRef::ST_Unknown;
-  if (Symbol != Obj.symbol_end()) {
+  if (Symbol != Obj.end_symbols()) {
     lsi = Symbols.find(TargetName.data());
     Symbol->getType(SymType);
   }
@@ -930,7 +965,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
   } else {
     // Search for the symbol in the global symbol table
     SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end();
-    if (Symbol != Obj.symbol_end())
+    if (Symbol != Obj.end_symbols())
       gsi = GlobalSymbolTable.find(TargetName.data());
     if (gsi != GlobalSymbolTable.end()) {
       Value.SectionID = gsi->second.first;
@@ -942,9 +977,9 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
         // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously
         // and can be changed by another developers. Maybe best way is add
         // a new symbol type ST_Section to SymbolRef and use it.
-        section_iterator si(Obj.section_end());
+        section_iterator si(Obj.end_sections());
         Symbol->getSection(si);
-        if (si == Obj.section_end())
+        if (si == Obj.end_sections())
           llvm_unreachable("Symbol section not found, bad object file format!");
         DEBUG(dbgs() << "\t\tThis is section symbol\n");
         bool isCode = si->isText();
@@ -1100,7 +1135,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
     if (RelType == ELF::R_PPC64_REL24) {
       // Determine ABI variant in use for this object.
       unsigned AbiVariant;
-      Obj.getPlatformFlags(AbiVariant);
+      Obj.getObjectFile()->getPlatformFlags(AbiVariant);
       AbiVariant &= ELF::EF_PPC64_ABI;
       // A PPC branch relocation will need a stub function if the target is
       // an external symbol (Symbol::ST_Unknown) or if the target address
@@ -1460,7 +1495,7 @@ uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, uint64_t Offset) {
   return 0;
 }
 
-void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,
+void RuntimeDyldELF::finalizeLoad(ObjectImage &ObjImg,
                                   ObjSectionToIDMap &SectionMap) {
   // If necessary, allocate the global offset table
   if (MemMgr) {
@@ -1498,8 +1533,15 @@ void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,
   }
 }
 
-bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const {
-  return Obj.isELF();
+bool RuntimeDyldELF::isCompatibleFormat(const ObjectBuffer *Buffer) const {
+  if (Buffer->getBufferSize() < strlen(ELF::ElfMagic))
+    return false;
+  return (memcmp(Buffer->getBufferStart(), ELF::ElfMagic,
+                 strlen(ELF::ElfMagic))) == 0;
+}
+
+bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile *Obj) const {
+  return Obj->isELF();
 }
 
 } // namespace llvm