forked from OSchip/llvm-project
Documented RecordingMemoryManager and removed an
undefined, unused function from its API. llvm-svn: 111335
This commit is contained in:
parent
aa94cc3fcd
commit
5fb17ea113
|
@ -27,67 +27,196 @@
|
|||
|
||||
namespace lldb_private {
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// @class RecordingMemoryManager RecordingMemoryManager.h "lldb/Expression/RecordingMemoryManager.h"
|
||||
/// @brief Passthrough memory manager for the JIT that records what was allocated where
|
||||
///
|
||||
/// The LLVM JIT is built to compile code for execution in the current
|
||||
/// process, so it needs to be able to allocate memory. Because different
|
||||
/// clients have different requirements for the locations of JIT compiled
|
||||
/// code, the interface for allocating memory has been abstracted out and
|
||||
/// can be implemented by any client.
|
||||
///
|
||||
/// LLDB, however, needs to move JIT-compiled code into the target process.
|
||||
/// Because writing individual bytes of code hasn't been abstracted out of
|
||||
/// the JIT, LLDB instead implements a custom memory allocator that records
|
||||
/// what regions have been allocated for code. When JIT compilation is
|
||||
/// complete, these regions are then copied as necessary into the target
|
||||
/// process.
|
||||
///
|
||||
/// Ideally the memory manager would handle this copying, but this class has
|
||||
/// to be built without RTTI, which means it cannot include Process.h. As a
|
||||
/// result, ClangExpression::WriteJITCode() accesses the stored mappings
|
||||
/// directly.
|
||||
//----------------------------------------------------------------------
|
||||
class RecordingMemoryManager : public llvm::JITMemoryManager
|
||||
{
|
||||
|
||||
// I can't write the JIT code in this class because this class has to be
|
||||
// built without RTTI, which means I can't include Process.h. But I don't
|
||||
// want to write iterators or "do_over_regions" functions right now, so I'm
|
||||
// just going to let the ClangExpression handle it using our data members directly.
|
||||
|
||||
friend bool ClangExpression::WriteJITCode (const ExecutionContext &exc_context);
|
||||
|
||||
public:
|
||||
//------------------------------------------------------------------
|
||||
/// Constructor
|
||||
//------------------------------------------------------------------
|
||||
RecordingMemoryManager ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Destructor
|
||||
//------------------------------------------------------------------
|
||||
virtual ~RecordingMemoryManager();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual void setMemoryWritable ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual void setMemoryExecutable ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual void setPoisonMemory (bool poison)
|
||||
{
|
||||
m_default_mm_ap->setPoisonMemory (poison);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual void AllocateGOT()
|
||||
{
|
||||
m_default_mm_ap->AllocateGOT();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual uint8_t *getGOTBase() const
|
||||
{
|
||||
return m_default_mm_ap->getGOTBase();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual uint8_t *startFunctionBody(const llvm::Function *F,
|
||||
uintptr_t &ActualSize);
|
||||
uintptr_t &ActualSize);
|
||||
|
||||
virtual uint8_t *allocateStub(const llvm::GlobalValue* F, unsigned StubSize,
|
||||
unsigned Alignment);
|
||||
|
||||
virtual void endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
|
||||
uint8_t *FunctionEnd);
|
||||
//------------------------------------------------------------------
|
||||
/// Allocate room for a dyld stub for a lazy-referenced function,
|
||||
/// and add it to the m_stubs map
|
||||
///
|
||||
/// @param[in] F
|
||||
/// The function being referenced.
|
||||
///
|
||||
/// @param[in] StubSize
|
||||
/// The size of the stub.
|
||||
///
|
||||
/// @param[in] Alignment
|
||||
/// The required alignment of the stub.
|
||||
///
|
||||
/// @return
|
||||
/// Allocated space for the stub.
|
||||
//------------------------------------------------------------------
|
||||
virtual uint8_t *allocateStub(const llvm::GlobalValue* F,
|
||||
unsigned StubSize,
|
||||
unsigned Alignment);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Complete the body of a function, and add it to the m_functions map
|
||||
///
|
||||
/// @param[in] F
|
||||
/// The function being completed.
|
||||
///
|
||||
/// @param[in] FunctionStart
|
||||
/// The first instruction of the function.
|
||||
///
|
||||
/// @param[in] FunctionEnd
|
||||
/// The last byte of the last instruction of the function.
|
||||
//------------------------------------------------------------------
|
||||
virtual void endFunctionBody(const llvm::Function *F,
|
||||
uint8_t *FunctionStart,
|
||||
uint8_t *FunctionEnd);
|
||||
//------------------------------------------------------------------
|
||||
/// Allocate space for an unspecified purpose, and add it to the
|
||||
/// m_spaceBlocks map
|
||||
///
|
||||
/// @param[in] Size
|
||||
/// The size of the area.
|
||||
///
|
||||
/// @param[in] Alignment
|
||||
/// The required alignment of the area.
|
||||
///
|
||||
/// @return
|
||||
/// Allocated space.
|
||||
//------------------------------------------------------------------
|
||||
virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment);
|
||||
|
||||
virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
|
||||
//------------------------------------------------------------------
|
||||
/// Allocate space for a global variable, and add it to the
|
||||
/// m_spaceBlocks map
|
||||
///
|
||||
/// @param[in] Size
|
||||
/// The size of the variable.
|
||||
///
|
||||
/// @param[in] Alignment
|
||||
/// The required alignment of the variable.
|
||||
///
|
||||
/// @return
|
||||
/// Allocated space for the global.
|
||||
//------------------------------------------------------------------
|
||||
virtual uint8_t *allocateGlobal(uintptr_t Size,
|
||||
unsigned Alignment);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual void deallocateFunctionBody(void *Body);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual uint8_t* startExceptionTable(const llvm::Function* F,
|
||||
uintptr_t &ActualSize);
|
||||
uintptr_t &ActualSize);
|
||||
|
||||
virtual void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
|
||||
uint8_t *TableEnd, uint8_t* FrameRegister);
|
||||
//------------------------------------------------------------------
|
||||
/// Complete the exception table for a function, and add it to the
|
||||
/// m_exception_tables map
|
||||
///
|
||||
/// @param[in] F
|
||||
/// The function whose exception table is being written.
|
||||
///
|
||||
/// @param[in] TableStart
|
||||
/// The first byte of the exception table.
|
||||
///
|
||||
/// @param[in] TableEnd
|
||||
/// The last byte of the exception table.
|
||||
///
|
||||
/// @param[in] FrameRegister
|
||||
/// I don't know what this does, but it's passed through.
|
||||
//------------------------------------------------------------------
|
||||
virtual void endExceptionTable(const llvm::Function *F,
|
||||
uint8_t *TableStart,
|
||||
uint8_t *TableEnd,
|
||||
uint8_t* FrameRegister);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual void deallocateExceptionTable(void *ET);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual size_t GetDefaultCodeSlabSize() {
|
||||
return m_default_mm_ap->GetDefaultCodeSlabSize();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual size_t GetDefaultDataSlabSize() {
|
||||
return m_default_mm_ap->GetDefaultDataSlabSize();
|
||||
}
|
||||
|
@ -96,48 +225,82 @@ public:
|
|||
return m_default_mm_ap->GetDefaultStubSlabSize();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual unsigned GetNumCodeSlabs() {
|
||||
return m_default_mm_ap->GetNumCodeSlabs();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual unsigned GetNumDataSlabs() {
|
||||
return m_default_mm_ap->GetNumDataSlabs();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual unsigned GetNumStubSlabs() {
|
||||
return m_default_mm_ap->GetNumStubSlabs();
|
||||
}
|
||||
|
||||
// These are methods I've added so we can transfer the memory we've remembered down
|
||||
// to the target program. For now I'm assuming all this code is PIC without fixups,
|
||||
// so I'll just copy it blind, but if we need to we can do fixups later.
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// [Convenience method for ClangExpression] Look up the object in
|
||||
/// m_address_map that contains a given address, find where it was
|
||||
/// copied to, and return the remote address at the same offset into
|
||||
/// the copied entity
|
||||
///
|
||||
/// @param[in] local_address
|
||||
/// The address in the debugger.
|
||||
///
|
||||
/// @return
|
||||
/// The address in the target process.
|
||||
//------------------------------------------------------------------
|
||||
lldb::addr_t
|
||||
GetRemoteAddressForLocal (lldb::addr_t local_address);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// [Convenience method for ClangExpression] Look up the object in
|
||||
/// m_address_map that contains a given address, find where it was
|
||||
/// copied to, and return its address range in the target process
|
||||
///
|
||||
/// @param[in] local_address
|
||||
/// The address in the debugger.
|
||||
///
|
||||
/// @return
|
||||
/// The range of the containing object in the target process.
|
||||
//------------------------------------------------------------------
|
||||
std::pair <lldb::addr_t, lldb::addr_t>
|
||||
GetRemoteRangeForLocal (lldb::addr_t local_address);
|
||||
|
||||
bool
|
||||
WriteJITRegions (const ExecutionContext &exc_context);
|
||||
|
||||
|
||||
private:
|
||||
std::auto_ptr<JITMemoryManager> m_default_mm_ap;
|
||||
std::map<uint8_t *, uint8_t *> m_functions;
|
||||
std::map<uint8_t *, intptr_t> m_spaceBlocks;
|
||||
std::map<uint8_t *, unsigned> m_stubs;
|
||||
std::map<uint8_t *, uintptr_t> m_globals;
|
||||
std::map<uint8_t *, uint8_t *> m_exception_tables;
|
||||
std::auto_ptr<JITMemoryManager> m_default_mm_ap; ///< The memory allocator to use in actually creating space. All calls are passed through to it.
|
||||
std::map<uint8_t *, uint8_t *> m_functions; ///< A map from function base addresses to their end addresses.
|
||||
std::map<uint8_t *, intptr_t> m_spaceBlocks; ///< A map from the base addresses of generic allocations to their sizes.
|
||||
std::map<uint8_t *, unsigned> m_stubs; ///< A map from the base addresses of stubs to their sizes.
|
||||
std::map<uint8_t *, uintptr_t> m_globals; ///< A map from the base addresses of globals to their sizes.
|
||||
std::map<uint8_t *, uint8_t *> m_exception_tables; ///< A map from the base addresses of exception tables to their end addresses.
|
||||
|
||||
lldb_private::Log *m_log;
|
||||
lldb_private::Log *m_log; ///< The log to use when printing log messages. May be NULL.
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// @class LocalToRemoteAddressRange RecordingMemoryManager.h "lldb/Expression/RecordingMemoryManager.h"
|
||||
/// @brief A record of an allocated region that has been copied into the target
|
||||
///
|
||||
/// The RecordingMemoryManager makes records of all regions that need copying;
|
||||
/// then, ClangExpression copies these regions into the target. It records
|
||||
/// what was copied where in records of type LocalToRemoteAddressRange.
|
||||
//----------------------------------------------------------------------
|
||||
struct LocalToRemoteAddressRange
|
||||
{
|
||||
lldb::addr_t m_local_start;
|
||||
size_t m_size;
|
||||
lldb::addr_t m_remote_start;
|
||||
lldb::addr_t m_local_start; ///< The base address of the local allocation
|
||||
size_t m_size; ///< The size of the allocation
|
||||
lldb::addr_t m_remote_start; ///< The base address of the remote allocation
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Constructor
|
||||
//------------------------------------------------------------------
|
||||
LocalToRemoteAddressRange (lldb::addr_t lstart, size_t size, lldb::addr_t rstart) :
|
||||
m_local_start (lstart),
|
||||
m_size (size),
|
||||
|
@ -146,15 +309,24 @@ private:
|
|||
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Add a range to the list of copied ranges.
|
||||
///
|
||||
/// @param[in] lstart
|
||||
/// The base address of the local allocation.
|
||||
///
|
||||
/// @param[in] size
|
||||
/// The size of the allocation.
|
||||
///
|
||||
/// @param[in] rstart
|
||||
/// The base address of the remote allocation.
|
||||
//------------------------------------------------------------------
|
||||
void
|
||||
AddToLocalToRemoteMap (lldb::addr_t lstart, size_t size, lldb::addr_t rstart);
|
||||
|
||||
// We should probably store this by address so we can efficiently
|
||||
// search it but there really won't be many elements in this array
|
||||
// at present. So we can put that off for now.
|
||||
std::vector<LocalToRemoteAddressRange> m_address_map;
|
||||
|
||||
std::vector<LocalToRemoteAddressRange> m_address_map; ///< The base address of the remote allocation
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // lldb_RecordingMemoryManager_h_
|
||||
|
|
Loading…
Reference in New Issue