mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[MCJIT] Reapply r222828 and r222810-r222812 with fix for MSVC move-op issues.
llvm-svn: 222840
This commit is contained in:
parent
18c93c9af6
commit
787f3dbf64
@ -15,6 +15,7 @@
|
|||||||
#ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
|
#ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
|
||||||
#define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
|
#define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
|
||||||
|
|
||||||
|
#include "RuntimeDyld.h"
|
||||||
#include "llvm/Config/llvm-config.h"
|
#include "llvm/Config/llvm-config.h"
|
||||||
#include "llvm/IR/DebugLoc.h"
|
#include "llvm/IR/DebugLoc.h"
|
||||||
#include "llvm/Support/DataTypes.h"
|
#include "llvm/Support/DataTypes.h"
|
||||||
@ -25,7 +26,10 @@ class Function;
|
|||||||
class MachineFunction;
|
class MachineFunction;
|
||||||
class OProfileWrapper;
|
class OProfileWrapper;
|
||||||
class IntelJITEventsWrapper;
|
class IntelJITEventsWrapper;
|
||||||
class ObjectImage;
|
|
||||||
|
namespace object {
|
||||||
|
class ObjectFile;
|
||||||
|
}
|
||||||
|
|
||||||
/// JITEvent_EmittedFunctionDetails - Helper struct for containing information
|
/// JITEvent_EmittedFunctionDetails - Helper struct for containing information
|
||||||
/// about a generated machine code function.
|
/// about a generated machine code function.
|
||||||
@ -57,7 +61,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
JITEventListener() {}
|
JITEventListener() {}
|
||||||
virtual ~JITEventListener();
|
virtual ~JITEventListener() {}
|
||||||
|
|
||||||
/// NotifyObjectEmitted - Called after an object has been successfully
|
/// NotifyObjectEmitted - Called after an object has been successfully
|
||||||
/// emitted to memory. NotifyFunctionEmitted will not be called for
|
/// emitted to memory. NotifyFunctionEmitted will not be called for
|
||||||
@ -67,11 +71,15 @@ public:
|
|||||||
/// The ObjectImage contains the generated object image
|
/// The ObjectImage contains the generated object image
|
||||||
/// with section headers updated to reflect the address at which sections
|
/// with section headers updated to reflect the address at which sections
|
||||||
/// were loaded and with relocations performed in-place on debug sections.
|
/// were loaded and with relocations performed in-place on debug sections.
|
||||||
virtual void NotifyObjectEmitted(const ObjectImage &Obj) {}
|
virtual void NotifyObjectEmitted(const object::ObjectFile &Obj,
|
||||||
|
const RuntimeDyld::LoadedObjectInfo &L) {}
|
||||||
|
|
||||||
/// NotifyFreeingObject - Called just before the memory associated with
|
/// NotifyFreeingObject - Called just before the memory associated with
|
||||||
/// a previously emitted object is released.
|
/// a previously emitted object is released.
|
||||||
virtual void NotifyFreeingObject(const ObjectImage &Obj) {}
|
virtual void NotifyFreeingObject(const object::ObjectFile &Obj) {}
|
||||||
|
|
||||||
|
// Get a pointe to the GDB debugger registration listener.
|
||||||
|
static JITEventListener *createGDBRegistrationListener();
|
||||||
|
|
||||||
#if LLVM_USE_INTEL_JITEVENTS
|
#if LLVM_USE_INTEL_JITEVENTS
|
||||||
// Construct an IntelJITEventListener
|
// Construct an IntelJITEventListener
|
||||||
@ -105,7 +113,8 @@ public:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif // USE_OPROFILE
|
#endif // USE_OPROFILE
|
||||||
|
private:
|
||||||
|
virtual void anchor();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm.
|
} // end namespace llvm.
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
//===---- ObjectBuffer.h - Utility class to wrap object image memory -----===//
|
|
||||||
//
|
|
||||||
// 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 wrapper class to hold the memory into which an
|
|
||||||
// object will be generated.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef LLVM_EXECUTIONENGINE_OBJECTBUFFER_H
|
|
||||||
#define LLVM_EXECUTIONENGINE_OBJECTBUFFER_H
|
|
||||||
|
|
||||||
#include "llvm/ADT/SmallVector.h"
|
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
|
||||||
#include "llvm/Support/raw_ostream.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
|
|
||||||
/// This class acts as a container for the memory buffer used during generation
|
|
||||||
/// and loading of executable objects using MCJIT and RuntimeDyld. The
|
|
||||||
/// underlying memory for the object will be owned by the ObjectBuffer instance
|
|
||||||
/// throughout its lifetime.
|
|
||||||
class ObjectBuffer {
|
|
||||||
virtual void anchor();
|
|
||||||
public:
|
|
||||||
ObjectBuffer() {}
|
|
||||||
ObjectBuffer(std::unique_ptr<MemoryBuffer> Buf) : Buffer(std::move(Buf)) {}
|
|
||||||
virtual ~ObjectBuffer() {}
|
|
||||||
|
|
||||||
MemoryBufferRef getMemBuffer() const { return Buffer->getMemBufferRef(); }
|
|
||||||
|
|
||||||
const char *getBufferStart() const { return Buffer->getBufferStart(); }
|
|
||||||
size_t getBufferSize() const { return Buffer->getBufferSize(); }
|
|
||||||
StringRef getBuffer() const { return Buffer->getBuffer(); }
|
|
||||||
StringRef getBufferIdentifier() const {
|
|
||||||
return Buffer->getBufferIdentifier();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// The memory contained in an ObjectBuffer
|
|
||||||
std::unique_ptr<MemoryBuffer> Buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// This class encapsulates the SmallVector and raw_svector_ostream needed to
|
|
||||||
/// generate an object using MC code emission while providing a common
|
|
||||||
/// ObjectBuffer interface for access to the memory once the object has been
|
|
||||||
/// generated.
|
|
||||||
class ObjectBufferStream : public ObjectBuffer {
|
|
||||||
void anchor() override;
|
|
||||||
public:
|
|
||||||
ObjectBufferStream() : OS(SV) {}
|
|
||||||
virtual ~ObjectBufferStream() {}
|
|
||||||
|
|
||||||
raw_ostream &getOStream() { return OS; }
|
|
||||||
void flush()
|
|
||||||
{
|
|
||||||
OS.flush();
|
|
||||||
|
|
||||||
// Make the data accessible via the ObjectBuffer::Buffer
|
|
||||||
Buffer =
|
|
||||||
MemoryBuffer::getMemBuffer(StringRef(SV.data(), SV.size()), "", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
SmallVector<char, 4096> SV; // Working buffer into which we JIT.
|
|
||||||
raw_svector_ostream OS; // streaming wrapper
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace llvm
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,76 +0,0 @@
|
|||||||
//===---- ObjectImage.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_EXECUTIONENGINE_OBJECTIMAGE_H
|
|
||||||
#define LLVM_EXECUTIONENGINE_OBJECTIMAGE_H
|
|
||||||
|
|
||||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
|
||||||
#include "llvm/Object/ObjectFile.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
|
|
||||||
|
|
||||||
/// ObjectImage - A container class that represents an ObjectFile that has been
|
|
||||||
/// or is in the process of being loaded into memory for execution.
|
|
||||||
class ObjectImage {
|
|
||||||
ObjectImage() LLVM_DELETED_FUNCTION;
|
|
||||||
ObjectImage(const ObjectImage &other) LLVM_DELETED_FUNCTION;
|
|
||||||
virtual void anchor();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::unique_ptr<ObjectBuffer> Buffer;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ObjectImage(std::unique_ptr<ObjectBuffer> Input) : Buffer(std::move(Input)) {}
|
|
||||||
virtual ~ObjectImage() {}
|
|
||||||
|
|
||||||
virtual object::symbol_iterator begin_symbols() const = 0;
|
|
||||||
virtual object::symbol_iterator end_symbols() const = 0;
|
|
||||||
iterator_range<object::symbol_iterator> symbols() const {
|
|
||||||
return iterator_range<object::symbol_iterator>(begin_symbols(),
|
|
||||||
end_symbols());
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual object::section_iterator begin_sections() const = 0;
|
|
||||||
virtual object::section_iterator end_sections() const = 0;
|
|
||||||
iterator_range<object::section_iterator> sections() const {
|
|
||||||
return iterator_range<object::section_iterator>(begin_sections(),
|
|
||||||
end_sections());
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual /* Triple::ArchType */ unsigned getArch() const = 0;
|
|
||||||
|
|
||||||
// Return the name associated with this ObjectImage.
|
|
||||||
// This is usually the name of the file or MemoryBuffer that the the
|
|
||||||
// ObjectBuffer was constructed from.
|
|
||||||
StringRef getImageName() const { return Buffer->getBufferIdentifier(); }
|
|
||||||
|
|
||||||
// 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) = 0;
|
|
||||||
virtual void updateSymbolAddress(const object::SymbolRef &Sym,
|
|
||||||
uint64_t Addr) = 0;
|
|
||||||
|
|
||||||
virtual StringRef getData() const = 0;
|
|
||||||
|
|
||||||
virtual object::ObjectFile* getObjectFile() const = 0;
|
|
||||||
|
|
||||||
// Subclasses can override these methods to provide JIT debugging support
|
|
||||||
virtual void registerWithDebugger() = 0;
|
|
||||||
virtual void deregisterWithDebugger() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace llvm
|
|
||||||
|
|
||||||
#endif // LLVM_EXECUTIONENGINE_OBJECTIMAGE_H
|
|
@ -22,7 +22,10 @@
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class ExecutionEngine;
|
class ExecutionEngine;
|
||||||
class ObjectImage;
|
|
||||||
|
namespace object {
|
||||||
|
class ObjectFile;
|
||||||
|
}
|
||||||
|
|
||||||
// RuntimeDyld clients often want to handle the memory management of
|
// RuntimeDyld clients often want to handle the memory management of
|
||||||
// what gets placed where. For JIT clients, this is the subset of
|
// what gets placed where. For JIT clients, this is the subset of
|
||||||
@ -109,7 +112,7 @@ public:
|
|||||||
/// address space can use this call to remap the section addresses for the
|
/// address space can use this call to remap the section addresses for the
|
||||||
/// newly loaded object.
|
/// newly loaded object.
|
||||||
virtual void notifyObjectLoaded(ExecutionEngine *EE,
|
virtual void notifyObjectLoaded(ExecutionEngine *EE,
|
||||||
const ObjectImage *) {}
|
const object::ObjectFile &) {}
|
||||||
|
|
||||||
/// This method is called when object loading is complete and section page
|
/// This method is called when object loading is complete and section page
|
||||||
/// permissions can be applied. It is up to the memory manager implementation
|
/// permissions can be applied. It is up to the memory manager implementation
|
||||||
|
@ -15,19 +15,19 @@
|
|||||||
#define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H
|
#define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H
|
||||||
|
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
|
||||||
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
||||||
#include "llvm/Support/Memory.h"
|
#include "llvm/Support/Memory.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
namespace object {
|
namespace object {
|
||||||
class ObjectFile;
|
class ObjectFile;
|
||||||
|
template <typename T> class OwningBinary;
|
||||||
}
|
}
|
||||||
|
|
||||||
class RuntimeDyldImpl;
|
class RuntimeDyldImpl;
|
||||||
class RuntimeDyldCheckerImpl;
|
class RuntimeDyldCheckerImpl;
|
||||||
class ObjectImage;
|
|
||||||
|
|
||||||
class RuntimeDyld {
|
class RuntimeDyld {
|
||||||
friend class RuntimeDyldCheckerImpl;
|
friend class RuntimeDyldCheckerImpl;
|
||||||
@ -46,22 +46,35 @@ protected:
|
|||||||
// Any relocations already associated with the symbol will be re-resolved.
|
// Any relocations already associated with the symbol will be re-resolved.
|
||||||
void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
|
void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/// \brief Information about the loaded object.
|
||||||
|
class LoadedObjectInfo {
|
||||||
|
friend class RuntimeDyldImpl;
|
||||||
|
public:
|
||||||
|
LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
|
||||||
|
unsigned EndIdx)
|
||||||
|
: RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { }
|
||||||
|
|
||||||
|
virtual ~LoadedObjectInfo() {}
|
||||||
|
|
||||||
|
virtual object::OwningBinary<object::ObjectFile>
|
||||||
|
getObjectForDebug(const object::ObjectFile &Obj) const = 0;
|
||||||
|
|
||||||
|
uint64_t getSectionLoadAddress(StringRef Name) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void anchor();
|
||||||
|
|
||||||
|
RuntimeDyldImpl &RTDyld;
|
||||||
|
unsigned BeginIdx, EndIdx;
|
||||||
|
};
|
||||||
|
|
||||||
RuntimeDyld(RTDyldMemoryManager *);
|
RuntimeDyld(RTDyldMemoryManager *);
|
||||||
~RuntimeDyld();
|
~RuntimeDyld();
|
||||||
|
|
||||||
/// Prepare the object contained in the input buffer for execution.
|
/// Add the referenced object file to the list of objects to be loaded and
|
||||||
/// Ownership of the input buffer is transferred to the ObjectImage
|
/// relocated.
|
||||||
/// instance returned from this function if successful. In the case of load
|
std::unique_ptr<LoadedObjectInfo> loadObject(const object::ObjectFile &O);
|
||||||
/// failure, the input buffer will be deleted.
|
|
||||||
std::unique_ptr<ObjectImage>
|
|
||||||
loadObject(std::unique_ptr<ObjectBuffer> InputBuffer);
|
|
||||||
|
|
||||||
/// Prepare the referenced object file for execution.
|
|
||||||
/// Ownership of the input object is transferred to the ObjectImage
|
|
||||||
/// instance returned from this function if successful. In the case of load
|
|
||||||
/// failure, the input object will be deleted.
|
|
||||||
std::unique_ptr<ObjectImage>
|
|
||||||
loadObject(std::unique_ptr<object::ObjectFile> InputObject);
|
|
||||||
|
|
||||||
/// Get the address of our local copy of the symbol. This may or may not
|
/// Get the address of our local copy of the symbol. This may or may not
|
||||||
/// be the address used for relocation (clients can copy the data around
|
/// be the address used for relocation (clients can copy the data around
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
add_llvm_library(LLVMExecutionEngine
|
add_llvm_library(LLVMExecutionEngine
|
||||||
ExecutionEngine.cpp
|
ExecutionEngine.cpp
|
||||||
ExecutionEngineBindings.cpp
|
ExecutionEngineBindings.cpp
|
||||||
JITEventListener.cpp
|
|
||||||
RTDyldMemoryManager.cpp
|
RTDyldMemoryManager.cpp
|
||||||
TargetSelect.cpp
|
TargetSelect.cpp
|
||||||
)
|
)
|
||||||
|
@ -16,8 +16,7 @@
|
|||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
#include "llvm/ExecutionEngine/JITEventListener.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectCache.h"
|
|
||||||
#include "llvm/IR/Constants.h"
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/DataLayout.h"
|
#include "llvm/IR/DataLayout.h"
|
||||||
#include "llvm/IR/DerivedTypes.h"
|
#include "llvm/IR/DerivedTypes.h"
|
||||||
@ -43,17 +42,15 @@ using namespace llvm;
|
|||||||
STATISTIC(NumInitBytes, "Number of bytes of global vars initialized");
|
STATISTIC(NumInitBytes, "Number of bytes of global vars initialized");
|
||||||
STATISTIC(NumGlobals , "Number of global vars initialized");
|
STATISTIC(NumGlobals , "Number of global vars initialized");
|
||||||
|
|
||||||
// Pin the vtable to this file.
|
|
||||||
void ObjectCache::anchor() {}
|
|
||||||
void ObjectBuffer::anchor() {}
|
|
||||||
void ObjectBufferStream::anchor() {}
|
|
||||||
|
|
||||||
ExecutionEngine *(*ExecutionEngine::MCJITCtor)(
|
ExecutionEngine *(*ExecutionEngine::MCJITCtor)(
|
||||||
std::unique_ptr<Module> M, std::string *ErrorStr,
|
std::unique_ptr<Module> M, std::string *ErrorStr,
|
||||||
RTDyldMemoryManager *MCJMM, std::unique_ptr<TargetMachine> TM) = nullptr;
|
RTDyldMemoryManager *MCJMM, std::unique_ptr<TargetMachine> TM) = nullptr;
|
||||||
ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr<Module> M,
|
ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr<Module> M,
|
||||||
std::string *ErrorStr) =nullptr;
|
std::string *ErrorStr) =nullptr;
|
||||||
|
|
||||||
|
// Anchor for the JITEventListener class.
|
||||||
|
void JITEventListener::anchor() {}
|
||||||
|
|
||||||
ExecutionEngine::ExecutionEngine(std::unique_ptr<Module> M)
|
ExecutionEngine::ExecutionEngine(std::unique_ptr<Module> M)
|
||||||
: EEState(*this),
|
: EEState(*this),
|
||||||
LazyFunctionCreator(nullptr) {
|
LazyFunctionCreator(nullptr) {
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
#include "llvm/DebugInfo/DIContext.h"
|
#include "llvm/DebugInfo/DIContext.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
|
||||||
#include "llvm/Object/ObjectFile.h"
|
#include "llvm/Object/ObjectFile.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
@ -32,6 +31,7 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::jitprofiling;
|
using namespace llvm::jitprofiling;
|
||||||
|
using namespace llvm::object;
|
||||||
|
|
||||||
#define DEBUG_TYPE "amplifier-jit-event-listener"
|
#define DEBUG_TYPE "amplifier-jit-event-listener"
|
||||||
|
|
||||||
@ -48,6 +48,7 @@ class IntelJITEventListener : public JITEventListener {
|
|||||||
typedef DenseMap<const void *, MethodAddressVector> ObjectMap;
|
typedef DenseMap<const void *, MethodAddressVector> ObjectMap;
|
||||||
|
|
||||||
ObjectMap LoadedObjectMap;
|
ObjectMap LoadedObjectMap;
|
||||||
|
std::map<const char*, OwningBinary<ObjectFile>> DebugObjects;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IntelJITEventListener(IntelJITEventsWrapper* libraryWrapper) {
|
IntelJITEventListener(IntelJITEventsWrapper* libraryWrapper) {
|
||||||
@ -57,9 +58,10 @@ public:
|
|||||||
~IntelJITEventListener() {
|
~IntelJITEventListener() {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void NotifyObjectEmitted(const ObjectImage &Obj);
|
void NotifyObjectEmitted(const ObjectFile &Obj,
|
||||||
|
const RuntimeDyld::LoadedObjectInfo &L) override;
|
||||||
|
|
||||||
virtual void NotifyFreeingObject(const ObjectImage &Obj);
|
void NotifyFreeingObject(const ObjectFile &Obj) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
static LineNumberInfo DILineInfoToIntelJITFormat(uintptr_t StartAddress,
|
static LineNumberInfo DILineInfoToIntelJITFormat(uintptr_t StartAddress,
|
||||||
@ -95,23 +97,29 @@ static iJIT_Method_Load FunctionDescToIntelJITFormat(
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntelJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) {
|
void IntelJITEventListener::NotifyObjectEmitted(
|
||||||
|
const ObjectFile &Obj,
|
||||||
|
const RuntimeDyld::LoadedObjectInfo &L) {
|
||||||
|
|
||||||
|
OwningBinary<ObjectFile> DebugObjOwner = L.getObjectForDebug(Obj);
|
||||||
|
const ObjectFile &DebugObj = *DebugObjOwner.getBinary();
|
||||||
|
|
||||||
// Get the address of the object image for use as a unique identifier
|
// Get the address of the object image for use as a unique identifier
|
||||||
const void* ObjData = Obj.getData().data();
|
const void* ObjData = DebugObj.getData().data();
|
||||||
DIContext* Context = DIContext::getDWARFContext(*Obj.getObjectFile());
|
DIContext* Context = DIContext::getDWARFContext(DebugObj);
|
||||||
MethodAddressVector Functions;
|
MethodAddressVector Functions;
|
||||||
|
|
||||||
// Use symbol info to iterate functions in the object.
|
// Use symbol info to iterate functions in the object.
|
||||||
for (object::symbol_iterator I = Obj.begin_symbols(),
|
for (symbol_iterator I = DebugObj.symbol_begin(),
|
||||||
E = Obj.end_symbols();
|
E = DebugObj.symbol_end();
|
||||||
I != E;
|
I != E;
|
||||||
++I) {
|
++I) {
|
||||||
std::vector<LineNumberInfo> LineInfo;
|
std::vector<LineNumberInfo> LineInfo;
|
||||||
std::string SourceFileName;
|
std::string SourceFileName;
|
||||||
|
|
||||||
object::SymbolRef::Type SymType;
|
SymbolRef::Type SymType;
|
||||||
if (I->getType(SymType)) continue;
|
if (I->getType(SymType)) continue;
|
||||||
if (SymType == object::SymbolRef::ST_Function) {
|
if (SymType == SymbolRef::ST_Function) {
|
||||||
StringRef Name;
|
StringRef Name;
|
||||||
uint64_t Addr;
|
uint64_t Addr;
|
||||||
uint64_t Size;
|
uint64_t Size;
|
||||||
@ -162,11 +170,18 @@ void IntelJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) {
|
|||||||
// registered function addresses for each loaded object. We will
|
// registered function addresses for each loaded object. We will
|
||||||
// use the MethodIDs map to get the registered ID for each function.
|
// use the MethodIDs map to get the registered ID for each function.
|
||||||
LoadedObjectMap[ObjData] = Functions;
|
LoadedObjectMap[ObjData] = Functions;
|
||||||
|
DebugObjects[Obj.getData().data()] = std::move(DebugObjOwner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntelJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) {
|
void IntelJITEventListener::NotifyFreeingObject(const ObjectFile &Obj) {
|
||||||
|
// This object may not have been registered with the listener. If it wasn't,
|
||||||
|
// bail out.
|
||||||
|
if (DebugObjects.find(Obj.getData().data()) == DebugObjects.end())
|
||||||
|
return;
|
||||||
|
|
||||||
// Get the address of the object image for use as a unique identifier
|
// Get the address of the object image for use as a unique identifier
|
||||||
const void* ObjData = Obj.getData().data();
|
const ObjectFile &DebugObj = *DebugObjects[Obj.getData().data()].getBinary();
|
||||||
|
const void* ObjData = DebugObj.getData().data();
|
||||||
|
|
||||||
// Get the object's function list from LoadedObjectMap
|
// Get the object's function list from LoadedObjectMap
|
||||||
ObjectMap::iterator OI = LoadedObjectMap.find(ObjData);
|
ObjectMap::iterator OI = LoadedObjectMap.find(ObjData);
|
||||||
@ -190,6 +205,7 @@ void IntelJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) {
|
|||||||
|
|
||||||
// Erase the object from LoadedObjectMap
|
// Erase the object from LoadedObjectMap
|
||||||
LoadedObjectMap.erase(OI);
|
LoadedObjectMap.erase(OI);
|
||||||
|
DebugObjects.erase(Obj.getData().data());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace.
|
} // anonymous namespace.
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
//===-- JITEventListener.cpp ----------------------------------------------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "llvm/ExecutionEngine/JITEventListener.h"
|
|
||||||
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
// Out-of-line definition of the virtual destructor as this is the key function.
|
|
||||||
JITEventListener::~JITEventListener() {}
|
|
@ -11,8 +11,6 @@
|
|||||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||||
#include "llvm/ExecutionEngine/JITEventListener.h"
|
#include "llvm/ExecutionEngine/JITEventListener.h"
|
||||||
#include "llvm/ExecutionEngine/MCJIT.h"
|
#include "llvm/ExecutionEngine/MCJIT.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
|
||||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
|
||||||
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
||||||
#include "llvm/IR/DataLayout.h"
|
#include "llvm/IR/DataLayout.h"
|
||||||
#include "llvm/IR/DerivedTypes.h"
|
#include "llvm/IR/DerivedTypes.h"
|
||||||
@ -21,6 +19,7 @@
|
|||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
#include "llvm/MC/MCAsmInfo.h"
|
#include "llvm/MC/MCAsmInfo.h"
|
||||||
#include "llvm/Object/Archive.h"
|
#include "llvm/Object/Archive.h"
|
||||||
|
#include "llvm/Object/ObjectFile.h"
|
||||||
#include "llvm/PassManager.h"
|
#include "llvm/PassManager.h"
|
||||||
#include "llvm/Support/DynamicLibrary.h"
|
#include "llvm/Support/DynamicLibrary.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
@ -31,6 +30,8 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
void ObjectCache::anchor() {}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static struct RegisterJIT {
|
static struct RegisterJIT {
|
||||||
@ -74,6 +75,7 @@ MCJIT::MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> tm,
|
|||||||
|
|
||||||
OwnedModules.addModule(std::move(First));
|
OwnedModules.addModule(std::move(First));
|
||||||
setDataLayout(TM->getSubtargetImpl()->getDataLayout());
|
setDataLayout(TM->getSubtargetImpl()->getDataLayout());
|
||||||
|
RegisterJITEventListener(JITEventListener::createGDBRegistrationListener());
|
||||||
}
|
}
|
||||||
|
|
||||||
MCJIT::~MCJIT() {
|
MCJIT::~MCJIT() {
|
||||||
@ -99,13 +101,13 @@ bool MCJIT::removeModule(Module *M) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MCJIT::addObjectFile(std::unique_ptr<object::ObjectFile> Obj) {
|
void MCJIT::addObjectFile(std::unique_ptr<object::ObjectFile> Obj) {
|
||||||
std::unique_ptr<ObjectImage> LoadedObject = Dyld.loadObject(std::move(Obj));
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L = Dyld.loadObject(*Obj);
|
||||||
if (!LoadedObject || Dyld.hasError())
|
if (Dyld.hasError())
|
||||||
report_fatal_error(Dyld.getErrorString());
|
report_fatal_error(Dyld.getErrorString());
|
||||||
|
|
||||||
NotifyObjectEmitted(*LoadedObject);
|
NotifyObjectEmitted(*Obj, *L);
|
||||||
|
|
||||||
LoadedObjects.push_back(std::move(LoadedObject));
|
LoadedObjects.push_back(std::move(Obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCJIT::addObjectFile(object::OwningBinary<object::ObjectFile> Obj) {
|
void MCJIT::addObjectFile(object::OwningBinary<object::ObjectFile> Obj) {
|
||||||
@ -125,7 +127,7 @@ void MCJIT::setObjectCache(ObjectCache* NewCache) {
|
|||||||
ObjCache = NewCache;
|
ObjCache = NewCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ObjectBufferStream> MCJIT::emitObject(Module *M) {
|
std::unique_ptr<MemoryBuffer> MCJIT::emitObject(Module *M) {
|
||||||
MutexGuard locked(lock);
|
MutexGuard locked(lock);
|
||||||
|
|
||||||
// This must be a module which has already been added but not loaded to this
|
// This must be a module which has already been added but not loaded to this
|
||||||
@ -138,30 +140,32 @@ std::unique_ptr<ObjectBufferStream> MCJIT::emitObject(Module *M) {
|
|||||||
PM.add(new DataLayoutPass());
|
PM.add(new DataLayoutPass());
|
||||||
|
|
||||||
// The RuntimeDyld will take ownership of this shortly
|
// The RuntimeDyld will take ownership of this shortly
|
||||||
std::unique_ptr<ObjectBufferStream> CompiledObject(new ObjectBufferStream());
|
SmallVector<char, 4096> ObjBufferSV;
|
||||||
|
raw_svector_ostream ObjStream(ObjBufferSV);
|
||||||
|
|
||||||
// Turn the machine code intermediate representation into bytes in memory
|
// Turn the machine code intermediate representation into bytes in memory
|
||||||
// that may be executed.
|
// that may be executed.
|
||||||
if (TM->addPassesToEmitMC(PM, Ctx, CompiledObject->getOStream(),
|
if (TM->addPassesToEmitMC(PM, Ctx, ObjStream, !getVerifyModules()))
|
||||||
!getVerifyModules())) {
|
|
||||||
report_fatal_error("Target does not support MC emission!");
|
report_fatal_error("Target does not support MC emission!");
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize passes.
|
// Initialize passes.
|
||||||
PM.run(*M);
|
PM.run(*M);
|
||||||
// Flush the output buffer to get the generated code into memory
|
// Flush the output buffer to get the generated code into memory
|
||||||
CompiledObject->flush();
|
ObjStream.flush();
|
||||||
|
|
||||||
|
std::unique_ptr<MemoryBuffer> CompiledObjBuffer(
|
||||||
|
new ObjectMemoryBuffer(std::move(ObjBufferSV)));
|
||||||
|
|
||||||
// If we have an object cache, tell it about the new object.
|
// If we have an object cache, tell it about the new object.
|
||||||
// Note that we're using the compiled image, not the loaded image (as below).
|
// Note that we're using the compiled image, not the loaded image (as below).
|
||||||
if (ObjCache) {
|
if (ObjCache) {
|
||||||
// MemoryBuffer is a thin wrapper around the actual memory, so it's OK
|
// MemoryBuffer is a thin wrapper around the actual memory, so it's OK
|
||||||
// to create a temporary object here and delete it after the call.
|
// to create a temporary object here and delete it after the call.
|
||||||
MemoryBufferRef MB = CompiledObject->getMemBuffer();
|
MemoryBufferRef MB = CompiledObjBuffer->getMemBufferRef();
|
||||||
ObjCache->notifyObjectCompiled(M, MB);
|
ObjCache->notifyObjectCompiled(M, MB);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CompiledObject;
|
return CompiledObjBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCJIT::generateCodeForModule(Module *M) {
|
void MCJIT::generateCodeForModule(Module *M) {
|
||||||
@ -176,14 +180,10 @@ void MCJIT::generateCodeForModule(Module *M) {
|
|||||||
if (OwnedModules.hasModuleBeenLoaded(M))
|
if (OwnedModules.hasModuleBeenLoaded(M))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::unique_ptr<ObjectBuffer> ObjectToLoad;
|
std::unique_ptr<MemoryBuffer> ObjectToLoad;
|
||||||
// Try to load the pre-compiled object from cache if possible
|
// Try to load the pre-compiled object from cache if possible
|
||||||
if (ObjCache) {
|
if (ObjCache)
|
||||||
if (std::unique_ptr<MemoryBuffer> PreCompiledObject =
|
ObjectToLoad = ObjCache->getObject(M);
|
||||||
ObjCache->getObject(M))
|
|
||||||
ObjectToLoad =
|
|
||||||
llvm::make_unique<ObjectBuffer>(std::move(PreCompiledObject));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the cache did not contain a suitable object, compile the object
|
// If the cache did not contain a suitable object, compile the object
|
||||||
if (!ObjectToLoad) {
|
if (!ObjectToLoad) {
|
||||||
@ -193,17 +193,18 @@ void MCJIT::generateCodeForModule(Module *M) {
|
|||||||
|
|
||||||
// Load the object into the dynamic linker.
|
// Load the object into the dynamic linker.
|
||||||
// MCJIT now owns the ObjectImage pointer (via its LoadedObjects list).
|
// MCJIT now owns the ObjectImage pointer (via its LoadedObjects list).
|
||||||
std::unique_ptr<ObjectImage> LoadedObject =
|
ErrorOr<std::unique_ptr<object::ObjectFile>> LoadedObject =
|
||||||
Dyld.loadObject(std::move(ObjectToLoad));
|
object::ObjectFile::createObjectFile(ObjectToLoad->getMemBufferRef());
|
||||||
if (!LoadedObject)
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L =
|
||||||
|
Dyld.loadObject(*LoadedObject.get());
|
||||||
|
|
||||||
|
if (Dyld.hasError())
|
||||||
report_fatal_error(Dyld.getErrorString());
|
report_fatal_error(Dyld.getErrorString());
|
||||||
|
|
||||||
// FIXME: Make this optional, maybe even move it to a JIT event listener
|
NotifyObjectEmitted(*LoadedObject.get(), *L);
|
||||||
LoadedObject->registerWithDebugger();
|
|
||||||
|
|
||||||
NotifyObjectEmitted(*LoadedObject);
|
Buffers.push_back(std::move(ObjectToLoad));
|
||||||
|
LoadedObjects.push_back(std::move(*LoadedObject));
|
||||||
LoadedObjects.push_back(std::move(LoadedObject));
|
|
||||||
|
|
||||||
OwnedModules.markModuleAsLoaded(M);
|
OwnedModules.markModuleAsLoaded(M);
|
||||||
}
|
}
|
||||||
@ -549,6 +550,7 @@ void MCJIT::RegisterJITEventListener(JITEventListener *L) {
|
|||||||
MutexGuard locked(lock);
|
MutexGuard locked(lock);
|
||||||
EventListeners.push_back(L);
|
EventListeners.push_back(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCJIT::UnregisterJITEventListener(JITEventListener *L) {
|
void MCJIT::UnregisterJITEventListener(JITEventListener *L) {
|
||||||
if (!L)
|
if (!L)
|
||||||
return;
|
return;
|
||||||
@ -559,14 +561,17 @@ void MCJIT::UnregisterJITEventListener(JITEventListener *L) {
|
|||||||
EventListeners.pop_back();
|
EventListeners.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void MCJIT::NotifyObjectEmitted(const ObjectImage& Obj) {
|
|
||||||
|
void MCJIT::NotifyObjectEmitted(const object::ObjectFile& Obj,
|
||||||
|
const RuntimeDyld::LoadedObjectInfo &L) {
|
||||||
MutexGuard locked(lock);
|
MutexGuard locked(lock);
|
||||||
MemMgr.notifyObjectLoaded(this, &Obj);
|
MemMgr.notifyObjectLoaded(this, Obj);
|
||||||
for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) {
|
for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) {
|
||||||
EventListeners[I]->NotifyObjectEmitted(Obj);
|
EventListeners[I]->NotifyObjectEmitted(Obj, L);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void MCJIT::NotifyFreeingObject(const ObjectImage& Obj) {
|
|
||||||
|
void MCJIT::NotifyFreeingObject(const object::ObjectFile& Obj) {
|
||||||
MutexGuard locked(lock);
|
MutexGuard locked(lock);
|
||||||
for (JITEventListener *L : EventListeners)
|
for (JITEventListener *L : EventListeners)
|
||||||
L->NotifyFreeingObject(Obj);
|
L->NotifyFreeingObject(Obj);
|
||||||
|
@ -10,12 +10,12 @@
|
|||||||
#ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H
|
#ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H
|
||||||
#define LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H
|
#define LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H
|
||||||
|
|
||||||
|
#include "ObjectBuffer.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectCache.h"
|
#include "llvm/ExecutionEngine/ObjectCache.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
|
||||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void notifyObjectLoaded(ExecutionEngine *EE,
|
void notifyObjectLoaded(ExecutionEngine *EE,
|
||||||
const ObjectImage *Obj) override {
|
const object::ObjectFile &Obj) override {
|
||||||
ClientMM->notifyObjectLoaded(EE, Obj);
|
ClientMM->notifyObjectLoaded(EE, Obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ class MCJIT : public ExecutionEngine {
|
|||||||
SmallVector<object::OwningBinary<object::Archive>, 2> Archives;
|
SmallVector<object::OwningBinary<object::Archive>, 2> Archives;
|
||||||
SmallVector<std::unique_ptr<MemoryBuffer>, 2> Buffers;
|
SmallVector<std::unique_ptr<MemoryBuffer>, 2> Buffers;
|
||||||
|
|
||||||
SmallVector<std::unique_ptr<ObjectImage>, 2> LoadedObjects;
|
SmallVector<std::unique_ptr<object::ObjectFile>, 2> LoadedObjects;
|
||||||
|
|
||||||
// An optional ObjectCache to be notified of compiled objects and used to
|
// An optional ObjectCache to be notified of compiled objects and used to
|
||||||
// perform lookup of pre-compiled code to avoid re-compilation.
|
// perform lookup of pre-compiled code to avoid re-compilation.
|
||||||
@ -341,10 +341,11 @@ protected:
|
|||||||
/// this function call is expected to be the contained module. The module
|
/// this function call is expected to be the contained module. The module
|
||||||
/// is passed as a parameter here to prepare for multiple module support in
|
/// is passed as a parameter here to prepare for multiple module support in
|
||||||
/// the future.
|
/// the future.
|
||||||
std::unique_ptr<ObjectBufferStream> emitObject(Module *M);
|
std::unique_ptr<MemoryBuffer> emitObject(Module *M);
|
||||||
|
|
||||||
void NotifyObjectEmitted(const ObjectImage& Obj);
|
void NotifyObjectEmitted(const object::ObjectFile& Obj,
|
||||||
void NotifyFreeingObject(const ObjectImage& Obj);
|
const RuntimeDyld::LoadedObjectInfo &L);
|
||||||
|
void NotifyFreeingObject(const object::ObjectFile& Obj);
|
||||||
|
|
||||||
uint64_t getExistingSymbolAddress(const std::string &Name);
|
uint64_t getExistingSymbolAddress(const std::string &Name);
|
||||||
Module *findModuleForSymbol(const std::string &Name,
|
Module *findModuleForSymbol(const std::string &Name,
|
||||||
|
48
lib/ExecutionEngine/MCJIT/ObjectBuffer.h
Normal file
48
lib/ExecutionEngine/MCJIT/ObjectBuffer.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
//===--- ObjectBuffer.h - Utility class to wrap object memory ---*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// 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 wrapper class to hold the memory into which an
|
||||||
|
// object will be generated.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_EXECUTIONENGINE_OBJECTBUFFER_H
|
||||||
|
#define LLVM_EXECUTIONENGINE_OBJECTBUFFER_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
class ObjectMemoryBuffer : public MemoryBuffer {
|
||||||
|
public:
|
||||||
|
template <unsigned N>
|
||||||
|
ObjectMemoryBuffer(SmallVector<char, N> SV)
|
||||||
|
: SV(SV), BufferName("<in-memory object>") {
|
||||||
|
init(this->SV.begin(), this->SV.end(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <unsigned N>
|
||||||
|
ObjectMemoryBuffer(SmallVector<char, N> SV, StringRef Name)
|
||||||
|
: SV(SV), BufferName(Name) {
|
||||||
|
init(this->SV.begin(), this->SV.end(), false);
|
||||||
|
}
|
||||||
|
const char* getBufferIdentifier() const override { return BufferName.c_str(); }
|
||||||
|
|
||||||
|
BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
SmallVector<char, 4096> SV;
|
||||||
|
std::string BufferName;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace llvm
|
||||||
|
|
||||||
|
#endif
|
@ -18,8 +18,8 @@
|
|||||||
#include "llvm/IR/DebugInfo.h"
|
#include "llvm/IR/DebugInfo.h"
|
||||||
#include "llvm/IR/Function.h"
|
#include "llvm/IR/Function.h"
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
|
||||||
#include "llvm/ExecutionEngine/OProfileWrapper.h"
|
#include "llvm/ExecutionEngine/OProfileWrapper.h"
|
||||||
|
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||||
#include "llvm/Object/ObjectFile.h"
|
#include "llvm/Object/ObjectFile.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
@ -31,31 +31,34 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::jitprofiling;
|
using namespace llvm::jitprofiling;
|
||||||
|
using namespace llvm::object;
|
||||||
|
|
||||||
#define DEBUG_TYPE "oprofile-jit-event-listener"
|
#define DEBUG_TYPE "oprofile-jit-event-listener"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class OProfileJITEventListener : public JITEventListener {
|
class OProfileJITEventListener : public JITEventListener {
|
||||||
OProfileWrapper& Wrapper;
|
std::unique_ptr<OProfileWrapper> Wrapper;
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
|
std::map<const char*, OwningBinary<ObjectFile>> DebugObjects;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OProfileJITEventListener(OProfileWrapper& LibraryWrapper)
|
OProfileJITEventListener(std::unique_ptr<OProfileWrapper> LibraryWrapper)
|
||||||
: Wrapper(LibraryWrapper) {
|
: Wrapper(std::move(LibraryWrapper)) {
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
~OProfileJITEventListener();
|
~OProfileJITEventListener();
|
||||||
|
|
||||||
virtual void NotifyObjectEmitted(const ObjectImage &Obj);
|
void NotifyObjectEmitted(const ObjectFile &Obj,
|
||||||
|
const RuntimeDyld::LoadedObjectInfo &L) override;
|
||||||
|
|
||||||
virtual void NotifyFreeingObject(const ObjectImage &Obj);
|
void NotifyFreeingObject(const ObjectFile &Obj) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
void OProfileJITEventListener::initialize() {
|
void OProfileJITEventListener::initialize() {
|
||||||
if (!Wrapper.op_open_agent()) {
|
if (!Wrapper->op_open_agent()) {
|
||||||
const std::string err_str = sys::StrError();
|
const std::string err_str = sys::StrError();
|
||||||
DEBUG(dbgs() << "Failed to connect to OProfile agent: " << err_str << "\n");
|
DEBUG(dbgs() << "Failed to connect to OProfile agent: " << err_str << "\n");
|
||||||
} else {
|
} else {
|
||||||
@ -64,8 +67,8 @@ void OProfileJITEventListener::initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OProfileJITEventListener::~OProfileJITEventListener() {
|
OProfileJITEventListener::~OProfileJITEventListener() {
|
||||||
if (Wrapper.isAgentAvailable()) {
|
if (Wrapper->isAgentAvailable()) {
|
||||||
if (Wrapper.op_close_agent() == -1) {
|
if (Wrapper->op_close_agent() == -1) {
|
||||||
const std::string err_str = sys::StrError();
|
const std::string err_str = sys::StrError();
|
||||||
DEBUG(dbgs() << "Failed to disconnect from OProfile agent: "
|
DEBUG(dbgs() << "Failed to disconnect from OProfile agent: "
|
||||||
<< err_str << "\n");
|
<< err_str << "\n");
|
||||||
@ -75,17 +78,22 @@ OProfileJITEventListener::~OProfileJITEventListener() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OProfileJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) {
|
void OProfileJITEventListener::NotifyObjectEmitted(
|
||||||
if (!Wrapper.isAgentAvailable()) {
|
const ObjectFile &Obj,
|
||||||
|
const RuntimeDyld::LoadedObjectInfo &L) {
|
||||||
|
if (!Wrapper->isAgentAvailable()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OwningBinary<ObjectFile> DebugObjOwner = L.getObjectForDebug(Obj);
|
||||||
|
const ObjectFile &DebugObj = *DebugObjOwner.getBinary();
|
||||||
|
|
||||||
// Use symbol info to iterate functions in the object.
|
// Use symbol info to iterate functions in the object.
|
||||||
for (object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols();
|
for (symbol_iterator I = DebugObj.symbol_begin(), E = DebugObj.symbol_end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
object::SymbolRef::Type SymType;
|
SymbolRef::Type SymType;
|
||||||
if (I->getType(SymType)) continue;
|
if (I->getType(SymType)) continue;
|
||||||
if (SymType == object::SymbolRef::ST_Function) {
|
if (SymType == SymbolRef::ST_Function) {
|
||||||
StringRef Name;
|
StringRef Name;
|
||||||
uint64_t Addr;
|
uint64_t Addr;
|
||||||
uint64_t Size;
|
uint64_t Size;
|
||||||
@ -93,7 +101,7 @@ void OProfileJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) {
|
|||||||
if (I->getAddress(Addr)) continue;
|
if (I->getAddress(Addr)) continue;
|
||||||
if (I->getSize(Size)) continue;
|
if (I->getSize(Size)) continue;
|
||||||
|
|
||||||
if (Wrapper.op_write_native_code(Name.data(), Addr, (void*)Addr, Size)
|
if (Wrapper->op_write_native_code(Name.data(), Addr, (void*)Addr, Size)
|
||||||
== -1) {
|
== -1) {
|
||||||
DEBUG(dbgs() << "Failed to tell OProfile about native function "
|
DEBUG(dbgs() << "Failed to tell OProfile about native function "
|
||||||
<< Name << " at ["
|
<< Name << " at ["
|
||||||
@ -103,45 +111,48 @@ void OProfileJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) {
|
|||||||
// TODO: support line number info (similar to IntelJITEventListener.cpp)
|
// TODO: support line number info (similar to IntelJITEventListener.cpp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DebugObjects[Obj.getData().data()] = std::move(DebugObjOwner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OProfileJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) {
|
void OProfileJITEventListener::NotifyFreeingObject(const ObjectFile &Obj) {
|
||||||
if (!Wrapper.isAgentAvailable()) {
|
if (Wrapper->isAgentAvailable()) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use symbol info to iterate functions in the object.
|
// If there was no agent registered when the original object was loaded then
|
||||||
for (object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols();
|
// we won't have created a debug object for it, so bail out.
|
||||||
I != E; ++I) {
|
if (DebugObjects.find(Obj.getData().data()) == DebugObjects.end())
|
||||||
object::SymbolRef::Type SymType;
|
return;
|
||||||
if (I->getType(SymType)) continue;
|
|
||||||
if (SymType == object::SymbolRef::ST_Function) {
|
|
||||||
uint64_t Addr;
|
|
||||||
if (I->getAddress(Addr)) continue;
|
|
||||||
|
|
||||||
if (Wrapper.op_unload_native_code(Addr) == -1) {
|
const ObjectFile &DebugObj = *DebugObjects[Obj.getData().data()].getBinary();
|
||||||
DEBUG(dbgs()
|
|
||||||
<< "Failed to tell OProfile about unload of native function at "
|
// Use symbol info to iterate functions in the object.
|
||||||
<< (void*)Addr << "\n");
|
for (symbol_iterator I = DebugObj.symbol_begin(),
|
||||||
continue;
|
E = DebugObj.symbol_end();
|
||||||
|
I != E; ++I) {
|
||||||
|
SymbolRef::Type SymType;
|
||||||
|
if (I->getType(SymType)) continue;
|
||||||
|
if (SymType == SymbolRef::ST_Function) {
|
||||||
|
uint64_t Addr;
|
||||||
|
if (I->getAddress(Addr)) continue;
|
||||||
|
|
||||||
|
if (Wrapper->op_unload_native_code(Addr) == -1) {
|
||||||
|
DEBUG(dbgs()
|
||||||
|
<< "Failed to tell OProfile about unload of native function at "
|
||||||
|
<< (void*)Addr << "\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DebugObjects.erase(Obj.getData().data());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace.
|
} // anonymous namespace.
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
JITEventListener *JITEventListener::createOProfileJITEventListener() {
|
JITEventListener *JITEventListener::createOProfileJITEventListener() {
|
||||||
static std::unique_ptr<OProfileWrapper> JITProfilingWrapper(
|
return new OProfileJITEventListener(llvm::make_unique<OProfileWrapper>());
|
||||||
new OProfileWrapper);
|
|
||||||
return new OProfileJITEventListener(*JITProfilingWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
// for testing
|
|
||||||
JITEventListener *JITEventListener::createOProfileJITEventListener(
|
|
||||||
OProfileWrapper* TestImpl) {
|
|
||||||
return new OProfileJITEventListener(*TestImpl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
add_llvm_library(LLVMRuntimeDyld
|
add_llvm_library(LLVMRuntimeDyld
|
||||||
GDBRegistrar.cpp
|
GDBRegistrationListener.cpp
|
||||||
RuntimeDyld.cpp
|
RuntimeDyld.cpp
|
||||||
RuntimeDyldChecker.cpp
|
RuntimeDyldChecker.cpp
|
||||||
RuntimeDyldELF.cpp
|
RuntimeDyldELF.cpp
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//===-- GDBRegistrar.cpp - Registers objects with GDB ---------------------===//
|
//===----- GDBRegistrationListener.cpp - Registers objects with GDB -------===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -7,8 +7,9 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "JITRegistrar.h"
|
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
#include "llvm/ExecutionEngine/JITEventListener.h"
|
||||||
|
#include "llvm/Object/ObjectFile.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/Mutex.h"
|
#include "llvm/Support/Mutex.h"
|
||||||
@ -16,6 +17,7 @@
|
|||||||
#include "llvm/Support/ManagedStatic.h"
|
#include "llvm/Support/ManagedStatic.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace llvm::object;
|
||||||
|
|
||||||
// This must be kept in sync with gdb/gdb/jit.h .
|
// This must be kept in sync with gdb/gdb/jit.h .
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -60,37 +62,58 @@ extern "C" {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
struct RegisteredObjectInfo {
|
||||||
|
RegisteredObjectInfo() {}
|
||||||
|
|
||||||
|
RegisteredObjectInfo(std::size_t Size, jit_code_entry *Entry,
|
||||||
|
OwningBinary<ObjectFile> Obj)
|
||||||
|
: Size(Size), Entry(Entry), Obj(std::move(Obj)) {}
|
||||||
|
|
||||||
|
RegisteredObjectInfo(RegisteredObjectInfo &&Other)
|
||||||
|
: Size(Other.Size), Entry(Other.Entry), Obj(std::move(Other.Obj)) {}
|
||||||
|
|
||||||
|
RegisteredObjectInfo& operator=(RegisteredObjectInfo &&Other) {
|
||||||
|
Size = Other.Size;
|
||||||
|
Entry = Other.Entry;
|
||||||
|
Obj = std::move(Other.Obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t Size;
|
||||||
|
jit_code_entry *Entry;
|
||||||
|
OwningBinary<ObjectFile> Obj;
|
||||||
|
};
|
||||||
|
|
||||||
// Buffer for an in-memory object file in executable memory
|
// Buffer for an in-memory object file in executable memory
|
||||||
typedef llvm::DenseMap< const char*,
|
typedef llvm::DenseMap< const char*, RegisteredObjectInfo>
|
||||||
std::pair<std::size_t, jit_code_entry*> >
|
|
||||||
RegisteredObjectBufferMap;
|
RegisteredObjectBufferMap;
|
||||||
|
|
||||||
/// Global access point for the JIT debugging interface designed for use with a
|
/// Global access point for the JIT debugging interface designed for use with a
|
||||||
/// singleton toolbox. Handles thread-safe registration and deregistration of
|
/// singleton toolbox. Handles thread-safe registration and deregistration of
|
||||||
/// object files that are in executable memory managed by the client of this
|
/// object files that are in executable memory managed by the client of this
|
||||||
/// class.
|
/// class.
|
||||||
class GDBJITRegistrar : public JITRegistrar {
|
class GDBJITRegistrationListener : public JITEventListener {
|
||||||
/// A map of in-memory object files that have been registered with the
|
/// A map of in-memory object files that have been registered with the
|
||||||
/// JIT interface.
|
/// JIT interface.
|
||||||
RegisteredObjectBufferMap ObjectBufferMap;
|
RegisteredObjectBufferMap ObjectBufferMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Instantiates the JIT service.
|
/// Instantiates the JIT service.
|
||||||
GDBJITRegistrar() : ObjectBufferMap() {}
|
GDBJITRegistrationListener() : ObjectBufferMap() {}
|
||||||
|
|
||||||
/// Unregisters each object that was previously registered and releases all
|
/// Unregisters each object that was previously registered and releases all
|
||||||
/// internal resources.
|
/// internal resources.
|
||||||
virtual ~GDBJITRegistrar();
|
virtual ~GDBJITRegistrationListener();
|
||||||
|
|
||||||
/// Creates an entry in the JIT registry for the buffer @p Object,
|
/// Creates an entry in the JIT registry for the buffer @p Object,
|
||||||
/// which must contain an object file in executable memory with any
|
/// which must contain an object file in executable memory with any
|
||||||
/// debug information for the debugger.
|
/// debug information for the debugger.
|
||||||
void registerObject(const ObjectBuffer &Object) override;
|
void NotifyObjectEmitted(const ObjectFile &Object,
|
||||||
|
const RuntimeDyld::LoadedObjectInfo &L) override;
|
||||||
|
|
||||||
/// Removes the internal registration of @p Object, and
|
/// Removes the internal registration of @p Object, and
|
||||||
/// frees associated resources.
|
/// frees associated resources.
|
||||||
/// Returns true if @p Object was found in ObjectBufferMap.
|
/// Returns true if @p Object was found in ObjectBufferMap.
|
||||||
bool deregisterObject(const ObjectBuffer &Object) override;
|
void NotifyFreeingObject(const ObjectFile &Object) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Deregister the debug info for the given object file from the debugger
|
/// Deregister the debug info for the given object file from the debugger
|
||||||
@ -119,10 +142,11 @@ void NotifyDebugger(jit_code_entry* JITCodeEntry) {
|
|||||||
__jit_debug_register_code();
|
__jit_debug_register_code();
|
||||||
}
|
}
|
||||||
|
|
||||||
GDBJITRegistrar::~GDBJITRegistrar() {
|
GDBJITRegistrationListener::~GDBJITRegistrationListener() {
|
||||||
// Free all registered object files.
|
// Free all registered object files.
|
||||||
llvm::MutexGuard locked(*JITDebugLock);
|
llvm::MutexGuard locked(*JITDebugLock);
|
||||||
for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(), E = ObjectBufferMap.end();
|
for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(),
|
||||||
|
E = ObjectBufferMap.end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
// Call the private method that doesn't update the map so our iterator
|
// Call the private method that doesn't update the map so our iterator
|
||||||
// doesn't break.
|
// doesn't break.
|
||||||
@ -131,14 +155,24 @@ GDBJITRegistrar::~GDBJITRegistrar() {
|
|||||||
ObjectBufferMap.clear();
|
ObjectBufferMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDBJITRegistrar::registerObject(const ObjectBuffer &Object) {
|
void GDBJITRegistrationListener::NotifyObjectEmitted(
|
||||||
|
const ObjectFile &Object,
|
||||||
|
const RuntimeDyld::LoadedObjectInfo &L) {
|
||||||
|
|
||||||
const char *Buffer = Object.getBufferStart();
|
OwningBinary<ObjectFile> DebugObj = L.getObjectForDebug(Object);
|
||||||
size_t Size = Object.getBufferSize();
|
|
||||||
|
|
||||||
assert(Buffer && "Attempt to register a null object with a debugger.");
|
// Bail out if debug objects aren't supported.
|
||||||
|
if (!DebugObj.getBinary())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char *Buffer = DebugObj.getBinary()->getMemoryBufferRef().getBufferStart();
|
||||||
|
size_t Size = DebugObj.getBinary()->getMemoryBufferRef().getBufferSize();
|
||||||
|
|
||||||
|
const char *Key = Object.getMemoryBufferRef().getBufferStart();
|
||||||
|
|
||||||
|
assert(Key && "Attempt to register a null object with a debugger.");
|
||||||
llvm::MutexGuard locked(*JITDebugLock);
|
llvm::MutexGuard locked(*JITDebugLock);
|
||||||
assert(ObjectBufferMap.find(Buffer) == ObjectBufferMap.end() &&
|
assert(ObjectBufferMap.find(Key) == ObjectBufferMap.end() &&
|
||||||
"Second attempt to perform debug registration.");
|
"Second attempt to perform debug registration.");
|
||||||
jit_code_entry* JITCodeEntry = new jit_code_entry();
|
jit_code_entry* JITCodeEntry = new jit_code_entry();
|
||||||
|
|
||||||
@ -149,28 +183,27 @@ void GDBJITRegistrar::registerObject(const ObjectBuffer &Object) {
|
|||||||
JITCodeEntry->symfile_addr = Buffer;
|
JITCodeEntry->symfile_addr = Buffer;
|
||||||
JITCodeEntry->symfile_size = Size;
|
JITCodeEntry->symfile_size = Size;
|
||||||
|
|
||||||
ObjectBufferMap[Buffer] = std::make_pair(Size, JITCodeEntry);
|
ObjectBufferMap[Key] = RegisteredObjectInfo(Size, JITCodeEntry,
|
||||||
|
std::move(DebugObj));
|
||||||
NotifyDebugger(JITCodeEntry);
|
NotifyDebugger(JITCodeEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GDBJITRegistrar::deregisterObject(const ObjectBuffer& Object) {
|
void GDBJITRegistrationListener::NotifyFreeingObject(const ObjectFile& Object) {
|
||||||
const char *Buffer = Object.getBufferStart();
|
const char *Key = Object.getMemoryBufferRef().getBufferStart();
|
||||||
llvm::MutexGuard locked(*JITDebugLock);
|
llvm::MutexGuard locked(*JITDebugLock);
|
||||||
RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Buffer);
|
RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Key);
|
||||||
|
|
||||||
if (I != ObjectBufferMap.end()) {
|
if (I != ObjectBufferMap.end()) {
|
||||||
deregisterObjectInternal(I);
|
deregisterObjectInternal(I);
|
||||||
ObjectBufferMap.erase(I);
|
ObjectBufferMap.erase(I);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDBJITRegistrar::deregisterObjectInternal(
|
void GDBJITRegistrationListener::deregisterObjectInternal(
|
||||||
RegisteredObjectBufferMap::iterator I) {
|
RegisteredObjectBufferMap::iterator I) {
|
||||||
|
|
||||||
jit_code_entry*& JITCodeEntry = I->second.second;
|
jit_code_entry*& JITCodeEntry = I->second.Entry;
|
||||||
|
|
||||||
// Do the unregistration.
|
// Do the unregistration.
|
||||||
{
|
{
|
||||||
@ -200,14 +233,14 @@ void GDBJITRegistrar::deregisterObjectInternal(
|
|||||||
JITCodeEntry = nullptr;
|
JITCodeEntry = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::ManagedStatic<GDBJITRegistrar> TheRegistrar;
|
llvm::ManagedStatic<GDBJITRegistrationListener> GDBRegListener;
|
||||||
|
|
||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
JITRegistrar& JITRegistrar::getGDBRegistrar() {
|
JITEventListener* JITEventListener::createGDBRegistrationListener() {
|
||||||
return *TheRegistrar;
|
return &*GDBRegListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace llvm
|
} // namespace llvm
|
@ -1,44 +0,0 @@
|
|||||||
//===-- 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_LIB_EXECUTIONENGINE_RUNTIMEDYLD_JITREGISTRAR_H
|
|
||||||
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_JITREGISTRAR_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
|
|
@ -1,86 +0,0 @@
|
|||||||
//===-- 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_LIB_EXECUTIONENGINE_RUNTIMEDYLD_OBJECTIMAGECOMMON_H
|
|
||||||
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_OBJECTIMAGECOMMON_H
|
|
||||||
|
|
||||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
|
||||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
|
||||||
#include "llvm/Object/ObjectFile.h"
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
|
|
||||||
namespace object {
|
|
||||||
class ObjectFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ObjectImageCommon : public ObjectImage {
|
|
||||||
ObjectImageCommon(); // = delete
|
|
||||||
ObjectImageCommon(const ObjectImageCommon &other); // = delete
|
|
||||||
void anchor() override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::unique_ptr<object::ObjectFile> ObjFile;
|
|
||||||
|
|
||||||
// This form of the constructor allows subclasses to use
|
|
||||||
// format-specific subclasses of ObjectFile directly
|
|
||||||
ObjectImageCommon(std::unique_ptr<ObjectBuffer> Input,
|
|
||||||
std::unique_ptr<object::ObjectFile> Obj)
|
|
||||||
: ObjectImage(std::move(Input)), ObjFile(std::move(Obj)) {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
ObjectImageCommon(std::unique_ptr<ObjectBuffer> Input)
|
|
||||||
: ObjectImage(std::move(Input)) {
|
|
||||||
// FIXME: error checking? createObjectFile returns an ErrorOr<ObjectFile*>
|
|
||||||
// and should probably be checked for failure.
|
|
||||||
MemoryBufferRef Buf = Buffer->getMemBuffer();
|
|
||||||
ObjFile = std::move(object::ObjectFile::createObjectFile(Buf).get());
|
|
||||||
}
|
|
||||||
ObjectImageCommon(std::unique_ptr<object::ObjectFile> Input)
|
|
||||||
: ObjectImage(nullptr), ObjFile(std::move(Input)) {}
|
|
||||||
virtual ~ObjectImageCommon() { }
|
|
||||||
|
|
||||||
object::symbol_iterator begin_symbols() const override
|
|
||||||
{ return ObjFile->symbol_begin(); }
|
|
||||||
object::symbol_iterator end_symbols() const override
|
|
||||||
{ return ObjFile->symbol_end(); }
|
|
||||||
|
|
||||||
object::section_iterator begin_sections() const override
|
|
||||||
{ return ObjFile->section_begin(); }
|
|
||||||
object::section_iterator end_sections() const override
|
|
||||||
{ return ObjFile->section_end(); }
|
|
||||||
|
|
||||||
/* Triple::ArchType */ unsigned getArch() const override
|
|
||||||
{ return ObjFile->getArch(); }
|
|
||||||
|
|
||||||
StringRef getData() const override { return ObjFile->getData(); }
|
|
||||||
|
|
||||||
object::ObjectFile* getObjectFile() const override { return ObjFile.get(); }
|
|
||||||
|
|
||||||
// Subclasses can override these methods to update the image with loaded
|
|
||||||
// addresses for sections and common symbols
|
|
||||||
void updateSectionAddress(const object::SectionRef &Sec,
|
|
||||||
uint64_t Addr) override {}
|
|
||||||
void updateSymbolAddress(const object::SymbolRef &Sym,
|
|
||||||
uint64_t Addr) override {}
|
|
||||||
|
|
||||||
// Subclasses can override these methods to provide JIT debugging support
|
|
||||||
void registerWithDebugger() override {}
|
|
||||||
void deregisterWithDebugger() override {}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace llvm
|
|
||||||
|
|
||||||
#endif
|
|
@ -12,8 +12,6 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||||
#include "JITRegistrar.h"
|
|
||||||
#include "ObjectImageCommon.h"
|
|
||||||
#include "RuntimeDyldCheckerImpl.h"
|
#include "RuntimeDyldCheckerImpl.h"
|
||||||
#include "RuntimeDyldELF.h"
|
#include "RuntimeDyldELF.h"
|
||||||
#include "RuntimeDyldImpl.h"
|
#include "RuntimeDyldImpl.h"
|
||||||
@ -30,10 +28,8 @@ using namespace llvm::object;
|
|||||||
// Empty out-of-line virtual destructor as the key function.
|
// Empty out-of-line virtual destructor as the key function.
|
||||||
RuntimeDyldImpl::~RuntimeDyldImpl() {}
|
RuntimeDyldImpl::~RuntimeDyldImpl() {}
|
||||||
|
|
||||||
// Pin the JITRegistrar's and ObjectImage*'s vtables to this file.
|
// Pin LoadedObjectInfo's vtables to this file.
|
||||||
void JITRegistrar::anchor() {}
|
void RuntimeDyld::LoadedObjectInfo::anchor() {}
|
||||||
void ObjectImage::anchor() {}
|
|
||||||
void ObjectImageCommon::anchor() {}
|
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
@ -139,22 +135,23 @@ static std::error_code getOffset(const SymbolRef &Sym, uint64_t &Result) {
|
|||||||
return object_error::success;
|
return object_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ObjectImage>
|
std::pair<unsigned, unsigned>
|
||||||
RuntimeDyldImpl::loadObject(std::unique_ptr<ObjectImage> Obj) {
|
RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
|
||||||
MutexGuard locked(lock);
|
MutexGuard locked(lock);
|
||||||
|
|
||||||
if (!Obj)
|
// Grab the first Section ID. We'll use this later to construct the underlying
|
||||||
return nullptr;
|
// range for the returned LoadedObjectInfo.
|
||||||
|
unsigned SectionsAddedBeginIdx = Sections.size();
|
||||||
|
|
||||||
// Save information about our target
|
// Save information about our target
|
||||||
Arch = (Triple::ArchType)Obj->getArch();
|
Arch = (Triple::ArchType)Obj.getArch();
|
||||||
IsTargetLittleEndian = Obj->getObjectFile()->isLittleEndian();
|
IsTargetLittleEndian = Obj.isLittleEndian();
|
||||||
|
|
||||||
// Compute the memory size required to load all sections to be loaded
|
// Compute the memory size required to load all sections to be loaded
|
||||||
// and pass this information to the memory manager
|
// and pass this information to the memory manager
|
||||||
if (MemMgr->needsToReserveAllocationSpace()) {
|
if (MemMgr->needsToReserveAllocationSpace()) {
|
||||||
uint64_t CodeSize = 0, DataSizeRO = 0, DataSizeRW = 0;
|
uint64_t CodeSize = 0, DataSizeRO = 0, DataSizeRW = 0;
|
||||||
computeTotalAllocSize(*Obj, CodeSize, DataSizeRO, DataSizeRW);
|
computeTotalAllocSize(Obj, CodeSize, DataSizeRO, DataSizeRW);
|
||||||
MemMgr->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW);
|
MemMgr->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +167,7 @@ RuntimeDyldImpl::loadObject(std::unique_ptr<ObjectImage> Obj) {
|
|||||||
|
|
||||||
// Parse symbols
|
// Parse symbols
|
||||||
DEBUG(dbgs() << "Parse symbols:\n");
|
DEBUG(dbgs() << "Parse symbols:\n");
|
||||||
for (symbol_iterator I = Obj->begin_symbols(), E = Obj->end_symbols(); I != E;
|
for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E;
|
||||||
++I) {
|
++I) {
|
||||||
object::SymbolRef::Type SymType;
|
object::SymbolRef::Type SymType;
|
||||||
StringRef Name;
|
StringRef Name;
|
||||||
@ -196,15 +193,15 @@ RuntimeDyldImpl::loadObject(std::unique_ptr<ObjectImage> Obj) {
|
|||||||
SymType == object::SymbolRef::ST_Unknown) {
|
SymType == object::SymbolRef::ST_Unknown) {
|
||||||
uint64_t SectOffset;
|
uint64_t SectOffset;
|
||||||
StringRef SectionData;
|
StringRef SectionData;
|
||||||
section_iterator SI = Obj->end_sections();
|
section_iterator SI = Obj.section_end();
|
||||||
Check(getOffset(*I, SectOffset));
|
Check(getOffset(*I, SectOffset));
|
||||||
Check(I->getSection(SI));
|
Check(I->getSection(SI));
|
||||||
if (SI == Obj->end_sections())
|
if (SI == Obj.section_end())
|
||||||
continue;
|
continue;
|
||||||
Check(SI->getContents(SectionData));
|
Check(SI->getContents(SectionData));
|
||||||
bool IsCode = SI->isText();
|
bool IsCode = SI->isText();
|
||||||
unsigned SectionID =
|
unsigned SectionID =
|
||||||
findOrEmitSection(*Obj, *SI, IsCode, LocalSections);
|
findOrEmitSection(Obj, *SI, IsCode, LocalSections);
|
||||||
LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset);
|
LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset);
|
||||||
DEBUG(dbgs() << "\tOffset: " << format("%p", (uintptr_t)SectOffset)
|
DEBUG(dbgs() << "\tOffset: " << format("%p", (uintptr_t)SectOffset)
|
||||||
<< " flags: " << Flags << " SID: " << SectionID);
|
<< " flags: " << Flags << " SID: " << SectionID);
|
||||||
@ -216,11 +213,11 @@ RuntimeDyldImpl::loadObject(std::unique_ptr<ObjectImage> Obj) {
|
|||||||
|
|
||||||
// Allocate common symbols
|
// Allocate common symbols
|
||||||
if (CommonSize != 0)
|
if (CommonSize != 0)
|
||||||
emitCommonSymbols(*Obj, CommonSymbols, CommonSize, GlobalSymbolTable);
|
emitCommonSymbols(Obj, CommonSymbols, CommonSize, GlobalSymbolTable);
|
||||||
|
|
||||||
// Parse and process relocations
|
// Parse and process relocations
|
||||||
DEBUG(dbgs() << "Parse relocations:\n");
|
DEBUG(dbgs() << "Parse relocations:\n");
|
||||||
for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections();
|
for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
|
||||||
SI != SE; ++SI) {
|
SI != SE; ++SI) {
|
||||||
unsigned SectionID = 0;
|
unsigned SectionID = 0;
|
||||||
StubMap Stubs;
|
StubMap Stubs;
|
||||||
@ -234,23 +231,25 @@ RuntimeDyldImpl::loadObject(std::unique_ptr<ObjectImage> Obj) {
|
|||||||
|
|
||||||
bool IsCode = RelocatedSection->isText();
|
bool IsCode = RelocatedSection->isText();
|
||||||
SectionID =
|
SectionID =
|
||||||
findOrEmitSection(*Obj, *RelocatedSection, IsCode, LocalSections);
|
findOrEmitSection(Obj, *RelocatedSection, IsCode, LocalSections);
|
||||||
DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
|
DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
|
||||||
|
|
||||||
for (; I != E;)
|
for (; I != E;)
|
||||||
I = processRelocationRef(SectionID, I, *Obj, LocalSections, LocalSymbols,
|
I = processRelocationRef(SectionID, I, Obj, LocalSections, LocalSymbols,
|
||||||
Stubs);
|
Stubs);
|
||||||
|
|
||||||
// If there is an attached checker, notify it about the stubs for this
|
// If there is an attached checker, notify it about the stubs for this
|
||||||
// section so that they can be verified.
|
// section so that they can be verified.
|
||||||
if (Checker)
|
if (Checker)
|
||||||
Checker->registerStubMap(Obj->getImageName(), SectionID, Stubs);
|
Checker->registerStubMap(Obj.getFileName(), SectionID, Stubs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give the subclasses a chance to tie-up any loose ends.
|
// Give the subclasses a chance to tie-up any loose ends.
|
||||||
finalizeLoad(*Obj, LocalSections);
|
finalizeLoad(Obj, LocalSections);
|
||||||
|
|
||||||
return Obj;
|
unsigned SectionsAddedEndIdx = Sections.size();
|
||||||
|
|
||||||
|
return std::make_pair(SectionsAddedBeginIdx, SectionsAddedEndIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A helper method for computeTotalAllocSize.
|
// A helper method for computeTotalAllocSize.
|
||||||
@ -270,7 +269,7 @@ computeAllocationSizeForSections(std::vector<uint64_t> &SectionSizes,
|
|||||||
|
|
||||||
// Compute an upper bound of the memory size that is required to load all
|
// Compute an upper bound of the memory size that is required to load all
|
||||||
// sections
|
// sections
|
||||||
void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj,
|
void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj,
|
||||||
uint64_t &CodeSize,
|
uint64_t &CodeSize,
|
||||||
uint64_t &DataSizeRO,
|
uint64_t &DataSizeRO,
|
||||||
uint64_t &DataSizeRW) {
|
uint64_t &DataSizeRW) {
|
||||||
@ -282,7 +281,7 @@ void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj,
|
|||||||
|
|
||||||
// Collect sizes of all sections to be loaded;
|
// Collect sizes of all sections to be loaded;
|
||||||
// also determine the max alignment of all sections
|
// also determine the max alignment of all sections
|
||||||
for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections();
|
for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
|
||||||
SI != SE; ++SI) {
|
SI != SE; ++SI) {
|
||||||
const SectionRef &Section = *SI;
|
const SectionRef &Section = *SI;
|
||||||
|
|
||||||
@ -328,7 +327,7 @@ void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj,
|
|||||||
|
|
||||||
// Compute the size of all common symbols
|
// Compute the size of all common symbols
|
||||||
uint64_t CommonSize = 0;
|
uint64_t CommonSize = 0;
|
||||||
for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E;
|
for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E;
|
||||||
++I) {
|
++I) {
|
||||||
uint32_t Flags = I->getFlags();
|
uint32_t Flags = I->getFlags();
|
||||||
if (Flags & SymbolRef::SF_Common) {
|
if (Flags & SymbolRef::SF_Common) {
|
||||||
@ -353,7 +352,7 @@ void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute stub buffer size for the given section
|
// compute stub buffer size for the given section
|
||||||
unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj,
|
unsigned RuntimeDyldImpl::computeSectionStubBufSize(const ObjectFile &Obj,
|
||||||
const SectionRef &Section) {
|
const SectionRef &Section) {
|
||||||
unsigned StubSize = getMaxStubSize();
|
unsigned StubSize = getMaxStubSize();
|
||||||
if (StubSize == 0) {
|
if (StubSize == 0) {
|
||||||
@ -363,7 +362,7 @@ unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj,
|
|||||||
// necessary section allocation size in loadObject by walking all the sections
|
// necessary section allocation size in loadObject by walking all the sections
|
||||||
// once.
|
// once.
|
||||||
unsigned StubBufSize = 0;
|
unsigned StubBufSize = 0;
|
||||||
for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections();
|
for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
|
||||||
SI != SE; ++SI) {
|
SI != SE; ++SI) {
|
||||||
section_iterator RelSecI = SI->getRelocatedSection();
|
section_iterator RelSecI = SI->getRelocatedSection();
|
||||||
if (!(RelSecI == Section))
|
if (!(RelSecI == Section))
|
||||||
@ -418,7 +417,7 @@ void RuntimeDyldImpl::writeBytesUnaligned(uint64_t Value, uint8_t *Dst,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj,
|
void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
|
||||||
const CommonSymbolMap &CommonSymbols,
|
const CommonSymbolMap &CommonSymbols,
|
||||||
uint64_t TotalSize,
|
uint64_t TotalSize,
|
||||||
SymbolTableMap &SymbolTable) {
|
SymbolTableMap &SymbolTable) {
|
||||||
@ -450,14 +449,13 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj,
|
|||||||
DEBUG(dbgs() << "Allocating common symbol " << Name << " address "
|
DEBUG(dbgs() << "Allocating common symbol " << Name << " address "
|
||||||
<< format("%p\n", Addr));
|
<< format("%p\n", Addr));
|
||||||
}
|
}
|
||||||
Obj.updateSymbolAddress(it->first, (uint64_t)Addr);
|
|
||||||
SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset);
|
SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset);
|
||||||
Offset += Size;
|
Offset += Size;
|
||||||
Addr += Size;
|
Addr += Size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
|
unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
|
||||||
const SectionRef &Section, bool IsCode) {
|
const SectionRef &Section, bool IsCode) {
|
||||||
|
|
||||||
StringRef data;
|
StringRef data;
|
||||||
@ -521,7 +519,6 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
|
|||||||
<< " new addr: " << format("%p", Addr)
|
<< " new addr: " << format("%p", Addr)
|
||||||
<< " DataSize: " << DataSize << " StubBufSize: " << StubBufSize
|
<< " DataSize: " << DataSize << " StubBufSize: " << StubBufSize
|
||||||
<< " Allocate: " << Allocate << "\n");
|
<< " Allocate: " << Allocate << "\n");
|
||||||
Obj.updateSectionAddress(Section, (uint64_t)Addr);
|
|
||||||
} else {
|
} else {
|
||||||
// Even if we didn't load the section, we need to record an entry for it
|
// 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
|
// to handle later processing (and by 'handle' I mean don't do anything
|
||||||
@ -537,12 +534,12 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
|
|||||||
Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData));
|
Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData));
|
||||||
|
|
||||||
if (Checker)
|
if (Checker)
|
||||||
Checker->registerSection(Obj.getImageName(), SectionID);
|
Checker->registerSection(Obj.getFileName(), SectionID);
|
||||||
|
|
||||||
return SectionID;
|
return SectionID;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned RuntimeDyldImpl::findOrEmitSection(ObjectImage &Obj,
|
unsigned RuntimeDyldImpl::findOrEmitSection(const ObjectFile &Obj,
|
||||||
const SectionRef &Section,
|
const SectionRef &Section,
|
||||||
bool IsCode,
|
bool IsCode,
|
||||||
ObjSectionToIDMap &LocalSections) {
|
ObjSectionToIDMap &LocalSections) {
|
||||||
@ -739,6 +736,16 @@ void RuntimeDyldImpl::resolveExternalSymbols() {
|
|||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// RuntimeDyld class implementation
|
// RuntimeDyld class implementation
|
||||||
|
|
||||||
|
uint64_t RuntimeDyld::LoadedObjectInfo::getSectionLoadAddress(
|
||||||
|
StringRef SectionName) const {
|
||||||
|
for (unsigned I = BeginIdx; I != EndIdx; ++I)
|
||||||
|
if (RTDyld.Sections[I].Name == SectionName)
|
||||||
|
return RTDyld.Sections[I].LoadAddress;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) {
|
RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) {
|
||||||
// FIXME: There's a potential issue lurking here if a single instance of
|
// FIXME: There's a potential issue lurking here if a single instance of
|
||||||
// RuntimeDyld is used to load multiple objects. The current implementation
|
// RuntimeDyld is used to load multiple objects. The current implementation
|
||||||
@ -772,78 +779,23 @@ createRuntimeDyldMachO(Triple::ArchType Arch, RTDyldMemoryManager *MM,
|
|||||||
return Dyld;
|
return Dyld;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ObjectImage>
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||||
RuntimeDyld::loadObject(std::unique_ptr<ObjectFile> InputObject) {
|
RuntimeDyld::loadObject(const ObjectFile &Obj) {
|
||||||
std::unique_ptr<ObjectImage> InputImage;
|
if (!Dyld) {
|
||||||
|
if (Obj.isELF())
|
||||||
ObjectFile &Obj = *InputObject;
|
|
||||||
|
|
||||||
if (InputObject->isELF()) {
|
|
||||||
InputImage.reset(RuntimeDyldELF::createObjectImageFromFile(std::move(InputObject)));
|
|
||||||
if (!Dyld)
|
|
||||||
Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker);
|
Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker);
|
||||||
} else if (InputObject->isMachO()) {
|
else if (Obj.isMachO())
|
||||||
InputImage.reset(RuntimeDyldMachO::createObjectImageFromFile(std::move(InputObject)));
|
|
||||||
if (!Dyld)
|
|
||||||
Dyld = createRuntimeDyldMachO(
|
Dyld = createRuntimeDyldMachO(
|
||||||
static_cast<Triple::ArchType>(InputImage->getArch()), MM,
|
static_cast<Triple::ArchType>(Obj.getArch()), MM,
|
||||||
ProcessAllSections, Checker);
|
ProcessAllSections, Checker);
|
||||||
} else
|
else
|
||||||
report_fatal_error("Incompatible object format!");
|
report_fatal_error("Incompatible object format!");
|
||||||
|
|
||||||
if (!Dyld->isCompatibleFile(&Obj))
|
|
||||||
report_fatal_error("Incompatible object format!");
|
|
||||||
|
|
||||||
return Dyld->loadObject(std::move(InputImage));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<ObjectImage>
|
|
||||||
RuntimeDyld::loadObject(std::unique_ptr<ObjectBuffer> InputBuffer) {
|
|
||||||
std::unique_ptr<ObjectImage> InputImage;
|
|
||||||
sys::fs::file_magic Type = sys::fs::identify_magic(InputBuffer->getBuffer());
|
|
||||||
auto *InputBufferPtr = InputBuffer.get();
|
|
||||||
|
|
||||||
switch (Type) {
|
|
||||||
case sys::fs::file_magic::elf:
|
|
||||||
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:
|
|
||||||
InputImage = RuntimeDyldELF::createObjectImage(std::move(InputBuffer));
|
|
||||||
if (!Dyld)
|
|
||||||
Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker);
|
|
||||||
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:
|
|
||||||
InputImage = RuntimeDyldMachO::createObjectImage(std::move(InputBuffer));
|
|
||||||
if (!Dyld)
|
|
||||||
Dyld = createRuntimeDyldMachO(
|
|
||||||
static_cast<Triple::ArchType>(InputImage->getArch()), MM,
|
|
||||||
ProcessAllSections, Checker);
|
|
||||||
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!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Dyld->isCompatibleFormat(InputBufferPtr))
|
if (!Dyld->isCompatibleFile(Obj))
|
||||||
report_fatal_error("Incompatible object format!");
|
report_fatal_error("Incompatible object format!");
|
||||||
|
|
||||||
return Dyld->loadObject(std::move(InputImage));
|
return Dyld->loadObject(Obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *RuntimeDyld::getSymbolAddress(StringRef Name) const {
|
void *RuntimeDyld::getSymbolAddress(StringRef Name) const {
|
||||||
|
@ -12,27 +12,23 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "RuntimeDyldELF.h"
|
#include "RuntimeDyldELF.h"
|
||||||
#include "JITRegistrar.h"
|
|
||||||
#include "ObjectImageCommon.h"
|
|
||||||
#include "llvm/ADT/IntervalMap.h"
|
#include "llvm/ADT/IntervalMap.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/ADT/Triple.h"
|
#include "llvm/ADT/Triple.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
#include "llvm/MC/MCStreamer.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
|
||||||
#include "llvm/Object/ELFObjectFile.h"
|
#include "llvm/Object/ELFObjectFile.h"
|
||||||
#include "llvm/Object/ObjectFile.h"
|
#include "llvm/Object/ObjectFile.h"
|
||||||
#include "llvm/Support/ELF.h"
|
#include "llvm/Support/ELF.h"
|
||||||
#include "llvm/Support/Endian.h"
|
#include "llvm/Support/Endian.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
|
#include "llvm/Support/TargetRegistry.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::object;
|
using namespace llvm::object;
|
||||||
|
|
||||||
#define DEBUG_TYPE "dyld"
|
#define DEBUG_TYPE "dyld"
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
static inline std::error_code check(std::error_code Err) {
|
static inline std::error_code check(std::error_code Err) {
|
||||||
if (Err) {
|
if (Err) {
|
||||||
report_fatal_error(Err.message());
|
report_fatal_error(Err.message());
|
||||||
@ -40,6 +36,8 @@ static inline std::error_code check(std::error_code Err) {
|
|||||||
return Err;
|
return Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> {
|
template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> {
|
||||||
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
|
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
|
||||||
|
|
||||||
@ -52,16 +50,12 @@ template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> {
|
|||||||
|
|
||||||
typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type;
|
typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type;
|
||||||
|
|
||||||
std::unique_ptr<ObjectFile> UnderlyingFile;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DyldELFObject(std::unique_ptr<ObjectFile> UnderlyingFile,
|
|
||||||
MemoryBufferRef Wrapper, std::error_code &ec);
|
|
||||||
|
|
||||||
DyldELFObject(MemoryBufferRef Wrapper, std::error_code &ec);
|
DyldELFObject(MemoryBufferRef Wrapper, std::error_code &ec);
|
||||||
|
|
||||||
void updateSectionAddress(const SectionRef &Sec, uint64_t Addr);
|
void updateSectionAddress(const SectionRef &Sec, uint64_t Addr);
|
||||||
void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr);
|
|
||||||
|
void updateSymbolAddress(const SymbolRef &SymRef, uint64_t Addr);
|
||||||
|
|
||||||
// Methods for type inquiry through isa, cast and dyn_cast
|
// Methods for type inquiry through isa, cast and dyn_cast
|
||||||
static inline bool classof(const Binary *v) {
|
static inline bool classof(const Binary *v) {
|
||||||
@ -71,42 +65,10 @@ public:
|
|||||||
static inline bool classof(const ELFObjectFile<ELFT> *v) {
|
static inline bool classof(const ELFObjectFile<ELFT> *v) {
|
||||||
return v->isDyldType();
|
return v->isDyldType();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class ELFT> class ELFObjectImage : public ObjectImageCommon {
|
|
||||||
bool Registered;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ELFObjectImage(std::unique_ptr<ObjectBuffer> Input,
|
|
||||||
std::unique_ptr<DyldELFObject<ELFT>> Obj)
|
|
||||||
: ObjectImageCommon(std::move(Input), std::move(Obj)), Registered(false) {
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~ELFObjectImage() {
|
|
||||||
if (Registered)
|
|
||||||
deregisterWithDebugger();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subclasses can override these methods to update the image with loaded
|
|
||||||
// addresses for sections and common symbols
|
|
||||||
void updateSectionAddress(const SectionRef &Sec, uint64_t Addr) override {
|
|
||||||
static_cast<DyldELFObject<ELFT>*>(getObjectFile())
|
|
||||||
->updateSectionAddress(Sec, Addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr) override {
|
|
||||||
static_cast<DyldELFObject<ELFT>*>(getObjectFile())
|
|
||||||
->updateSymbolAddress(Sym, Addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void registerWithDebugger() override {
|
|
||||||
JITRegistrar::getGDBRegistrar().registerObject(*Buffer);
|
|
||||||
Registered = true;
|
|
||||||
}
|
|
||||||
void deregisterWithDebugger() override {
|
|
||||||
JITRegistrar::getGDBRegistrar().deregisterObject(*Buffer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// The MemoryBuffer passed into this constructor is just a wrapper around the
|
// The MemoryBuffer passed into this constructor is just a wrapper around the
|
||||||
// actual memory. Ultimately, the Binary parent class will take ownership of
|
// actual memory. Ultimately, the Binary parent class will take ownership of
|
||||||
@ -117,14 +79,6 @@ DyldELFObject<ELFT>::DyldELFObject(MemoryBufferRef Wrapper, std::error_code &EC)
|
|||||||
this->isDyldELFObject = true;
|
this->isDyldELFObject = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
|
||||||
DyldELFObject<ELFT>::DyldELFObject(std::unique_ptr<ObjectFile> UnderlyingFile,
|
|
||||||
MemoryBufferRef Wrapper, std::error_code &EC)
|
|
||||||
: ELFObjectFile<ELFT>(Wrapper, EC),
|
|
||||||
UnderlyingFile(std::move(UnderlyingFile)) {
|
|
||||||
this->isDyldELFObject = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
void DyldELFObject<ELFT>::updateSectionAddress(const SectionRef &Sec,
|
void DyldELFObject<ELFT>::updateSectionAddress(const SectionRef &Sec,
|
||||||
uint64_t Addr) {
|
uint64_t Addr) {
|
||||||
@ -149,10 +103,89 @@ void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef,
|
|||||||
sym->st_value = static_cast<addr_type>(Addr);
|
sym->st_value = static_cast<addr_type>(Addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LoadedELFObjectInfo : public RuntimeDyld::LoadedObjectInfo {
|
||||||
|
public:
|
||||||
|
LoadedELFObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
|
||||||
|
unsigned EndIdx)
|
||||||
|
: RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {}
|
||||||
|
|
||||||
|
OwningBinary<ObjectFile>
|
||||||
|
getObjectForDebug(const ObjectFile &Obj) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ELFT>
|
||||||
|
std::unique_ptr<DyldELFObject<ELFT>>
|
||||||
|
createRTDyldELFObject(MemoryBufferRef Buffer,
|
||||||
|
const LoadedELFObjectInfo &L,
|
||||||
|
std::error_code &ec) {
|
||||||
|
typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
|
||||||
|
typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type;
|
||||||
|
|
||||||
|
std::unique_ptr<DyldELFObject<ELFT>> Obj =
|
||||||
|
llvm::make_unique<DyldELFObject<ELFT>>(Buffer, ec);
|
||||||
|
|
||||||
|
// Iterate over all sections in the object.
|
||||||
|
for (const auto &Sec : Obj->sections()) {
|
||||||
|
StringRef SectionName;
|
||||||
|
Sec.getName(SectionName);
|
||||||
|
if (SectionName != "") {
|
||||||
|
DataRefImpl ShdrRef = Sec.getRawDataRefImpl();
|
||||||
|
Elf_Shdr *shdr = const_cast<Elf_Shdr *>(
|
||||||
|
reinterpret_cast<const Elf_Shdr *>(ShdrRef.p));
|
||||||
|
|
||||||
|
if (uint64_t SecLoadAddr = L.getSectionLoadAddress(SectionName)) {
|
||||||
|
// This assumes that the address passed in matches the target address
|
||||||
|
// bitness. The template-based type cast handles everything else.
|
||||||
|
shdr->sh_addr = static_cast<addr_type>(SecLoadAddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
OwningBinary<ObjectFile> createELFDebugObject(const ObjectFile &Obj,
|
||||||
|
const LoadedELFObjectInfo &L) {
|
||||||
|
assert(Obj.isELF() && "Not an ELF object file.");
|
||||||
|
|
||||||
|
std::unique_ptr<MemoryBuffer> Buffer =
|
||||||
|
MemoryBuffer::getMemBufferCopy(Obj.getData(), Obj.getFileName());
|
||||||
|
|
||||||
|
std::error_code ec;
|
||||||
|
|
||||||
|
std::unique_ptr<ObjectFile> DebugObj;
|
||||||
|
if (Obj.getBytesInAddress() == 4 && Obj.isLittleEndian()) {
|
||||||
|
typedef ELFType<support::little, 2, false> ELF32LE;
|
||||||
|
DebugObj = createRTDyldELFObject<ELF32LE>(Buffer->getMemBufferRef(), L, ec);
|
||||||
|
} else if (Obj.getBytesInAddress() == 4 && !Obj.isLittleEndian()) {
|
||||||
|
typedef ELFType<support::big, 2, false> ELF32BE;
|
||||||
|
DebugObj = createRTDyldELFObject<ELF32BE>(Buffer->getMemBufferRef(), L, ec);
|
||||||
|
} else if (Obj.getBytesInAddress() == 8 && !Obj.isLittleEndian()) {
|
||||||
|
typedef ELFType<support::big, 2, true> ELF64BE;
|
||||||
|
DebugObj = createRTDyldELFObject<ELF64BE>(Buffer->getMemBufferRef(), L, ec);
|
||||||
|
} else if (Obj.getBytesInAddress() == 8 && Obj.isLittleEndian()) {
|
||||||
|
typedef ELFType<support::little, 2, true> ELF64LE;
|
||||||
|
DebugObj = createRTDyldELFObject<ELF64LE>(Buffer->getMemBufferRef(), L, ec);
|
||||||
|
} else
|
||||||
|
llvm_unreachable("Unexpected ELF format");
|
||||||
|
|
||||||
|
assert(!ec && "Could not construct copy ELF object file");
|
||||||
|
|
||||||
|
return OwningBinary<ObjectFile>(std::move(DebugObj), std::move(Buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
OwningBinary<ObjectFile>
|
||||||
|
LoadedELFObjectInfo::getObjectForDebug(const ObjectFile &Obj) const {
|
||||||
|
return createELFDebugObject(Obj, *this);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
RuntimeDyldELF::RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
|
||||||
|
RuntimeDyldELF::~RuntimeDyldELF() {}
|
||||||
|
|
||||||
void RuntimeDyldELF::registerEHFrames() {
|
void RuntimeDyldELF::registerEHFrames() {
|
||||||
if (!MemMgr)
|
if (!MemMgr)
|
||||||
return;
|
return;
|
||||||
@ -180,83 +213,14 @@ void RuntimeDyldELF::deregisterEHFrames() {
|
|||||||
RegisteredEHFrameSections.clear();
|
RegisteredEHFrameSections.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectImage *
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||||
RuntimeDyldELF::createObjectImageFromFile(std::unique_ptr<object::ObjectFile> ObjFile) {
|
RuntimeDyldELF::loadObject(const object::ObjectFile &O) {
|
||||||
if (!ObjFile)
|
unsigned SectionStartIdx, SectionEndIdx;
|
||||||
return nullptr;
|
std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O);
|
||||||
|
return llvm::make_unique<LoadedELFObjectInfo>(*this, SectionStartIdx,
|
||||||
std::error_code ec;
|
SectionEndIdx);
|
||||||
MemoryBufferRef Buffer = ObjFile->getMemoryBufferRef();
|
|
||||||
|
|
||||||
if (ObjFile->getBytesInAddress() == 4 && ObjFile->isLittleEndian()) {
|
|
||||||
auto Obj =
|
|
||||||
llvm::make_unique<DyldELFObject<ELFType<support::little, 2, false>>>(
|
|
||||||
std::move(ObjFile), Buffer, ec);
|
|
||||||
return new ELFObjectImage<ELFType<support::little, 2, false>>(
|
|
||||||
nullptr, std::move(Obj));
|
|
||||||
} else if (ObjFile->getBytesInAddress() == 4 && !ObjFile->isLittleEndian()) {
|
|
||||||
auto Obj =
|
|
||||||
llvm::make_unique<DyldELFObject<ELFType<support::big, 2, false>>>(
|
|
||||||
std::move(ObjFile), Buffer, ec);
|
|
||||||
return new ELFObjectImage<ELFType<support::big, 2, false>>(nullptr, std::move(Obj));
|
|
||||||
} else if (ObjFile->getBytesInAddress() == 8 && !ObjFile->isLittleEndian()) {
|
|
||||||
auto Obj = llvm::make_unique<DyldELFObject<ELFType<support::big, 2, true>>>(
|
|
||||||
std::move(ObjFile), Buffer, ec);
|
|
||||||
return new ELFObjectImage<ELFType<support::big, 2, true>>(nullptr,
|
|
||||||
std::move(Obj));
|
|
||||||
} else if (ObjFile->getBytesInAddress() == 8 && ObjFile->isLittleEndian()) {
|
|
||||||
auto Obj =
|
|
||||||
llvm::make_unique<DyldELFObject<ELFType<support::little, 2, true>>>(
|
|
||||||
std::move(ObjFile), Buffer, ec);
|
|
||||||
return new ELFObjectImage<ELFType<support::little, 2, true>>(
|
|
||||||
nullptr, std::move(Obj));
|
|
||||||
} else
|
|
||||||
llvm_unreachable("Unexpected ELF format");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ObjectImage>
|
|
||||||
RuntimeDyldELF::createObjectImage(std::unique_ptr<ObjectBuffer> Buffer) {
|
|
||||||
if (Buffer->getBufferSize() < ELF::EI_NIDENT)
|
|
||||||
llvm_unreachable("Unexpected ELF object size");
|
|
||||||
std::pair<unsigned char, unsigned char> Ident =
|
|
||||||
std::make_pair((uint8_t)Buffer->getBufferStart()[ELF::EI_CLASS],
|
|
||||||
(uint8_t)Buffer->getBufferStart()[ELF::EI_DATA]);
|
|
||||||
std::error_code ec;
|
|
||||||
|
|
||||||
MemoryBufferRef Buf = Buffer->getMemBuffer();
|
|
||||||
|
|
||||||
if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) {
|
|
||||||
auto Obj =
|
|
||||||
llvm::make_unique<DyldELFObject<ELFType<support::little, 4, false>>>(
|
|
||||||
Buf, ec);
|
|
||||||
return llvm::make_unique<
|
|
||||||
ELFObjectImage<ELFType<support::little, 4, false>>>(std::move(Buffer),
|
|
||||||
std::move(Obj));
|
|
||||||
}
|
|
||||||
if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) {
|
|
||||||
auto Obj =
|
|
||||||
llvm::make_unique<DyldELFObject<ELFType<support::big, 4, false>>>(Buf,
|
|
||||||
ec);
|
|
||||||
return llvm::make_unique<ELFObjectImage<ELFType<support::big, 4, false>>>(
|
|
||||||
std::move(Buffer), std::move(Obj));
|
|
||||||
}
|
|
||||||
if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) {
|
|
||||||
auto Obj = llvm::make_unique<DyldELFObject<ELFType<support::big, 8, true>>>(
|
|
||||||
Buf, ec);
|
|
||||||
return llvm::make_unique<ELFObjectImage<ELFType<support::big, 8, true>>>(
|
|
||||||
std::move(Buffer), std::move(Obj));
|
|
||||||
}
|
|
||||||
assert(Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB &&
|
|
||||||
"Unexpected ELF format");
|
|
||||||
auto Obj =
|
|
||||||
llvm::make_unique<DyldELFObject<ELFType<support::little, 8, true>>>(Buf,
|
|
||||||
ec);
|
|
||||||
return llvm::make_unique<ELFObjectImage<ELFType<support::little, 8, true>>>(
|
|
||||||
std::move(Buffer), std::move(Obj));
|
|
||||||
}
|
|
||||||
|
|
||||||
RuntimeDyldELF::~RuntimeDyldELF() {}
|
|
||||||
|
|
||||||
void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
|
void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
|
||||||
uint64_t Offset, uint64_t Value,
|
uint64_t Offset, uint64_t Value,
|
||||||
uint32_t Type, int64_t Addend,
|
uint32_t Type, int64_t Addend,
|
||||||
@ -615,7 +579,7 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return the .TOC. section and offset.
|
// Return the .TOC. section and offset.
|
||||||
void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj,
|
void RuntimeDyldELF::findPPC64TOCSection(const ObjectFile &Obj,
|
||||||
ObjSectionToIDMap &LocalSections,
|
ObjSectionToIDMap &LocalSections,
|
||||||
RelocationValueRef &Rel) {
|
RelocationValueRef &Rel) {
|
||||||
// Set a default SectionID in case we do not find a TOC section below.
|
// Set a default SectionID in case we do not find a TOC section below.
|
||||||
@ -628,7 +592,7 @@ void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj,
|
|||||||
|
|
||||||
// The TOC consists of sections .got, .toc, .tocbss, .plt in that
|
// The TOC consists of sections .got, .toc, .tocbss, .plt in that
|
||||||
// order. The TOC starts where the first of these sections starts.
|
// order. The TOC starts where the first of these sections starts.
|
||||||
for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections();
|
for (section_iterator si = Obj.section_begin(), se = Obj.section_end();
|
||||||
si != se; ++si) {
|
si != se; ++si) {
|
||||||
|
|
||||||
StringRef SectionName;
|
StringRef SectionName;
|
||||||
@ -650,15 +614,15 @@ void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj,
|
|||||||
|
|
||||||
// Returns the sections and offset associated with the ODP entry referenced
|
// Returns the sections and offset associated with the ODP entry referenced
|
||||||
// by Symbol.
|
// by Symbol.
|
||||||
void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj,
|
void RuntimeDyldELF::findOPDEntrySection(const ObjectFile &Obj,
|
||||||
ObjSectionToIDMap &LocalSections,
|
ObjSectionToIDMap &LocalSections,
|
||||||
RelocationValueRef &Rel) {
|
RelocationValueRef &Rel) {
|
||||||
// Get the ELF symbol value (st_value) to compare with Relocation offset in
|
// Get the ELF symbol value (st_value) to compare with Relocation offset in
|
||||||
// .opd entries
|
// .opd entries
|
||||||
for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections();
|
for (section_iterator si = Obj.section_begin(), se = Obj.section_end();
|
||||||
si != se; ++si) {
|
si != se; ++si) {
|
||||||
section_iterator RelSecI = si->getRelocatedSection();
|
section_iterator RelSecI = si->getRelocatedSection();
|
||||||
if (RelSecI == Obj.end_sections())
|
if (RelSecI == Obj.section_end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
StringRef RelSectionName;
|
StringRef RelSectionName;
|
||||||
@ -700,7 +664,7 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj,
|
|||||||
if (Rel.Addend != (int64_t)TargetSymbolOffset)
|
if (Rel.Addend != (int64_t)TargetSymbolOffset)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
section_iterator tsi(Obj.end_sections());
|
section_iterator tsi(Obj.section_end());
|
||||||
check(TargetSymbol->getSection(tsi));
|
check(TargetSymbol->getSection(tsi));
|
||||||
bool IsCode = tsi->isText();
|
bool IsCode = tsi->isText();
|
||||||
Rel.SectionID = findOrEmitSection(Obj, (*tsi), IsCode, LocalSections);
|
Rel.SectionID = findOrEmitSection(Obj, (*tsi), IsCode, LocalSections);
|
||||||
@ -935,7 +899,8 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
|
|||||||
}
|
}
|
||||||
|
|
||||||
relocation_iterator RuntimeDyldELF::processRelocationRef(
|
relocation_iterator RuntimeDyldELF::processRelocationRef(
|
||||||
unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj,
|
unsigned SectionID, relocation_iterator RelI,
|
||||||
|
const ObjectFile &Obj,
|
||||||
ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols,
|
ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols,
|
||||||
StubMap &Stubs) {
|
StubMap &Stubs) {
|
||||||
uint64_t RelType;
|
uint64_t RelType;
|
||||||
@ -946,7 +911,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
|
|||||||
|
|
||||||
// Obtain the symbol name which is referenced in the relocation
|
// Obtain the symbol name which is referenced in the relocation
|
||||||
StringRef TargetName;
|
StringRef TargetName;
|
||||||
if (Symbol != Obj.end_symbols())
|
if (Symbol != Obj.symbol_end())
|
||||||
Symbol->getName(TargetName);
|
Symbol->getName(TargetName);
|
||||||
DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend
|
DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend
|
||||||
<< " TargetName: " << TargetName << "\n");
|
<< " TargetName: " << TargetName << "\n");
|
||||||
@ -954,7 +919,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
|
|||||||
// First search for the symbol in the local symbol table
|
// First search for the symbol in the local symbol table
|
||||||
SymbolTableMap::const_iterator lsi = Symbols.end();
|
SymbolTableMap::const_iterator lsi = Symbols.end();
|
||||||
SymbolRef::Type SymType = SymbolRef::ST_Unknown;
|
SymbolRef::Type SymType = SymbolRef::ST_Unknown;
|
||||||
if (Symbol != Obj.end_symbols()) {
|
if (Symbol != Obj.symbol_end()) {
|
||||||
lsi = Symbols.find(TargetName.data());
|
lsi = Symbols.find(TargetName.data());
|
||||||
Symbol->getType(SymType);
|
Symbol->getType(SymType);
|
||||||
}
|
}
|
||||||
@ -965,7 +930,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
|
|||||||
} else {
|
} else {
|
||||||
// Search for the symbol in the global symbol table
|
// Search for the symbol in the global symbol table
|
||||||
SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end();
|
SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end();
|
||||||
if (Symbol != Obj.end_symbols())
|
if (Symbol != Obj.symbol_end())
|
||||||
gsi = GlobalSymbolTable.find(TargetName.data());
|
gsi = GlobalSymbolTable.find(TargetName.data());
|
||||||
if (gsi != GlobalSymbolTable.end()) {
|
if (gsi != GlobalSymbolTable.end()) {
|
||||||
Value.SectionID = gsi->second.first;
|
Value.SectionID = gsi->second.first;
|
||||||
@ -977,9 +942,9 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
|
|||||||
// TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously
|
// TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously
|
||||||
// and can be changed by another developers. Maybe best way is add
|
// and can be changed by another developers. Maybe best way is add
|
||||||
// a new symbol type ST_Section to SymbolRef and use it.
|
// a new symbol type ST_Section to SymbolRef and use it.
|
||||||
section_iterator si(Obj.end_sections());
|
section_iterator si(Obj.section_end());
|
||||||
Symbol->getSection(si);
|
Symbol->getSection(si);
|
||||||
if (si == Obj.end_sections())
|
if (si == Obj.section_end())
|
||||||
llvm_unreachable("Symbol section not found, bad object file format!");
|
llvm_unreachable("Symbol section not found, bad object file format!");
|
||||||
DEBUG(dbgs() << "\t\tThis is section symbol\n");
|
DEBUG(dbgs() << "\t\tThis is section symbol\n");
|
||||||
bool isCode = si->isText();
|
bool isCode = si->isText();
|
||||||
@ -1135,7 +1100,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
|
|||||||
if (RelType == ELF::R_PPC64_REL24) {
|
if (RelType == ELF::R_PPC64_REL24) {
|
||||||
// Determine ABI variant in use for this object.
|
// Determine ABI variant in use for this object.
|
||||||
unsigned AbiVariant;
|
unsigned AbiVariant;
|
||||||
Obj.getObjectFile()->getPlatformFlags(AbiVariant);
|
Obj.getPlatformFlags(AbiVariant);
|
||||||
AbiVariant &= ELF::EF_PPC64_ABI;
|
AbiVariant &= ELF::EF_PPC64_ABI;
|
||||||
// A PPC branch relocation will need a stub function if the target is
|
// A PPC branch relocation will need a stub function if the target is
|
||||||
// an external symbol (Symbol::ST_Unknown) or if the target address
|
// an external symbol (Symbol::ST_Unknown) or if the target address
|
||||||
@ -1495,7 +1460,7 @@ uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, uint64_t Offset) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RuntimeDyldELF::finalizeLoad(ObjectImage &ObjImg,
|
void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,
|
||||||
ObjSectionToIDMap &SectionMap) {
|
ObjSectionToIDMap &SectionMap) {
|
||||||
// If necessary, allocate the global offset table
|
// If necessary, allocate the global offset table
|
||||||
if (MemMgr) {
|
if (MemMgr) {
|
||||||
@ -1533,15 +1498,8 @@ void RuntimeDyldELF::finalizeLoad(ObjectImage &ObjImg,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuntimeDyldELF::isCompatibleFormat(const ObjectBuffer *Buffer) const {
|
bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const {
|
||||||
if (Buffer->getBufferSize() < strlen(ELF::ElfMagic))
|
return Obj.isELF();
|
||||||
return false;
|
|
||||||
return (memcmp(Buffer->getBufferStart(), ELF::ElfMagic,
|
|
||||||
strlen(ELF::ElfMagic))) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile *Obj) const {
|
|
||||||
return Obj->isELF();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
@ -28,9 +28,11 @@ std::error_code Check(std::error_code Err) {
|
|||||||
}
|
}
|
||||||
return Err;
|
return Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
class RuntimeDyldELF : public RuntimeDyldImpl {
|
class RuntimeDyldELF : public RuntimeDyldImpl {
|
||||||
|
|
||||||
void resolveRelocation(const SectionEntry &Section, uint64_t Offset,
|
void resolveRelocation(const SectionEntry &Section, uint64_t Offset,
|
||||||
uint64_t Value, uint32_t Type, int64_t Addend,
|
uint64_t Value, uint32_t Type, int64_t Addend,
|
||||||
uint64_t SymOffset = 0);
|
uint64_t SymOffset = 0);
|
||||||
@ -81,9 +83,11 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void findPPC64TOCSection(ObjectImage &Obj, ObjSectionToIDMap &LocalSections,
|
void findPPC64TOCSection(const ObjectFile &Obj,
|
||||||
|
ObjSectionToIDMap &LocalSections,
|
||||||
RelocationValueRef &Rel);
|
RelocationValueRef &Rel);
|
||||||
void findOPDEntrySection(ObjectImage &Obj, ObjSectionToIDMap &LocalSections,
|
void findOPDEntrySection(const ObjectFile &Obj,
|
||||||
|
ObjSectionToIDMap &LocalSections,
|
||||||
RelocationValueRef &Rel);
|
RelocationValueRef &Rel);
|
||||||
|
|
||||||
uint64_t findGOTEntry(uint64_t LoadAddr, uint64_t Offset);
|
uint64_t findGOTEntry(uint64_t LoadAddr, uint64_t Offset);
|
||||||
@ -104,24 +108,23 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
|
|||||||
SmallVector<SID, 2> RegisteredEHFrameSections;
|
SmallVector<SID, 2> RegisteredEHFrameSections;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
|
RuntimeDyldELF(RTDyldMemoryManager *mm);
|
||||||
|
virtual ~RuntimeDyldELF();
|
||||||
|
|
||||||
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||||
|
loadObject(const object::ObjectFile &O) override;
|
||||||
|
|
||||||
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override;
|
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override;
|
||||||
relocation_iterator
|
relocation_iterator
|
||||||
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
||||||
ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID,
|
const ObjectFile &Obj,
|
||||||
|
ObjSectionToIDMap &ObjSectionToID,
|
||||||
const SymbolTableMap &Symbols, StubMap &Stubs) override;
|
const SymbolTableMap &Symbols, StubMap &Stubs) override;
|
||||||
bool isCompatibleFormat(const ObjectBuffer *Buffer) const override;
|
bool isCompatibleFile(const object::ObjectFile &Obj) const override;
|
||||||
bool isCompatibleFile(const object::ObjectFile *Buffer) const override;
|
|
||||||
void registerEHFrames() override;
|
void registerEHFrames() override;
|
||||||
void deregisterEHFrames() override;
|
void deregisterEHFrames() override;
|
||||||
void finalizeLoad(ObjectImage &ObjImg,
|
void finalizeLoad(const ObjectFile &Obj,
|
||||||
ObjSectionToIDMap &SectionMap) override;
|
ObjSectionToIDMap &SectionMap) override;
|
||||||
virtual ~RuntimeDyldELF();
|
|
||||||
|
|
||||||
static std::unique_ptr<ObjectImage>
|
|
||||||
createObjectImage(std::unique_ptr<ObjectBuffer> InputBuffer);
|
|
||||||
static ObjectImage *createObjectImageFromFile(std::unique_ptr<object::ObjectFile> Obj);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/ADT/Triple.h"
|
#include "llvm/ADT/Triple.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
|
||||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||||
#include "llvm/ExecutionEngine/RuntimeDyldChecker.h"
|
#include "llvm/ExecutionEngine/RuntimeDyldChecker.h"
|
||||||
#include "llvm/Object/ObjectFile.h"
|
#include "llvm/Object/ObjectFile.h"
|
||||||
@ -37,7 +36,6 @@ using namespace llvm::object;
|
|||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class ObjectBuffer;
|
|
||||||
class Twine;
|
class Twine;
|
||||||
|
|
||||||
/// SectionEntry - represents a section emitted into memory by the dynamic
|
/// SectionEntry - represents a section emitted into memory by the dynamic
|
||||||
@ -159,6 +157,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class RuntimeDyldImpl {
|
class RuntimeDyldImpl {
|
||||||
|
friend class RuntimeDyld::LoadedObjectInfo;
|
||||||
friend class RuntimeDyldCheckerImpl;
|
friend class RuntimeDyldCheckerImpl;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -296,14 +295,15 @@ protected:
|
|||||||
/// \brief Given the common symbols discovered in the object file, emit a
|
/// \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
|
/// new section for them and update the symbol mappings in the object and
|
||||||
/// symbol table.
|
/// symbol table.
|
||||||
void emitCommonSymbols(ObjectImage &Obj, const CommonSymbolMap &CommonSymbols,
|
void emitCommonSymbols(const ObjectFile &Obj,
|
||||||
|
const CommonSymbolMap &CommonSymbols,
|
||||||
uint64_t TotalSize, SymbolTableMap &SymbolTable);
|
uint64_t TotalSize, SymbolTableMap &SymbolTable);
|
||||||
|
|
||||||
/// \brief Emits section data from the object file to the MemoryManager.
|
/// \brief Emits section data from the object file to the MemoryManager.
|
||||||
/// \param IsCode if it's true then allocateCodeSection() will be
|
/// \param IsCode if it's true then allocateCodeSection() will be
|
||||||
/// used for emits, else allocateDataSection() will be used.
|
/// used for emits, else allocateDataSection() will be used.
|
||||||
/// \return SectionID.
|
/// \return SectionID.
|
||||||
unsigned emitSection(ObjectImage &Obj, const SectionRef &Section,
|
unsigned emitSection(const ObjectFile &Obj, const SectionRef &Section,
|
||||||
bool IsCode);
|
bool IsCode);
|
||||||
|
|
||||||
/// \brief Find Section in LocalSections. If the secton is not found - emit
|
/// \brief Find Section in LocalSections. If the secton is not found - emit
|
||||||
@ -311,7 +311,7 @@ protected:
|
|||||||
/// \param IsCode if it's true then allocateCodeSection() will be
|
/// \param IsCode if it's true then allocateCodeSection() will be
|
||||||
/// used for emmits, else allocateDataSection() will be used.
|
/// used for emmits, else allocateDataSection() will be used.
|
||||||
/// \return SectionID.
|
/// \return SectionID.
|
||||||
unsigned findOrEmitSection(ObjectImage &Obj, const SectionRef &Section,
|
unsigned findOrEmitSection(const ObjectFile &Obj, const SectionRef &Section,
|
||||||
bool IsCode, ObjSectionToIDMap &LocalSections);
|
bool IsCode, ObjSectionToIDMap &LocalSections);
|
||||||
|
|
||||||
// \brief Add a relocation entry that uses the given section.
|
// \brief Add a relocation entry that uses the given section.
|
||||||
@ -339,7 +339,7 @@ protected:
|
|||||||
/// \return Iterator to the next relocation that needs to be parsed.
|
/// \return Iterator to the next relocation that needs to be parsed.
|
||||||
virtual relocation_iterator
|
virtual relocation_iterator
|
||||||
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
||||||
ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID,
|
const ObjectFile &Obj, ObjSectionToIDMap &ObjSectionToID,
|
||||||
const SymbolTableMap &Symbols, StubMap &Stubs) = 0;
|
const SymbolTableMap &Symbols, StubMap &Stubs) = 0;
|
||||||
|
|
||||||
/// \brief Resolve relocations to external symbols.
|
/// \brief Resolve relocations to external symbols.
|
||||||
@ -351,13 +351,16 @@ protected:
|
|||||||
|
|
||||||
// \brief Compute an upper bound of the memory that is required to load all
|
// \brief Compute an upper bound of the memory that is required to load all
|
||||||
// sections
|
// sections
|
||||||
void computeTotalAllocSize(ObjectImage &Obj, uint64_t &CodeSize,
|
void computeTotalAllocSize(const ObjectFile &Obj, uint64_t &CodeSize,
|
||||||
uint64_t &DataSizeRO, uint64_t &DataSizeRW);
|
uint64_t &DataSizeRO, uint64_t &DataSizeRW);
|
||||||
|
|
||||||
// \brief Compute the stub buffer size required for a section
|
// \brief Compute the stub buffer size required for a section
|
||||||
unsigned computeSectionStubBufSize(ObjectImage &Obj,
|
unsigned computeSectionStubBufSize(const ObjectFile &Obj,
|
||||||
const SectionRef &Section);
|
const SectionRef &Section);
|
||||||
|
|
||||||
|
// \brief Implementation of the generic part of the loadObject algorithm.
|
||||||
|
std::pair<unsigned, unsigned> loadObjectImpl(const object::ObjectFile &Obj);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RuntimeDyldImpl(RTDyldMemoryManager *mm)
|
RuntimeDyldImpl(RTDyldMemoryManager *mm)
|
||||||
: MemMgr(mm), Checker(nullptr), ProcessAllSections(false), HasError(false) {
|
: MemMgr(mm), Checker(nullptr), ProcessAllSections(false), HasError(false) {
|
||||||
@ -373,8 +376,8 @@ public:
|
|||||||
this->Checker = Checker;
|
this->Checker = Checker;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ObjectImage>
|
virtual std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||||
loadObject(std::unique_ptr<ObjectImage> InputObject);
|
loadObject(const object::ObjectFile &Obj) = 0;
|
||||||
|
|
||||||
uint8_t* getSymbolAddress(StringRef Name) const {
|
uint8_t* getSymbolAddress(StringRef Name) const {
|
||||||
// FIXME: Just look up as a function for now. Overly simple of course.
|
// FIXME: Just look up as a function for now. Overly simple of course.
|
||||||
@ -411,14 +414,14 @@ public:
|
|||||||
// Get the error message.
|
// Get the error message.
|
||||||
StringRef getErrorString() { return ErrorStr; }
|
StringRef getErrorString() { return ErrorStr; }
|
||||||
|
|
||||||
virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0;
|
virtual bool isCompatibleFile(const ObjectFile &Obj) const = 0;
|
||||||
virtual bool isCompatibleFile(const ObjectFile *Obj) const = 0;
|
|
||||||
|
|
||||||
virtual void registerEHFrames();
|
virtual void registerEHFrames();
|
||||||
|
|
||||||
virtual void deregisterEHFrames();
|
virtual void deregisterEHFrames();
|
||||||
|
|
||||||
virtual void finalizeLoad(ObjectImage &ObjImg, ObjSectionToIDMap &SectionMap) {}
|
virtual void finalizeLoad(const ObjectFile &ObjImg,
|
||||||
|
ObjSectionToIDMap &SectionMap) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@ -25,6 +25,22 @@ using namespace llvm::object;
|
|||||||
|
|
||||||
#define DEBUG_TYPE "dyld"
|
#define DEBUG_TYPE "dyld"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class LoadedMachOObjectInfo : public RuntimeDyld::LoadedObjectInfo {
|
||||||
|
public:
|
||||||
|
LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
|
||||||
|
unsigned EndIdx)
|
||||||
|
: RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {}
|
||||||
|
|
||||||
|
OwningBinary<ObjectFile>
|
||||||
|
getObjectForDebug(const ObjectFile &Obj) const override {
|
||||||
|
return OwningBinary<ObjectFile>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const {
|
int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const {
|
||||||
@ -35,12 +51,12 @@ int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RelocationValueRef RuntimeDyldMachO::getRelocationValueRef(
|
RelocationValueRef RuntimeDyldMachO::getRelocationValueRef(
|
||||||
ObjectImage &ObjImg, const relocation_iterator &RI,
|
const ObjectFile &BaseTObj, const relocation_iterator &RI,
|
||||||
const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID,
|
const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID,
|
||||||
const SymbolTableMap &Symbols) {
|
const SymbolTableMap &Symbols) {
|
||||||
|
|
||||||
const MachOObjectFile &Obj =
|
const MachOObjectFile &Obj =
|
||||||
static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile());
|
static_cast<const MachOObjectFile &>(BaseTObj);
|
||||||
MachO::any_relocation_info RelInfo =
|
MachO::any_relocation_info RelInfo =
|
||||||
Obj.getRelocation(RI->getRawDataRefImpl());
|
Obj.getRelocation(RI->getRawDataRefImpl());
|
||||||
RelocationValueRef Value;
|
RelocationValueRef Value;
|
||||||
@ -67,7 +83,7 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef(
|
|||||||
} else {
|
} else {
|
||||||
SectionRef Sec = Obj.getRelocationSection(RelInfo);
|
SectionRef Sec = Obj.getRelocationSection(RelInfo);
|
||||||
bool IsCode = Sec.isText();
|
bool IsCode = Sec.isText();
|
||||||
Value.SectionID = findOrEmitSection(ObjImg, Sec, IsCode, ObjSectionToID);
|
Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID);
|
||||||
uint64_t Addr = Sec.getAddress();
|
uint64_t Addr = Sec.getAddress();
|
||||||
Value.Offset = RE.Addend - Addr;
|
Value.Offset = RE.Addend - Addr;
|
||||||
}
|
}
|
||||||
@ -76,11 +92,11 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value,
|
void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value,
|
||||||
ObjectImage &ObjImg,
|
const ObjectFile &BaseTObj,
|
||||||
const relocation_iterator &RI,
|
const relocation_iterator &RI,
|
||||||
unsigned OffsetToNextPC) {
|
unsigned OffsetToNextPC) {
|
||||||
const MachOObjectFile &Obj =
|
const MachOObjectFile &Obj =
|
||||||
static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile());
|
static_cast<const MachOObjectFile &>(BaseTObj);
|
||||||
MachO::any_relocation_info RelInfo =
|
MachO::any_relocation_info RelInfo =
|
||||||
Obj.getRelocation(RI->getRawDataRefImpl());
|
Obj.getRelocation(RI->getRawDataRefImpl());
|
||||||
|
|
||||||
@ -125,7 +141,7 @@ RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj,
|
|||||||
|
|
||||||
// Populate __pointers section.
|
// Populate __pointers section.
|
||||||
void RuntimeDyldMachO::populateIndirectSymbolPointersSection(
|
void RuntimeDyldMachO::populateIndirectSymbolPointersSection(
|
||||||
MachOObjectFile &Obj,
|
const MachOObjectFile &Obj,
|
||||||
const SectionRef &PTSection,
|
const SectionRef &PTSection,
|
||||||
unsigned PTSectionID) {
|
unsigned PTSectionID) {
|
||||||
assert(!Obj.is64Bit() &&
|
assert(!Obj.is64Bit() &&
|
||||||
@ -163,28 +179,12 @@ void RuntimeDyldMachO::populateIndirectSymbolPointersSection(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const {
|
||||||
RuntimeDyldMachO::isCompatibleFormat(const ObjectBuffer *InputBuffer) const {
|
return Obj.isMachO();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile *Obj) const {
|
|
||||||
return Obj->isMachO();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Impl>
|
template <typename Impl>
|
||||||
void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(ObjectImage &ObjImg,
|
void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &ObjImg,
|
||||||
ObjSectionToIDMap &SectionMap) {
|
ObjSectionToIDMap &SectionMap) {
|
||||||
unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID;
|
unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID;
|
||||||
unsigned TextSID = RTDYLD_INVALID_SECTION_ID;
|
unsigned TextSID = RTDYLD_INVALID_SECTION_ID;
|
||||||
@ -284,7 +284,7 @@ void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<RuntimeDyldMachO>
|
std::unique_ptr<RuntimeDyldMachO>
|
||||||
llvm::RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) {
|
RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) {
|
||||||
switch (Arch) {
|
switch (Arch) {
|
||||||
default:
|
default:
|
||||||
llvm_unreachable("Unsupported target for RuntimeDyldMachO.");
|
llvm_unreachable("Unsupported target for RuntimeDyldMachO.");
|
||||||
@ -296,4 +296,12 @@ llvm::RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||||
|
RuntimeDyldMachO::loadObject(const object::ObjectFile &O) {
|
||||||
|
unsigned SectionStartIdx, SectionEndIdx;
|
||||||
|
std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O);
|
||||||
|
return llvm::make_unique<LoadedMachOObjectInfo>(*this, SectionStartIdx,
|
||||||
|
SectionEndIdx);
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDMACHO_H
|
#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDMACHO_H
|
||||||
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDMACHO_H
|
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDMACHO_H
|
||||||
|
|
||||||
#include "ObjectImageCommon.h"
|
|
||||||
#include "RuntimeDyldImpl.h"
|
#include "RuntimeDyldImpl.h"
|
||||||
#include "llvm/Object/MachO.h"
|
#include "llvm/Object/MachO.h"
|
||||||
#include "llvm/Support/Format.h"
|
#include "llvm/Support/Format.h"
|
||||||
@ -61,10 +60,11 @@ protected:
|
|||||||
/// filled in, since immediate encodings are highly target/opcode specific.
|
/// filled in, since immediate encodings are highly target/opcode specific.
|
||||||
/// For targets/opcodes with simple, contiguous immediates (e.g. X86) the
|
/// For targets/opcodes with simple, contiguous immediates (e.g. X86) the
|
||||||
/// memcpyAddend method can be used to read the immediate.
|
/// memcpyAddend method can be used to read the immediate.
|
||||||
RelocationEntry getRelocationEntry(unsigned SectionID, ObjectImage &ObjImg,
|
RelocationEntry getRelocationEntry(unsigned SectionID,
|
||||||
|
const ObjectFile &BaseTObj,
|
||||||
const relocation_iterator &RI) const {
|
const relocation_iterator &RI) const {
|
||||||
const MachOObjectFile &Obj =
|
const MachOObjectFile &Obj =
|
||||||
static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile());
|
static_cast<const MachOObjectFile &>(BaseTObj);
|
||||||
MachO::any_relocation_info RelInfo =
|
MachO::any_relocation_info RelInfo =
|
||||||
Obj.getRelocation(RI->getRawDataRefImpl());
|
Obj.getRelocation(RI->getRawDataRefImpl());
|
||||||
|
|
||||||
@ -87,14 +87,15 @@ protected:
|
|||||||
/// In both cases the Addend field is *NOT* fixed up to be PC-relative. That
|
/// In both cases the Addend field is *NOT* fixed up to be PC-relative. That
|
||||||
/// should be done by the caller where appropriate by calling makePCRel on
|
/// should be done by the caller where appropriate by calling makePCRel on
|
||||||
/// the RelocationValueRef.
|
/// the RelocationValueRef.
|
||||||
RelocationValueRef getRelocationValueRef(ObjectImage &ObjImg,
|
RelocationValueRef getRelocationValueRef(const ObjectFile &BaseTObj,
|
||||||
const relocation_iterator &RI,
|
const relocation_iterator &RI,
|
||||||
const RelocationEntry &RE,
|
const RelocationEntry &RE,
|
||||||
ObjSectionToIDMap &ObjSectionToID,
|
ObjSectionToIDMap &ObjSectionToID,
|
||||||
const SymbolTableMap &Symbols);
|
const SymbolTableMap &Symbols);
|
||||||
|
|
||||||
/// Make the RelocationValueRef addend PC-relative.
|
/// Make the RelocationValueRef addend PC-relative.
|
||||||
void makeValueAddendPCRel(RelocationValueRef &Value, ObjectImage &ObjImg,
|
void makeValueAddendPCRel(RelocationValueRef &Value,
|
||||||
|
const ObjectFile &BaseTObj,
|
||||||
const relocation_iterator &RI,
|
const relocation_iterator &RI,
|
||||||
unsigned OffsetToNextPC);
|
unsigned OffsetToNextPC);
|
||||||
|
|
||||||
@ -107,31 +108,22 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
// Populate __pointers section.
|
// Populate __pointers section.
|
||||||
void populateIndirectSymbolPointersSection(MachOObjectFile &Obj,
|
void populateIndirectSymbolPointersSection(const MachOObjectFile &Obj,
|
||||||
const SectionRef &PTSection,
|
const SectionRef &PTSection,
|
||||||
unsigned PTSectionID);
|
unsigned PTSectionID);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Create an ObjectImage from the given ObjectBuffer.
|
|
||||||
static std::unique_ptr<ObjectImage>
|
|
||||||
createObjectImage(std::unique_ptr<ObjectBuffer> InputBuffer) {
|
|
||||||
return llvm::make_unique<ObjectImageCommon>(std::move(InputBuffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create an ObjectImage from the given ObjectFile.
|
|
||||||
static ObjectImage *
|
|
||||||
createObjectImageFromFile(std::unique_ptr<object::ObjectFile> InputObject) {
|
|
||||||
return new ObjectImageCommon(std::move(InputObject));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a RuntimeDyldMachO instance for the given target architecture.
|
/// Create a RuntimeDyldMachO instance for the given target architecture.
|
||||||
static std::unique_ptr<RuntimeDyldMachO> create(Triple::ArchType Arch,
|
static std::unique_ptr<RuntimeDyldMachO> create(Triple::ArchType Arch,
|
||||||
RTDyldMemoryManager *mm);
|
RTDyldMemoryManager *mm);
|
||||||
|
|
||||||
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||||
|
loadObject(const object::ObjectFile &O) override;
|
||||||
|
|
||||||
SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; }
|
SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; }
|
||||||
|
|
||||||
bool isCompatibleFormat(const ObjectBuffer *Buffer) const override;
|
bool isCompatibleFile(const object::ObjectFile &Obj) const override;
|
||||||
bool isCompatibleFile(const object::ObjectFile *Obj) const override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// RuntimeDyldMachOTarget - Templated base class for generic MachO linker
|
/// RuntimeDyldMachOTarget - Templated base class for generic MachO linker
|
||||||
@ -153,7 +145,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
RuntimeDyldMachOCRTPBase(RTDyldMemoryManager *mm) : RuntimeDyldMachO(mm) {}
|
RuntimeDyldMachOCRTPBase(RTDyldMemoryManager *mm) : RuntimeDyldMachO(mm) {}
|
||||||
|
|
||||||
void finalizeLoad(ObjectImage &ObjImg,
|
void finalizeLoad(const ObjectFile &Obj,
|
||||||
ObjSectionToIDMap &SectionMap) override;
|
ObjSectionToIDMap &SectionMap) override;
|
||||||
void registerEHFrames() override;
|
void registerEHFrames() override;
|
||||||
};
|
};
|
||||||
|
@ -243,10 +243,11 @@ public:
|
|||||||
|
|
||||||
relocation_iterator
|
relocation_iterator
|
||||||
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
||||||
ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID,
|
const ObjectFile &BaseObjT,
|
||||||
|
ObjSectionToIDMap &ObjSectionToID,
|
||||||
const SymbolTableMap &Symbols, StubMap &Stubs) override {
|
const SymbolTableMap &Symbols, StubMap &Stubs) override {
|
||||||
const MachOObjectFile &Obj =
|
const MachOObjectFile &Obj =
|
||||||
static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile());
|
static_cast<const MachOObjectFile &>(BaseObjT);
|
||||||
MachO::any_relocation_info RelInfo =
|
MachO::any_relocation_info RelInfo =
|
||||||
Obj.getRelocation(RelI->getRawDataRefImpl());
|
Obj.getRelocation(RelI->getRawDataRefImpl());
|
||||||
|
|
||||||
@ -268,10 +269,10 @@ public:
|
|||||||
RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl());
|
RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl());
|
||||||
}
|
}
|
||||||
|
|
||||||
RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI));
|
RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
|
||||||
RE.Addend = decodeAddend(RE);
|
RE.Addend = decodeAddend(RE);
|
||||||
RelocationValueRef Value(
|
RelocationValueRef Value(
|
||||||
getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols));
|
getRelocationValueRef(Obj, RelI, RE, ObjSectionToID, Symbols));
|
||||||
|
|
||||||
assert((ExplicitAddend == 0 || RE.Addend == 0) && "Relocation has "\
|
assert((ExplicitAddend == 0 || RE.Addend == 0) && "Relocation has "\
|
||||||
"ARM64_RELOC_ADDEND and embedded addend in the instruction.");
|
"ARM64_RELOC_ADDEND and embedded addend in the instruction.");
|
||||||
@ -282,7 +283,7 @@ public:
|
|||||||
|
|
||||||
bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
|
bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
|
||||||
if (!IsExtern && RE.IsPCRel)
|
if (!IsExtern && RE.IsPCRel)
|
||||||
makeValueAddendPCRel(Value, ObjImg, RelI, 1 << RE.Size);
|
makeValueAddendPCRel(Value, Obj, RelI, 1 << RE.Size);
|
||||||
|
|
||||||
RE.Addend = Value.Offset;
|
RE.Addend = Value.Offset;
|
||||||
|
|
||||||
@ -359,7 +360,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void finalizeSection(ObjectImage &ObjImg, unsigned SectionID,
|
void finalizeSection(const ObjectFile &Obj, unsigned SectionID,
|
||||||
const SectionRef &Section) {}
|
const SectionRef &Section) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -49,29 +49,30 @@ public:
|
|||||||
|
|
||||||
relocation_iterator
|
relocation_iterator
|
||||||
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
||||||
ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID,
|
const ObjectFile &BaseObjT,
|
||||||
|
ObjSectionToIDMap &ObjSectionToID,
|
||||||
const SymbolTableMap &Symbols, StubMap &Stubs) override {
|
const SymbolTableMap &Symbols, StubMap &Stubs) override {
|
||||||
const MachOObjectFile &Obj =
|
const MachOObjectFile &Obj =
|
||||||
static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile());
|
static_cast<const MachOObjectFile &>(BaseObjT);
|
||||||
MachO::any_relocation_info RelInfo =
|
MachO::any_relocation_info RelInfo =
|
||||||
Obj.getRelocation(RelI->getRawDataRefImpl());
|
Obj.getRelocation(RelI->getRawDataRefImpl());
|
||||||
uint32_t RelType = Obj.getAnyRelocationType(RelInfo);
|
uint32_t RelType = Obj.getAnyRelocationType(RelInfo);
|
||||||
|
|
||||||
if (Obj.isRelocationScattered(RelInfo)) {
|
if (Obj.isRelocationScattered(RelInfo)) {
|
||||||
if (RelType == MachO::ARM_RELOC_HALF_SECTDIFF)
|
if (RelType == MachO::ARM_RELOC_HALF_SECTDIFF)
|
||||||
return processHALFSECTDIFFRelocation(SectionID, RelI, ObjImg,
|
return processHALFSECTDIFFRelocation(SectionID, RelI, Obj,
|
||||||
ObjSectionToID);
|
ObjSectionToID);
|
||||||
else
|
else
|
||||||
return ++++RelI;
|
return ++++RelI;
|
||||||
}
|
}
|
||||||
|
|
||||||
RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI));
|
RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
|
||||||
RE.Addend = decodeAddend(RE);
|
RE.Addend = decodeAddend(RE);
|
||||||
RelocationValueRef Value(
|
RelocationValueRef Value(
|
||||||
getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols));
|
getRelocationValueRef(Obj, RelI, RE, ObjSectionToID, Symbols));
|
||||||
|
|
||||||
if (RE.IsPCRel)
|
if (RE.IsPCRel)
|
||||||
makeValueAddendPCRel(Value, ObjImg, RelI, 8);
|
makeValueAddendPCRel(Value, Obj, RelI, 8);
|
||||||
|
|
||||||
if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24)
|
if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24)
|
||||||
processBranchRelocation(RE, Value, Stubs);
|
processBranchRelocation(RE, Value, Stubs);
|
||||||
@ -154,15 +155,14 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void finalizeSection(ObjectImage &ObjImg, unsigned SectionID,
|
void finalizeSection(const ObjectFile &Obj, unsigned SectionID,
|
||||||
const SectionRef &Section) {
|
const SectionRef &Section) {
|
||||||
StringRef Name;
|
StringRef Name;
|
||||||
Section.getName(Name);
|
Section.getName(Name);
|
||||||
|
|
||||||
if (Name == "__nl_symbol_ptr")
|
if (Name == "__nl_symbol_ptr")
|
||||||
populateIndirectSymbolPointersSection(
|
populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj),
|
||||||
cast<MachOObjectFile>(*ObjImg.getObjectFile()),
|
Section, SectionID);
|
||||||
Section, SectionID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -199,25 +199,25 @@ private:
|
|||||||
|
|
||||||
relocation_iterator
|
relocation_iterator
|
||||||
processHALFSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI,
|
processHALFSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI,
|
||||||
ObjectImage &Obj,
|
const ObjectFile &BaseTObj,
|
||||||
ObjSectionToIDMap &ObjSectionToID) {
|
ObjSectionToIDMap &ObjSectionToID) {
|
||||||
const MachOObjectFile *MachO =
|
const MachOObjectFile &MachO =
|
||||||
static_cast<const MachOObjectFile *>(Obj.getObjectFile());
|
static_cast<const MachOObjectFile&>(BaseTObj);
|
||||||
MachO::any_relocation_info RE =
|
MachO::any_relocation_info RE =
|
||||||
MachO->getRelocation(RelI->getRawDataRefImpl());
|
MachO.getRelocation(RelI->getRawDataRefImpl());
|
||||||
|
|
||||||
|
|
||||||
// For a half-diff relocation the length bits actually record whether this
|
// For a half-diff relocation the length bits actually record whether this
|
||||||
// is a movw/movt, and whether this is arm or thumb.
|
// is a movw/movt, and whether this is arm or thumb.
|
||||||
// Bit 0 indicates movw (b0 == 0) or movt (b0 == 1).
|
// Bit 0 indicates movw (b0 == 0) or movt (b0 == 1).
|
||||||
// Bit 1 indicates arm (b1 == 0) or thumb (b1 == 1).
|
// Bit 1 indicates arm (b1 == 0) or thumb (b1 == 1).
|
||||||
unsigned HalfDiffKindBits = MachO->getAnyRelocationLength(RE);
|
unsigned HalfDiffKindBits = MachO.getAnyRelocationLength(RE);
|
||||||
if (HalfDiffKindBits & 0x2)
|
if (HalfDiffKindBits & 0x2)
|
||||||
llvm_unreachable("Thumb not yet supported.");
|
llvm_unreachable("Thumb not yet supported.");
|
||||||
|
|
||||||
SectionEntry &Section = Sections[SectionID];
|
SectionEntry &Section = Sections[SectionID];
|
||||||
uint32_t RelocType = MachO->getAnyRelocationType(RE);
|
uint32_t RelocType = MachO.getAnyRelocationType(RE);
|
||||||
bool IsPCRel = MachO->getAnyRelocationPCRel(RE);
|
bool IsPCRel = MachO.getAnyRelocationPCRel(RE);
|
||||||
uint64_t Offset;
|
uint64_t Offset;
|
||||||
RelI->getOffset(Offset);
|
RelI->getOffset(Offset);
|
||||||
uint8_t *LocalAddress = Section.Address + Offset;
|
uint8_t *LocalAddress = Section.Address + Offset;
|
||||||
@ -226,27 +226,27 @@ private:
|
|||||||
|
|
||||||
++RelI;
|
++RelI;
|
||||||
MachO::any_relocation_info RE2 =
|
MachO::any_relocation_info RE2 =
|
||||||
MachO->getRelocation(RelI->getRawDataRefImpl());
|
MachO.getRelocation(RelI->getRawDataRefImpl());
|
||||||
uint32_t AddrA = MachO->getScatteredRelocationValue(RE);
|
uint32_t AddrA = MachO.getScatteredRelocationValue(RE);
|
||||||
section_iterator SAI = getSectionByAddress(*MachO, AddrA);
|
section_iterator SAI = getSectionByAddress(MachO, AddrA);
|
||||||
assert(SAI != MachO->section_end() && "Can't find section for address A");
|
assert(SAI != MachO.section_end() && "Can't find section for address A");
|
||||||
uint64_t SectionABase = SAI->getAddress();
|
uint64_t SectionABase = SAI->getAddress();
|
||||||
uint64_t SectionAOffset = AddrA - SectionABase;
|
uint64_t SectionAOffset = AddrA - SectionABase;
|
||||||
SectionRef SectionA = *SAI;
|
SectionRef SectionA = *SAI;
|
||||||
bool IsCode = SectionA.isText();
|
bool IsCode = SectionA.isText();
|
||||||
uint32_t SectionAID =
|
uint32_t SectionAID =
|
||||||
findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID);
|
findOrEmitSection(MachO, SectionA, IsCode, ObjSectionToID);
|
||||||
|
|
||||||
uint32_t AddrB = MachO->getScatteredRelocationValue(RE2);
|
uint32_t AddrB = MachO.getScatteredRelocationValue(RE2);
|
||||||
section_iterator SBI = getSectionByAddress(*MachO, AddrB);
|
section_iterator SBI = getSectionByAddress(MachO, AddrB);
|
||||||
assert(SBI != MachO->section_end() && "Can't find section for address B");
|
assert(SBI != MachO.section_end() && "Can't find section for address B");
|
||||||
uint64_t SectionBBase = SBI->getAddress();
|
uint64_t SectionBBase = SBI->getAddress();
|
||||||
uint64_t SectionBOffset = AddrB - SectionBBase;
|
uint64_t SectionBOffset = AddrB - SectionBBase;
|
||||||
SectionRef SectionB = *SBI;
|
SectionRef SectionB = *SBI;
|
||||||
uint32_t SectionBID =
|
uint32_t SectionBID =
|
||||||
findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID);
|
findOrEmitSection(MachO, SectionB, IsCode, ObjSectionToID);
|
||||||
|
|
||||||
uint32_t OtherHalf = MachO->getAnyRelocationAddress(RE2) & 0xffff;
|
uint32_t OtherHalf = MachO.getAnyRelocationAddress(RE2) & 0xffff;
|
||||||
unsigned Shift = (HalfDiffKindBits & 0x1) ? 16 : 0;
|
unsigned Shift = (HalfDiffKindBits & 0x1) ? 16 : 0;
|
||||||
uint32_t FullImmVal = (Immediate << Shift) | (OtherHalf << (16 - Shift));
|
uint32_t FullImmVal = (Immediate << Shift) | (OtherHalf << (16 - Shift));
|
||||||
int64_t Addend = FullImmVal - (AddrA - AddrB);
|
int64_t Addend = FullImmVal - (AddrA - AddrB);
|
||||||
|
@ -31,10 +31,11 @@ public:
|
|||||||
|
|
||||||
relocation_iterator
|
relocation_iterator
|
||||||
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
||||||
ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID,
|
const ObjectFile &BaseObjT,
|
||||||
|
ObjSectionToIDMap &ObjSectionToID,
|
||||||
const SymbolTableMap &Symbols, StubMap &Stubs) override {
|
const SymbolTableMap &Symbols, StubMap &Stubs) override {
|
||||||
const MachOObjectFile &Obj =
|
const MachOObjectFile &Obj =
|
||||||
static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile());
|
static_cast<const MachOObjectFile &>(BaseObjT);
|
||||||
MachO::any_relocation_info RelInfo =
|
MachO::any_relocation_info RelInfo =
|
||||||
Obj.getRelocation(RelI->getRawDataRefImpl());
|
Obj.getRelocation(RelI->getRawDataRefImpl());
|
||||||
uint32_t RelType = Obj.getAnyRelocationType(RelInfo);
|
uint32_t RelType = Obj.getAnyRelocationType(RelInfo);
|
||||||
@ -42,18 +43,18 @@ public:
|
|||||||
if (Obj.isRelocationScattered(RelInfo)) {
|
if (Obj.isRelocationScattered(RelInfo)) {
|
||||||
if (RelType == MachO::GENERIC_RELOC_SECTDIFF ||
|
if (RelType == MachO::GENERIC_RELOC_SECTDIFF ||
|
||||||
RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)
|
RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)
|
||||||
return processSECTDIFFRelocation(SectionID, RelI, ObjImg,
|
return processSECTDIFFRelocation(SectionID, RelI, Obj,
|
||||||
ObjSectionToID);
|
ObjSectionToID);
|
||||||
else if (RelType == MachO::GENERIC_RELOC_VANILLA)
|
else if (RelType == MachO::GENERIC_RELOC_VANILLA)
|
||||||
return processI386ScatteredVANILLA(SectionID, RelI, ObjImg,
|
return processI386ScatteredVANILLA(SectionID, RelI, Obj,
|
||||||
ObjSectionToID);
|
ObjSectionToID);
|
||||||
llvm_unreachable("Unhandled scattered relocation.");
|
llvm_unreachable("Unhandled scattered relocation.");
|
||||||
}
|
}
|
||||||
|
|
||||||
RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI));
|
RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
|
||||||
RE.Addend = memcpyAddend(RE);
|
RE.Addend = memcpyAddend(RE);
|
||||||
RelocationValueRef Value(
|
RelocationValueRef Value(
|
||||||
getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols));
|
getRelocationValueRef(Obj, RelI, RE, ObjSectionToID, Symbols));
|
||||||
|
|
||||||
// Addends for external, PC-rel relocations on i386 point back to the zero
|
// Addends for external, PC-rel relocations on i386 point back to the zero
|
||||||
// offset. Calculate the final offset from the relocation target instead.
|
// offset. Calculate the final offset from the relocation target instead.
|
||||||
@ -66,7 +67,7 @@ public:
|
|||||||
// Value.Addend += RelocAddr + 4;
|
// Value.Addend += RelocAddr + 4;
|
||||||
// }
|
// }
|
||||||
if (RE.IsPCRel)
|
if (RE.IsPCRel)
|
||||||
makeValueAddendPCRel(Value, ObjImg, RelI, 1 << RE.Size);
|
makeValueAddendPCRel(Value, Obj, RelI, 1 << RE.Size);
|
||||||
|
|
||||||
RE.Addend = Value.Offset;
|
RE.Addend = Value.Offset;
|
||||||
|
|
||||||
@ -110,34 +111,32 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void finalizeSection(ObjectImage &ObjImg, unsigned SectionID,
|
void finalizeSection(const ObjectFile &Obj, unsigned SectionID,
|
||||||
const SectionRef &Section) {
|
const SectionRef &Section) {
|
||||||
StringRef Name;
|
StringRef Name;
|
||||||
Section.getName(Name);
|
Section.getName(Name);
|
||||||
|
|
||||||
if (Name == "__jump_table")
|
if (Name == "__jump_table")
|
||||||
populateJumpTable(cast<MachOObjectFile>(*ObjImg.getObjectFile()), Section,
|
populateJumpTable(cast<MachOObjectFile>(Obj), Section, SectionID);
|
||||||
SectionID);
|
|
||||||
else if (Name == "__pointers")
|
else if (Name == "__pointers")
|
||||||
populateIndirectSymbolPointersSection(
|
populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj),
|
||||||
cast<MachOObjectFile>(*ObjImg.getObjectFile()),
|
Section, SectionID);
|
||||||
Section, SectionID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
relocation_iterator
|
relocation_iterator
|
||||||
processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI,
|
processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI,
|
||||||
ObjectImage &Obj,
|
const ObjectFile &BaseObjT,
|
||||||
ObjSectionToIDMap &ObjSectionToID) {
|
ObjSectionToIDMap &ObjSectionToID) {
|
||||||
const MachOObjectFile *MachO =
|
const MachOObjectFile &Obj =
|
||||||
static_cast<const MachOObjectFile *>(Obj.getObjectFile());
|
static_cast<const MachOObjectFile&>(BaseObjT);
|
||||||
MachO::any_relocation_info RE =
|
MachO::any_relocation_info RE =
|
||||||
MachO->getRelocation(RelI->getRawDataRefImpl());
|
Obj.getRelocation(RelI->getRawDataRefImpl());
|
||||||
|
|
||||||
SectionEntry &Section = Sections[SectionID];
|
SectionEntry &Section = Sections[SectionID];
|
||||||
uint32_t RelocType = MachO->getAnyRelocationType(RE);
|
uint32_t RelocType = Obj.getAnyRelocationType(RE);
|
||||||
bool IsPCRel = MachO->getAnyRelocationPCRel(RE);
|
bool IsPCRel = Obj.getAnyRelocationPCRel(RE);
|
||||||
unsigned Size = MachO->getAnyRelocationLength(RE);
|
unsigned Size = Obj.getAnyRelocationLength(RE);
|
||||||
uint64_t Offset;
|
uint64_t Offset;
|
||||||
RelI->getOffset(Offset);
|
RelI->getOffset(Offset);
|
||||||
uint8_t *LocalAddress = Section.Address + Offset;
|
uint8_t *LocalAddress = Section.Address + Offset;
|
||||||
@ -146,11 +145,11 @@ private:
|
|||||||
|
|
||||||
++RelI;
|
++RelI;
|
||||||
MachO::any_relocation_info RE2 =
|
MachO::any_relocation_info RE2 =
|
||||||
MachO->getRelocation(RelI->getRawDataRefImpl());
|
Obj.getRelocation(RelI->getRawDataRefImpl());
|
||||||
|
|
||||||
uint32_t AddrA = MachO->getScatteredRelocationValue(RE);
|
uint32_t AddrA = Obj.getScatteredRelocationValue(RE);
|
||||||
section_iterator SAI = getSectionByAddress(*MachO, AddrA);
|
section_iterator SAI = getSectionByAddress(Obj, AddrA);
|
||||||
assert(SAI != MachO->section_end() && "Can't find section for address A");
|
assert(SAI != Obj.section_end() && "Can't find section for address A");
|
||||||
uint64_t SectionABase = SAI->getAddress();
|
uint64_t SectionABase = SAI->getAddress();
|
||||||
uint64_t SectionAOffset = AddrA - SectionABase;
|
uint64_t SectionAOffset = AddrA - SectionABase;
|
||||||
SectionRef SectionA = *SAI;
|
SectionRef SectionA = *SAI;
|
||||||
@ -158,9 +157,9 @@ private:
|
|||||||
uint32_t SectionAID =
|
uint32_t SectionAID =
|
||||||
findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID);
|
findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID);
|
||||||
|
|
||||||
uint32_t AddrB = MachO->getScatteredRelocationValue(RE2);
|
uint32_t AddrB = Obj.getScatteredRelocationValue(RE2);
|
||||||
section_iterator SBI = getSectionByAddress(*MachO, AddrB);
|
section_iterator SBI = getSectionByAddress(Obj, AddrB);
|
||||||
assert(SBI != MachO->section_end() && "Can't find section for address B");
|
assert(SBI != Obj.section_end() && "Can't find section for address B");
|
||||||
uint64_t SectionBBase = SBI->getAddress();
|
uint64_t SectionBBase = SBI->getAddress();
|
||||||
uint64_t SectionBOffset = AddrB - SectionBBase;
|
uint64_t SectionBOffset = AddrB - SectionBBase;
|
||||||
SectionRef SectionB = *SBI;
|
SectionRef SectionB = *SBI;
|
||||||
@ -186,26 +185,27 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
relocation_iterator processI386ScatteredVANILLA(
|
relocation_iterator processI386ScatteredVANILLA(
|
||||||
unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj,
|
unsigned SectionID, relocation_iterator RelI,
|
||||||
|
const ObjectFile &BaseObjT,
|
||||||
RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) {
|
RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) {
|
||||||
const MachOObjectFile *MachO =
|
const MachOObjectFile &Obj =
|
||||||
static_cast<const MachOObjectFile *>(Obj.getObjectFile());
|
static_cast<const MachOObjectFile&>(BaseObjT);
|
||||||
MachO::any_relocation_info RE =
|
MachO::any_relocation_info RE =
|
||||||
MachO->getRelocation(RelI->getRawDataRefImpl());
|
Obj.getRelocation(RelI->getRawDataRefImpl());
|
||||||
|
|
||||||
SectionEntry &Section = Sections[SectionID];
|
SectionEntry &Section = Sections[SectionID];
|
||||||
uint32_t RelocType = MachO->getAnyRelocationType(RE);
|
uint32_t RelocType = Obj.getAnyRelocationType(RE);
|
||||||
bool IsPCRel = MachO->getAnyRelocationPCRel(RE);
|
bool IsPCRel = Obj.getAnyRelocationPCRel(RE);
|
||||||
unsigned Size = MachO->getAnyRelocationLength(RE);
|
unsigned Size = Obj.getAnyRelocationLength(RE);
|
||||||
uint64_t Offset;
|
uint64_t Offset;
|
||||||
RelI->getOffset(Offset);
|
RelI->getOffset(Offset);
|
||||||
uint8_t *LocalAddress = Section.Address + Offset;
|
uint8_t *LocalAddress = Section.Address + Offset;
|
||||||
unsigned NumBytes = 1 << Size;
|
unsigned NumBytes = 1 << Size;
|
||||||
int64_t Addend = readBytesUnaligned(LocalAddress, NumBytes);
|
int64_t Addend = readBytesUnaligned(LocalAddress, NumBytes);
|
||||||
|
|
||||||
unsigned SymbolBaseAddr = MachO->getScatteredRelocationValue(RE);
|
unsigned SymbolBaseAddr = Obj.getScatteredRelocationValue(RE);
|
||||||
section_iterator TargetSI = getSectionByAddress(*MachO, SymbolBaseAddr);
|
section_iterator TargetSI = getSectionByAddress(Obj, SymbolBaseAddr);
|
||||||
assert(TargetSI != MachO->section_end() && "Can't find section for symbol");
|
assert(TargetSI != Obj.section_end() && "Can't find section for symbol");
|
||||||
uint64_t SectionBaseAddr = TargetSI->getAddress();
|
uint64_t SectionBaseAddr = TargetSI->getAddress();
|
||||||
SectionRef TargetSection = *TargetSI;
|
SectionRef TargetSection = *TargetSI;
|
||||||
bool IsCode = TargetSection.isText();
|
bool IsCode = TargetSection.isText();
|
||||||
@ -221,7 +221,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Populate stubs in __jump_table section.
|
// Populate stubs in __jump_table section.
|
||||||
void populateJumpTable(MachOObjectFile &Obj, const SectionRef &JTSection,
|
void populateJumpTable(const MachOObjectFile &Obj, const SectionRef &JTSection,
|
||||||
unsigned JTSectionID) {
|
unsigned JTSectionID) {
|
||||||
assert(!Obj.is64Bit() &&
|
assert(!Obj.is64Bit() &&
|
||||||
"__jump_table section not supported in 64-bit MachO.");
|
"__jump_table section not supported in 64-bit MachO.");
|
||||||
|
@ -31,24 +31,25 @@ public:
|
|||||||
|
|
||||||
relocation_iterator
|
relocation_iterator
|
||||||
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
||||||
ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID,
|
const ObjectFile &BaseObjT,
|
||||||
|
ObjSectionToIDMap &ObjSectionToID,
|
||||||
const SymbolTableMap &Symbols, StubMap &Stubs) override {
|
const SymbolTableMap &Symbols, StubMap &Stubs) override {
|
||||||
const MachOObjectFile &Obj =
|
const MachOObjectFile &Obj =
|
||||||
static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile());
|
static_cast<const MachOObjectFile &>(BaseObjT);
|
||||||
MachO::any_relocation_info RelInfo =
|
MachO::any_relocation_info RelInfo =
|
||||||
Obj.getRelocation(RelI->getRawDataRefImpl());
|
Obj.getRelocation(RelI->getRawDataRefImpl());
|
||||||
|
|
||||||
assert(!Obj.isRelocationScattered(RelInfo) &&
|
assert(!Obj.isRelocationScattered(RelInfo) &&
|
||||||
"Scattered relocations not supported on X86_64");
|
"Scattered relocations not supported on X86_64");
|
||||||
|
|
||||||
RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI));
|
RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
|
||||||
RE.Addend = memcpyAddend(RE);
|
RE.Addend = memcpyAddend(RE);
|
||||||
RelocationValueRef Value(
|
RelocationValueRef Value(
|
||||||
getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols));
|
getRelocationValueRef(Obj, RelI, RE, ObjSectionToID, Symbols));
|
||||||
|
|
||||||
bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
|
bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
|
||||||
if (!IsExtern && RE.IsPCRel)
|
if (!IsExtern && RE.IsPCRel)
|
||||||
makeValueAddendPCRel(Value, ObjImg, RelI, 1 << RE.Size);
|
makeValueAddendPCRel(Value, Obj, RelI, 1 << RE.Size);
|
||||||
|
|
||||||
if (RE.RelType == MachO::X86_64_RELOC_GOT ||
|
if (RE.RelType == MachO::X86_64_RELOC_GOT ||
|
||||||
RE.RelType == MachO::X86_64_RELOC_GOT_LOAD)
|
RE.RelType == MachO::X86_64_RELOC_GOT_LOAD)
|
||||||
@ -97,7 +98,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void finalizeSection(ObjectImage &ObjImg, unsigned SectionID,
|
void finalizeSection(const ObjectFile &Obj, unsigned SectionID,
|
||||||
const SectionRef &Section) {}
|
const SectionRef &Section) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
#include "RemoteMemoryManager.h"
|
#include "RemoteMemoryManager.h"
|
||||||
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/Format.h"
|
#include "llvm/Support/Format.h"
|
||||||
|
|
||||||
@ -78,7 +77,7 @@ sys::MemoryBlock RemoteMemoryManager::allocateSection(uintptr_t Size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE,
|
void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE,
|
||||||
const ObjectImage *Obj) {
|
const object::ObjectFile &Obj) {
|
||||||
// The client should have called setRemoteTarget() before triggering any
|
// The client should have called setRemoteTarget() before triggering any
|
||||||
// code generation.
|
// code generation.
|
||||||
assert(Target);
|
assert(Target);
|
||||||
|
@ -80,7 +80,8 @@ public:
|
|||||||
// symbols from Modules it contains.
|
// symbols from Modules it contains.
|
||||||
uint64_t getSymbolAddress(const std::string &Name) override { return 0; }
|
uint64_t getSymbolAddress(const std::string &Name) override { return 0; }
|
||||||
|
|
||||||
void notifyObjectLoaded(ExecutionEngine *EE, const ObjectImage *Obj) override;
|
void notifyObjectLoaded(ExecutionEngine *EE,
|
||||||
|
const object::ObjectFile &Obj) override;
|
||||||
|
|
||||||
bool finalizeMemory(std::string *ErrMsg) override;
|
bool finalizeMemory(std::string *ErrMsg) override;
|
||||||
|
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
#include "llvm/ExecutionEngine/JITEventListener.h"
|
#include "llvm/ExecutionEngine/JITEventListener.h"
|
||||||
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
||||||
#include "llvm/ExecutionEngine/MCJIT.h"
|
#include "llvm/ExecutionEngine/MCJIT.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
#include "llvm/IRReader/IRReader.h"
|
#include "llvm/IRReader/IRReader.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/Host.h"
|
#include "llvm/Support/Host.h"
|
||||||
#include "llvm/Support/ManagedStatic.h"
|
#include "llvm/Support/ManagedStatic.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
|
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/DebugInfo/DIContext.h"
|
#include "llvm/DebugInfo/DIContext.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
|
||||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
|
||||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||||
#include "llvm/ExecutionEngine/RuntimeDyldChecker.h"
|
#include "llvm/ExecutionEngine/RuntimeDyldChecker.h"
|
||||||
#include "llvm/MC/MCAsmInfo.h"
|
#include "llvm/MC/MCAsmInfo.h"
|
||||||
@ -207,23 +205,32 @@ static int printLineInfoForInput() {
|
|||||||
if (std::error_code EC = InputBuffer.getError())
|
if (std::error_code EC = InputBuffer.getError())
|
||||||
return Error("unable to read input: '" + EC.message() + "'");
|
return Error("unable to read input: '" + EC.message() + "'");
|
||||||
|
|
||||||
std::unique_ptr<ObjectImage> LoadedObject;
|
ErrorOr<std::unique_ptr<ObjectFile>> MaybeObj(
|
||||||
|
ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef()));
|
||||||
|
|
||||||
|
if (std::error_code EC = MaybeObj.getError())
|
||||||
|
return Error("unable to create object file: '" + EC.message() + "'");
|
||||||
|
|
||||||
|
ObjectFile &Obj = **MaybeObj;
|
||||||
|
|
||||||
// Load the object file
|
// Load the object file
|
||||||
LoadedObject = Dyld.loadObject(
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo =
|
||||||
llvm::make_unique<ObjectBuffer>(std::move(*InputBuffer)));
|
Dyld.loadObject(Obj);
|
||||||
if (!LoadedObject) {
|
|
||||||
|
if (Dyld.hasError())
|
||||||
return Error(Dyld.getErrorString());
|
return Error(Dyld.getErrorString());
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve all the relocations we can.
|
// Resolve all the relocations we can.
|
||||||
Dyld.resolveRelocations();
|
Dyld.resolveRelocations();
|
||||||
|
|
||||||
|
OwningBinary<ObjectFile> DebugObj = LoadedObjInfo->getObjectForDebug(Obj);
|
||||||
|
|
||||||
std::unique_ptr<DIContext> Context(
|
std::unique_ptr<DIContext> Context(
|
||||||
DIContext::getDWARFContext(*LoadedObject->getObjectFile()));
|
DIContext::getDWARFContext(*DebugObj.getBinary()));
|
||||||
|
|
||||||
// Use symbol info to iterate functions in the object.
|
// Use symbol info to iterate functions in the object.
|
||||||
for (object::symbol_iterator I = LoadedObject->begin_symbols(),
|
for (object::symbol_iterator I = DebugObj.getBinary()->symbol_begin(),
|
||||||
E = LoadedObject->end_symbols();
|
E = DebugObj.getBinary()->symbol_end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
object::SymbolRef::Type SymType;
|
object::SymbolRef::Type SymType;
|
||||||
if (I->getType(SymType)) continue;
|
if (I->getType(SymType)) continue;
|
||||||
@ -268,11 +275,17 @@ static int executeInput() {
|
|||||||
MemoryBuffer::getFileOrSTDIN(InputFileList[i]);
|
MemoryBuffer::getFileOrSTDIN(InputFileList[i]);
|
||||||
if (std::error_code EC = InputBuffer.getError())
|
if (std::error_code EC = InputBuffer.getError())
|
||||||
return Error("unable to read input: '" + EC.message() + "'");
|
return Error("unable to read input: '" + EC.message() + "'");
|
||||||
std::unique_ptr<ObjectImage> LoadedObject;
|
ErrorOr<std::unique_ptr<ObjectFile>> MaybeObj(
|
||||||
|
ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef()));
|
||||||
|
|
||||||
|
if (std::error_code EC = MaybeObj.getError())
|
||||||
|
return Error("unable to create object file: '" + EC.message() + "'");
|
||||||
|
|
||||||
|
ObjectFile &Obj = **MaybeObj;
|
||||||
|
|
||||||
// Load the object file
|
// Load the object file
|
||||||
LoadedObject = Dyld.loadObject(
|
Dyld.loadObject(Obj);
|
||||||
llvm::make_unique<ObjectBuffer>(std::move(*InputBuffer)));
|
if (Dyld.hasError()) {
|
||||||
if (!LoadedObject) {
|
|
||||||
return Error(Dyld.getErrorString());
|
return Error(Dyld.getErrorString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -512,14 +525,21 @@ static int linkAndVerify() {
|
|||||||
// Load the input memory buffer.
|
// Load the input memory buffer.
|
||||||
ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer =
|
ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer =
|
||||||
MemoryBuffer::getFileOrSTDIN(InputFileList[i]);
|
MemoryBuffer::getFileOrSTDIN(InputFileList[i]);
|
||||||
|
|
||||||
if (std::error_code EC = InputBuffer.getError())
|
if (std::error_code EC = InputBuffer.getError())
|
||||||
return Error("unable to read input: '" + EC.message() + "'");
|
return Error("unable to read input: '" + EC.message() + "'");
|
||||||
|
|
||||||
std::unique_ptr<ObjectImage> LoadedObject;
|
ErrorOr<std::unique_ptr<ObjectFile>> MaybeObj(
|
||||||
|
ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef()));
|
||||||
|
|
||||||
|
if (std::error_code EC = MaybeObj.getError())
|
||||||
|
return Error("unable to create object file: '" + EC.message() + "'");
|
||||||
|
|
||||||
|
ObjectFile &Obj = **MaybeObj;
|
||||||
|
|
||||||
// Load the object file
|
// Load the object file
|
||||||
LoadedObject = Dyld.loadObject(
|
Dyld.loadObject(Obj);
|
||||||
llvm::make_unique<ObjectBuffer>(std::move(*InputBuffer)));
|
if (Dyld.hasError()) {
|
||||||
if (!LoadedObject) {
|
|
||||||
return Error(Dyld.getErrorString());
|
return Error(Dyld.getErrorString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user