mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-28 22:20:37 +00:00
Clean-up of memory buffer and object ownership model in MCJIT
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165053 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9fd304672c
commit
3f23cef24f
80
include/llvm/ExecutionEngine/ObjectBuffer.h
Normal file
80
include/llvm/ExecutionEngine/ObjectBuffer.h
Normal file
@ -0,0 +1,80 @@
|
||||
//===---- 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/ADT/OwningPtr.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// ObjectBuffer - 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. The getMemBuffer() method provides a way to create a
|
||||
/// MemoryBuffer wrapper object instance to be owned by other classes (such as
|
||||
/// ObjectFile) as needed, but the MemoryBuffer instance returned does not own the
|
||||
/// actual memory it points to.
|
||||
class ObjectBuffer {
|
||||
public:
|
||||
ObjectBuffer() {}
|
||||
ObjectBuffer(MemoryBuffer* Buf) : Buffer(Buf) {}
|
||||
virtual ~ObjectBuffer() {}
|
||||
|
||||
/// getMemBuffer - Like MemoryBuffer::getMemBuffer() this function
|
||||
/// returns a pointer to an object that is owned by the caller. However,
|
||||
/// the caller does not take ownership of the underlying memory.
|
||||
MemoryBuffer *getMemBuffer() const {
|
||||
return MemoryBuffer::getMemBuffer(Buffer->getBuffer(), "", false);
|
||||
}
|
||||
|
||||
const char *getBufferStart() const { return Buffer->getBufferStart(); }
|
||||
size_t getBufferSize() const { return Buffer->getBufferSize(); }
|
||||
|
||||
protected:
|
||||
// The memory contained in an ObjectBuffer
|
||||
OwningPtr<MemoryBuffer> Buffer;
|
||||
};
|
||||
|
||||
/// ObjectBufferStream - 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 {
|
||||
public:
|
||||
ObjectBufferStream() : OS(SV) {}
|
||||
virtual ~ObjectBufferStream() {}
|
||||
|
||||
raw_ostream &getOStream() { return OS; }
|
||||
void flush()
|
||||
{
|
||||
OS.flush();
|
||||
|
||||
// Make the data accessible via the ObjectBuffer::Buffer
|
||||
Buffer.reset(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
|
61
include/llvm/ExecutionEngine/ObjectImage.h
Normal file
61
include/llvm/ExecutionEngine/ObjectImage.h
Normal file
@ -0,0 +1,61 @@
|
||||
//===---- 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/Object/ObjectFile.h"
|
||||
#include "llvm/ExecutionEngine/ObjectBuffer.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;
|
||||
|
||||
protected:
|
||||
OwningPtr<ObjectBuffer> Buffer;
|
||||
|
||||
public:
|
||||
ObjectImage(ObjectBuffer *Input) : Buffer(Input) {}
|
||||
virtual ~ObjectImage() {}
|
||||
|
||||
virtual object::symbol_iterator begin_symbols() const = 0;
|
||||
virtual object::symbol_iterator end_symbols() const = 0;
|
||||
|
||||
virtual object::section_iterator begin_sections() const = 0;
|
||||
virtual object::section_iterator end_sections() const = 0;
|
||||
|
||||
virtual /* Triple::ArchType */ unsigned getArch() const = 0;
|
||||
|
||||
// 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;
|
||||
|
||||
// Subclasses can override these methods to provide JIT debugging support
|
||||
virtual void registerWithDebugger() = 0;
|
||||
virtual void deregisterWithDebugger() = 0;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_RUNTIMEDYLD_OBJECT_IMAGE_H
|
||||
|
@ -15,12 +15,13 @@
|
||||
#define LLVM_RUNTIME_DYLD_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
||||
#include "llvm/Support/Memory.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class RuntimeDyldImpl;
|
||||
class MemoryBuffer;
|
||||
class ObjectImage;
|
||||
|
||||
// RuntimeDyld clients often want to handle the memory management of
|
||||
// what gets placed where. For JIT clients, this is an abstraction layer
|
||||
@ -65,8 +66,11 @@ public:
|
||||
RuntimeDyld(RTDyldMemoryManager*);
|
||||
~RuntimeDyld();
|
||||
|
||||
/// Load an in-memory object file into the dynamic linker.
|
||||
bool loadObject(MemoryBuffer *InputBuffer);
|
||||
/// loadObject - prepare the object contained in the input buffer for
|
||||
/// execution. Ownership of the input buffer is transferred to the
|
||||
/// ObjectImage instance returned from this function if successful.
|
||||
/// In the case of load failure, the input buffer will be deleted.
|
||||
ObjectImage *loadObject(ObjectBuffer *InputBuffer);
|
||||
|
||||
/// 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
|
||||
|
@ -12,8 +12,10 @@
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
#include "llvm/ExecutionEngine/MCJIT.h"
|
||||
#include "llvm/ExecutionEngine/JITMemoryManager.h"
|
||||
#include "llvm/ExecutionEngine/MCJIT.h"
|
||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/DynamicLibrary.h"
|
||||
@ -50,7 +52,7 @@ ExecutionEngine *MCJIT::createJIT(Module *M,
|
||||
MCJIT::MCJIT(Module *m, TargetMachine *tm, RTDyldMemoryManager *MM,
|
||||
bool AllocateGVsWithCode)
|
||||
: ExecutionEngine(m), TM(tm), Ctx(0), MemMgr(MM), Dyld(MM),
|
||||
isCompiled(false), M(m), OS(Buffer) {
|
||||
isCompiled(false), M(m) {
|
||||
|
||||
setTargetData(TM->getTargetData());
|
||||
}
|
||||
@ -63,7 +65,7 @@ MCJIT::~MCJIT() {
|
||||
void MCJIT::emitObject(Module *m) {
|
||||
/// Currently, MCJIT only supports a single module and the module passed to
|
||||
/// 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.
|
||||
assert(M == m);
|
||||
|
||||
@ -80,30 +82,32 @@ void MCJIT::emitObject(Module *m) {
|
||||
|
||||
PM.add(new TargetData(*TM->getTargetData()));
|
||||
|
||||
// The RuntimeDyld will take ownership of this shortly
|
||||
OwningPtr<ObjectBufferStream> Buffer(new ObjectBufferStream());
|
||||
|
||||
// Turn the machine code intermediate representation into bytes in memory
|
||||
// that may be executed.
|
||||
if (TM->addPassesToEmitMC(PM, Ctx, OS, false)) {
|
||||
if (TM->addPassesToEmitMC(PM, Ctx, Buffer->getOStream(), false)) {
|
||||
report_fatal_error("Target does not support MC emission!");
|
||||
}
|
||||
|
||||
// Initialize passes.
|
||||
// FIXME: When we support multiple modules, we'll want to move the code
|
||||
// gen and finalization out of the constructor here and do it more
|
||||
// on-demand as part of getPointerToFunction().
|
||||
PM.run(*m);
|
||||
// Flush the output buffer so the SmallVector gets its data.
|
||||
OS.flush();
|
||||
// Flush the output buffer to get the generated code into memory
|
||||
Buffer->flush();
|
||||
|
||||
// Load the object into the dynamic linker.
|
||||
MemoryBuffer* MB = MemoryBuffer::getMemBuffer(StringRef(Buffer.data(),
|
||||
Buffer.size()),
|
||||
"", false);
|
||||
if (Dyld.loadObject(MB))
|
||||
// handing off ownership of the buffer
|
||||
LoadedObject.reset(Dyld.loadObject(Buffer.take()));
|
||||
if (!LoadedObject)
|
||||
report_fatal_error(Dyld.getErrorString());
|
||||
|
||||
// Resolve any relocations.
|
||||
Dyld.resolveRelocations();
|
||||
|
||||
// FIXME: Make this optional, maybe even move it to a JIT event listener
|
||||
LoadedObject->registerWithDebugger();
|
||||
|
||||
// FIXME: Add support for per-module compilation state
|
||||
isCompiled = true;
|
||||
}
|
||||
|
@ -13,11 +13,11 @@
|
||||
#include "llvm/PassManager.h"
|
||||
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class ObjectImage;
|
||||
|
||||
// FIXME: This makes all kinds of horrible assumptions for the time being,
|
||||
// like only having one module, not needing to worry about multi-threading,
|
||||
// blah blah. Purely in get-it-up-and-limping mode for now.
|
||||
@ -34,10 +34,7 @@ class MCJIT : public ExecutionEngine {
|
||||
// FIXME: Add support for multiple modules
|
||||
bool isCompiled;
|
||||
Module *M;
|
||||
|
||||
// FIXME: Move these to a single container which manages JITed objects
|
||||
SmallVector<char, 4096> Buffer; // Working buffer into which we JIT.
|
||||
raw_svector_ostream OS;
|
||||
OwningPtr<ObjectImage> LoadedObject;
|
||||
|
||||
public:
|
||||
~MCJIT();
|
||||
|
@ -78,12 +78,12 @@ public:
|
||||
/// Creates an entry in the JIT registry for the buffer @p Object,
|
||||
/// which must contain an object file in executable memory with any
|
||||
/// debug information for the debugger.
|
||||
void registerObject(const MemoryBuffer &Object);
|
||||
void registerObject(const ObjectBuffer &Object);
|
||||
|
||||
/// Removes the internal registration of @p Object, and
|
||||
/// frees associated resources.
|
||||
/// Returns true if @p Object was found in ObjectBufferMap.
|
||||
bool deregisterObject(const MemoryBuffer &Object);
|
||||
bool deregisterObject(const ObjectBuffer &Object);
|
||||
|
||||
private:
|
||||
/// Deregister the debug info for the given object file from the debugger
|
||||
@ -124,7 +124,7 @@ GDBJITRegistrar::~GDBJITRegistrar() {
|
||||
ObjectBufferMap.clear();
|
||||
}
|
||||
|
||||
void GDBJITRegistrar::registerObject(const MemoryBuffer &Object) {
|
||||
void GDBJITRegistrar::registerObject(const ObjectBuffer &Object) {
|
||||
|
||||
const char *Buffer = Object.getBufferStart();
|
||||
size_t Size = Object.getBufferSize();
|
||||
@ -147,7 +147,7 @@ void GDBJITRegistrar::registerObject(const MemoryBuffer &Object) {
|
||||
}
|
||||
}
|
||||
|
||||
bool GDBJITRegistrar::deregisterObject(const MemoryBuffer& Object) {
|
||||
bool GDBJITRegistrar::deregisterObject(const ObjectBuffer& Object) {
|
||||
const char *Buffer = Object.getBufferStart();
|
||||
RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Buffer);
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#ifndef LLVM_EXECUTION_ENGINE_JIT_REGISTRAR_H
|
||||
#define LLVM_EXECUTION_ENGINE_JIT_REGISTRAR_H
|
||||
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -27,12 +27,12 @@ public:
|
||||
/// 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 MemoryBuffer &Object) = 0;
|
||||
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 MemoryBuffer &Object) = 0;
|
||||
virtual bool deregisterObject(const ObjectBuffer &Object) = 0;
|
||||
|
||||
/// Returns a reference to a GDB JIT registrar singleton
|
||||
static JITRegistrar& getGDBRegistrar();
|
||||
|
@ -1,59 +1,76 @@
|
||||
//===---- 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_RUNTIMEDYLD_OBJECT_IMAGE_H
|
||||
#define LLVM_RUNTIMEDYLD_OBJECT_IMAGE_H
|
||||
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class ObjectImage {
|
||||
ObjectImage() LLVM_DELETED_FUNCTION;
|
||||
ObjectImage(const ObjectImage &other) LLVM_DELETED_FUNCTION;
|
||||
protected:
|
||||
object::ObjectFile *ObjFile;
|
||||
|
||||
public:
|
||||
ObjectImage(object::ObjectFile *Obj) { ObjFile = Obj; }
|
||||
virtual ~ObjectImage() {}
|
||||
|
||||
virtual object::symbol_iterator begin_symbols() const
|
||||
{ return ObjFile->begin_symbols(); }
|
||||
virtual object::symbol_iterator end_symbols() const
|
||||
{ return ObjFile->end_symbols(); }
|
||||
|
||||
virtual object::section_iterator begin_sections() const
|
||||
{ return ObjFile->begin_sections(); }
|
||||
virtual object::section_iterator end_sections() const
|
||||
{ return ObjFile->end_sections(); }
|
||||
|
||||
virtual /* Triple::ArchType */ unsigned getArch() const
|
||||
{ return ObjFile->getArch(); }
|
||||
|
||||
// Subclasses can override these methods to update the image with loaded
|
||||
// addresses for sections and common symbols
|
||||
virtual void updateSectionAddress(const object::SectionRef &Sec,
|
||||
uint64_t Addr) {}
|
||||
virtual void updateSymbolAddress(const object::SymbolRef &Sym, uint64_t Addr)
|
||||
{}
|
||||
|
||||
// Subclasses can override these methods to provide JIT debugging support
|
||||
virtual void registerWithDebugger() {}
|
||||
virtual void deregisterWithDebugger() {}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_RUNTIMEDYLD_OBJECT_IMAGE_H
|
||||
|
||||
//===-- ObjectImageCommon.h - Format independent executuable object image -===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares a file format independent ObjectImage class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_RUNTIMEDYLD_OBJECTIMAGECOMMON_H
|
||||
#define LLVM_RUNTIMEDYLD_OBJECTIMAGECOMMON_H
|
||||
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class ObjectImageCommon : public ObjectImage {
|
||||
ObjectImageCommon(); // = delete
|
||||
ObjectImageCommon(const ObjectImageCommon &other); // = delete
|
||||
|
||||
protected:
|
||||
object::ObjectFile *ObjFile;
|
||||
|
||||
// This form of the constructor allows subclasses to use
|
||||
// format-specific subclasses of ObjectFile directly
|
||||
ObjectImageCommon(ObjectBuffer *Input, object::ObjectFile *Obj)
|
||||
: ObjectImage(Input), // saves Input as Buffer and takes ownership
|
||||
ObjFile(Obj)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
ObjectImageCommon(ObjectBuffer* Input)
|
||||
: ObjectImage(Input) // saves Input as Buffer and takes ownership
|
||||
{
|
||||
ObjFile = object::ObjectFile::createObjectFile(Buffer->getMemBuffer());
|
||||
}
|
||||
virtual ~ObjectImageCommon() { delete ObjFile; }
|
||||
|
||||
virtual object::symbol_iterator begin_symbols() const
|
||||
{ return ObjFile->begin_symbols(); }
|
||||
virtual object::symbol_iterator end_symbols() const
|
||||
{ return ObjFile->end_symbols(); }
|
||||
|
||||
virtual object::section_iterator begin_sections() const
|
||||
{ return ObjFile->begin_sections(); }
|
||||
virtual object::section_iterator end_sections() const
|
||||
{ return ObjFile->end_sections(); }
|
||||
|
||||
virtual /* Triple::ArchType */ unsigned getArch() const
|
||||
{ return ObjFile->getArch(); }
|
||||
|
||||
virtual StringRef getData() const { return ObjFile->getData(); }
|
||||
|
||||
// Subclasses can override these methods to update the image with loaded
|
||||
// addresses for sections and common symbols
|
||||
virtual void updateSectionAddress(const object::SectionRef &Sec,
|
||||
uint64_t Addr) {}
|
||||
virtual void updateSymbolAddress(const object::SymbolRef &Sym, uint64_t Addr)
|
||||
{}
|
||||
|
||||
// Subclasses can override these methods to provide JIT debugging support
|
||||
virtual void registerWithDebugger() {}
|
||||
virtual void deregisterWithDebugger() {}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_RUNTIMEDYLD_OBJECT_IMAGE_H
|
||||
|
@ -12,6 +12,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
#include "ObjectImageCommon.h"
|
||||
#include "RuntimeDyldImpl.h"
|
||||
#include "RuntimeDyldELF.h"
|
||||
#include "RuntimeDyldMachO.h"
|
||||
@ -61,14 +62,11 @@ void RuntimeDyldImpl::mapSectionAddress(const void *LocalAddress,
|
||||
|
||||
// Subclasses can implement this method to create specialized image instances.
|
||||
// The caller owns the pointer that is returned.
|
||||
ObjectImage *RuntimeDyldImpl::createObjectImage(const MemoryBuffer *InputBuffer) {
|
||||
ObjectFile *ObjFile = ObjectFile::createObjectFile(const_cast<MemoryBuffer*>
|
||||
(InputBuffer));
|
||||
ObjectImage *Obj = new ObjectImage(ObjFile);
|
||||
return Obj;
|
||||
ObjectImage *RuntimeDyldImpl::createObjectImage(ObjectBuffer *InputBuffer) {
|
||||
return new ObjectImageCommon(InputBuffer);
|
||||
}
|
||||
|
||||
bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
|
||||
ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) {
|
||||
OwningPtr<ObjectImage> obj(createObjectImage(InputBuffer));
|
||||
if (!obj)
|
||||
report_fatal_error("Unable to create object image from memory buffer!");
|
||||
@ -178,9 +176,7 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
|
||||
}
|
||||
}
|
||||
|
||||
handleObjectLoaded(obj.take());
|
||||
|
||||
return false;
|
||||
return obj.take();
|
||||
}
|
||||
|
||||
void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj,
|
||||
@ -437,7 +433,7 @@ RuntimeDyld::~RuntimeDyld() {
|
||||
delete Dyld;
|
||||
}
|
||||
|
||||
bool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) {
|
||||
ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) {
|
||||
if (!Dyld) {
|
||||
sys::LLVMFileType type = sys::IdentifyFileType(
|
||||
InputBuffer->getBufferStart(),
|
||||
|
@ -12,16 +12,19 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
#include "RuntimeDyldELF.h"
|
||||
#include "JITRegistrar.h"
|
||||
#include "ObjectImageCommon.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/IntervalMap.h"
|
||||
#include "RuntimeDyldELF.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "JITRegistrar.h"
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
|
||||
@ -41,19 +44,12 @@ class DyldELFObject : public ELFObjectFile<target_endianness, is64Bits> {
|
||||
typedef typename ELFDataTypeTypedefHelper<
|
||||
target_endianness, is64Bits>::value_type addr_type;
|
||||
|
||||
protected:
|
||||
// This duplicates the 'Data' member in the 'Binary' base class
|
||||
// but it is necessary to workaround a bug in gcc 4.2
|
||||
MemoryBuffer *InputData;
|
||||
|
||||
public:
|
||||
DyldELFObject(MemoryBuffer *Object, error_code &ec);
|
||||
DyldELFObject(MemoryBuffer *Wrapper, error_code &ec);
|
||||
|
||||
void updateSectionAddress(const SectionRef &Sec, uint64_t Addr);
|
||||
void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr);
|
||||
|
||||
const MemoryBuffer& getBuffer() const { return *InputData; }
|
||||
|
||||
// Methods for type inquiry through isa, cast and dyn_cast
|
||||
static inline bool classof(const Binary *v) {
|
||||
return (isa<ELFObjectFile<target_endianness, is64Bits> >(v)
|
||||
@ -69,14 +65,15 @@ public:
|
||||
};
|
||||
|
||||
template<support::endianness target_endianness, bool is64Bits>
|
||||
class ELFObjectImage : public ObjectImage {
|
||||
class ELFObjectImage : public ObjectImageCommon {
|
||||
protected:
|
||||
DyldELFObject<target_endianness, is64Bits> *DyldObj;
|
||||
bool Registered;
|
||||
|
||||
public:
|
||||
ELFObjectImage(DyldELFObject<target_endianness, is64Bits> *Obj)
|
||||
: ObjectImage(Obj),
|
||||
ELFObjectImage(ObjectBuffer *Input,
|
||||
DyldELFObject<target_endianness, is64Bits> *Obj)
|
||||
: ObjectImageCommon(Input, Obj),
|
||||
DyldObj(Obj),
|
||||
Registered(false) {}
|
||||
|
||||
@ -99,20 +96,22 @@ class ELFObjectImage : public ObjectImage {
|
||||
|
||||
virtual void registerWithDebugger()
|
||||
{
|
||||
JITRegistrar::getGDBRegistrar().registerObject(DyldObj->getBuffer());
|
||||
JITRegistrar::getGDBRegistrar().registerObject(*Buffer);
|
||||
Registered = true;
|
||||
}
|
||||
virtual void deregisterWithDebugger()
|
||||
{
|
||||
JITRegistrar::getGDBRegistrar().deregisterObject(DyldObj->getBuffer());
|
||||
JITRegistrar::getGDBRegistrar().deregisterObject(*Buffer);
|
||||
}
|
||||
};
|
||||
|
||||
// The MemoryBuffer passed into this constructor is just a wrapper around the
|
||||
// actual memory. Ultimately, the Binary parent class will take ownership of
|
||||
// this MemoryBuffer object but not the underlying memory.
|
||||
template<support::endianness target_endianness, bool is64Bits>
|
||||
DyldELFObject<target_endianness, is64Bits>::DyldELFObject(MemoryBuffer *Object,
|
||||
DyldELFObject<target_endianness, is64Bits>::DyldELFObject(MemoryBuffer *Wrapper,
|
||||
error_code &ec)
|
||||
: ELFObjectFile<target_endianness, is64Bits>(Object, ec),
|
||||
InputData(Object) {
|
||||
: ELFObjectFile<target_endianness, is64Bits>(Wrapper, ec) {
|
||||
this->isDyldELFObject = true;
|
||||
}
|
||||
|
||||
@ -148,46 +147,39 @@ void DyldELFObject<target_endianness, is64Bits>::updateSymbolAddress(
|
||||
|
||||
namespace llvm {
|
||||
|
||||
ObjectImage *RuntimeDyldELF::createObjectImage(
|
||||
const MemoryBuffer *ConstInputBuffer) {
|
||||
MemoryBuffer *InputBuffer = const_cast<MemoryBuffer*>(ConstInputBuffer);
|
||||
std::pair<unsigned char, unsigned char> Ident = getElfArchType(InputBuffer);
|
||||
ObjectImage *RuntimeDyldELF::createObjectImage(ObjectBuffer *Buffer) {
|
||||
if (Buffer->getBufferSize() < ELF::EI_NIDENT)
|
||||
llvm_unreachable("Unexpected ELF object size");
|
||||
std::pair<unsigned char, unsigned char> Ident = std::make_pair(
|
||||
(uint8_t)Buffer->getBufferStart()[ELF::EI_CLASS],
|
||||
(uint8_t)Buffer->getBufferStart()[ELF::EI_DATA]);
|
||||
error_code ec;
|
||||
|
||||
if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) {
|
||||
DyldELFObject<support::little, false> *Obj =
|
||||
new DyldELFObject<support::little, false>(InputBuffer, ec);
|
||||
return new ELFObjectImage<support::little, false>(Obj);
|
||||
new DyldELFObject<support::little, false>(Buffer->getMemBuffer(), ec);
|
||||
return new ELFObjectImage<support::little, false>(Buffer, Obj);
|
||||
}
|
||||
else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) {
|
||||
DyldELFObject<support::big, false> *Obj =
|
||||
new DyldELFObject<support::big, false>(InputBuffer, ec);
|
||||
return new ELFObjectImage<support::big, false>(Obj);
|
||||
new DyldELFObject<support::big, false>(Buffer->getMemBuffer(), ec);
|
||||
return new ELFObjectImage<support::big, false>(Buffer, Obj);
|
||||
}
|
||||
else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) {
|
||||
DyldELFObject<support::big, true> *Obj =
|
||||
new DyldELFObject<support::big, true>(InputBuffer, ec);
|
||||
return new ELFObjectImage<support::big, true>(Obj);
|
||||
new DyldELFObject<support::big, true>(Buffer->getMemBuffer(), ec);
|
||||
return new ELFObjectImage<support::big, true>(Buffer, Obj);
|
||||
}
|
||||
else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) {
|
||||
DyldELFObject<support::little, true> *Obj =
|
||||
new DyldELFObject<support::little, true>(InputBuffer, ec);
|
||||
return new ELFObjectImage<support::little, true>(Obj);
|
||||
new DyldELFObject<support::little, true>(Buffer->getMemBuffer(), ec);
|
||||
return new ELFObjectImage<support::little, true>(Buffer, Obj);
|
||||
}
|
||||
else
|
||||
llvm_unreachable("Unexpected ELF format");
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::handleObjectLoaded(ObjectImage *Obj)
|
||||
{
|
||||
Obj->registerWithDebugger();
|
||||
// Save the loaded object. It will deregister itself when deleted
|
||||
LoadedObject = Obj;
|
||||
}
|
||||
|
||||
RuntimeDyldELF::~RuntimeDyldELF() {
|
||||
if (LoadedObject)
|
||||
delete LoadedObject;
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::resolveX86_64Relocation(uint8_t *LocalAddress,
|
||||
@ -522,8 +514,9 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
}
|
||||
}
|
||||
|
||||
bool RuntimeDyldELF::isCompatibleFormat(const MemoryBuffer *InputBuffer) const {
|
||||
StringRef Magic = InputBuffer->getBuffer().slice(0, ELF::EI_NIDENT);
|
||||
return (memcmp(Magic.data(), ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;
|
||||
bool RuntimeDyldELF::isCompatibleFormat(const ObjectBuffer *Buffer) const {
|
||||
if (Buffer->getBufferSize() < strlen(ELF::ElfMagic))
|
||||
return false;
|
||||
return (memcmp(Buffer->getBufferStart(), ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;
|
||||
}
|
||||
} // namespace llvm
|
||||
|
@ -22,8 +22,6 @@ using namespace llvm;
|
||||
namespace llvm {
|
||||
class RuntimeDyldELF : public RuntimeDyldImpl {
|
||||
protected:
|
||||
ObjectImage *LoadedObject;
|
||||
|
||||
void resolveX86_64Relocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
uint64_t Value,
|
||||
@ -60,16 +58,15 @@ protected:
|
||||
const SymbolTableMap &Symbols,
|
||||
StubMap &Stubs);
|
||||
|
||||
virtual ObjectImage *createObjectImage(const MemoryBuffer *InputBuffer);
|
||||
virtual void handleObjectLoaded(ObjectImage *Obj);
|
||||
virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer);
|
||||
|
||||
public:
|
||||
RuntimeDyldELF(RTDyldMemoryManager *mm)
|
||||
: RuntimeDyldImpl(mm), LoadedObject(0) {}
|
||||
: RuntimeDyldImpl(mm) {}
|
||||
|
||||
virtual ~RuntimeDyldELF();
|
||||
|
||||
bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const;
|
||||
bool isCompatibleFormat(const ObjectBuffer *Buffer) const;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -14,8 +14,8 @@
|
||||
#ifndef LLVM_RUNTIME_DYLD_IMPL_H
|
||||
#define LLVM_RUNTIME_DYLD_IMPL_H
|
||||
|
||||
#include "ObjectImage.h"
|
||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
@ -33,7 +33,7 @@ using namespace llvm::object;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MemoryBuffer;
|
||||
class ObjectBuffer;
|
||||
class Twine;
|
||||
|
||||
|
||||
@ -251,19 +251,13 @@ protected:
|
||||
|
||||
/// \brief Resolve relocations to external symbols.
|
||||
void resolveExternalSymbols();
|
||||
virtual ObjectImage *createObjectImage(const MemoryBuffer *InputBuffer);
|
||||
virtual void handleObjectLoaded(ObjectImage *Obj)
|
||||
{
|
||||
// Subclasses may choose to retain this image if they have a use for it
|
||||
delete Obj;
|
||||
}
|
||||
|
||||
virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer);
|
||||
public:
|
||||
RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {}
|
||||
|
||||
virtual ~RuntimeDyldImpl();
|
||||
|
||||
bool loadObject(const MemoryBuffer *InputBuffer);
|
||||
ObjectImage *loadObject(ObjectBuffer *InputBuffer);
|
||||
|
||||
void *getSymbolAddress(StringRef Name) {
|
||||
// FIXME: Just look up as a function for now. Overly simple of course.
|
||||
@ -298,8 +292,7 @@ public:
|
||||
// Get the error message.
|
||||
StringRef getErrorString() { return ErrorStr; }
|
||||
|
||||
virtual bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const = 0;
|
||||
|
||||
virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -295,8 +295,10 @@ void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
|
||||
|
||||
bool RuntimeDyldMachO::isCompatibleFormat(
|
||||
const MemoryBuffer *InputBuffer) const {
|
||||
StringRef Magic = InputBuffer->getBuffer().slice(0, 4);
|
||||
const ObjectBuffer *InputBuffer) const {
|
||||
if (InputBuffer->getBufferSize() < 4)
|
||||
return false;
|
||||
StringRef Magic(InputBuffer->getBufferStart(), 4);
|
||||
if (Magic == "\xFE\xED\xFA\xCE") return true;
|
||||
if (Magic == "\xCE\xFA\xED\xFE") return true;
|
||||
if (Magic == "\xFE\xED\xFA\xCF") return true;
|
||||
|
@ -63,7 +63,7 @@ public:
|
||||
|
||||
RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
|
||||
|
||||
bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const;
|
||||
bool isCompatibleFormat(const ObjectBuffer *Buffer) const;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
||||
#include "llvm/Object/MachOObject.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
@ -120,12 +122,14 @@ static int executeInput() {
|
||||
for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) {
|
||||
// Load the input memory buffer.
|
||||
OwningPtr<MemoryBuffer> InputBuffer;
|
||||
OwningPtr<ObjectImage> LoadedObject;
|
||||
if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i],
|
||||
InputBuffer))
|
||||
return Error("unable to read input: '" + ec.message() + "'");
|
||||
|
||||
// Load the object file into it.
|
||||
if (Dyld.loadObject(InputBuffer.take())) {
|
||||
// Load the object file
|
||||
LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.take())));
|
||||
if (!LoadedObject) {
|
||||
return Error(Dyld.getErrorString());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user