aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/ExecutionEngine/RuntimeDyld
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/ExecutionEngine/RuntimeDyld')
-rw-r--r--contrib/llvm/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp214
-rw-r--r--contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h44
-rw-r--r--contrib/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h79
-rw-r--r--contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp647
-rw-r--r--contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp1406
-rw-r--r--contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h152
-rw-r--r--contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h368
-rw-r--r--contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp458
-rw-r--r--contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h103
9 files changed, 3471 insertions, 0 deletions
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp
new file mode 100644
index 000000000000..603c526d06e3
--- /dev/null
+++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp
@@ -0,0 +1,214 @@
+//===-- GDBRegistrar.cpp - Registers objects with GDB ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JITRegistrar.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/MutexGuard.h"
+
+using namespace llvm;
+
+// This must be kept in sync with gdb/gdb/jit.h .
+extern "C" {
+
+ typedef enum {
+ JIT_NOACTION = 0,
+ JIT_REGISTER_FN,
+ JIT_UNREGISTER_FN
+ } jit_actions_t;
+
+ struct jit_code_entry {
+ struct jit_code_entry *next_entry;
+ struct jit_code_entry *prev_entry;
+ const char *symfile_addr;
+ uint64_t symfile_size;
+ };
+
+ struct jit_descriptor {
+ uint32_t version;
+ // This should be jit_actions_t, but we want to be specific about the
+ // bit-width.
+ uint32_t action_flag;
+ struct jit_code_entry *relevant_entry;
+ struct jit_code_entry *first_entry;
+ };
+
+ // We put information about the JITed function in this global, which the
+ // debugger reads. Make sure to specify the version statically, because the
+ // debugger checks the version before we can set it during runtime.
+ struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
+
+ // Debuggers puts a breakpoint in this function.
+ LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() { }
+
+}
+
+namespace {
+
+// Buffer for an in-memory object file in executable memory
+typedef llvm::DenseMap< const char*,
+ std::pair<std::size_t, jit_code_entry*> >
+ RegisteredObjectBufferMap;
+
+/// Global access point for the JIT debugging interface designed for use with a
+/// singleton toolbox. Handles thread-safe registration and deregistration of
+/// object files that are in executable memory managed by the client of this
+/// class.
+class GDBJITRegistrar : public JITRegistrar {
+ /// A map of in-memory object files that have been registered with the
+ /// JIT interface.
+ RegisteredObjectBufferMap ObjectBufferMap;
+
+public:
+ /// Instantiates the JIT service.
+ GDBJITRegistrar() : ObjectBufferMap() {}
+
+ /// Unregisters each object that was previously registered and releases all
+ /// internal resources.
+ virtual ~GDBJITRegistrar();
+
+ /// Creates an entry in the JIT registry for the buffer @p Object,
+ /// which must contain an object file in executable memory with any
+ /// debug information for the debugger.
+ void registerObject(const ObjectBuffer &Object);
+
+ /// Removes the internal registration of @p Object, and
+ /// frees associated resources.
+ /// Returns true if @p Object was found in ObjectBufferMap.
+ bool deregisterObject(const ObjectBuffer &Object);
+
+private:
+ /// Deregister the debug info for the given object file from the debugger
+ /// and delete any temporary copies. This private method does not remove
+ /// the function from Map so that it can be called while iterating over Map.
+ void deregisterObjectInternal(RegisteredObjectBufferMap::iterator I);
+};
+
+/// Lock used to serialize all jit registration events, since they
+/// modify global variables.
+llvm::sys::Mutex JITDebugLock;
+
+/// Acquire the lock and do the registration.
+void NotifyDebugger(jit_code_entry* JITCodeEntry) {
+ llvm::MutexGuard locked(JITDebugLock);
+ __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
+
+ // Insert this entry at the head of the list.
+ JITCodeEntry->prev_entry = NULL;
+ jit_code_entry* NextEntry = __jit_debug_descriptor.first_entry;
+ JITCodeEntry->next_entry = NextEntry;
+ if (NextEntry != NULL) {
+ NextEntry->prev_entry = JITCodeEntry;
+ }
+ __jit_debug_descriptor.first_entry = JITCodeEntry;
+ __jit_debug_descriptor.relevant_entry = JITCodeEntry;
+ __jit_debug_register_code();
+}
+
+GDBJITRegistrar::~GDBJITRegistrar() {
+ // Free all registered object files.
+ for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(), E = ObjectBufferMap.end();
+ I != E; ++I) {
+ // Call the private method that doesn't update the map so our iterator
+ // doesn't break.
+ deregisterObjectInternal(I);
+ }
+ ObjectBufferMap.clear();
+}
+
+void GDBJITRegistrar::registerObject(const ObjectBuffer &Object) {
+
+ const char *Buffer = Object.getBufferStart();
+ size_t Size = Object.getBufferSize();
+
+ assert(Buffer && "Attempt to register a null object with a debugger.");
+ assert(ObjectBufferMap.find(Buffer) == ObjectBufferMap.end() &&
+ "Second attempt to perform debug registration.");
+ jit_code_entry* JITCodeEntry = new jit_code_entry();
+
+ if (JITCodeEntry == 0) {
+ llvm::report_fatal_error(
+ "Allocation failed when registering a JIT entry!\n");
+ }
+ else {
+ JITCodeEntry->symfile_addr = Buffer;
+ JITCodeEntry->symfile_size = Size;
+
+ ObjectBufferMap[Buffer] = std::make_pair(Size, JITCodeEntry);
+ NotifyDebugger(JITCodeEntry);
+ }
+}
+
+bool GDBJITRegistrar::deregisterObject(const ObjectBuffer& Object) {
+ const char *Buffer = Object.getBufferStart();
+ RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Buffer);
+
+ if (I != ObjectBufferMap.end()) {
+ deregisterObjectInternal(I);
+ ObjectBufferMap.erase(I);
+ return true;
+ }
+ return false;
+}
+
+void GDBJITRegistrar::deregisterObjectInternal(
+ RegisteredObjectBufferMap::iterator I) {
+
+ jit_code_entry*& JITCodeEntry = I->second.second;
+
+ // Acquire the lock and do the unregistration.
+ {
+ llvm::MutexGuard locked(JITDebugLock);
+ __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
+
+ // Remove the jit_code_entry from the linked list.
+ jit_code_entry* PrevEntry = JITCodeEntry->prev_entry;
+ jit_code_entry* NextEntry = JITCodeEntry->next_entry;
+
+ if (NextEntry) {
+ NextEntry->prev_entry = PrevEntry;
+ }
+ if (PrevEntry) {
+ PrevEntry->next_entry = NextEntry;
+ }
+ else {
+ assert(__jit_debug_descriptor.first_entry == JITCodeEntry);
+ __jit_debug_descriptor.first_entry = NextEntry;
+ }
+
+ // Tell the debugger which entry we removed, and unregister the code.
+ __jit_debug_descriptor.relevant_entry = JITCodeEntry;
+ __jit_debug_register_code();
+ }
+
+ delete JITCodeEntry;
+ JITCodeEntry = NULL;
+}
+
+} // end namespace
+
+namespace llvm {
+
+JITRegistrar& JITRegistrar::getGDBRegistrar() {
+ static GDBJITRegistrar* sRegistrar = NULL;
+ if (sRegistrar == NULL) {
+ // The mutex is here so that it won't slow down access once the registrar
+ // is instantiated
+ llvm::MutexGuard locked(JITDebugLock);
+ // Check again to be sure another thread didn't create this while we waited
+ if (sRegistrar == NULL) {
+ sRegistrar = new GDBJITRegistrar;
+ }
+ }
+ return *sRegistrar;
+}
+
+} // namespace llvm
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h
new file mode 100644
index 000000000000..6a514ea3ec3b
--- /dev/null
+++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h
@@ -0,0 +1,44 @@
+//===-- JITRegistrar.h - Registers objects with a debugger ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTION_ENGINE_JIT_REGISTRAR_H
+#define LLVM_EXECUTION_ENGINE_JIT_REGISTRAR_H
+
+#include "llvm/ExecutionEngine/ObjectBuffer.h"
+
+namespace llvm {
+
+/// Global access point for the JIT debugging interface.
+class JITRegistrar {
+ virtual void anchor();
+public:
+ /// Instantiates the JIT service.
+ JITRegistrar() {}
+
+ /// Unregisters each object that was previously registered and releases all
+ /// internal resources.
+ virtual ~JITRegistrar() {}
+
+ /// Creates an entry in the JIT registry for the buffer @p Object,
+ /// which must contain an object file in executable memory with any
+ /// debug information for the debugger.
+ virtual void registerObject(const ObjectBuffer &Object) = 0;
+
+ /// Removes the internal registration of @p Object, and
+ /// frees associated resources.
+ /// Returns true if @p Object was previously registered.
+ virtual bool deregisterObject(const ObjectBuffer &Object) = 0;
+
+ /// Returns a reference to a GDB JIT registrar singleton
+ static JITRegistrar& getGDBRegistrar();
+};
+
+} // end namespace llvm
+
+#endif // LLVM_EXECUTION_ENGINE_JIT_REGISTRAR_H
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h
new file mode 100644
index 000000000000..9cbde5daede5
--- /dev/null
+++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h
@@ -0,0 +1,79 @@
+//===-- ObjectImageCommon.h - Format independent executuable object image -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares a file format independent ObjectImage class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_RUNTIMEDYLD_OBJECTIMAGECOMMON_H
+#define LLVM_RUNTIMEDYLD_OBJECTIMAGECOMMON_H
+
+#include "llvm/ExecutionEngine/ObjectBuffer.h"
+#include "llvm/ExecutionEngine/ObjectImage.h"
+#include "llvm/Object/ObjectFile.h"
+
+namespace llvm {
+
+class ObjectImageCommon : public ObjectImage {
+ ObjectImageCommon(); // = delete
+ ObjectImageCommon(const ObjectImageCommon &other); // = delete
+ virtual void anchor();
+
+protected:
+ object::ObjectFile *ObjFile;
+
+ // This form of the constructor allows subclasses to use
+ // format-specific subclasses of ObjectFile directly
+ ObjectImageCommon(ObjectBuffer *Input, object::ObjectFile *Obj)
+ : ObjectImage(Input), // saves Input as Buffer and takes ownership
+ ObjFile(Obj)
+ {
+ }
+
+public:
+ ObjectImageCommon(ObjectBuffer* Input)
+ : ObjectImage(Input) // saves Input as Buffer and takes ownership
+ {
+ ObjFile = object::ObjectFile::createObjectFile(Buffer->getMemBuffer());
+ }
+ virtual ~ObjectImageCommon() { delete ObjFile; }
+
+ virtual object::symbol_iterator begin_symbols() const
+ { return ObjFile->begin_symbols(); }
+ virtual object::symbol_iterator end_symbols() const
+ { return ObjFile->end_symbols(); }
+
+ virtual object::section_iterator begin_sections() const
+ { return ObjFile->begin_sections(); }
+ virtual object::section_iterator end_sections() const
+ { return ObjFile->end_sections(); }
+
+ virtual /* Triple::ArchType */ unsigned getArch() const
+ { return ObjFile->getArch(); }
+
+ virtual StringRef getData() const { return ObjFile->getData(); }
+
+ virtual object::ObjectFile* getObjectFile() const { return ObjFile; }
+
+ // Subclasses can override these methods to update the image with loaded
+ // addresses for sections and common symbols
+ virtual void updateSectionAddress(const object::SectionRef &Sec,
+ uint64_t Addr) {}
+ virtual void updateSymbolAddress(const object::SymbolRef &Sym, uint64_t Addr)
+ {}
+
+ // Subclasses can override these methods to provide JIT debugging support
+ virtual void registerWithDebugger() {}
+ virtual void deregisterWithDebugger() {}
+};
+
+} // end namespace llvm
+
+#endif // LLVM_RUNTIMEDYLD_OBJECT_IMAGE_H
+
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
new file mode 100644
index 000000000000..161135a4f8c0
--- /dev/null
+++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
@@ -0,0 +1,647 @@
+//===-- RuntimeDyld.cpp - Run-time dynamic linker for MC-JIT ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of the MC-JIT runtime dynamic linker.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "dyld"
+#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include "JITRegistrar.h"
+#include "ObjectImageCommon.h"
+#include "RuntimeDyldELF.h"
+#include "RuntimeDyldImpl.h"
+#include "RuntimeDyldMachO.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MutexGuard.h"
+#include "llvm/Object/ELF.h"
+
+using namespace llvm;
+using namespace llvm::object;
+
+// Empty out-of-line virtual destructor as the key function.
+RuntimeDyldImpl::~RuntimeDyldImpl() {}
+
+// Pin the JITRegistrar's and ObjectImage*'s vtables to this file.
+void JITRegistrar::anchor() {}
+void ObjectImage::anchor() {}
+void ObjectImageCommon::anchor() {}
+
+namespace llvm {
+
+void RuntimeDyldImpl::registerEHFrames() {
+}
+
+void RuntimeDyldImpl::deregisterEHFrames() {
+}
+
+// Resolve the relocations for all symbols we currently know about.
+void RuntimeDyldImpl::resolveRelocations() {
+ MutexGuard locked(lock);
+
+ // First, resolve relocations associated with external symbols.
+ resolveExternalSymbols();
+
+ // Just iterate over the sections we have and resolve all the relocations
+ // in them. Gross overkill, but it gets the job done.
+ for (int i = 0, e = Sections.size(); i != e; ++i) {
+ // The Section here (Sections[i]) refers to the section in which the
+ // symbol for the relocation is located. The SectionID in the relocation
+ // entry provides the section to which the relocation will be applied.
+ uint64_t Addr = Sections[i].LoadAddress;
+ DEBUG(dbgs() << "Resolving relocations Section #" << i
+ << "\t" << format("%p", (uint8_t *)Addr)
+ << "\n");
+ resolveRelocationList(Relocations[i], Addr);
+ Relocations.erase(i);
+ }
+}
+
+void RuntimeDyldImpl::mapSectionAddress(const void *LocalAddress,
+ uint64_t TargetAddress) {
+ MutexGuard locked(lock);
+ for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
+ if (Sections[i].Address == LocalAddress) {
+ reassignSectionAddress(i, TargetAddress);
+ return;
+ }
+ }
+ llvm_unreachable("Attempting to remap address of unknown section!");
+}
+
+// Subclasses can implement this method to create specialized image instances.
+// The caller owns the pointer that is returned.
+ObjectImage *RuntimeDyldImpl::createObjectImage(ObjectBuffer *InputBuffer) {
+ return new ObjectImageCommon(InputBuffer);
+}
+
+ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) {
+ MutexGuard locked(lock);
+
+ OwningPtr<ObjectImage> obj(createObjectImage(InputBuffer));
+ if (!obj)
+ report_fatal_error("Unable to create object image from memory buffer!");
+
+ // Save information about our target
+ Arch = (Triple::ArchType)obj->getArch();
+ IsTargetLittleEndian = obj->getObjectFile()->isLittleEndian();
+
+ // Symbols found in this object
+ StringMap<SymbolLoc> LocalSymbols;
+ // Used sections from the object file
+ ObjSectionToIDMap LocalSections;
+
+ // Common symbols requiring allocation, with their sizes and alignments
+ CommonSymbolMap CommonSymbols;
+ // Maximum required total memory to allocate all common symbols
+ uint64_t CommonSize = 0;
+
+ error_code err;
+ // Parse symbols
+ DEBUG(dbgs() << "Parse symbols:\n");
+ for (symbol_iterator i = obj->begin_symbols(), e = obj->end_symbols();
+ i != e; i.increment(err)) {
+ Check(err);
+ object::SymbolRef::Type SymType;
+ StringRef Name;
+ Check(i->getType(SymType));
+ Check(i->getName(Name));
+
+ uint32_t flags;
+ Check(i->getFlags(flags));
+
+ bool isCommon = flags & SymbolRef::SF_Common;
+ if (isCommon) {
+ // Add the common symbols to a list. We'll allocate them all below.
+ uint32_t Align;
+ Check(i->getAlignment(Align));
+ uint64_t Size = 0;
+ Check(i->getSize(Size));
+ CommonSize += Size + Align;
+ CommonSymbols[*i] = CommonSymbolInfo(Size, Align);
+ } else {
+ if (SymType == object::SymbolRef::ST_Function ||
+ SymType == object::SymbolRef::ST_Data ||
+ SymType == object::SymbolRef::ST_Unknown) {
+ uint64_t FileOffset;
+ StringRef SectionData;
+ bool IsCode;
+ section_iterator si = obj->end_sections();
+ Check(i->getFileOffset(FileOffset));
+ Check(i->getSection(si));
+ if (si == obj->end_sections()) continue;
+ Check(si->getContents(SectionData));
+ Check(si->isText(IsCode));
+ const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() +
+ (uintptr_t)FileOffset;
+ uintptr_t SectOffset = (uintptr_t)(SymPtr -
+ (const uint8_t*)SectionData.begin());
+ unsigned SectionID = findOrEmitSection(*obj, *si, IsCode, LocalSections);
+ LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset);
+ DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset)
+ << " flags: " << flags
+ << " SID: " << SectionID
+ << " Offset: " << format("%p", SectOffset));
+ GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset);
+ }
+ }
+ DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n");
+ }
+
+ // Allocate common symbols
+ if (CommonSize != 0)
+ emitCommonSymbols(*obj, CommonSymbols, CommonSize, LocalSymbols);
+
+ // Parse and process relocations
+ DEBUG(dbgs() << "Parse relocations:\n");
+ for (section_iterator si = obj->begin_sections(),
+ se = obj->end_sections(); si != se; si.increment(err)) {
+ Check(err);
+ bool isFirstRelocation = true;
+ unsigned SectionID = 0;
+ StubMap Stubs;
+ section_iterator RelocatedSection = si->getRelocatedSection();
+
+ for (relocation_iterator i = si->begin_relocations(),
+ e = si->end_relocations(); i != e; i.increment(err)) {
+ Check(err);
+
+ // If it's the first relocation in this section, find its SectionID
+ if (isFirstRelocation) {
+ SectionID =
+ findOrEmitSection(*obj, *RelocatedSection, true, LocalSections);
+ DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
+ isFirstRelocation = false;
+ }
+
+ processRelocationRef(SectionID, *i, *obj, LocalSections, LocalSymbols,
+ Stubs);
+ }
+ }
+
+ // Give the subclasses a chance to tie-up any loose ends.
+ finalizeLoad(LocalSections);
+
+ return obj.take();
+}
+
+void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj,
+ const CommonSymbolMap &CommonSymbols,
+ uint64_t TotalSize,
+ SymbolTableMap &SymbolTable) {
+ // Allocate memory for the section
+ unsigned SectionID = Sections.size();
+ uint8_t *Addr = MemMgr->allocateDataSection(
+ TotalSize, sizeof(void*), SectionID, StringRef(), false);
+ if (!Addr)
+ report_fatal_error("Unable to allocate memory for common symbols!");
+ uint64_t Offset = 0;
+ Sections.push_back(SectionEntry(StringRef(), Addr, TotalSize, 0));
+ memset(Addr, 0, TotalSize);
+
+ DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID
+ << " new addr: " << format("%p", Addr)
+ << " DataSize: " << TotalSize
+ << "\n");
+
+ // Assign the address of each symbol
+ for (CommonSymbolMap::const_iterator it = CommonSymbols.begin(),
+ itEnd = CommonSymbols.end(); it != itEnd; it++) {
+ uint64_t Size = it->second.first;
+ uint64_t Align = it->second.second;
+ StringRef Name;
+ it->first.getName(Name);
+ if (Align) {
+ // This symbol has an alignment requirement.
+ uint64_t AlignOffset = OffsetToAlignment((uint64_t)Addr, Align);
+ Addr += AlignOffset;
+ Offset += AlignOffset;
+ DEBUG(dbgs() << "Allocating common symbol " << Name << " address " <<
+ format("%p\n", Addr));
+ }
+ Obj.updateSymbolAddress(it->first, (uint64_t)Addr);
+ SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset);
+ Offset += Size;
+ Addr += Size;
+ }
+}
+
+unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
+ const SectionRef &Section,
+ bool IsCode) {
+
+ unsigned StubBufSize = 0,
+ StubSize = getMaxStubSize();
+ error_code err;
+ const ObjectFile *ObjFile = Obj.getObjectFile();
+ // FIXME: this is an inefficient way to handle this. We should computed the
+ // necessary section allocation size in loadObject by walking all the sections
+ // once.
+ if (StubSize > 0) {
+ for (section_iterator SI = ObjFile->begin_sections(),
+ SE = ObjFile->end_sections();
+ SI != SE; SI.increment(err), Check(err)) {
+ section_iterator RelSecI = SI->getRelocatedSection();
+ if (!(RelSecI == Section))
+ continue;
+
+ for (relocation_iterator I = SI->begin_relocations(),
+ E = SI->end_relocations(); I != E; I.increment(err), Check(err)) {
+ StubBufSize += StubSize;
+ }
+ }
+ }
+
+ StringRef data;
+ uint64_t Alignment64;
+ Check(Section.getContents(data));
+ Check(Section.getAlignment(Alignment64));
+
+ unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
+ bool IsRequired;
+ bool IsVirtual;
+ bool IsZeroInit;
+ bool IsReadOnly;
+ uint64_t DataSize;
+ unsigned PaddingSize = 0;
+ StringRef Name;
+ Check(Section.isRequiredForExecution(IsRequired));
+ Check(Section.isVirtual(IsVirtual));
+ Check(Section.isZeroInit(IsZeroInit));
+ Check(Section.isReadOnlyData(IsReadOnly));
+ Check(Section.getSize(DataSize));
+ Check(Section.getName(Name));
+ if (StubSize > 0) {
+ unsigned StubAlignment = getStubAlignment();
+ unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment);
+ if (StubAlignment > EndAlignment)
+ StubBufSize += StubAlignment - EndAlignment;
+ }
+
+ // The .eh_frame section (at least on Linux) needs an extra four bytes padded
+ // with zeroes added at the end. For MachO objects, this section has a
+ // slightly different name, so this won't have any effect for MachO objects.
+ if (Name == ".eh_frame")
+ PaddingSize = 4;
+
+ unsigned Allocate;
+ unsigned SectionID = Sections.size();
+ uint8_t *Addr;
+ const char *pData = 0;
+
+ // Some sections, such as debug info, don't need to be loaded for execution.
+ // Leave those where they are.
+ if (IsRequired) {
+ Allocate = DataSize + PaddingSize + StubBufSize;
+ Addr = IsCode
+ ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID, Name)
+ : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, Name,
+ IsReadOnly);
+ if (!Addr)
+ report_fatal_error("Unable to allocate section memory!");
+
+ // Virtual sections have no data in the object image, so leave pData = 0
+ if (!IsVirtual)
+ pData = data.data();
+
+ // Zero-initialize or copy the data from the image
+ if (IsZeroInit || IsVirtual)
+ memset(Addr, 0, DataSize);
+ else
+ memcpy(Addr, pData, DataSize);
+
+ // Fill in any extra bytes we allocated for padding
+ if (PaddingSize != 0) {
+ memset(Addr + DataSize, 0, PaddingSize);
+ // Update the DataSize variable so that the stub offset is set correctly.
+ DataSize += PaddingSize;
+ }
+
+ DEBUG(dbgs() << "emitSection SectionID: " << SectionID
+ << " Name: " << Name
+ << " obj addr: " << format("%p", pData)
+ << " new addr: " << format("%p", Addr)
+ << " DataSize: " << DataSize
+ << " StubBufSize: " << StubBufSize
+ << " Allocate: " << Allocate
+ << "\n");
+ Obj.updateSectionAddress(Section, (uint64_t)Addr);
+ }
+ else {
+ // Even if we didn't load the section, we need to record an entry for it
+ // to handle later processing (and by 'handle' I mean don't do anything
+ // with these sections).
+ Allocate = 0;
+ Addr = 0;
+ DEBUG(dbgs() << "emitSection SectionID: " << SectionID
+ << " Name: " << Name
+ << " obj addr: " << format("%p", data.data())
+ << " new addr: 0"
+ << " DataSize: " << DataSize
+ << " StubBufSize: " << StubBufSize
+ << " Allocate: " << Allocate
+ << "\n");
+ }
+
+ Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData));
+ return SectionID;
+}
+
+unsigned RuntimeDyldImpl::findOrEmitSection(ObjectImage &Obj,
+ const SectionRef &Section,
+ bool IsCode,
+ ObjSectionToIDMap &LocalSections) {
+
+ unsigned SectionID = 0;
+ ObjSectionToIDMap::iterator i = LocalSections.find(Section);
+ if (i != LocalSections.end())
+ SectionID = i->second;
+ else {
+ SectionID = emitSection(Obj, Section, IsCode);
+ LocalSections[Section] = SectionID;
+ }
+ return SectionID;
+}
+
+void RuntimeDyldImpl::addRelocationForSection(const RelocationEntry &RE,
+ unsigned SectionID) {
+ Relocations[SectionID].push_back(RE);
+}
+
+void RuntimeDyldImpl::addRelocationForSymbol(const RelocationEntry &RE,
+ StringRef SymbolName) {
+ // Relocation by symbol. If the symbol is found in the global symbol table,
+ // create an appropriate section relocation. Otherwise, add it to
+ // ExternalSymbolRelocations.
+ SymbolTableMap::const_iterator Loc =
+ GlobalSymbolTable.find(SymbolName);
+ if (Loc == GlobalSymbolTable.end()) {
+ ExternalSymbolRelocations[SymbolName].push_back(RE);
+ } else {
+ // Copy the RE since we want to modify its addend.
+ RelocationEntry RECopy = RE;
+ RECopy.Addend += Loc->second.second;
+ Relocations[Loc->second.first].push_back(RECopy);
+ }
+}
+
+uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) {
+ if (Arch == Triple::aarch64) {
+ // This stub has to be able to access the full address space,
+ // since symbol lookup won't necessarily find a handy, in-range,
+ // PLT stub for functions which could be anywhere.
+ uint32_t *StubAddr = (uint32_t*)Addr;
+
+ // Stub can use ip0 (== x16) to calculate address
+ *StubAddr = 0xd2e00010; // movz ip0, #:abs_g3:<addr>
+ StubAddr++;
+ *StubAddr = 0xf2c00010; // movk ip0, #:abs_g2_nc:<addr>
+ StubAddr++;
+ *StubAddr = 0xf2a00010; // movk ip0, #:abs_g1_nc:<addr>
+ StubAddr++;
+ *StubAddr = 0xf2800010; // movk ip0, #:abs_g0_nc:<addr>
+ StubAddr++;
+ *StubAddr = 0xd61f0200; // br ip0
+
+ return Addr;
+ } else if (Arch == Triple::arm) {
+ // TODO: There is only ARM far stub now. We should add the Thumb stub,
+ // and stubs for branches Thumb - ARM and ARM - Thumb.
+ uint32_t *StubAddr = (uint32_t*)Addr;
+ *StubAddr = 0xe51ff004; // ldr pc,<label>
+ return (uint8_t*)++StubAddr;
+ } else if (Arch == Triple::mipsel || Arch == Triple::mips) {
+ uint32_t *StubAddr = (uint32_t*)Addr;
+ // 0: 3c190000 lui t9,%hi(addr).
+ // 4: 27390000 addiu t9,t9,%lo(addr).
+ // 8: 03200008 jr t9.
+ // c: 00000000 nop.
+ const unsigned LuiT9Instr = 0x3c190000, AdduiT9Instr = 0x27390000;
+ const unsigned JrT9Instr = 0x03200008, NopInstr = 0x0;
+
+ *StubAddr = LuiT9Instr;
+ StubAddr++;
+ *StubAddr = AdduiT9Instr;
+ StubAddr++;
+ *StubAddr = JrT9Instr;
+ StubAddr++;
+ *StubAddr = NopInstr;
+ return Addr;
+ } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
+ // PowerPC64 stub: the address points to a function descriptor
+ // instead of the function itself. Load the function address
+ // on r11 and sets it to control register. Also loads the function
+ // TOC in r2 and environment pointer to r11.
+ writeInt32BE(Addr, 0x3D800000); // lis r12, highest(addr)
+ writeInt32BE(Addr+4, 0x618C0000); // ori r12, higher(addr)
+ writeInt32BE(Addr+8, 0x798C07C6); // sldi r12, r12, 32
+ writeInt32BE(Addr+12, 0x658C0000); // oris r12, r12, h(addr)
+ writeInt32BE(Addr+16, 0x618C0000); // ori r12, r12, l(addr)
+ writeInt32BE(Addr+20, 0xF8410028); // std r2, 40(r1)
+ writeInt32BE(Addr+24, 0xE96C0000); // ld r11, 0(r12)
+ writeInt32BE(Addr+28, 0xE84C0008); // ld r2, 0(r12)
+ writeInt32BE(Addr+32, 0x7D6903A6); // mtctr r11
+ writeInt32BE(Addr+36, 0xE96C0010); // ld r11, 16(r2)
+ writeInt32BE(Addr+40, 0x4E800420); // bctr
+
+ return Addr;
+ } else if (Arch == Triple::systemz) {
+ writeInt16BE(Addr, 0xC418); // lgrl %r1,.+8
+ writeInt16BE(Addr+2, 0x0000);
+ writeInt16BE(Addr+4, 0x0004);
+ writeInt16BE(Addr+6, 0x07F1); // brc 15,%r1
+ // 8-byte address stored at Addr + 8
+ return Addr;
+ } else if (Arch == Triple::x86_64) {
+ *Addr = 0xFF; // jmp
+ *(Addr+1) = 0x25; // rip
+ // 32-bit PC-relative address of the GOT entry will be stored at Addr+2
+ }
+ return Addr;
+}
+
+// Assign an address to a symbol name and resolve all the relocations
+// associated with it.
+void RuntimeDyldImpl::reassignSectionAddress(unsigned SectionID,
+ uint64_t Addr) {
+ // The address to use for relocation resolution is not
+ // the address of the local section buffer. We must be doing
+ // a remote execution environment of some sort. Relocations can't
+ // be applied until all the sections have been moved. The client must
+ // trigger this with a call to MCJIT::finalize() or
+ // RuntimeDyld::resolveRelocations().
+ //
+ // Addr is a uint64_t because we can't assume the pointer width
+ // of the target is the same as that of the host. Just use a generic
+ // "big enough" type.
+ Sections[SectionID].LoadAddress = Addr;
+}
+
+void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs,
+ uint64_t Value) {
+ for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
+ const RelocationEntry &RE = Relocs[i];
+ // Ignore relocations for sections that were not loaded
+ if (Sections[RE.SectionID].Address == 0)
+ continue;
+ resolveRelocation(RE, Value);
+ }
+}
+
+void RuntimeDyldImpl::resolveExternalSymbols() {
+ while(!ExternalSymbolRelocations.empty()) {
+ StringMap<RelocationList>::iterator i = ExternalSymbolRelocations.begin();
+
+ StringRef Name = i->first();
+ if (Name.size() == 0) {
+ // This is an absolute symbol, use an address of zero.
+ DEBUG(dbgs() << "Resolving absolute relocations." << "\n");
+ RelocationList &Relocs = i->second;
+ resolveRelocationList(Relocs, 0);
+ } else {
+ uint64_t Addr = 0;
+ SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(Name);
+ if (Loc == GlobalSymbolTable.end()) {
+ // This is an external symbol, try to get its address from
+ // MemoryManager.
+ Addr = MemMgr->getSymbolAddress(Name.data());
+ // The call to getSymbolAddress may have caused additional modules to
+ // be loaded, which may have added new entries to the
+ // ExternalSymbolRelocations map. Consquently, we need to update our
+ // iterator. This is also why retrieval of the relocation list
+ // associated with this symbol is deferred until below this point.
+ // New entries may have been added to the relocation list.
+ i = ExternalSymbolRelocations.find(Name);
+ } else {
+ // We found the symbol in our global table. It was probably in a
+ // Module that we loaded previously.
+ SymbolLoc SymLoc = Loc->second;
+ Addr = getSectionLoadAddress(SymLoc.first) + SymLoc.second;
+ }
+
+ // FIXME: Implement error handling that doesn't kill the host program!
+ if (!Addr)
+ report_fatal_error("Program used external function '" + Name +
+ "' which could not be resolved!");
+
+ updateGOTEntries(Name, Addr);
+ DEBUG(dbgs() << "Resolving relocations Name: " << Name
+ << "\t" << format("0x%lx", Addr)
+ << "\n");
+ // This list may have been updated when we called getSymbolAddress, so
+ // don't change this code to get the list earlier.
+ RelocationList &Relocs = i->second;
+ resolveRelocationList(Relocs, Addr);
+ }
+
+ ExternalSymbolRelocations.erase(i);
+ }
+}
+
+
+//===----------------------------------------------------------------------===//
+// RuntimeDyld class implementation
+RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) {
+ // FIXME: There's a potential issue lurking here if a single instance of
+ // RuntimeDyld is used to load multiple objects. The current implementation
+ // associates a single memory manager with a RuntimeDyld instance. Even
+ // though the public class spawns a new 'impl' instance for each load,
+ // they share a single memory manager. This can become a problem when page
+ // permissions are applied.
+ Dyld = 0;
+ MM = mm;
+}
+
+RuntimeDyld::~RuntimeDyld() {
+ delete Dyld;
+}
+
+ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) {
+ if (!Dyld) {
+ sys::fs::file_magic Type =
+ sys::fs::identify_magic(InputBuffer->getBuffer());
+ switch (Type) {
+ case sys::fs::file_magic::elf_relocatable:
+ case sys::fs::file_magic::elf_executable:
+ case sys::fs::file_magic::elf_shared_object:
+ case sys::fs::file_magic::elf_core:
+ Dyld = new RuntimeDyldELF(MM);
+ break;
+ case sys::fs::file_magic::macho_object:
+ case sys::fs::file_magic::macho_executable:
+ case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib:
+ case sys::fs::file_magic::macho_core:
+ case sys::fs::file_magic::macho_preload_executable:
+ case sys::fs::file_magic::macho_dynamically_linked_shared_lib:
+ case sys::fs::file_magic::macho_dynamic_linker:
+ case sys::fs::file_magic::macho_bundle:
+ case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub:
+ case sys::fs::file_magic::macho_dsym_companion:
+ Dyld = new RuntimeDyldMachO(MM);
+ break;
+ case sys::fs::file_magic::unknown:
+ case sys::fs::file_magic::bitcode:
+ case sys::fs::file_magic::archive:
+ case sys::fs::file_magic::coff_object:
+ case sys::fs::file_magic::coff_import_library:
+ case sys::fs::file_magic::pecoff_executable:
+ case sys::fs::file_magic::macho_universal_binary:
+ case sys::fs::file_magic::windows_resource:
+ report_fatal_error("Incompatible object format!");
+ }
+ } else {
+ if (!Dyld->isCompatibleFormat(InputBuffer))
+ report_fatal_error("Incompatible object format!");
+ }
+
+ return Dyld->loadObject(InputBuffer);
+}
+
+void *RuntimeDyld::getSymbolAddress(StringRef Name) {
+ if (!Dyld)
+ return NULL;
+ return Dyld->getSymbolAddress(Name);
+}
+
+uint64_t RuntimeDyld::getSymbolLoadAddress(StringRef Name) {
+ if (!Dyld)
+ return 0;
+ return Dyld->getSymbolLoadAddress(Name);
+}
+
+void RuntimeDyld::resolveRelocations() {
+ Dyld->resolveRelocations();
+}
+
+void RuntimeDyld::reassignSectionAddress(unsigned SectionID,
+ uint64_t Addr) {
+ Dyld->reassignSectionAddress(SectionID, Addr);
+}
+
+void RuntimeDyld::mapSectionAddress(const void *LocalAddress,
+ uint64_t TargetAddress) {
+ Dyld->mapSectionAddress(LocalAddress, TargetAddress);
+}
+
+StringRef RuntimeDyld::getErrorString() {
+ return Dyld->getErrorString();
+}
+
+void RuntimeDyld::registerEHFrames() {
+ if (Dyld)
+ Dyld->registerEHFrames();
+}
+
+void RuntimeDyld::deregisterEHFrames() {
+ if (Dyld)
+ Dyld->deregisterEHFrames();
+}
+
+} // end namespace llvm
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
new file mode 100644
index 000000000000..f2c69fc99cec
--- /dev/null
+++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -0,0 +1,1406 @@
+//===-- RuntimeDyldELF.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of ELF support for the MC-JIT runtime dynamic linker.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "dyld"
+#include "RuntimeDyldELF.h"
+#include "JITRegistrar.h"
+#include "ObjectImageCommon.h"
+#include "llvm/ADT/IntervalMap.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.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"
+using namespace llvm;
+using namespace llvm::object;
+
+namespace {
+
+static inline
+error_code check(error_code Err) {
+ if (Err) {
+ report_fatal_error(Err.message());
+ }
+ return Err;
+}
+
+template<class ELFT>
+class DyldELFObject
+ : public ELFObjectFile<ELFT> {
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
+
+ typedef Elf_Shdr_Impl<ELFT> Elf_Shdr;
+ typedef Elf_Sym_Impl<ELFT> Elf_Sym;
+ typedef
+ Elf_Rel_Impl<ELFT, false> Elf_Rel;
+ typedef
+ Elf_Rel_Impl<ELFT, true> Elf_Rela;
+
+ typedef Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
+
+ typedef typename ELFDataTypeTypedefHelper<
+ ELFT>::value_type addr_type;
+
+public:
+ DyldELFObject(MemoryBuffer *Wrapper, error_code &ec);
+
+ void updateSectionAddress(const SectionRef &Sec, 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) {
+ return (isa<ELFObjectFile<ELFT> >(v)
+ && classof(cast<ELFObjectFile
+ <ELFT> >(v)));
+ }
+ static inline bool classof(
+ const ELFObjectFile<ELFT> *v) {
+ return v->isDyldType();
+ }
+};
+
+template<class ELFT>
+class ELFObjectImage : public ObjectImageCommon {
+ protected:
+ DyldELFObject<ELFT> *DyldObj;
+ bool Registered;
+
+ public:
+ ELFObjectImage(ObjectBuffer *Input,
+ DyldELFObject<ELFT> *Obj)
+ : ObjectImageCommon(Input, Obj),
+ DyldObj(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
+ virtual void updateSectionAddress(const SectionRef &Sec, uint64_t Addr)
+ {
+ DyldObj->updateSectionAddress(Sec, Addr);
+ }
+
+ virtual void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr)
+ {
+ DyldObj->updateSymbolAddress(Sym, Addr);
+ }
+
+ virtual void registerWithDebugger()
+ {
+ JITRegistrar::getGDBRegistrar().registerObject(*Buffer);
+ Registered = true;
+ }
+ virtual void deregisterWithDebugger()
+ {
+ 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
+// this MemoryBuffer object but not the underlying memory.
+template<class ELFT>
+DyldELFObject<ELFT>::DyldELFObject(MemoryBuffer *Wrapper, error_code &ec)
+ : ELFObjectFile<ELFT>(Wrapper, ec) {
+ this->isDyldELFObject = true;
+}
+
+template<class ELFT>
+void DyldELFObject<ELFT>::updateSectionAddress(const SectionRef &Sec,
+ uint64_t Addr) {
+ DataRefImpl ShdrRef = Sec.getRawDataRefImpl();
+ Elf_Shdr *shdr = const_cast<Elf_Shdr*>(
+ reinterpret_cast<const Elf_Shdr *>(ShdrRef.p));
+
+ // This assumes the address passed in matches the target address bitness
+ // The template-based type cast handles everything else.
+ shdr->sh_addr = static_cast<addr_type>(Addr);
+}
+
+template<class ELFT>
+void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef,
+ uint64_t Addr) {
+
+ Elf_Sym *sym = const_cast<Elf_Sym*>(
+ ELFObjectFile<ELFT>::getSymbol(SymRef.getRawDataRefImpl()));
+
+ // This assumes the address passed in matches the target address bitness
+ // The template-based type cast handles everything else.
+ sym->st_value = static_cast<addr_type>(Addr);
+}
+
+} // namespace
+
+namespace llvm {
+
+void RuntimeDyldELF::registerEHFrames() {
+ if (!MemMgr)
+ return;
+ for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) {
+ SID EHFrameSID = UnregisteredEHFrameSections[i];
+ uint8_t *EHFrameAddr = Sections[EHFrameSID].Address;
+ uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress;
+ size_t EHFrameSize = Sections[EHFrameSID].Size;
+ MemMgr->registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize);
+ RegisteredEHFrameSections.push_back(EHFrameSID);
+ }
+ UnregisteredEHFrameSections.clear();
+}
+
+void RuntimeDyldELF::deregisterEHFrames() {
+ if (!MemMgr)
+ return;
+ for (int i = 0, e = RegisteredEHFrameSections.size(); i != e; ++i) {
+ SID EHFrameSID = RegisteredEHFrameSections[i];
+ uint8_t *EHFrameAddr = Sections[EHFrameSID].Address;
+ uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress;
+ size_t EHFrameSize = Sections[EHFrameSID].Size;
+ MemMgr->deregisterEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize);
+ }
+ RegisteredEHFrameSections.clear();
+}
+
+ObjectImage *RuntimeDyldELF::createObjectImage(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]);
+ error_code ec;
+
+ if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) {
+ DyldELFObject<ELFType<support::little, 4, false> > *Obj =
+ new DyldELFObject<ELFType<support::little, 4, false> >(
+ Buffer->getMemBuffer(), ec);
+ return new ELFObjectImage<ELFType<support::little, 4, false> >(Buffer, Obj);
+ }
+ else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) {
+ DyldELFObject<ELFType<support::big, 4, false> > *Obj =
+ new DyldELFObject<ELFType<support::big, 4, false> >(
+ Buffer->getMemBuffer(), ec);
+ return new ELFObjectImage<ELFType<support::big, 4, false> >(Buffer, Obj);
+ }
+ else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) {
+ DyldELFObject<ELFType<support::big, 8, true> > *Obj =
+ new DyldELFObject<ELFType<support::big, 8, true> >(
+ Buffer->getMemBuffer(), ec);
+ return new ELFObjectImage<ELFType<support::big, 8, true> >(Buffer, Obj);
+ }
+ else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) {
+ DyldELFObject<ELFType<support::little, 8, true> > *Obj =
+ new DyldELFObject<ELFType<support::little, 8, true> >(
+ Buffer->getMemBuffer(), ec);
+ return new ELFObjectImage<ELFType<support::little, 8, true> >(Buffer, Obj);
+ }
+ else
+ llvm_unreachable("Unexpected ELF format");
+}
+
+RuntimeDyldELF::~RuntimeDyldELF() {
+}
+
+void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend,
+ uint64_t SymOffset) {
+ switch (Type) {
+ default:
+ llvm_unreachable("Relocation type not implemented yet!");
+ break;
+ case ELF::R_X86_64_64: {
+ uint64_t *Target = reinterpret_cast<uint64_t*>(Section.Address + Offset);
+ *Target = Value + Addend;
+ DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend))
+ << " at " << format("%p\n",Target));
+ break;
+ }
+ case ELF::R_X86_64_32:
+ case ELF::R_X86_64_32S: {
+ Value += Addend;
+ assert((Type == ELF::R_X86_64_32 && (Value <= UINT32_MAX)) ||
+ (Type == ELF::R_X86_64_32S &&
+ ((int64_t)Value <= INT32_MAX && (int64_t)Value >= INT32_MIN)));
+ uint32_t TruncatedAddr = (Value & 0xFFFFFFFF);
+ uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset);
+ *Target = TruncatedAddr;
+ DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr)
+ << " at " << format("%p\n",Target));
+ break;
+ }
+ case ELF::R_X86_64_GOTPCREL: {
+ // findGOTEntry returns the 'G + GOT' part of the relocation calculation
+ // based on the load/target address of the GOT (not the current/local addr).
+ uint64_t GOTAddr = findGOTEntry(Value, SymOffset);
+ uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset);
+ uint64_t FinalAddress = Section.LoadAddress + Offset;
+ // The processRelocationRef method combines the symbol offset and the addend
+ // and in most cases that's what we want. For this relocation type, we need
+ // the raw addend, so we subtract the symbol offset to get it.
+ int64_t RealOffset = GOTAddr + Addend - SymOffset - FinalAddress;
+ assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN);
+ int32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
+ *Target = TruncOffset;
+ break;
+ }
+ case ELF::R_X86_64_PC32: {
+ // Get the placeholder value from the generated object since
+ // a previous relocation attempt may have overwritten the loaded version
+ uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress
+ + Offset);
+ uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset);
+ uint64_t FinalAddress = Section.LoadAddress + Offset;
+ int64_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
+ assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN);
+ int32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
+ *Target = TruncOffset;
+ break;
+ }
+ case ELF::R_X86_64_PC64: {
+ // Get the placeholder value from the generated object since
+ // a previous relocation attempt may have overwritten the loaded version
+ uint64_t *Placeholder = reinterpret_cast<uint64_t*>(Section.ObjAddress
+ + Offset);
+ uint64_t *Target = reinterpret_cast<uint64_t*>(Section.Address + Offset);
+ uint64_t FinalAddress = Section.LoadAddress + Offset;
+ *Target = *Placeholder + Value + Addend - FinalAddress;
+ break;
+ }
+ }
+}
+
+void RuntimeDyldELF::resolveX86Relocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint32_t Value,
+ uint32_t Type,
+ int32_t Addend) {
+ switch (Type) {
+ case ELF::R_386_32: {
+ // Get the placeholder value from the generated object since
+ // a previous relocation attempt may have overwritten the loaded version
+ uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress
+ + Offset);
+ uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset);
+ *Target = *Placeholder + Value + Addend;
+ break;
+ }
+ case ELF::R_386_PC32: {
+ // Get the placeholder value from the generated object since
+ // a previous relocation attempt may have overwritten the loaded version
+ uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress
+ + Offset);
+ uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset);
+ uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF);
+ uint32_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
+ *Target = RealOffset;
+ break;
+ }
+ default:
+ // There are other relocation types, but it appears these are the
+ // only ones currently used by the LLVM ELF object writer
+ llvm_unreachable("Relocation type not implemented yet!");
+ break;
+ }
+}
+
+void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend) {
+ uint32_t *TargetPtr = reinterpret_cast<uint32_t*>(Section.Address + Offset);
+ uint64_t FinalAddress = Section.LoadAddress + Offset;
+
+ DEBUG(dbgs() << "resolveAArch64Relocation, LocalAddress: 0x"
+ << format("%llx", Section.Address + Offset)
+ << " FinalAddress: 0x" << format("%llx",FinalAddress)
+ << " Value: 0x" << format("%llx",Value)
+ << " Type: 0x" << format("%x",Type)
+ << " Addend: 0x" << format("%llx",Addend)
+ << "\n");
+
+ switch (Type) {
+ default:
+ llvm_unreachable("Relocation type not implemented yet!");
+ break;
+ case ELF::R_AARCH64_ABS64: {
+ uint64_t *TargetPtr = reinterpret_cast<uint64_t*>(Section.Address + Offset);
+ *TargetPtr = Value + Addend;
+ break;
+ }
+ case ELF::R_AARCH64_PREL32: {
+ uint64_t Result = Value + Addend - FinalAddress;
+ assert(static_cast<int64_t>(Result) >= INT32_MIN &&
+ static_cast<int64_t>(Result) <= UINT32_MAX);
+ *TargetPtr = static_cast<uint32_t>(Result & 0xffffffffU);
+ break;
+ }
+ case ELF::R_AARCH64_CALL26: // fallthrough
+ case ELF::R_AARCH64_JUMP26: {
+ // Operation: S+A-P. Set Call or B immediate value to bits fff_fffc of the
+ // calculation.
+ uint64_t BranchImm = Value + Addend - FinalAddress;
+
+ // "Check that -2^27 <= result < 2^27".
+ assert(-(1LL << 27) <= static_cast<int64_t>(BranchImm) &&
+ static_cast<int64_t>(BranchImm) < (1LL << 27));
+
+ // AArch64 code is emitted with .rela relocations. The data already in any
+ // bits affected by the relocation on entry is garbage.
+ *TargetPtr &= 0xfc000000U;
+ // Immediate goes in bits 25:0 of B and BL.
+ *TargetPtr |= static_cast<uint32_t>(BranchImm & 0xffffffcU) >> 2;
+ break;
+ }
+ case ELF::R_AARCH64_MOVW_UABS_G3: {
+ uint64_t Result = Value + Addend;
+
+ // AArch64 code is emitted with .rela relocations. The data already in any
+ // bits affected by the relocation on entry is garbage.
+ *TargetPtr &= 0xffe0001fU;
+ // Immediate goes in bits 20:5 of MOVZ/MOVK instruction
+ *TargetPtr |= Result >> (48 - 5);
+ // Shift must be "lsl #48", in bits 22:21
+ assert((*TargetPtr >> 21 & 0x3) == 3 && "invalid shift for relocation");
+ break;
+ }
+ case ELF::R_AARCH64_MOVW_UABS_G2_NC: {
+ uint64_t Result = Value + Addend;
+
+ // AArch64 code is emitted with .rela relocations. The data already in any
+ // bits affected by the relocation on entry is garbage.
+ *TargetPtr &= 0xffe0001fU;
+ // Immediate goes in bits 20:5 of MOVZ/MOVK instruction
+ *TargetPtr |= ((Result & 0xffff00000000ULL) >> (32 - 5));
+ // Shift must be "lsl #32", in bits 22:21
+ assert((*TargetPtr >> 21 & 0x3) == 2 && "invalid shift for relocation");
+ break;
+ }
+ case ELF::R_AARCH64_MOVW_UABS_G1_NC: {
+ uint64_t Result = Value + Addend;
+
+ // AArch64 code is emitted with .rela relocations. The data already in any
+ // bits affected by the relocation on entry is garbage.
+ *TargetPtr &= 0xffe0001fU;
+ // Immediate goes in bits 20:5 of MOVZ/MOVK instruction
+ *TargetPtr |= ((Result & 0xffff0000U) >> (16 - 5));
+ // Shift must be "lsl #16", in bits 22:2
+ assert((*TargetPtr >> 21 & 0x3) == 1 && "invalid shift for relocation");
+ break;
+ }
+ case ELF::R_AARCH64_MOVW_UABS_G0_NC: {
+ uint64_t Result = Value + Addend;
+
+ // AArch64 code is emitted with .rela relocations. The data already in any
+ // bits affected by the relocation on entry is garbage.
+ *TargetPtr &= 0xffe0001fU;
+ // Immediate goes in bits 20:5 of MOVZ/MOVK instruction
+ *TargetPtr |= ((Result & 0xffffU) << 5);
+ // Shift must be "lsl #0", in bits 22:21.
+ assert((*TargetPtr >> 21 & 0x3) == 0 && "invalid shift for relocation");
+ break;
+ }
+ }
+}
+
+void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint32_t Value,
+ uint32_t Type,
+ int32_t Addend) {
+ // TODO: Add Thumb relocations.
+ uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress +
+ Offset);
+ uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset);
+ uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF);
+ Value += Addend;
+
+ DEBUG(dbgs() << "resolveARMRelocation, LocalAddress: "
+ << Section.Address + Offset
+ << " FinalAddress: " << format("%p",FinalAddress)
+ << " Value: " << format("%x",Value)
+ << " Type: " << format("%x",Type)
+ << " Addend: " << format("%x",Addend)
+ << "\n");
+
+ switch(Type) {
+ default:
+ llvm_unreachable("Not implemented relocation type!");
+
+ // Write a 32bit value to relocation address, taking into account the
+ // implicit addend encoded in the target.
+ case ELF::R_ARM_TARGET1:
+ case ELF::R_ARM_ABS32:
+ *TargetPtr = *Placeholder + Value;
+ break;
+ // Write first 16 bit of 32 bit value to the mov instruction.
+ // Last 4 bit should be shifted.
+ case ELF::R_ARM_MOVW_ABS_NC:
+ // We are not expecting any other addend in the relocation address.
+ // Using 0x000F0FFF because MOVW has its 16 bit immediate split into 2
+ // non-contiguous fields.
+ assert((*Placeholder & 0x000F0FFF) == 0);
+ Value = Value & 0xFFFF;
+ *TargetPtr = *Placeholder | (Value & 0xFFF);
+ *TargetPtr |= ((Value >> 12) & 0xF) << 16;
+ break;
+ // Write last 16 bit of 32 bit value to the mov instruction.
+ // Last 4 bit should be shifted.
+ case ELF::R_ARM_MOVT_ABS:
+ // We are not expecting any other addend in the relocation address.
+ // Use 0x000F0FFF for the same reason as R_ARM_MOVW_ABS_NC.
+ assert((*Placeholder & 0x000F0FFF) == 0);
+
+ Value = (Value >> 16) & 0xFFFF;
+ *TargetPtr = *Placeholder | (Value & 0xFFF);
+ *TargetPtr |= ((Value >> 12) & 0xF) << 16;
+ break;
+ // Write 24 bit relative value to the branch instruction.
+ case ELF::R_ARM_PC24 : // Fall through.
+ case ELF::R_ARM_CALL : // Fall through.
+ case ELF::R_ARM_JUMP24: {
+ int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8);
+ RelValue = (RelValue & 0x03FFFFFC) >> 2;
+ assert((*TargetPtr & 0xFFFFFF) == 0xFFFFFE);
+ *TargetPtr &= 0xFF000000;
+ *TargetPtr |= RelValue;
+ break;
+ }
+ case ELF::R_ARM_PRIVATE_0:
+ // This relocation is reserved by the ARM ELF ABI for internal use. We
+ // appropriate it here to act as an R_ARM_ABS32 without any addend for use
+ // in the stubs created during JIT (which can't put an addend into the
+ // original object file).
+ *TargetPtr = Value;
+ break;
+ }
+}
+
+void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint32_t Value,
+ uint32_t Type,
+ int32_t Addend) {
+ uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress +
+ Offset);
+ uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset);
+ Value += Addend;
+
+ DEBUG(dbgs() << "resolveMipselocation, LocalAddress: "
+ << Section.Address + Offset
+ << " FinalAddress: "
+ << format("%p",Section.LoadAddress + Offset)
+ << " Value: " << format("%x",Value)
+ << " Type: " << format("%x",Type)
+ << " Addend: " << format("%x",Addend)
+ << "\n");
+
+ switch(Type) {
+ default:
+ llvm_unreachable("Not implemented relocation type!");
+ break;
+ case ELF::R_MIPS_32:
+ *TargetPtr = Value + (*Placeholder);
+ break;
+ case ELF::R_MIPS_26:
+ *TargetPtr = ((*Placeholder) & 0xfc000000) | (( Value & 0x0fffffff) >> 2);
+ break;
+ case ELF::R_MIPS_HI16:
+ // Get the higher 16-bits. Also add 1 if bit 15 is 1.
+ Value += ((*Placeholder) & 0x0000ffff) << 16;
+ *TargetPtr = ((*Placeholder) & 0xffff0000) |
+ (((Value + 0x8000) >> 16) & 0xffff);
+ break;
+ case ELF::R_MIPS_LO16:
+ Value += ((*Placeholder) & 0x0000ffff);
+ *TargetPtr = ((*Placeholder) & 0xffff0000) | (Value & 0xffff);
+ break;
+ case ELF::R_MIPS_UNUSED1:
+ // Similar to ELF::R_ARM_PRIVATE_0, R_MIPS_UNUSED1 and R_MIPS_UNUSED2
+ // are used for internal JIT purpose. These relocations are similar to
+ // R_MIPS_HI16 and R_MIPS_LO16, but they do not take any addend into
+ // account.
+ *TargetPtr = ((*TargetPtr) & 0xffff0000) |
+ (((Value + 0x8000) >> 16) & 0xffff);
+ break;
+ case ELF::R_MIPS_UNUSED2:
+ *TargetPtr = ((*TargetPtr) & 0xffff0000) | (Value & 0xffff);
+ break;
+ }
+}
+
+// Return the .TOC. section address to R_PPC64_TOC relocations.
+uint64_t RuntimeDyldELF::findPPC64TOC() const {
+ // The TOC consists of sections .got, .toc, .tocbss, .plt in that
+ // order. The TOC starts where the first of these sections starts.
+ SectionList::const_iterator it = Sections.begin();
+ SectionList::const_iterator ite = Sections.end();
+ for (; it != ite; ++it) {
+ if (it->Name == ".got" ||
+ it->Name == ".toc" ||
+ it->Name == ".tocbss" ||
+ it->Name == ".plt")
+ break;
+ }
+ if (it == ite) {
+ // This may happen for
+ // * references to TOC base base (sym@toc, .odp relocation) without
+ // a .toc directive.
+ // In this case just use the first section (which is usually
+ // the .odp) since the code won't reference the .toc base
+ // directly.
+ it = Sections.begin();
+ }
+ assert (it != ite);
+ // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
+ // thus permitting a full 64 Kbytes segment.
+ return it->LoadAddress + 0x8000;
+}
+
+// Returns the sections and offset associated with the ODP entry referenced
+// by Symbol.
+void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj,
+ ObjSectionToIDMap &LocalSections,
+ RelocationValueRef &Rel) {
+ // Get the ELF symbol value (st_value) to compare with Relocation offset in
+ // .opd entries
+
+ error_code err;
+ for (section_iterator si = Obj.begin_sections(),
+ se = Obj.end_sections(); si != se; si.increment(err)) {
+ section_iterator RelSecI = si->getRelocatedSection();
+ if (RelSecI == Obj.end_sections())
+ continue;
+
+ StringRef RelSectionName;
+ check(RelSecI->getName(RelSectionName));
+ if (RelSectionName != ".opd")
+ continue;
+
+ for (relocation_iterator i = si->begin_relocations(),
+ e = si->end_relocations(); i != e;) {
+ check(err);
+
+ // The R_PPC64_ADDR64 relocation indicates the first field
+ // of a .opd entry
+ uint64_t TypeFunc;
+ check(i->getType(TypeFunc));
+ if (TypeFunc != ELF::R_PPC64_ADDR64) {
+ i.increment(err);
+ continue;
+ }
+
+ uint64_t TargetSymbolOffset;
+ symbol_iterator TargetSymbol = i->getSymbol();
+ check(i->getOffset(TargetSymbolOffset));
+ int64_t Addend;
+ check(getELFRelocationAddend(*i, Addend));
+
+ i = i.increment(err);
+ if (i == e)
+ break;
+ check(err);
+
+ // Just check if following relocation is a R_PPC64_TOC
+ uint64_t TypeTOC;
+ check(i->getType(TypeTOC));
+ if (TypeTOC != ELF::R_PPC64_TOC)
+ continue;
+
+ // Finally compares the Symbol value and the target symbol offset
+ // to check if this .opd entry refers to the symbol the relocation
+ // points to.
+ if (Rel.Addend != (int64_t)TargetSymbolOffset)
+ continue;
+
+ section_iterator tsi(Obj.end_sections());
+ check(TargetSymbol->getSection(tsi));
+ Rel.SectionID = findOrEmitSection(Obj, (*tsi), true, LocalSections);
+ Rel.Addend = (intptr_t)Addend;
+ return;
+ }
+ }
+ llvm_unreachable("Attempting to get address of ODP entry!");
+}
+
+// Relocation masks following the #lo(value), #hi(value), #higher(value),
+// and #highest(value) macros defined in section 4.5.1. Relocation Types
+// in PPC-elf64abi document.
+//
+static inline
+uint16_t applyPPClo (uint64_t value)
+{
+ return value & 0xffff;
+}
+
+static inline
+uint16_t applyPPChi (uint64_t value)
+{
+ return (value >> 16) & 0xffff;
+}
+
+static inline
+uint16_t applyPPChigher (uint64_t value)
+{
+ return (value >> 32) & 0xffff;
+}
+
+static inline
+uint16_t applyPPChighest (uint64_t value)
+{
+ return (value >> 48) & 0xffff;
+}
+
+void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend) {
+ uint8_t* LocalAddress = Section.Address + Offset;
+ switch (Type) {
+ default:
+ llvm_unreachable("Relocation type not implemented yet!");
+ break;
+ case ELF::R_PPC64_ADDR16_LO :
+ writeInt16BE(LocalAddress, applyPPClo (Value + Addend));
+ break;
+ case ELF::R_PPC64_ADDR16_HI :
+ writeInt16BE(LocalAddress, applyPPChi (Value + Addend));
+ break;
+ case ELF::R_PPC64_ADDR16_HIGHER :
+ writeInt16BE(LocalAddress, applyPPChigher (Value + Addend));
+ break;
+ case ELF::R_PPC64_ADDR16_HIGHEST :
+ writeInt16BE(LocalAddress, applyPPChighest (Value + Addend));
+ break;
+ case ELF::R_PPC64_ADDR14 : {
+ assert(((Value + Addend) & 3) == 0);
+ // Preserve the AA/LK bits in the branch instruction
+ uint8_t aalk = *(LocalAddress+3);
+ writeInt16BE(LocalAddress + 2, (aalk & 3) | ((Value + Addend) & 0xfffc));
+ } break;
+ case ELF::R_PPC64_ADDR32 : {
+ int32_t Result = static_cast<int32_t>(Value + Addend);
+ if (SignExtend32<32>(Result) != Result)
+ llvm_unreachable("Relocation R_PPC64_ADDR32 overflow");
+ writeInt32BE(LocalAddress, Result);
+ } break;
+ case ELF::R_PPC64_REL24 : {
+ uint64_t FinalAddress = (Section.LoadAddress + Offset);
+ int32_t delta = static_cast<int32_t>(Value - FinalAddress + Addend);
+ if (SignExtend32<24>(delta) != delta)
+ llvm_unreachable("Relocation R_PPC64_REL24 overflow");
+ // Generates a 'bl <address>' instruction
+ writeInt32BE(LocalAddress, 0x48000001 | (delta & 0x03FFFFFC));
+ } break;
+ case ELF::R_PPC64_REL32 : {
+ uint64_t FinalAddress = (Section.LoadAddress + Offset);
+ int32_t delta = static_cast<int32_t>(Value - FinalAddress + Addend);
+ if (SignExtend32<32>(delta) != delta)
+ llvm_unreachable("Relocation R_PPC64_REL32 overflow");
+ writeInt32BE(LocalAddress, delta);
+ } break;
+ case ELF::R_PPC64_REL64: {
+ uint64_t FinalAddress = (Section.LoadAddress + Offset);
+ uint64_t Delta = Value - FinalAddress + Addend;
+ writeInt64BE(LocalAddress, Delta);
+ } break;
+ case ELF::R_PPC64_ADDR64 :
+ writeInt64BE(LocalAddress, Value + Addend);
+ break;
+ case ELF::R_PPC64_TOC :
+ writeInt64BE(LocalAddress, findPPC64TOC());
+ break;
+ case ELF::R_PPC64_TOC16 : {
+ uint64_t TOCStart = findPPC64TOC();
+ Value = applyPPClo((Value + Addend) - TOCStart);
+ writeInt16BE(LocalAddress, applyPPClo(Value));
+ } break;
+ case ELF::R_PPC64_TOC16_DS : {
+ uint64_t TOCStart = findPPC64TOC();
+ Value = ((Value + Addend) - TOCStart);
+ writeInt16BE(LocalAddress, applyPPClo(Value));
+ } break;
+ }
+}
+
+void RuntimeDyldELF::resolveSystemZRelocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend) {
+ uint8_t *LocalAddress = Section.Address + Offset;
+ switch (Type) {
+ default:
+ llvm_unreachable("Relocation type not implemented yet!");
+ break;
+ case ELF::R_390_PC16DBL:
+ case ELF::R_390_PLT16DBL: {
+ int64_t Delta = (Value + Addend) - (Section.LoadAddress + Offset);
+ assert(int16_t(Delta / 2) * 2 == Delta && "R_390_PC16DBL overflow");
+ writeInt16BE(LocalAddress, Delta / 2);
+ break;
+ }
+ case ELF::R_390_PC32DBL:
+ case ELF::R_390_PLT32DBL: {
+ int64_t Delta = (Value + Addend) - (Section.LoadAddress + Offset);
+ assert(int32_t(Delta / 2) * 2 == Delta && "R_390_PC32DBL overflow");
+ writeInt32BE(LocalAddress, Delta / 2);
+ break;
+ }
+ case ELF::R_390_PC32: {
+ int64_t Delta = (Value + Addend) - (Section.LoadAddress + Offset);
+ assert(int32_t(Delta) == Delta && "R_390_PC32 overflow");
+ writeInt32BE(LocalAddress, Delta);
+ break;
+ }
+ case ELF::R_390_64:
+ writeInt64BE(LocalAddress, Value + Addend);
+ break;
+ }
+}
+
+// The target location for the relocation is described by RE.SectionID and
+// RE.Offset. RE.SectionID can be used to find the SectionEntry. Each
+// SectionEntry has three members describing its location.
+// SectionEntry::Address is the address at which the section has been loaded
+// into memory in the current (host) process. SectionEntry::LoadAddress is the
+// address that the section will have in the target process.
+// SectionEntry::ObjAddress is the address of the bits for this section in the
+// original emitted object image (also in the current address space).
+//
+// Relocations will be applied as if the section were loaded at
+// SectionEntry::LoadAddress, but they will be applied at an address based
+// on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer to
+// Target memory contents if they are required for value calculations.
+//
+// The Value parameter here is the load address of the symbol for the
+// relocation to be applied. For relocations which refer to symbols in the
+// current object Value will be the LoadAddress of the section in which
+// the symbol resides (RE.Addend provides additional information about the
+// symbol location). For external symbols, Value will be the address of the
+// symbol in the target address space.
+void RuntimeDyldELF::resolveRelocation(const RelocationEntry &RE,
+ uint64_t Value) {
+ const SectionEntry &Section = Sections[RE.SectionID];
+ return resolveRelocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
+ RE.SymOffset);
+}
+
+void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend,
+ uint64_t SymOffset) {
+ switch (Arch) {
+ case Triple::x86_64:
+ resolveX86_64Relocation(Section, Offset, Value, Type, Addend, SymOffset);
+ break;
+ case Triple::x86:
+ resolveX86Relocation(Section, Offset,
+ (uint32_t)(Value & 0xffffffffL), Type,
+ (uint32_t)(Addend & 0xffffffffL));
+ break;
+ case Triple::aarch64:
+ resolveAArch64Relocation(Section, Offset, Value, Type, Addend);
+ break;
+ case Triple::arm: // Fall through.
+ case Triple::thumb:
+ resolveARMRelocation(Section, Offset,
+ (uint32_t)(Value & 0xffffffffL), Type,
+ (uint32_t)(Addend & 0xffffffffL));
+ break;
+ case Triple::mips: // Fall through.
+ case Triple::mipsel:
+ resolveMIPSRelocation(Section, Offset,
+ (uint32_t)(Value & 0xffffffffL), Type,
+ (uint32_t)(Addend & 0xffffffffL));
+ break;
+ case Triple::ppc64: // Fall through.
+ case Triple::ppc64le:
+ resolvePPC64Relocation(Section, Offset, Value, Type, Addend);
+ break;
+ case Triple::systemz:
+ resolveSystemZRelocation(Section, Offset, Value, Type, Addend);
+ break;
+ default: llvm_unreachable("Unsupported CPU type!");
+ }
+}
+
+void RuntimeDyldELF::processRelocationRef(unsigned SectionID,
+ RelocationRef RelI,
+ ObjectImage &Obj,
+ ObjSectionToIDMap &ObjSectionToID,
+ const SymbolTableMap &Symbols,
+ StubMap &Stubs) {
+ uint64_t RelType;
+ Check(RelI.getType(RelType));
+ int64_t Addend;
+ Check(getELFRelocationAddend(RelI, Addend));
+ symbol_iterator Symbol = RelI.getSymbol();
+
+ // Obtain the symbol name which is referenced in the relocation
+ StringRef TargetName;
+ if (Symbol != Obj.end_symbols())
+ Symbol->getName(TargetName);
+ DEBUG(dbgs() << "\t\tRelType: " << RelType
+ << " Addend: " << Addend
+ << " TargetName: " << TargetName
+ << "\n");
+ RelocationValueRef Value;
+ // 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.end_symbols()) {
+ lsi = Symbols.find(TargetName.data());
+ Symbol->getType(SymType);
+ }
+ if (lsi != Symbols.end()) {
+ Value.SectionID = lsi->second.first;
+ Value.Offset = lsi->second.second;
+ Value.Addend = lsi->second.second + Addend;
+ } else {
+ // Search for the symbol in the global symbol table
+ SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end();
+ if (Symbol != Obj.end_symbols())
+ gsi = GlobalSymbolTable.find(TargetName.data());
+ if (gsi != GlobalSymbolTable.end()) {
+ Value.SectionID = gsi->second.first;
+ Value.Offset = gsi->second.second;
+ Value.Addend = gsi->second.second + Addend;
+ } else {
+ switch (SymType) {
+ case SymbolRef::ST_Debug: {
+ // 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.end_sections());
+ Symbol->getSection(si);
+ if (si == Obj.end_sections())
+ llvm_unreachable("Symbol section not found, bad object file format!");
+ DEBUG(dbgs() << "\t\tThis is section symbol\n");
+ // Default to 'true' in case isText fails (though it never does).
+ bool isCode = true;
+ si->isText(isCode);
+ Value.SectionID = findOrEmitSection(Obj,
+ (*si),
+ isCode,
+ ObjSectionToID);
+ Value.Addend = Addend;
+ break;
+ }
+ case SymbolRef::ST_Data:
+ case SymbolRef::ST_Unknown: {
+ Value.SymbolName = TargetName.data();
+ Value.Addend = Addend;
+
+ // Absolute relocations will have a zero symbol ID (STN_UNDEF), which
+ // will manifest here as a NULL symbol name.
+ // We can set this as a valid (but empty) symbol name, and rely
+ // on addRelocationForSymbol to handle this.
+ if (!Value.SymbolName)
+ Value.SymbolName = "";
+ break;
+ }
+ default:
+ llvm_unreachable("Unresolved symbol type!");
+ break;
+ }
+ }
+ }
+ uint64_t Offset;
+ Check(RelI.getOffset(Offset));
+
+ DEBUG(dbgs() << "\t\tSectionID: " << SectionID
+ << " Offset: " << Offset
+ << "\n");
+ if (Arch == Triple::aarch64 &&
+ (RelType == ELF::R_AARCH64_CALL26 ||
+ RelType == ELF::R_AARCH64_JUMP26)) {
+ // This is an AArch64 branch relocation, need to use a stub function.
+ DEBUG(dbgs() << "\t\tThis is an AArch64 branch relocation.");
+ SectionEntry &Section = Sections[SectionID];
+
+ // Look for an existing stub.
+ StubMap::const_iterator i = Stubs.find(Value);
+ if (i != Stubs.end()) {
+ resolveRelocation(Section, Offset,
+ (uint64_t)Section.Address + i->second, RelType, 0);
+ DEBUG(dbgs() << " Stub function found\n");
+ } else {
+ // Create a new stub function.
+ DEBUG(dbgs() << " Create a new stub function\n");
+ Stubs[Value] = Section.StubOffset;
+ uint8_t *StubTargetAddr = createStubFunction(Section.Address +
+ Section.StubOffset);
+
+ RelocationEntry REmovz_g3(SectionID,
+ StubTargetAddr - Section.Address,
+ ELF::R_AARCH64_MOVW_UABS_G3, Value.Addend);
+ RelocationEntry REmovk_g2(SectionID,
+ StubTargetAddr - Section.Address + 4,
+ ELF::R_AARCH64_MOVW_UABS_G2_NC, Value.Addend);
+ RelocationEntry REmovk_g1(SectionID,
+ StubTargetAddr - Section.Address + 8,
+ ELF::R_AARCH64_MOVW_UABS_G1_NC, Value.Addend);
+ RelocationEntry REmovk_g0(SectionID,
+ StubTargetAddr - Section.Address + 12,
+ ELF::R_AARCH64_MOVW_UABS_G0_NC, Value.Addend);
+
+ if (Value.SymbolName) {
+ addRelocationForSymbol(REmovz_g3, Value.SymbolName);
+ addRelocationForSymbol(REmovk_g2, Value.SymbolName);
+ addRelocationForSymbol(REmovk_g1, Value.SymbolName);
+ addRelocationForSymbol(REmovk_g0, Value.SymbolName);
+ } else {
+ addRelocationForSection(REmovz_g3, Value.SectionID);
+ addRelocationForSection(REmovk_g2, Value.SectionID);
+ addRelocationForSection(REmovk_g1, Value.SectionID);
+ addRelocationForSection(REmovk_g0, Value.SectionID);
+ }
+ resolveRelocation(Section, Offset,
+ (uint64_t)Section.Address + Section.StubOffset,
+ RelType, 0);
+ Section.StubOffset += getMaxStubSize();
+ }
+ } else if (Arch == Triple::arm &&
+ (RelType == ELF::R_ARM_PC24 ||
+ RelType == ELF::R_ARM_CALL ||
+ RelType == ELF::R_ARM_JUMP24)) {
+ // This is an ARM branch relocation, need to use a stub function.
+ DEBUG(dbgs() << "\t\tThis is an ARM branch relocation.");
+ SectionEntry &Section = Sections[SectionID];
+
+ // Look for an existing stub.
+ StubMap::const_iterator i = Stubs.find(Value);
+ if (i != Stubs.end()) {
+ resolveRelocation(Section, Offset,
+ (uint64_t)Section.Address + i->second, RelType, 0);
+ DEBUG(dbgs() << " Stub function found\n");
+ } else {
+ // Create a new stub function.
+ DEBUG(dbgs() << " Create a new stub function\n");
+ Stubs[Value] = Section.StubOffset;
+ uint8_t *StubTargetAddr = createStubFunction(Section.Address +
+ Section.StubOffset);
+ RelocationEntry RE(SectionID, StubTargetAddr - Section.Address,
+ ELF::R_ARM_PRIVATE_0, Value.Addend);
+ if (Value.SymbolName)
+ addRelocationForSymbol(RE, Value.SymbolName);
+ else
+ addRelocationForSection(RE, Value.SectionID);
+
+ resolveRelocation(Section, Offset,
+ (uint64_t)Section.Address + Section.StubOffset,
+ RelType, 0);
+ Section.StubOffset += getMaxStubSize();
+ }
+ } else if ((Arch == Triple::mipsel || Arch == Triple::mips) &&
+ RelType == ELF::R_MIPS_26) {
+ // This is an Mips branch relocation, need to use a stub function.
+ DEBUG(dbgs() << "\t\tThis is a Mips branch relocation.");
+ SectionEntry &Section = Sections[SectionID];
+ uint8_t *Target = Section.Address + Offset;
+ uint32_t *TargetAddress = (uint32_t *)Target;
+
+ // Extract the addend from the instruction.
+ uint32_t Addend = ((*TargetAddress) & 0x03ffffff) << 2;
+
+ Value.Addend += Addend;
+
+ // Look up for existing stub.
+ StubMap::const_iterator i = Stubs.find(Value);
+ if (i != Stubs.end()) {
+ RelocationEntry RE(SectionID, Offset, RelType, i->second);
+ addRelocationForSection(RE, SectionID);
+ DEBUG(dbgs() << " Stub function found\n");
+ } else {
+ // Create a new stub function.
+ DEBUG(dbgs() << " Create a new stub function\n");
+ Stubs[Value] = Section.StubOffset;
+ uint8_t *StubTargetAddr = createStubFunction(Section.Address +
+ Section.StubOffset);
+
+ // Creating Hi and Lo relocations for the filled stub instructions.
+ RelocationEntry REHi(SectionID,
+ StubTargetAddr - Section.Address,
+ ELF::R_MIPS_UNUSED1, Value.Addend);
+ RelocationEntry RELo(SectionID,
+ StubTargetAddr - Section.Address + 4,
+ ELF::R_MIPS_UNUSED2, Value.Addend);
+
+ if (Value.SymbolName) {
+ addRelocationForSymbol(REHi, Value.SymbolName);
+ addRelocationForSymbol(RELo, Value.SymbolName);
+ } else {
+ addRelocationForSection(REHi, Value.SectionID);
+ addRelocationForSection(RELo, Value.SectionID);
+ }
+
+ RelocationEntry RE(SectionID, Offset, RelType, Section.StubOffset);
+ addRelocationForSection(RE, SectionID);
+ Section.StubOffset += getMaxStubSize();
+ }
+ } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
+ if (RelType == ELF::R_PPC64_REL24) {
+ // A PPC branch relocation will need a stub function if the target is
+ // an external symbol (Symbol::ST_Unknown) or if the target address
+ // is not within the signed 24-bits branch address.
+ SectionEntry &Section = Sections[SectionID];
+ uint8_t *Target = Section.Address + Offset;
+ bool RangeOverflow = false;
+ if (SymType != SymbolRef::ST_Unknown) {
+ // A function call may points to the .opd entry, so the final symbol value
+ // in calculated based in the relocation values in .opd section.
+ findOPDEntrySection(Obj, ObjSectionToID, Value);
+ uint8_t *RelocTarget = Sections[Value.SectionID].Address + Value.Addend;
+ int32_t delta = static_cast<int32_t>(Target - RelocTarget);
+ // If it is within 24-bits branch range, just set the branch target
+ if (SignExtend32<24>(delta) == delta) {
+ RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);
+ if (Value.SymbolName)
+ addRelocationForSymbol(RE, Value.SymbolName);
+ else
+ addRelocationForSection(RE, Value.SectionID);
+ } else {
+ RangeOverflow = true;
+ }
+ }
+ if (SymType == SymbolRef::ST_Unknown || RangeOverflow == true) {
+ // It is an external symbol (SymbolRef::ST_Unknown) or within a range
+ // larger than 24-bits.
+ StubMap::const_iterator i = Stubs.find(Value);
+ if (i != Stubs.end()) {
+ // Symbol function stub already created, just relocate to it
+ resolveRelocation(Section, Offset,
+ (uint64_t)Section.Address + i->second, RelType, 0);
+ DEBUG(dbgs() << " Stub function found\n");
+ } else {
+ // Create a new stub function.
+ DEBUG(dbgs() << " Create a new stub function\n");
+ Stubs[Value] = Section.StubOffset;
+ uint8_t *StubTargetAddr = createStubFunction(Section.Address +
+ Section.StubOffset);
+ RelocationEntry RE(SectionID, StubTargetAddr - Section.Address,
+ ELF::R_PPC64_ADDR64, Value.Addend);
+
+ // Generates the 64-bits address loads as exemplified in section
+ // 4.5.1 in PPC64 ELF ABI.
+ RelocationEntry REhst(SectionID,
+ StubTargetAddr - Section.Address + 2,
+ ELF::R_PPC64_ADDR16_HIGHEST, Value.Addend);
+ RelocationEntry REhr(SectionID,
+ StubTargetAddr - Section.Address + 6,
+ ELF::R_PPC64_ADDR16_HIGHER, Value.Addend);
+ RelocationEntry REh(SectionID,
+ StubTargetAddr - Section.Address + 14,
+ ELF::R_PPC64_ADDR16_HI, Value.Addend);
+ RelocationEntry REl(SectionID,
+ StubTargetAddr - Section.Address + 18,
+ ELF::R_PPC64_ADDR16_LO, Value.Addend);
+
+ if (Value.SymbolName) {
+ addRelocationForSymbol(REhst, Value.SymbolName);
+ addRelocationForSymbol(REhr, Value.SymbolName);
+ addRelocationForSymbol(REh, Value.SymbolName);
+ addRelocationForSymbol(REl, Value.SymbolName);
+ } else {
+ addRelocationForSection(REhst, Value.SectionID);
+ addRelocationForSection(REhr, Value.SectionID);
+ addRelocationForSection(REh, Value.SectionID);
+ addRelocationForSection(REl, Value.SectionID);
+ }
+
+ resolveRelocation(Section, Offset,
+ (uint64_t)Section.Address + Section.StubOffset,
+ RelType, 0);
+ if (SymType == SymbolRef::ST_Unknown)
+ // Restore the TOC for external calls
+ writeInt32BE(Target+4, 0xE8410028); // ld r2,40(r1)
+ Section.StubOffset += getMaxStubSize();
+ }
+ }
+ } else {
+ RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);
+ // Extra check to avoid relocation againt empty symbols (usually
+ // the R_PPC64_TOC).
+ if (SymType != SymbolRef::ST_Unknown && TargetName.empty())
+ Value.SymbolName = NULL;
+
+ if (Value.SymbolName)
+ addRelocationForSymbol(RE, Value.SymbolName);
+ else
+ addRelocationForSection(RE, Value.SectionID);
+ }
+ } else if (Arch == Triple::systemz &&
+ (RelType == ELF::R_390_PLT32DBL ||
+ RelType == ELF::R_390_GOTENT)) {
+ // Create function stubs for both PLT and GOT references, regardless of
+ // whether the GOT reference is to data or code. The stub contains the
+ // full address of the symbol, as needed by GOT references, and the
+ // executable part only adds an overhead of 8 bytes.
+ //
+ // We could try to conserve space by allocating the code and data
+ // parts of the stub separately. However, as things stand, we allocate
+ // a stub for every relocation, so using a GOT in JIT code should be
+ // no less space efficient than using an explicit constant pool.
+ DEBUG(dbgs() << "\t\tThis is a SystemZ indirect relocation.");
+ SectionEntry &Section = Sections[SectionID];
+
+ // Look for an existing stub.
+ StubMap::const_iterator i = Stubs.find(Value);
+ uintptr_t StubAddress;
+ if (i != Stubs.end()) {
+ StubAddress = uintptr_t(Section.Address) + i->second;
+ DEBUG(dbgs() << " Stub function found\n");
+ } else {
+ // Create a new stub function.
+ DEBUG(dbgs() << " Create a new stub function\n");
+
+ uintptr_t BaseAddress = uintptr_t(Section.Address);
+ uintptr_t StubAlignment = getStubAlignment();
+ StubAddress = (BaseAddress + Section.StubOffset +
+ StubAlignment - 1) & -StubAlignment;
+ unsigned StubOffset = StubAddress - BaseAddress;
+
+ Stubs[Value] = StubOffset;
+ createStubFunction((uint8_t *)StubAddress);
+ RelocationEntry RE(SectionID, StubOffset + 8,
+ ELF::R_390_64, Value.Addend - Addend);
+ if (Value.SymbolName)
+ addRelocationForSymbol(RE, Value.SymbolName);
+ else
+ addRelocationForSection(RE, Value.SectionID);
+ Section.StubOffset = StubOffset + getMaxStubSize();
+ }
+
+ if (RelType == ELF::R_390_GOTENT)
+ resolveRelocation(Section, Offset, StubAddress + 8,
+ ELF::R_390_PC32DBL, Addend);
+ else
+ resolveRelocation(Section, Offset, StubAddress, RelType, Addend);
+ } else if (Arch == Triple::x86_64 && RelType == ELF::R_X86_64_PLT32) {
+ // The way the PLT relocations normally work is that the linker allocates the
+ // PLT and this relocation makes a PC-relative call into the PLT. The PLT
+ // entry will then jump to an address provided by the GOT. On first call, the
+ // GOT address will point back into PLT code that resolves the symbol. After
+ // the first call, the GOT entry points to the actual function.
+ //
+ // For local functions we're ignoring all of that here and just replacing
+ // the PLT32 relocation type with PC32, which will translate the relocation
+ // into a PC-relative call directly to the function. For external symbols we
+ // can't be sure the function will be within 2^32 bytes of the call site, so
+ // we need to create a stub, which calls into the GOT. This case is
+ // equivalent to the usual PLT implementation except that we use the stub
+ // mechanism in RuntimeDyld (which puts stubs at the end of the section)
+ // rather than allocating a PLT section.
+ if (Value.SymbolName) {
+ // This is a call to an external function.
+ // Look for an existing stub.
+ SectionEntry &Section = Sections[SectionID];
+ StubMap::const_iterator i = Stubs.find(Value);
+ uintptr_t StubAddress;
+ if (i != Stubs.end()) {
+ StubAddress = uintptr_t(Section.Address) + i->second;
+ DEBUG(dbgs() << " Stub function found\n");
+ } else {
+ // Create a new stub function (equivalent to a PLT entry).
+ DEBUG(dbgs() << " Create a new stub function\n");
+
+ uintptr_t BaseAddress = uintptr_t(Section.Address);
+ uintptr_t StubAlignment = getStubAlignment();
+ StubAddress = (BaseAddress + Section.StubOffset +
+ StubAlignment - 1) & -StubAlignment;
+ unsigned StubOffset = StubAddress - BaseAddress;
+ Stubs[Value] = StubOffset;
+ createStubFunction((uint8_t *)StubAddress);
+
+ // Create a GOT entry for the external function.
+ GOTEntries.push_back(Value);
+
+ // Make our stub function a relative call to the GOT entry.
+ RelocationEntry RE(SectionID, StubOffset + 2,
+ ELF::R_X86_64_GOTPCREL, -4);
+ addRelocationForSymbol(RE, Value.SymbolName);
+
+ // Bump our stub offset counter
+ Section.StubOffset = StubOffset + getMaxStubSize();
+ }
+
+ // Make the target call a call into the stub table.
+ resolveRelocation(Section, Offset, StubAddress,
+ ELF::R_X86_64_PC32, Addend);
+ } else {
+ RelocationEntry RE(SectionID, Offset, ELF::R_X86_64_PC32, Value.Addend,
+ Value.Offset);
+ addRelocationForSection(RE, Value.SectionID);
+ }
+ } else {
+ if (Arch == Triple::x86_64 && RelType == ELF::R_X86_64_GOTPCREL) {
+ GOTEntries.push_back(Value);
+ }
+ RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, Value.Offset);
+ if (Value.SymbolName)
+ addRelocationForSymbol(RE, Value.SymbolName);
+ else
+ addRelocationForSection(RE, Value.SectionID);
+ }
+}
+
+void RuntimeDyldELF::updateGOTEntries(StringRef Name, uint64_t Addr) {
+
+ SmallVectorImpl<std::pair<SID, GOTRelocations> >::iterator it;
+ SmallVectorImpl<std::pair<SID, GOTRelocations> >::iterator end = GOTs.end();
+
+ for (it = GOTs.begin(); it != end; ++it) {
+ GOTRelocations &GOTEntries = it->second;
+ for (int i = 0, e = GOTEntries.size(); i != e; ++i) {
+ if (GOTEntries[i].SymbolName != 0 && GOTEntries[i].SymbolName == Name) {
+ GOTEntries[i].Offset = Addr;
+ }
+ }
+ }
+}
+
+size_t RuntimeDyldELF::getGOTEntrySize() {
+ // We don't use the GOT in all of these cases, but it's essentially free
+ // to put them all here.
+ size_t Result = 0;
+ switch (Arch) {
+ case Triple::x86_64:
+ case Triple::aarch64:
+ case Triple::ppc64:
+ case Triple::ppc64le:
+ case Triple::systemz:
+ Result = sizeof(uint64_t);
+ break;
+ case Triple::x86:
+ case Triple::arm:
+ case Triple::thumb:
+ case Triple::mips:
+ case Triple::mipsel:
+ Result = sizeof(uint32_t);
+ break;
+ default: llvm_unreachable("Unsupported CPU type!");
+ }
+ return Result;
+}
+
+uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress,
+ uint64_t Offset) {
+
+ const size_t GOTEntrySize = getGOTEntrySize();
+
+ SmallVectorImpl<std::pair<SID, GOTRelocations> >::const_iterator it;
+ SmallVectorImpl<std::pair<SID, GOTRelocations> >::const_iterator end = GOTs.end();
+
+ int GOTIndex = -1;
+ for (it = GOTs.begin(); it != end; ++it) {
+ SID GOTSectionID = it->first;
+ const GOTRelocations &GOTEntries = it->second;
+
+ // Find the matching entry in our vector.
+ uint64_t SymbolOffset = 0;
+ for (int i = 0, e = GOTEntries.size(); i != e; ++i) {
+ if (GOTEntries[i].SymbolName == 0) {
+ if (getSectionLoadAddress(GOTEntries[i].SectionID) == LoadAddress &&
+ GOTEntries[i].Offset == Offset) {
+ GOTIndex = i;
+ SymbolOffset = GOTEntries[i].Offset;
+ break;
+ }
+ } else {
+ // GOT entries for external symbols use the addend as the address when
+ // the external symbol has been resolved.
+ if (GOTEntries[i].Offset == LoadAddress) {
+ GOTIndex = i;
+ // Don't use the Addend here. The relocation handler will use it.
+ break;
+ }
+ }
+ }
+
+ if (GOTIndex != -1) {
+ if (GOTEntrySize == sizeof(uint64_t)) {
+ uint64_t *LocalGOTAddr = (uint64_t*)getSectionAddress(GOTSectionID);
+ // Fill in this entry with the address of the symbol being referenced.
+ LocalGOTAddr[GOTIndex] = LoadAddress + SymbolOffset;
+ } else {
+ uint32_t *LocalGOTAddr = (uint32_t*)getSectionAddress(GOTSectionID);
+ // Fill in this entry with the address of the symbol being referenced.
+ LocalGOTAddr[GOTIndex] = (uint32_t)(LoadAddress + SymbolOffset);
+ }
+
+ // Calculate the load address of this entry
+ return getSectionLoadAddress(GOTSectionID) + (GOTIndex * GOTEntrySize);
+ }
+ }
+
+ assert(GOTIndex != -1 && "Unable to find requested GOT entry.");
+ return 0;
+}
+
+void RuntimeDyldELF::finalizeLoad(ObjSectionToIDMap &SectionMap) {
+ // If necessary, allocate the global offset table
+ if (MemMgr) {
+ // Allocate the GOT if necessary
+ size_t numGOTEntries = GOTEntries.size();
+ if (numGOTEntries != 0) {
+ // Allocate memory for the section
+ unsigned SectionID = Sections.size();
+ size_t TotalSize = numGOTEntries * getGOTEntrySize();
+ uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, getGOTEntrySize(),
+ SectionID, ".got", false);
+ if (!Addr)
+ report_fatal_error("Unable to allocate memory for GOT!");
+
+ GOTs.push_back(std::make_pair(SectionID, GOTEntries));
+ Sections.push_back(SectionEntry(".got", Addr, TotalSize, 0));
+ // For now, initialize all GOT entries to zero. We'll fill them in as
+ // needed when GOT-based relocations are applied.
+ memset(Addr, 0, TotalSize);
+ }
+ }
+ else {
+ report_fatal_error("Unable to allocate memory for GOT!");
+ }
+
+ // Look for and record the EH frame section.
+ ObjSectionToIDMap::iterator i, e;
+ for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) {
+ const SectionRef &Section = i->first;
+ StringRef Name;
+ Section.getName(Name);
+ if (Name == ".eh_frame") {
+ UnregisteredEHFrameSections.push_back(i->second);
+ break;
+ }
+ }
+}
+
+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;
+}
+} // namespace llvm
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
new file mode 100644
index 000000000000..3adf82706ad0
--- /dev/null
+++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
@@ -0,0 +1,152 @@
+//===-- RuntimeDyldELF.h - Run-time dynamic linker for MC-JIT ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// ELF support for MC-JIT runtime dynamic linker.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_RUNTIME_DYLD_ELF_H
+#define LLVM_RUNTIME_DYLD_ELF_H
+
+#include "RuntimeDyldImpl.h"
+#include "llvm/ADT/DenseMap.h"
+
+using namespace llvm;
+
+namespace llvm {
+
+namespace {
+ // Helper for extensive error checking in debug builds.
+ error_code Check(error_code Err) {
+ if (Err) {
+ report_fatal_error(Err.message());
+ }
+ return Err;
+ }
+} // end anonymous namespace
+
+class RuntimeDyldELF : public RuntimeDyldImpl {
+ void resolveRelocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend,
+ uint64_t SymOffset=0);
+
+ void resolveX86_64Relocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend,
+ uint64_t SymOffset);
+
+ void resolveX86Relocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint32_t Value,
+ uint32_t Type,
+ int32_t Addend);
+
+ void resolveAArch64Relocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend);
+
+ void resolveARMRelocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint32_t Value,
+ uint32_t Type,
+ int32_t Addend);
+
+ void resolveMIPSRelocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint32_t Value,
+ uint32_t Type,
+ int32_t Addend);
+
+ void resolvePPC64Relocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend);
+
+ void resolveSystemZRelocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend);
+
+ unsigned getMaxStubSize() {
+ if (Arch == Triple::aarch64)
+ return 20; // movz; movk; movk; movk; br
+ if (Arch == Triple::arm || Arch == Triple::thumb)
+ return 8; // 32-bit instruction and 32-bit address
+ else if (Arch == Triple::mipsel || Arch == Triple::mips)
+ return 16;
+ else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le)
+ return 44;
+ else if (Arch == Triple::x86_64)
+ return 6; // 2-byte jmp instruction + 32-bit relative address
+ else if (Arch == Triple::systemz)
+ return 16;
+ else
+ return 0;
+ }
+
+ unsigned getStubAlignment() {
+ if (Arch == Triple::systemz)
+ return 8;
+ else
+ return 1;
+ }
+
+ uint64_t findPPC64TOC() const;
+ void findOPDEntrySection(ObjectImage &Obj,
+ ObjSectionToIDMap &LocalSections,
+ RelocationValueRef &Rel);
+
+ uint64_t findGOTEntry(uint64_t LoadAddr, uint64_t Offset);
+ size_t getGOTEntrySize();
+
+ virtual void updateGOTEntries(StringRef Name, uint64_t Addr);
+
+ // Relocation entries for symbols whose position-independant offset is
+ // updated in a global offset table.
+ typedef SmallVector<RelocationValueRef, 2> GOTRelocations;
+ GOTRelocations GOTEntries; // List of entries requiring finalization.
+ SmallVector<std::pair<SID, GOTRelocations>, 8> GOTs; // Allocated tables.
+
+ // When a module is loaded we save the SectionID of the EH frame section
+ // in a table until we receive a request to register all unregistered
+ // EH frame sections with the memory manager.
+ SmallVector<SID, 2> UnregisteredEHFrameSections;
+ SmallVector<SID, 2> RegisteredEHFrameSections;
+
+public:
+ RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm)
+ {}
+
+ virtual void resolveRelocation(const RelocationEntry &RE, uint64_t Value);
+ virtual void processRelocationRef(unsigned SectionID,
+ RelocationRef RelI,
+ ObjectImage &Obj,
+ ObjSectionToIDMap &ObjSectionToID,
+ const SymbolTableMap &Symbols,
+ StubMap &Stubs);
+ virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const;
+ virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer);
+ virtual void registerEHFrames();
+ virtual void deregisterEHFrames();
+ virtual void finalizeLoad(ObjSectionToIDMap &SectionMap);
+ virtual ~RuntimeDyldELF();
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
new file mode 100644
index 000000000000..3014b30773ac
--- /dev/null
+++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
@@ -0,0 +1,368 @@
+//===-- RuntimeDyldImpl.h - Run-time dynamic linker for MC-JIT --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Interface for the implementations of runtime dynamic linker facilities.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_RUNTIME_DYLD_IMPL_H
+#define LLVM_RUNTIME_DYLD_IMPL_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/ObjectImage.h"
+#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/SwapByteOrder.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+#include <map>
+
+using namespace llvm;
+using namespace llvm::object;
+
+namespace llvm {
+
+class ObjectBuffer;
+class Twine;
+
+
+/// SectionEntry - represents a section emitted into memory by the dynamic
+/// linker.
+class SectionEntry {
+public:
+ /// Name - section name.
+ StringRef Name;
+
+ /// Address - address in the linker's memory where the section resides.
+ uint8_t *Address;
+
+ /// Size - section size. Doesn't include the stubs.
+ size_t Size;
+
+ /// LoadAddress - the address of the section in the target process's memory.
+ /// Used for situations in which JIT-ed code is being executed in the address
+ /// space of a separate process. If the code executes in the same address
+ /// space where it was JIT-ed, this just equals Address.
+ uint64_t LoadAddress;
+
+ /// StubOffset - used for architectures with stub functions for far
+ /// relocations (like ARM).
+ uintptr_t StubOffset;
+
+ /// ObjAddress - address of the section in the in-memory object file. Used
+ /// for calculating relocations in some object formats (like MachO).
+ uintptr_t ObjAddress;
+
+ SectionEntry(StringRef name, uint8_t *address, size_t size,
+ uintptr_t objAddress)
+ : Name(name), Address(address), Size(size), LoadAddress((uintptr_t)address),
+ StubOffset(size), ObjAddress(objAddress) {}
+};
+
+/// RelocationEntry - used to represent relocations internally in the dynamic
+/// linker.
+class RelocationEntry {
+public:
+ /// SectionID - the section this relocation points to.
+ unsigned SectionID;
+
+ /// Offset - offset into the section.
+ uint64_t Offset;
+
+ /// RelType - relocation type.
+ uint32_t RelType;
+
+ /// Addend - the relocation addend encoded in the instruction itself. Also
+ /// used to make a relocation section relative instead of symbol relative.
+ int64_t Addend;
+
+ /// SymOffset - Section offset of the relocation entry's symbol (used for GOT
+ /// lookup).
+ uint64_t SymOffset;
+
+ /// True if this is a PCRel relocation (MachO specific).
+ bool IsPCRel;
+
+ /// The size of this relocation (MachO specific).
+ unsigned Size;
+
+ RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend)
+ : SectionID(id), Offset(offset), RelType(type), Addend(addend),
+ SymOffset(0), IsPCRel(false), Size(0) {}
+
+ RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend,
+ uint64_t symoffset)
+ : SectionID(id), Offset(offset), RelType(type), Addend(addend),
+ SymOffset(symoffset), IsPCRel(false), Size(0) {}
+
+ RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend,
+ bool IsPCRel, unsigned Size)
+ : SectionID(id), Offset(offset), RelType(type), Addend(addend),
+ SymOffset(0), IsPCRel(IsPCRel), Size(Size) {}
+};
+
+class RelocationValueRef {
+public:
+ unsigned SectionID;
+ uint64_t Offset;
+ int64_t Addend;
+ const char *SymbolName;
+ RelocationValueRef(): SectionID(0), Offset(0), Addend(0), SymbolName(0) {}
+
+ inline bool operator==(const RelocationValueRef &Other) const {
+ return SectionID == Other.SectionID && Offset == Other.Offset &&
+ Addend == Other.Addend && SymbolName == Other.SymbolName;
+ }
+ inline bool operator <(const RelocationValueRef &Other) const {
+ if (SectionID != Other.SectionID)
+ return SectionID < Other.SectionID;
+ if (Offset != Other.Offset)
+ return Offset < Other.Offset;
+ if (Addend != Other.Addend)
+ return Addend < Other.Addend;
+ return SymbolName < Other.SymbolName;
+ }
+};
+
+class RuntimeDyldImpl {
+protected:
+ // The MemoryManager to load objects into.
+ RTDyldMemoryManager *MemMgr;
+
+ // A list of all sections emitted by the dynamic linker. These sections are
+ // referenced in the code by means of their index in this list - SectionID.
+ typedef SmallVector<SectionEntry, 64> SectionList;
+ SectionList Sections;
+
+ typedef unsigned SID; // Type for SectionIDs
+ #define RTDYLD_INVALID_SECTION_ID ((SID)(-1))
+
+ // Keep a map of sections from object file to the SectionID which
+ // references it.
+ typedef std::map<SectionRef, unsigned> ObjSectionToIDMap;
+
+ // A global symbol table for symbols from all loaded modules. Maps the
+ // symbol name to a (SectionID, offset in section) pair.
+ typedef std::pair<unsigned, uintptr_t> SymbolLoc;
+ typedef StringMap<SymbolLoc> SymbolTableMap;
+ SymbolTableMap GlobalSymbolTable;
+
+ // Pair representing the size and alignment requirement for a common symbol.
+ typedef std::pair<unsigned, unsigned> CommonSymbolInfo;
+ // Keep a map of common symbols to their info pairs
+ typedef std::map<SymbolRef, CommonSymbolInfo> CommonSymbolMap;
+
+ // For each symbol, keep a list of relocations based on it. Anytime
+ // its address is reassigned (the JIT re-compiled the function, e.g.),
+ // the relocations get re-resolved.
+ // The symbol (or section) the relocation is sourced from is the Key
+ // in the relocation list where it's stored.
+ typedef SmallVector<RelocationEntry, 64> RelocationList;
+ // Relocations to sections already loaded. Indexed by SectionID which is the
+ // source of the address. The target where the address will be written is
+ // SectionID/Offset in the relocation itself.
+ DenseMap<unsigned, RelocationList> Relocations;
+
+ // Relocations to external symbols that are not yet resolved. Symbols are
+ // external when they aren't found in the global symbol table of all loaded
+ // modules. This map is indexed by symbol name.
+ StringMap<RelocationList> ExternalSymbolRelocations;
+
+ typedef std::map<RelocationValueRef, uintptr_t> StubMap;
+
+ Triple::ArchType Arch;
+ bool IsTargetLittleEndian;
+
+ // This mutex prevents simultaneously loading objects from two different
+ // threads. This keeps us from having to protect individual data structures
+ // and guarantees that section allocation requests to the memory manager
+ // won't be interleaved between modules. It is also used in mapSectionAddress
+ // and resolveRelocations to protect write access to internal data structures.
+ //
+ // loadObject may be called on the same thread during the handling of of
+ // processRelocations, and that's OK. The handling of the relocation lists
+ // is written in such a way as to work correctly if new elements are added to
+ // the end of the list while the list is being processed.
+ sys::Mutex lock;
+
+ virtual unsigned getMaxStubSize() = 0;
+ virtual unsigned getStubAlignment() = 0;
+
+ bool HasError;
+ std::string ErrorStr;
+
+ // Set the error state and record an error string.
+ bool Error(const Twine &Msg) {
+ ErrorStr = Msg.str();
+ HasError = true;
+ return true;
+ }
+
+ uint64_t getSectionLoadAddress(unsigned SectionID) {
+ return Sections[SectionID].LoadAddress;
+ }
+
+ uint8_t *getSectionAddress(unsigned SectionID) {
+ return (uint8_t*)Sections[SectionID].Address;
+ }
+
+ void writeInt16BE(uint8_t *Addr, uint16_t Value) {
+ if (IsTargetLittleEndian)
+ Value = sys::SwapByteOrder(Value);
+ *Addr = (Value >> 8) & 0xFF;
+ *(Addr+1) = Value & 0xFF;
+ }
+
+ void writeInt32BE(uint8_t *Addr, uint32_t Value) {
+ if (IsTargetLittleEndian)
+ Value = sys::SwapByteOrder(Value);
+ *Addr = (Value >> 24) & 0xFF;
+ *(Addr+1) = (Value >> 16) & 0xFF;
+ *(Addr+2) = (Value >> 8) & 0xFF;
+ *(Addr+3) = Value & 0xFF;
+ }
+
+ void writeInt64BE(uint8_t *Addr, uint64_t Value) {
+ if (IsTargetLittleEndian)
+ Value = sys::SwapByteOrder(Value);
+ *Addr = (Value >> 56) & 0xFF;
+ *(Addr+1) = (Value >> 48) & 0xFF;
+ *(Addr+2) = (Value >> 40) & 0xFF;
+ *(Addr+3) = (Value >> 32) & 0xFF;
+ *(Addr+4) = (Value >> 24) & 0xFF;
+ *(Addr+5) = (Value >> 16) & 0xFF;
+ *(Addr+6) = (Value >> 8) & 0xFF;
+ *(Addr+7) = Value & 0xFF;
+ }
+
+ /// \brief Given the common symbols discovered in the object file, emit a
+ /// new section for them and update the symbol mappings in the object and
+ /// symbol table.
+ void emitCommonSymbols(ObjectImage &Obj,
+ const CommonSymbolMap &CommonSymbols,
+ uint64_t TotalSize,
+ SymbolTableMap &SymbolTable);
+
+ /// \brief Emits section data from the object file to the MemoryManager.
+ /// \param IsCode if it's true then allocateCodeSection() will be
+ /// used for emits, else allocateDataSection() will be used.
+ /// \return SectionID.
+ unsigned emitSection(ObjectImage &Obj,
+ const SectionRef &Section,
+ bool IsCode);
+
+ /// \brief Find Section in LocalSections. If the secton is not found - emit
+ /// it and store in LocalSections.
+ /// \param IsCode if it's true then allocateCodeSection() will be
+ /// used for emmits, else allocateDataSection() will be used.
+ /// \return SectionID.
+ unsigned findOrEmitSection(ObjectImage &Obj,
+ const SectionRef &Section,
+ bool IsCode,
+ ObjSectionToIDMap &LocalSections);
+
+ // \brief Add a relocation entry that uses the given section.
+ void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID);
+
+ // \brief Add a relocation entry that uses the given symbol. This symbol may
+ // be found in the global symbol table, or it may be external.
+ void addRelocationForSymbol(const RelocationEntry &RE, StringRef SymbolName);
+
+ /// \brief Emits long jump instruction to Addr.
+ /// \return Pointer to the memory area for emitting target address.
+ uint8_t* createStubFunction(uint8_t *Addr);
+
+ /// \brief Resolves relocations from Relocs list with address from Value.
+ void resolveRelocationList(const RelocationList &Relocs, uint64_t Value);
+
+ /// \brief A object file specific relocation resolver
+ /// \param RE The relocation to be resolved
+ /// \param Value Target symbol address to apply the relocation action
+ virtual void resolveRelocation(const RelocationEntry &RE, uint64_t Value) = 0;
+
+ /// \brief Parses the object file relocation and stores it to Relocations
+ /// or SymbolRelocations (this depends on the object file type).
+ virtual void processRelocationRef(unsigned SectionID,
+ RelocationRef RelI,
+ ObjectImage &Obj,
+ ObjSectionToIDMap &ObjSectionToID,
+ const SymbolTableMap &Symbols,
+ StubMap &Stubs) = 0;
+
+ /// \brief Resolve relocations to external symbols.
+ void resolveExternalSymbols();
+
+ /// \brief Update GOT entries for external symbols.
+ // The base class does nothing. ELF overrides this.
+ virtual void updateGOTEntries(StringRef Name, uint64_t Addr) {}
+
+ virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer);
+public:
+ RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {}
+
+ virtual ~RuntimeDyldImpl();
+
+ ObjectImage *loadObject(ObjectBuffer *InputBuffer);
+
+ void *getSymbolAddress(StringRef Name) {
+ // FIXME: Just look up as a function for now. Overly simple of course.
+ // Work in progress.
+ SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name);
+ if (pos == GlobalSymbolTable.end())
+ return 0;
+ SymbolLoc Loc = pos->second;
+ return getSectionAddress(Loc.first) + Loc.second;
+ }
+
+ uint64_t getSymbolLoadAddress(StringRef Name) {
+ // FIXME: Just look up as a function for now. Overly simple of course.
+ // Work in progress.
+ SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name);
+ if (pos == GlobalSymbolTable.end())
+ return 0;
+ SymbolLoc Loc = pos->second;
+ return getSectionLoadAddress(Loc.first) + Loc.second;
+ }
+
+ void resolveRelocations();
+
+ void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
+
+ void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress);
+
+ // Is the linker in an error state?
+ bool hasError() { return HasError; }
+
+ // Mark the error condition as handled and continue.
+ void clearError() { HasError = false; }
+
+ // Get the error message.
+ StringRef getErrorString() { return ErrorStr; }
+
+ virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0;
+
+ virtual void registerEHFrames();
+
+ virtual void deregisterEHFrames();
+
+ virtual void finalizeLoad(ObjSectionToIDMap &SectionMap) {}
+};
+
+} // end namespace llvm
+
+
+#endif
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
new file mode 100644
index 000000000000..5b92867b4778
--- /dev/null
+++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
@@ -0,0 +1,458 @@
+//===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of the MC-JIT runtime dynamic linker.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "dyld"
+#include "RuntimeDyldMachO.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+using namespace llvm;
+using namespace llvm::object;
+
+namespace llvm {
+
+static unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText, intptr_t DeltaForEH) {
+ uint32_t Length = *((uint32_t*)P);
+ P += 4;
+ unsigned char *Ret = P + Length;
+ uint32_t Offset = *((uint32_t*)P);
+ if (Offset == 0) // is a CIE
+ return Ret;
+
+ P += 4;
+ intptr_t FDELocation = *((intptr_t*)P);
+ intptr_t NewLocation = FDELocation - DeltaForText;
+ *((intptr_t*)P) = NewLocation;
+ P += sizeof(intptr_t);
+
+ // Skip the FDE address range
+ P += sizeof(intptr_t);
+
+ uint8_t Augmentationsize = *P;
+ P += 1;
+ if (Augmentationsize != 0) {
+ intptr_t LSDA = *((intptr_t*)P);
+ intptr_t NewLSDA = LSDA - DeltaForEH;
+ *((intptr_t*)P) = NewLSDA;
+ }
+
+ return Ret;
+}
+
+static intptr_t computeDelta(SectionEntry *A, SectionEntry *B) {
+ intptr_t ObjDistance = A->ObjAddress - B->ObjAddress;
+ intptr_t MemDistance = A->LoadAddress - B->LoadAddress;
+ return ObjDistance - MemDistance;
+}
+
+void RuntimeDyldMachO::registerEHFrames() {
+
+ if (!MemMgr)
+ return;
+ for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) {
+ EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i];
+ if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID ||
+ SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID)
+ continue;
+ SectionEntry *Text = &Sections[SectionInfo.TextSID];
+ SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID];
+ SectionEntry *ExceptTab = NULL;
+ if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID)
+ ExceptTab = &Sections[SectionInfo.ExceptTabSID];
+
+ intptr_t DeltaForText = computeDelta(Text, EHFrame);
+ intptr_t DeltaForEH = 0;
+ if (ExceptTab)
+ DeltaForEH = computeDelta(ExceptTab, EHFrame);
+
+ unsigned char *P = EHFrame->Address;
+ unsigned char *End = P + EHFrame->Size;
+ do {
+ P = processFDE(P, DeltaForText, DeltaForEH);
+ } while(P != End);
+
+ MemMgr->registerEHFrames(EHFrame->Address,
+ EHFrame->LoadAddress,
+ EHFrame->Size);
+ }
+ UnregisteredEHFrameSections.clear();
+}
+
+void RuntimeDyldMachO::finalizeLoad(ObjSectionToIDMap &SectionMap) {
+ unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID;
+ unsigned TextSID = RTDYLD_INVALID_SECTION_ID;
+ unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID;
+ ObjSectionToIDMap::iterator i, e;
+ for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) {
+ const SectionRef &Section = i->first;
+ StringRef Name;
+ Section.getName(Name);
+ if (Name == "__eh_frame")
+ EHFrameSID = i->second;
+ else if (Name == "__text")
+ TextSID = i->second;
+ else if (Name == "__gcc_except_tab")
+ ExceptTabSID = i->second;
+ }
+ UnregisteredEHFrameSections.push_back(EHFrameRelatedSections(EHFrameSID,
+ TextSID,
+ ExceptTabSID));
+}
+
+// The target location for the relocation is described by RE.SectionID and
+// RE.Offset. RE.SectionID can be used to find the SectionEntry. Each
+// SectionEntry has three members describing its location.
+// SectionEntry::Address is the address at which the section has been loaded
+// into memory in the current (host) process. SectionEntry::LoadAddress is the
+// address that the section will have in the target process.
+// SectionEntry::ObjAddress is the address of the bits for this section in the
+// original emitted object image (also in the current address space).
+//
+// Relocations will be applied as if the section were loaded at
+// SectionEntry::LoadAddress, but they will be applied at an address based
+// on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer to
+// Target memory contents if they are required for value calculations.
+//
+// The Value parameter here is the load address of the symbol for the
+// relocation to be applied. For relocations which refer to symbols in the
+// current object Value will be the LoadAddress of the section in which
+// the symbol resides (RE.Addend provides additional information about the
+// symbol location). For external symbols, Value will be the address of the
+// symbol in the target address space.
+void RuntimeDyldMachO::resolveRelocation(const RelocationEntry &RE,
+ uint64_t Value) {
+ const SectionEntry &Section = Sections[RE.SectionID];
+ return resolveRelocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
+ RE.IsPCRel, RE.Size);
+}
+
+void RuntimeDyldMachO::resolveRelocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend,
+ bool isPCRel,
+ unsigned LogSize) {
+ uint8_t *LocalAddress = Section.Address + Offset;
+ uint64_t FinalAddress = Section.LoadAddress + Offset;
+ unsigned MachoType = Type;
+ unsigned Size = 1 << LogSize;
+
+ DEBUG(dbgs() << "resolveRelocation LocalAddress: "
+ << format("%p", LocalAddress)
+ << " FinalAddress: " << format("%p", FinalAddress)
+ << " Value: " << format("%p", Value)
+ << " Addend: " << Addend
+ << " isPCRel: " << isPCRel
+ << " MachoType: " << MachoType
+ << " Size: " << Size
+ << "\n");
+
+ // This just dispatches to the proper target specific routine.
+ switch (Arch) {
+ default: llvm_unreachable("Unsupported CPU type!");
+ case Triple::x86_64:
+ resolveX86_64Relocation(LocalAddress,
+ FinalAddress,
+ (uintptr_t)Value,
+ isPCRel,
+ MachoType,
+ Size,
+ Addend);
+ break;
+ case Triple::x86:
+ resolveI386Relocation(LocalAddress,
+ FinalAddress,
+ (uintptr_t)Value,
+ isPCRel,
+ MachoType,
+ Size,
+ Addend);
+ break;
+ case Triple::arm: // Fall through.
+ case Triple::thumb:
+ resolveARMRelocation(LocalAddress,
+ FinalAddress,
+ (uintptr_t)Value,
+ isPCRel,
+ MachoType,
+ Size,
+ Addend);
+ break;
+ }
+}
+
+bool RuntimeDyldMachO::resolveI386Relocation(uint8_t *LocalAddress,
+ uint64_t FinalAddress,
+ uint64_t Value,
+ bool isPCRel,
+ unsigned Type,
+ unsigned Size,
+ int64_t Addend) {
+ if (isPCRel)
+ Value -= FinalAddress + 4; // see resolveX86_64Relocation
+
+ switch (Type) {
+ default:
+ llvm_unreachable("Invalid relocation type!");
+ case MachO::GENERIC_RELOC_VANILLA: {
+ uint8_t *p = LocalAddress;
+ uint64_t ValueToWrite = Value + Addend;
+ for (unsigned i = 0; i < Size; ++i) {
+ *p++ = (uint8_t)(ValueToWrite & 0xff);
+ ValueToWrite >>= 8;
+ }
+ return false;
+ }
+ case MachO::GENERIC_RELOC_SECTDIFF:
+ case MachO::GENERIC_RELOC_LOCAL_SECTDIFF:
+ case MachO::GENERIC_RELOC_PB_LA_PTR:
+ return Error("Relocation type not implemented yet!");
+ }
+}
+
+bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress,
+ uint64_t FinalAddress,
+ uint64_t Value,
+ bool isPCRel,
+ unsigned Type,
+ unsigned Size,
+ int64_t Addend) {
+ // If the relocation is PC-relative, the value to be encoded is the
+ // pointer difference.
+ if (isPCRel)
+ // FIXME: It seems this value needs to be adjusted by 4 for an effective PC
+ // address. Is that expected? Only for branches, perhaps?
+ Value -= FinalAddress + 4;
+
+ switch(Type) {
+ default:
+ llvm_unreachable("Invalid relocation type!");
+ case MachO::X86_64_RELOC_SIGNED_1:
+ case MachO::X86_64_RELOC_SIGNED_2:
+ case MachO::X86_64_RELOC_SIGNED_4:
+ case MachO::X86_64_RELOC_SIGNED:
+ case MachO::X86_64_RELOC_UNSIGNED:
+ case MachO::X86_64_RELOC_BRANCH: {
+ Value += Addend;
+ // Mask in the target value a byte at a time (we don't have an alignment
+ // guarantee for the target address, so this is safest).
+ uint8_t *p = (uint8_t*)LocalAddress;
+ for (unsigned i = 0; i < Size; ++i) {
+ *p++ = (uint8_t)Value;
+ Value >>= 8;
+ }
+ return false;
+ }
+ case MachO::X86_64_RELOC_GOT_LOAD:
+ case MachO::X86_64_RELOC_GOT:
+ case MachO::X86_64_RELOC_SUBTRACTOR:
+ case MachO::X86_64_RELOC_TLV:
+ return Error("Relocation type not implemented yet!");
+ }
+}
+
+bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress,
+ uint64_t FinalAddress,
+ uint64_t Value,
+ bool isPCRel,
+ unsigned Type,
+ unsigned Size,
+ int64_t Addend) {
+ // If the relocation is PC-relative, the value to be encoded is the
+ // pointer difference.
+ if (isPCRel) {
+ Value -= FinalAddress;
+ // ARM PCRel relocations have an effective-PC offset of two instructions
+ // (four bytes in Thumb mode, 8 bytes in ARM mode).
+ // FIXME: For now, assume ARM mode.
+ Value -= 8;
+ }
+
+ switch(Type) {
+ default:
+ llvm_unreachable("Invalid relocation type!");
+ case MachO::ARM_RELOC_VANILLA: {
+ // Mask in the target value a byte at a time (we don't have an alignment
+ // guarantee for the target address, so this is safest).
+ uint8_t *p = (uint8_t*)LocalAddress;
+ for (unsigned i = 0; i < Size; ++i) {
+ *p++ = (uint8_t)Value;
+ Value >>= 8;
+ }
+ break;
+ }
+ case MachO::ARM_RELOC_BR24: {
+ // Mask the value into the target address. We know instructions are
+ // 32-bit aligned, so we can do it all at once.
+ uint32_t *p = (uint32_t*)LocalAddress;
+ // The low two bits of the value are not encoded.
+ Value >>= 2;
+ // Mask the value to 24 bits.
+ Value &= 0xffffff;
+ // FIXME: If the destination is a Thumb function (and the instruction
+ // is a non-predicated BL instruction), we need to change it to a BLX
+ // instruction instead.
+
+ // Insert the value into the instruction.
+ *p = (*p & ~0xffffff) | Value;
+ break;
+ }
+ case MachO::ARM_THUMB_RELOC_BR22:
+ case MachO::ARM_THUMB_32BIT_BRANCH:
+ case MachO::ARM_RELOC_HALF:
+ case MachO::ARM_RELOC_HALF_SECTDIFF:
+ case MachO::ARM_RELOC_PAIR:
+ case MachO::ARM_RELOC_SECTDIFF:
+ case MachO::ARM_RELOC_LOCAL_SECTDIFF:
+ case MachO::ARM_RELOC_PB_LA_PTR:
+ return Error("Relocation type not implemented yet!");
+ }
+ return false;
+}
+
+void RuntimeDyldMachO::processRelocationRef(unsigned SectionID,
+ RelocationRef RelI,
+ ObjectImage &Obj,
+ ObjSectionToIDMap &ObjSectionToID,
+ const SymbolTableMap &Symbols,
+ StubMap &Stubs) {
+ const ObjectFile *OF = Obj.getObjectFile();
+ const MachOObjectFile *MachO = static_cast<const MachOObjectFile*>(OF);
+ MachO::any_relocation_info RE= MachO->getRelocation(RelI.getRawDataRefImpl());
+
+ uint32_t RelType = MachO->getAnyRelocationType(RE);
+
+ // FIXME: Properly handle scattered relocations.
+ // For now, optimistically skip these: they can often be ignored, as
+ // the static linker will already have applied the relocation, and it
+ // only needs to be reapplied if symbols move relative to one another.
+ // Note: This will fail horribly where the relocations *do* need to be
+ // applied, but that was already the case.
+ if (MachO->isRelocationScattered(RE))
+ return;
+
+ RelocationValueRef Value;
+ SectionEntry &Section = Sections[SectionID];
+
+ bool isExtern = MachO->getPlainRelocationExternal(RE);
+ bool IsPCRel = MachO->getAnyRelocationPCRel(RE);
+ unsigned Size = MachO->getAnyRelocationLength(RE);
+ uint64_t Offset;
+ RelI.getOffset(Offset);
+ uint8_t *LocalAddress = Section.Address + Offset;
+ unsigned NumBytes = 1 << Size;
+ uint64_t Addend = 0;
+ memcpy(&Addend, LocalAddress, NumBytes);
+
+ if (isExtern) {
+ // Obtain the symbol name which is referenced in the relocation
+ symbol_iterator Symbol = RelI.getSymbol();
+ StringRef TargetName;
+ Symbol->getName(TargetName);
+ // First search for the symbol in the local symbol table
+ SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data());
+ if (lsi != Symbols.end()) {
+ Value.SectionID = lsi->second.first;
+ Value.Addend = lsi->second.second + Addend;
+ } else {
+ // Search for the symbol in the global symbol table
+ SymbolTableMap::const_iterator gsi = GlobalSymbolTable.find(TargetName.data());
+ if (gsi != GlobalSymbolTable.end()) {
+ Value.SectionID = gsi->second.first;
+ Value.Addend = gsi->second.second + Addend;
+ } else {
+ Value.SymbolName = TargetName.data();
+ Value.Addend = Addend;
+ }
+ }
+ } else {
+ SectionRef Sec = MachO->getRelocationSection(RE);
+ Value.SectionID = findOrEmitSection(Obj, Sec, true, ObjSectionToID);
+ uint64_t Addr;
+ Sec.getAddress(Addr);
+ Value.Addend = Addend - Addr;
+ }
+
+ if (Arch == Triple::x86_64 && (RelType == MachO::X86_64_RELOC_GOT ||
+ RelType == MachO::X86_64_RELOC_GOT_LOAD)) {
+ assert(IsPCRel);
+ assert(Size == 2);
+ StubMap::const_iterator i = Stubs.find(Value);
+ uint8_t *Addr;
+ if (i != Stubs.end()) {
+ Addr = Section.Address + i->second;
+ } else {
+ Stubs[Value] = Section.StubOffset;
+ uint8_t *GOTEntry = Section.Address + Section.StubOffset;
+ RelocationEntry RE(SectionID, Section.StubOffset,
+ MachO::X86_64_RELOC_UNSIGNED, 0, false, 3);
+ if (Value.SymbolName)
+ addRelocationForSymbol(RE, Value.SymbolName);
+ else
+ addRelocationForSection(RE, Value.SectionID);
+ Section.StubOffset += 8;
+ Addr = GOTEntry;
+ }
+ resolveRelocation(Section, Offset, (uint64_t)Addr,
+ MachO::X86_64_RELOC_UNSIGNED, Value.Addend, true, 2);
+ } else if (Arch == Triple::arm &&
+ (RelType & 0xf) == MachO::ARM_RELOC_BR24) {
+ // This is an ARM branch relocation, need to use a stub function.
+
+ // Look up for existing stub.
+ StubMap::const_iterator i = Stubs.find(Value);
+ if (i != Stubs.end())
+ resolveRelocation(Section, Offset,
+ (uint64_t)Section.Address + i->second,
+ RelType, 0, IsPCRel, Size);
+ else {
+ // Create a new stub function.
+ Stubs[Value] = Section.StubOffset;
+ uint8_t *StubTargetAddr = createStubFunction(Section.Address +
+ Section.StubOffset);
+ RelocationEntry RE(SectionID, StubTargetAddr - Section.Address,
+ MachO::GENERIC_RELOC_VANILLA, Value.Addend);
+ if (Value.SymbolName)
+ addRelocationForSymbol(RE, Value.SymbolName);
+ else
+ addRelocationForSection(RE, Value.SectionID);
+ resolveRelocation(Section, Offset,
+ (uint64_t)Section.Address + Section.StubOffset,
+ RelType, 0, IsPCRel, Size);
+ Section.StubOffset += getMaxStubSize();
+ }
+ } else {
+ RelocationEntry RE(SectionID, Offset, RelType, Value.Addend,
+ IsPCRel, Size);
+ if (Value.SymbolName)
+ addRelocationForSymbol(RE, Value.SymbolName);
+ else
+ addRelocationForSection(RE, Value.SectionID);
+ }
+}
+
+
+bool RuntimeDyldMachO::isCompatibleFormat(
+ const ObjectBuffer *InputBuffer) const {
+ if (InputBuffer->getBufferSize() < 4)
+ return false;
+ StringRef Magic(InputBuffer->getBufferStart(), 4);
+ if (Magic == "\xFE\xED\xFA\xCE") return true;
+ if (Magic == "\xCE\xFA\xED\xFE") return true;
+ if (Magic == "\xFE\xED\xFA\xCF") return true;
+ if (Magic == "\xCF\xFA\xED\xFE") return true;
+ return false;
+}
+
+} // end namespace llvm
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
new file mode 100644
index 000000000000..bbf6aa9f6506
--- /dev/null
+++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
@@ -0,0 +1,103 @@
+//===-- RuntimeDyldMachO.h - Run-time dynamic linker for MC-JIT ---*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// MachO support for MC-JIT runtime dynamic linker.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_RUNTIME_DYLD_MACHO_H
+#define LLVM_RUNTIME_DYLD_MACHO_H
+
+#include "RuntimeDyldImpl.h"
+#include "llvm/ADT/IndexedMap.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+using namespace llvm::object;
+
+
+namespace llvm {
+class RuntimeDyldMachO : public RuntimeDyldImpl {
+ bool resolveI386Relocation(uint8_t *LocalAddress,
+ uint64_t FinalAddress,
+ uint64_t Value,
+ bool isPCRel,
+ unsigned Type,
+ unsigned Size,
+ int64_t Addend);
+ bool resolveX86_64Relocation(uint8_t *LocalAddress,
+ uint64_t FinalAddress,
+ uint64_t Value,
+ bool isPCRel,
+ unsigned Type,
+ unsigned Size,
+ int64_t Addend);
+ bool resolveARMRelocation(uint8_t *LocalAddress,
+ uint64_t FinalAddress,
+ uint64_t Value,
+ bool isPCRel,
+ unsigned Type,
+ unsigned Size,
+ int64_t Addend);
+
+ void resolveRelocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend,
+ bool isPCRel,
+ unsigned Size);
+
+ unsigned getMaxStubSize() {
+ if (Arch == Triple::arm || Arch == Triple::thumb)
+ return 8; // 32-bit instruction and 32-bit address
+ else if (Arch == Triple::x86_64)
+ return 8; // GOT entry
+ else
+ return 0;
+ }
+
+ unsigned getStubAlignment() {
+ return 1;
+ }
+
+ struct EHFrameRelatedSections {
+ EHFrameRelatedSections() : EHFrameSID(RTDYLD_INVALID_SECTION_ID),
+ TextSID(RTDYLD_INVALID_SECTION_ID),
+ ExceptTabSID(RTDYLD_INVALID_SECTION_ID) {}
+ EHFrameRelatedSections(SID EH, SID T, SID Ex)
+ : EHFrameSID(EH), TextSID(T), ExceptTabSID(Ex) {}
+ SID EHFrameSID;
+ SID TextSID;
+ SID ExceptTabSID;
+ };
+
+ // When a module is loaded we save the SectionID of the EH frame section
+ // in a table until we receive a request to register all unregistered
+ // EH frame sections with the memory manager.
+ SmallVector<EHFrameRelatedSections, 2> UnregisteredEHFrameSections;
+public:
+ RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
+
+ virtual void resolveRelocation(const RelocationEntry &RE, uint64_t Value);
+ virtual void processRelocationRef(unsigned SectionID,
+ RelocationRef RelI,
+ ObjectImage &Obj,
+ ObjSectionToIDMap &ObjSectionToID,
+ const SymbolTableMap &Symbols,
+ StubMap &Stubs);
+ virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const;
+ virtual void registerEHFrames();
+ virtual void finalizeLoad(ObjSectionToIDMap &SectionMap);
+};
+
+} // end namespace llvm
+
+#endif