[MCJIT] Clean up RuntimeDyld's quirky object-ownership/modification scheme.

Previously, when loading an object file, RuntimeDyld (1) took ownership of the
ObjectFile instance (and associated MemoryBuffer), (2) potentially modified the
object in-place, and (3) returned an ObjectImage that managed ownership of the
now-modified object and provided some convenience methods. This scheme accreted
over several years as features were tacked on to RuntimeDyld, and was both
unintuitive and unsafe (See e.g. http://llvm.org/PR20722).

This patch fixes the issue by removing all ownership and in-place modification
of object files from RuntimeDyld. Existing behavior, including debugger
registration, is preserved.

Noteworthy changes include:

(1) ObjectFile instances are now passed to RuntimeDyld by const-ref.
(2) The ObjectImage and ObjectBuffer classes have been removed entirely, they
    existed to model ownership within RuntimeDyld, and so are no longer needed.
(3) RuntimeDyld::loadObject now returns an instance of a new class,
    RuntimeDyld::LoadedObjectInfo, which can be used to construct a modified
    object suitable for registration with the debugger, following the existing
    debugger registration scheme.
(4) The JITRegistrar class has been removed, and the GDBRegistrar class has been
    re-written as a JITEventListener.

This should fix http://llvm.org/PR20722 .



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222810 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Lang Hames
2014-11-26 06:53:26 +00:00
parent 568f7e8228
commit 7acaefabf6
31 changed files with 631 additions and 869 deletions

View File

@@ -15,6 +15,7 @@
#ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
#define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
#include "RuntimeDyld.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/Support/DataTypes.h"
@@ -25,7 +26,10 @@ class Function;
class MachineFunction;
class OProfileWrapper;
class IntelJITEventsWrapper;
class ObjectImage;
namespace object {
class ObjectFile;
}
/// JITEvent_EmittedFunctionDetails - Helper struct for containing information
/// about a generated machine code function.
@@ -57,7 +61,7 @@ public:
public:
JITEventListener() {}
virtual ~JITEventListener();
virtual ~JITEventListener() {}
/// NotifyObjectEmitted - Called after an object has been successfully
/// emitted to memory. NotifyFunctionEmitted will not be called for
@@ -67,11 +71,15 @@ public:
/// The ObjectImage contains the generated object image
/// with section headers updated to reflect the address at which 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
/// 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
// Construct an IntelJITEventListener
@@ -105,7 +113,8 @@ public:
return nullptr;
}
#endif // USE_OPROFILE
private:
virtual void anchor();
};
} // end namespace llvm.

View File

@@ -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

View File

@@ -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

View File

@@ -22,7 +22,10 @@
namespace llvm {
class ExecutionEngine;
class ObjectImage;
namespace object {
class ObjectFile;
}
// RuntimeDyld clients often want to handle the memory management 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
/// newly loaded object.
virtual void notifyObjectLoaded(ExecutionEngine *EE,
const ObjectImage *) {}
const object::ObjectFile &) {}
/// This method is called when object loading is complete and section page
/// permissions can be applied. It is up to the memory manager implementation

View File

@@ -15,19 +15,19 @@
#define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H
#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/ObjectBuffer.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/Support/Memory.h"
#include <memory>
namespace llvm {
namespace object {
class ObjectFile;
template <typename T> class OwningBinary;
}
class RuntimeDyldImpl;
class RuntimeDyldCheckerImpl;
class ObjectImage;
class RuntimeDyld {
friend class RuntimeDyldCheckerImpl;
@@ -46,22 +46,35 @@ protected:
// Any relocations already associated with the symbol will be re-resolved.
void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
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();
/// 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.
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);
/// Add the referenced object file to the list of objects to be loaded and
/// relocated.
std::unique_ptr<LoadedObjectInfo> loadObject(const object::ObjectFile &O);
/// 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