mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-24 22:24:54 +00:00
[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:
@@ -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.
|
||||
|
@@ -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 {
|
||||
|
||||
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
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user