2013-04-05 10:22:57 +08:00
//===-- IRExecutionUnit.cpp -------------------------------------*- C++ -*-===//
2013-03-19 08:10:07 +08:00
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// C Includes
// C++ Includes
// Other libraries and framework includes
# include "llvm/ExecutionEngine/ExecutionEngine.h"
2013-03-27 11:09:55 +08:00
# include "llvm/IR/LLVMContext.h"
2013-03-19 08:10:07 +08:00
# include "llvm/IR/Module.h"
2013-03-27 11:09:55 +08:00
# include "llvm/Support/SourceMgr.h"
2013-03-19 08:10:07 +08:00
// Project includes
# include "lldb/Core/DataBufferHeap.h"
# include "lldb/Core/DataExtractor.h"
# include "lldb/Core/Disassembler.h"
# include "lldb/Core/Log.h"
# include "lldb/Expression/IRExecutionUnit.h"
# include "lldb/Target/ExecutionContext.h"
# include "lldb/Target/Target.h"
using namespace lldb_private ;
2013-04-19 06:45:39 +08:00
IRExecutionUnit : : IRExecutionUnit ( std : : unique_ptr < llvm : : LLVMContext > & context_ap ,
std : : unique_ptr < llvm : : Module > & module_ap ,
2013-03-19 08:10:07 +08:00
ConstString & name ,
2013-04-16 01:12:47 +08:00
const lldb : : TargetSP & target_sp ,
2013-03-19 08:10:07 +08:00
std : : vector < std : : string > & cpu_features ) :
2013-04-16 01:12:47 +08:00
IRMemoryMap ( target_sp ) ,
2013-04-19 02:10:51 +08:00
m_context_ap ( context_ap . release ( ) ) ,
m_module_ap ( module_ap . release ( ) ) ,
2013-03-19 08:10:07 +08:00
m_module ( m_module_ap . get ( ) ) ,
2013-03-20 07:03:21 +08:00
m_cpu_features ( cpu_features ) ,
2013-03-19 08:10:07 +08:00
m_name ( name ) ,
m_did_jit ( false ) ,
m_function_load_addr ( LLDB_INVALID_ADDRESS ) ,
m_function_end_load_addr ( LLDB_INVALID_ADDRESS )
{
}
lldb : : addr_t
IRExecutionUnit : : WriteNow ( const uint8_t * bytes ,
size_t size ,
Error & error )
{
2013-04-05 10:22:57 +08:00
lldb : : addr_t allocation_process_addr = Malloc ( size ,
8 ,
lldb : : ePermissionsWritable | lldb : : ePermissionsReadable ,
eAllocationPolicyMirror ,
error ) ;
2013-03-19 08:10:07 +08:00
2013-04-05 10:22:57 +08:00
if ( ! error . Success ( ) )
2013-03-19 08:10:07 +08:00
return LLDB_INVALID_ADDRESS ;
2013-04-05 10:22:57 +08:00
WriteMemory ( allocation_process_addr , bytes , size , error ) ;
2013-03-19 08:10:07 +08:00
2013-04-05 10:22:57 +08:00
if ( ! error . Success ( ) )
2013-03-19 08:10:07 +08:00
{
2013-04-05 10:22:57 +08:00
Error err ;
Free ( allocation_process_addr , err ) ;
2013-03-19 08:10:07 +08:00
return LLDB_INVALID_ADDRESS ;
}
2013-04-05 10:22:57 +08:00
if ( Log * log = lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) )
2013-03-19 08:10:07 +08:00
{
2013-04-05 10:22:57 +08:00
DataBufferHeap my_buffer ( size , 0 ) ;
Error err ;
ReadMemory ( my_buffer . GetBytes ( ) , allocation_process_addr , size , err ) ;
2013-03-20 07:03:21 +08:00
2013-04-05 10:22:57 +08:00
if ( err . Success ( ) )
{
DataExtractor my_extractor ( my_buffer . GetBytes ( ) , my_buffer . GetByteSize ( ) , lldb : : eByteOrderBig , 8 ) ;
2014-01-21 08:54:48 +08:00
my_extractor . PutToLog ( log , 0 , my_buffer . GetByteSize ( ) , allocation_process_addr , 16 , DataExtractor : : TypeUInt8 ) ;
2013-04-05 10:22:57 +08:00
}
}
return allocation_process_addr ;
2013-03-19 08:10:07 +08:00
}
void
IRExecutionUnit : : FreeNow ( lldb : : addr_t allocation )
{
if ( allocation = = LLDB_INVALID_ADDRESS )
return ;
2013-04-05 10:22:57 +08:00
Error err ;
2013-03-19 08:10:07 +08:00
2013-04-05 10:22:57 +08:00
Free ( allocation , err ) ;
2013-03-19 08:10:07 +08:00
}
Error
IRExecutionUnit : : DisassembleFunction ( Stream & stream ,
lldb : : ProcessSP & process_wp )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2013-03-19 08:10:07 +08:00
ExecutionContext exe_ctx ( process_wp ) ;
Error ret ;
ret . Clear ( ) ;
lldb : : addr_t func_local_addr = LLDB_INVALID_ADDRESS ;
lldb : : addr_t func_remote_addr = LLDB_INVALID_ADDRESS ;
for ( JittedFunction & function : m_jitted_functions )
{
if ( strstr ( function . m_name . c_str ( ) , m_name . AsCString ( ) ) )
{
func_local_addr = function . m_local_addr ;
func_remote_addr = function . m_remote_addr ;
}
}
if ( func_local_addr = = LLDB_INVALID_ADDRESS )
{
ret . SetErrorToGenericError ( ) ;
ret . SetErrorStringWithFormat ( " Couldn't find function %s for disassembly " , m_name . AsCString ( ) ) ;
return ret ;
}
if ( log )
log - > Printf ( " Found function, has local address 0x% " PRIx64 " and remote address 0x% " PRIx64 , ( uint64_t ) func_local_addr , ( uint64_t ) func_remote_addr ) ;
std : : pair < lldb : : addr_t , lldb : : addr_t > func_range ;
func_range = GetRemoteRangeForLocal ( func_local_addr ) ;
if ( func_range . first = = 0 & & func_range . second = = 0 )
{
ret . SetErrorToGenericError ( ) ;
ret . SetErrorStringWithFormat ( " Couldn't find code range for function %s " , m_name . AsCString ( ) ) ;
return ret ;
}
if ( log )
log - > Printf ( " Function's code range is [0x% " PRIx64 " +0x% " PRIx64 " ] " , func_range . first , func_range . second ) ;
Target * target = exe_ctx . GetTargetPtr ( ) ;
if ( ! target )
{
ret . SetErrorToGenericError ( ) ;
ret . SetErrorString ( " Couldn't find the target " ) ;
return ret ;
}
lldb : : DataBufferSP buffer_sp ( new DataBufferHeap ( func_range . second , 0 ) ) ;
Process * process = exe_ctx . GetProcessPtr ( ) ;
Error err ;
process - > ReadMemory ( func_remote_addr , buffer_sp - > GetBytes ( ) , buffer_sp - > GetByteSize ( ) , err ) ;
if ( ! err . Success ( ) )
{
ret . SetErrorToGenericError ( ) ;
ret . SetErrorStringWithFormat ( " Couldn't read from process: %s " , err . AsCString ( " unknown error " ) ) ;
return ret ;
}
ArchSpec arch ( target - > GetArchitecture ( ) ) ;
const char * plugin_name = NULL ;
const char * flavor_string = NULL ;
2013-07-31 10:19:15 +08:00
lldb : : DisassemblerSP disassembler_sp = Disassembler : : FindPlugin ( arch , flavor_string , plugin_name ) ;
2013-03-19 08:10:07 +08:00
2013-07-31 10:19:15 +08:00
if ( ! disassembler_sp )
2013-03-19 08:10:07 +08:00
{
ret . SetErrorToGenericError ( ) ;
ret . SetErrorStringWithFormat ( " Unable to find disassembler plug-in for %s architecture. " , arch . GetArchitectureName ( ) ) ;
return ret ;
}
if ( ! process )
{
ret . SetErrorToGenericError ( ) ;
ret . SetErrorString ( " Couldn't find the process " ) ;
return ret ;
}
DataExtractor extractor ( buffer_sp ,
process - > GetByteOrder ( ) ,
target - > GetArchitecture ( ) . GetAddressByteSize ( ) ) ;
if ( log )
{
log - > Printf ( " Function data has contents: " ) ;
2013-03-28 07:08:40 +08:00
extractor . PutToLog ( log ,
2013-03-19 08:10:07 +08:00
0 ,
extractor . GetByteSize ( ) ,
func_remote_addr ,
16 ,
DataExtractor : : TypeUInt8 ) ;
}
2013-07-31 10:19:15 +08:00
disassembler_sp - > DecodeInstructions ( Address ( func_remote_addr ) , extractor , 0 , UINT32_MAX , false , false ) ;
2013-03-19 08:10:07 +08:00
2013-07-31 10:19:15 +08:00
InstructionList & instruction_list = disassembler_sp - > GetInstructionList ( ) ;
2013-03-19 08:10:07 +08:00
const uint32_t max_opcode_byte_size = instruction_list . GetMaxOpcocdeByteSize ( ) ;
for ( size_t instruction_index = 0 , num_instructions = instruction_list . GetSize ( ) ;
instruction_index < num_instructions ;
+ + instruction_index )
{
Instruction * instruction = instruction_list . GetInstructionAtIndex ( instruction_index ) . get ( ) ;
instruction - > Dump ( & stream ,
max_opcode_byte_size ,
true ,
true ,
& exe_ctx ) ;
stream . PutChar ( ' \n ' ) ;
}
2013-07-31 10:19:15 +08:00
// FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions.
// I'll fix that but for now, just clear the list and it will go away nicely.
disassembler_sp - > GetInstructionList ( ) . Clear ( ) ;
2013-03-19 08:10:07 +08:00
return ret ;
}
2013-03-27 11:09:55 +08:00
static void ReportInlineAsmError ( const llvm : : SMDiagnostic & diagnostic , void * Context , unsigned LocCookie )
{
Error * err = static_cast < Error * > ( Context ) ;
if ( err & & err - > Success ( ) )
{
err - > SetErrorToGenericError ( ) ;
err - > SetErrorStringWithFormat ( " Inline assembly error: %s " , diagnostic . getMessage ( ) . str ( ) . c_str ( ) ) ;
}
}
2013-03-19 08:10:07 +08:00
void
IRExecutionUnit : : GetRunnableInfo ( Error & error ,
lldb : : addr_t & func_addr ,
lldb : : addr_t & func_end )
{
2013-04-05 10:22:57 +08:00
lldb : : ProcessSP process_sp ( GetProcessWP ( ) . lock ( ) ) ;
2013-03-19 08:10:07 +08:00
func_addr = LLDB_INVALID_ADDRESS ;
func_end = LLDB_INVALID_ADDRESS ;
if ( ! process_sp )
{
error . SetErrorToGenericError ( ) ;
error . SetErrorString ( " Couldn't write the JIT compiled code into the process because the process is invalid " ) ;
return ;
}
if ( m_did_jit )
{
func_addr = m_function_load_addr ;
func_end = m_function_end_load_addr ;
return ;
2013-04-05 10:22:57 +08:00
} ;
m_did_jit = true ;
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
std : : string error_string ;
2013-03-19 08:10:07 +08:00
2013-04-05 10:22:57 +08:00
if ( log )
2013-03-19 08:10:07 +08:00
{
2013-04-05 10:22:57 +08:00
std : : string s ;
llvm : : raw_string_ostream oss ( s ) ;
2013-03-19 08:10:07 +08:00
2013-04-05 10:22:57 +08:00
m_module - > print ( oss , NULL ) ;
2013-03-19 08:10:07 +08:00
2013-04-05 10:22:57 +08:00
oss . flush ( ) ;
2013-03-19 08:10:07 +08:00
2013-04-05 10:22:57 +08:00
log - > Printf ( " Module being sent to JIT: \n %s " , s . c_str ( ) ) ;
}
llvm : : Triple triple ( m_module - > getTargetTriple ( ) ) ;
llvm : : Function * function = m_module - > getFunction ( m_name . AsCString ( ) ) ;
llvm : : Reloc : : Model relocModel ;
llvm : : CodeModel : : Model codeModel ;
if ( triple . isOSBinFormatELF ( ) )
{
relocModel = llvm : : Reloc : : Static ;
// This will be small for 32-bit and large for 64-bit.
codeModel = llvm : : CodeModel : : JITDefault ;
}
else
{
relocModel = llvm : : Reloc : : PIC_ ;
codeModel = llvm : : CodeModel : : Small ;
}
m_module_ap - > getContext ( ) . setInlineAsmDiagnosticHandler ( ReportInlineAsmError , & error ) ;
llvm : : EngineBuilder builder ( m_module_ap . get ( ) ) ;
builder . setEngineKind ( llvm : : EngineKind : : JIT )
. setErrorStr ( & error_string )
. setRelocationModel ( relocModel )
. setJITMemoryManager ( new MemoryManager ( * this ) )
. setOptLevel ( llvm : : CodeGenOpt : : Less )
. setAllocateGVsWithCode ( true )
. setCodeModel ( codeModel )
. setUseMCJIT ( true ) ;
llvm : : StringRef mArch ;
llvm : : StringRef mCPU ;
llvm : : SmallVector < std : : string , 0 > mAttrs ;
for ( std : : string & feature : m_cpu_features )
mAttrs . push_back ( feature ) ;
llvm : : TargetMachine * target_machine = builder . selectTarget ( triple ,
mArch ,
mCPU ,
mAttrs ) ;
m_execution_engine_ap . reset ( builder . create ( target_machine ) ) ;
if ( ! m_execution_engine_ap . get ( ) )
{
error . SetErrorToGenericError ( ) ;
error . SetErrorStringWithFormat ( " Couldn't JIT the function: %s " , error_string . c_str ( ) ) ;
return ;
}
else
{
m_module_ap . release ( ) ; // ownership was transferred
}
m_execution_engine_ap - > DisableLazyCompilation ( ) ;
// We don't actually need the function pointer here, this just forces it to get resolved.
void * fun_ptr = m_execution_engine_ap - > getPointerToFunction ( function ) ;
if ( ! error . Success ( ) )
{
// We got an error through our callback!
return ;
}
if ( ! function )
{
error . SetErrorToGenericError ( ) ;
error . SetErrorStringWithFormat ( " Couldn't find '%s' in the JITted module " , m_name . AsCString ( ) ) ;
return ;
}
if ( ! fun_ptr )
{
error . SetErrorToGenericError ( ) ;
error . SetErrorStringWithFormat ( " '%s' was in the JITted module but wasn't lowered " , m_name . AsCString ( ) ) ;
return ;
}
m_jitted_functions . push_back ( JittedFunction ( m_name . AsCString ( ) , ( lldb : : addr_t ) fun_ptr ) ) ;
CommitAllocations ( process_sp ) ;
ReportAllocations ( * m_execution_engine_ap ) ;
WriteData ( process_sp ) ;
2013-03-19 08:10:07 +08:00
2013-04-05 10:22:57 +08:00
for ( JittedFunction & jitted_function : m_jitted_functions )
{
jitted_function . m_remote_addr = GetRemoteAddressForLocal ( jitted_function . m_local_addr ) ;
2013-03-19 08:10:07 +08:00
2013-04-05 10:22:57 +08:00
if ( ! jitted_function . m_name . compare ( m_name . AsCString ( ) ) )
2013-03-19 08:10:07 +08:00
{
2013-04-05 10:22:57 +08:00
AddrRange func_range = GetRemoteRangeForLocal ( jitted_function . m_local_addr ) ;
m_function_end_load_addr = func_range . first + func_range . second ;
m_function_load_addr = jitted_function . m_remote_addr ;
2013-03-19 08:10:07 +08:00
}
2013-04-05 10:22:57 +08:00
}
if ( log )
{
log - > Printf ( " Code can be run in the target. " ) ;
2013-03-19 08:10:07 +08:00
2013-04-05 10:22:57 +08:00
StreamString disassembly_stream ;
2013-03-19 08:10:07 +08:00
2013-04-05 10:22:57 +08:00
Error err = DisassembleFunction ( disassembly_stream , process_sp ) ;
2013-03-19 08:10:07 +08:00
2013-04-05 10:22:57 +08:00
if ( ! err . Success ( ) )
2013-03-19 08:10:07 +08:00
{
2013-04-05 10:22:57 +08:00
log - > Printf ( " Couldn't disassemble function : %s " , err . AsCString ( " unknown error " ) ) ;
2013-03-19 08:10:07 +08:00
}
else
{
2013-04-05 10:22:57 +08:00
log - > Printf ( " Function disassembly: \n %s " , disassembly_stream . GetData ( ) ) ;
2013-03-19 08:10:07 +08:00
}
2014-01-21 08:54:48 +08:00
log - > Printf ( " Sections: " ) ;
for ( AllocationRecord & record : m_records )
{
if ( record . m_process_address ! = LLDB_INVALID_ADDRESS )
{
record . dump ( log ) ;
DataBufferHeap my_buffer ( record . m_size , 0 ) ;
Error err ;
ReadMemory ( my_buffer . GetBytes ( ) , record . m_process_address , record . m_size , err ) ;
if ( err . Success ( ) )
{
DataExtractor my_extractor ( my_buffer . GetBytes ( ) , my_buffer . GetByteSize ( ) , lldb : : eByteOrderBig , 8 ) ;
my_extractor . PutToLog ( log , 0 , my_buffer . GetByteSize ( ) , record . m_process_address , 16 , DataExtractor : : TypeUInt8 ) ;
}
}
}
2013-03-19 08:10:07 +08:00
}
2013-04-05 10:22:57 +08:00
func_addr = m_function_load_addr ;
func_end = m_function_end_load_addr ;
return ;
2013-03-19 08:10:07 +08:00
}
IRExecutionUnit : : ~ IRExecutionUnit ( )
{
2013-04-17 07:25:35 +08:00
m_module_ap . reset ( ) ;
m_execution_engine_ap . reset ( ) ;
m_context_ap . reset ( ) ;
2013-03-19 08:10:07 +08:00
}
IRExecutionUnit : : MemoryManager : : MemoryManager ( IRExecutionUnit & parent ) :
m_default_mm_ap ( llvm : : JITMemoryManager : : CreateDefaultMemManager ( ) ) ,
m_parent ( parent )
{
}
void
IRExecutionUnit : : MemoryManager : : setMemoryWritable ( )
{
m_default_mm_ap - > setMemoryWritable ( ) ;
}
void
IRExecutionUnit : : MemoryManager : : setMemoryExecutable ( )
{
m_default_mm_ap - > setMemoryExecutable ( ) ;
}
uint8_t *
IRExecutionUnit : : MemoryManager : : startFunctionBody ( const llvm : : Function * F ,
uintptr_t & ActualSize )
{
return m_default_mm_ap - > startFunctionBody ( F , ActualSize ) ;
}
uint8_t *
IRExecutionUnit : : MemoryManager : : allocateStub ( const llvm : : GlobalValue * F ,
unsigned StubSize ,
unsigned Alignment )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2013-03-19 08:10:07 +08:00
uint8_t * return_value = m_default_mm_ap - > allocateStub ( F , StubSize , Alignment ) ;
2013-04-05 10:22:57 +08:00
m_parent . m_records . push_back ( AllocationRecord ( ( uintptr_t ) return_value ,
lldb : : ePermissionsReadable | lldb : : ePermissionsWritable ,
StubSize ,
Alignment ) ) ;
2013-03-19 08:10:07 +08:00
if ( log )
{
log - > Printf ( " IRExecutionUnit::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p " ,
F , StubSize , Alignment , return_value ) ;
}
2013-03-20 07:03:21 +08:00
2013-03-19 08:10:07 +08:00
return return_value ;
}
void
IRExecutionUnit : : MemoryManager : : endFunctionBody ( const llvm : : Function * F ,
uint8_t * FunctionStart ,
uint8_t * FunctionEnd )
{
m_default_mm_ap - > endFunctionBody ( F , FunctionStart , FunctionEnd ) ;
}
uint8_t *
IRExecutionUnit : : MemoryManager : : allocateSpace ( intptr_t Size , unsigned Alignment )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2013-03-19 08:10:07 +08:00
uint8_t * return_value = m_default_mm_ap - > allocateSpace ( Size , Alignment ) ;
2013-04-05 10:22:57 +08:00
m_parent . m_records . push_back ( AllocationRecord ( ( uintptr_t ) return_value ,
lldb : : ePermissionsReadable | lldb : : ePermissionsWritable ,
Size ,
Alignment ) ) ;
2013-03-19 08:10:07 +08:00
if ( log )
{
log - > Printf ( " IRExecutionUnit::allocateSpace(Size=% " PRIu64 " , Alignment=%u) = %p " ,
( uint64_t ) Size , Alignment , return_value ) ;
}
2013-03-20 07:03:21 +08:00
2013-03-19 08:10:07 +08:00
return return_value ;
}
uint8_t *
IRExecutionUnit : : MemoryManager : : allocateCodeSection ( uintptr_t Size ,
unsigned Alignment ,
2013-10-02 09:43:46 +08:00
unsigned SectionID ,
llvm : : StringRef SectionName )
2013-03-19 08:10:07 +08:00
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2013-03-19 08:10:07 +08:00
2013-10-02 09:43:46 +08:00
uint8_t * return_value = m_default_mm_ap - > allocateCodeSection ( Size , Alignment , SectionID , SectionName ) ;
2013-03-19 08:10:07 +08:00
2013-04-05 10:22:57 +08:00
m_parent . m_records . push_back ( AllocationRecord ( ( uintptr_t ) return_value ,
2013-04-09 09:13:08 +08:00
lldb : : ePermissionsReadable | lldb : : ePermissionsExecutable ,
2013-04-05 10:22:57 +08:00
Size ,
Alignment ,
SectionID ) ) ;
2013-03-19 08:10:07 +08:00
if ( log )
{
log - > Printf ( " IRExecutionUnit::allocateCodeSection(Size=0x% " PRIx64 " , Alignment=%u, SectionID=%u) = %p " ,
( uint64_t ) Size , Alignment , SectionID , return_value ) ;
}
2013-03-20 07:03:21 +08:00
2013-03-19 08:10:07 +08:00
return return_value ;
}
uint8_t *
IRExecutionUnit : : MemoryManager : : allocateDataSection ( uintptr_t Size ,
unsigned Alignment ,
unsigned SectionID ,
2013-10-02 09:43:46 +08:00
llvm : : StringRef SectionName ,
2013-03-19 08:10:07 +08:00
bool IsReadOnly )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2013-03-19 08:10:07 +08:00
2013-10-02 09:43:46 +08:00
uint8_t * return_value = m_default_mm_ap - > allocateDataSection ( Size , Alignment , SectionID , SectionName , IsReadOnly ) ;
2013-03-19 08:10:07 +08:00
2013-04-05 10:22:57 +08:00
m_parent . m_records . push_back ( AllocationRecord ( ( uintptr_t ) return_value ,
lldb : : ePermissionsReadable | lldb : : ePermissionsWritable ,
Size ,
Alignment ,
SectionID ) ) ;
2013-03-19 08:10:07 +08:00
if ( log )
{
log - > Printf ( " IRExecutionUnit::allocateDataSection(Size=0x% " PRIx64 " , Alignment=%u, SectionID=%u) = %p " ,
( uint64_t ) Size , Alignment , SectionID , return_value ) ;
}
2013-03-20 07:03:21 +08:00
2013-03-19 08:10:07 +08:00
return return_value ;
}
uint8_t *
IRExecutionUnit : : MemoryManager : : allocateGlobal ( uintptr_t Size ,
unsigned Alignment )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2013-03-19 08:10:07 +08:00
uint8_t * return_value = m_default_mm_ap - > allocateGlobal ( Size , Alignment ) ;
2013-04-05 10:22:57 +08:00
m_parent . m_records . push_back ( AllocationRecord ( ( uintptr_t ) return_value ,
lldb : : ePermissionsReadable | lldb : : ePermissionsWritable ,
Size ,
Alignment ) ) ;
2013-03-19 08:10:07 +08:00
if ( log )
{
log - > Printf ( " IRExecutionUnit::allocateGlobal(Size=0x% " PRIx64 " , Alignment=%u) = %p " ,
( uint64_t ) Size , Alignment , return_value ) ;
}
return return_value ;
}
void
IRExecutionUnit : : MemoryManager : : deallocateFunctionBody ( void * Body )
{
m_default_mm_ap - > deallocateFunctionBody ( Body ) ;
}
lldb : : addr_t
IRExecutionUnit : : GetRemoteAddressForLocal ( lldb : : addr_t local_address )
{
2013-06-27 09:42:47 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2013-04-05 10:22:57 +08:00
for ( AllocationRecord & record : m_records )
2013-03-19 08:10:07 +08:00
{
2013-04-05 10:22:57 +08:00
if ( local_address > = record . m_host_address & &
local_address < record . m_host_address + record . m_size )
{
if ( record . m_process_address = = LLDB_INVALID_ADDRESS )
return LLDB_INVALID_ADDRESS ;
2013-06-27 09:42:47 +08:00
lldb : : addr_t ret = record . m_process_address + ( local_address - record . m_host_address ) ;
if ( log )
{
log - > Printf ( " IRExecutionUnit::GetRemoteAddressForLocal() found 0x% " PRIx64 " in [0x% " PRIx64 " ..0x% " PRIx64 " ], and returned 0x% " PRIx64 " from [0x% " PRIx64 " ..0x% " PRIx64 " ]. " ,
local_address ,
2013-08-08 03:05:15 +08:00
( uint64_t ) record . m_host_address ,
( uint64_t ) record . m_host_address + ( uint64_t ) record . m_size ,
2013-06-27 09:42:47 +08:00
ret ,
record . m_process_address ,
record . m_process_address + record . m_size ) ;
}
return ret ;
2013-04-05 10:22:57 +08:00
}
2013-03-19 08:10:07 +08:00
}
return LLDB_INVALID_ADDRESS ;
}
IRExecutionUnit : : AddrRange
IRExecutionUnit : : GetRemoteRangeForLocal ( lldb : : addr_t local_address )
{
2013-04-05 10:22:57 +08:00
for ( AllocationRecord & record : m_records )
2013-03-19 08:10:07 +08:00
{
2013-04-05 10:22:57 +08:00
if ( local_address > = record . m_host_address & &
local_address < record . m_host_address + record . m_size )
{
if ( record . m_process_address = = LLDB_INVALID_ADDRESS )
return AddrRange ( 0 , 0 ) ;
return AddrRange ( record . m_process_address , record . m_size ) ;
}
2013-03-19 08:10:07 +08:00
}
return AddrRange ( 0 , 0 ) ;
}
bool
IRExecutionUnit : : CommitAllocations ( lldb : : ProcessSP & process_sp )
{
bool ret = true ;
2013-04-05 10:22:57 +08:00
lldb_private : : Error err ;
for ( AllocationRecord & record : m_records )
2013-03-19 08:10:07 +08:00
{
2013-04-05 10:22:57 +08:00
if ( record . m_process_address ! = LLDB_INVALID_ADDRESS )
2013-03-19 08:10:07 +08:00
continue ;
2013-04-05 10:22:57 +08:00
record . m_process_address = Malloc ( record . m_size ,
record . m_alignment ,
record . m_permissions ,
eAllocationPolicyProcessOnly ,
err ) ;
2013-03-19 08:10:07 +08:00
if ( ! err . Success ( ) )
{
ret = false ;
break ;
}
}
if ( ! ret )
{
2013-04-05 10:22:57 +08:00
for ( AllocationRecord & record : m_records )
2013-03-19 08:10:07 +08:00
{
2013-04-05 10:22:57 +08:00
if ( record . m_process_address ! = LLDB_INVALID_ADDRESS )
{
Free ( record . m_process_address , err ) ;
record . m_process_address = LLDB_INVALID_ADDRESS ;
}
2013-03-19 08:10:07 +08:00
}
}
return ret ;
}
void
IRExecutionUnit : : ReportAllocations ( llvm : : ExecutionEngine & engine )
{
2013-04-05 10:22:57 +08:00
for ( AllocationRecord & record : m_records )
2013-03-19 08:10:07 +08:00
{
2013-04-05 10:22:57 +08:00
if ( record . m_process_address = = LLDB_INVALID_ADDRESS )
2013-03-19 08:10:07 +08:00
continue ;
2013-04-05 10:22:57 +08:00
if ( record . m_section_id = = eSectionIDInvalid )
2013-03-19 08:10:07 +08:00
continue ;
2013-04-05 10:22:57 +08:00
engine . mapSectionAddress ( ( void * ) record . m_host_address , record . m_process_address ) ;
2013-03-19 08:10:07 +08:00
}
2013-04-05 10:22:57 +08:00
2013-03-19 08:10:07 +08:00
// Trigger re-application of relocations.
engine . finalizeObject ( ) ;
}
bool
IRExecutionUnit : : WriteData ( lldb : : ProcessSP & process_sp )
{
2013-04-05 10:22:57 +08:00
for ( AllocationRecord & record : m_records )
2013-03-19 08:10:07 +08:00
{
2013-04-05 10:22:57 +08:00
if ( record . m_process_address = = LLDB_INVALID_ADDRESS )
2013-03-19 08:10:07 +08:00
return false ;
lldb_private : : Error err ;
2013-04-05 10:22:57 +08:00
WriteMemory ( record . m_process_address , ( uint8_t * ) record . m_host_address , record . m_size , err ) ;
2013-03-19 08:10:07 +08:00
}
return true ;
}
void
2013-04-05 10:22:57 +08:00
IRExecutionUnit : : AllocationRecord : : dump ( Log * log )
2013-03-19 08:10:07 +08:00
{
if ( ! log )
return ;
log - > Printf ( " [0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d) " ,
2013-04-05 10:22:57 +08:00
( unsigned long long ) m_host_address ,
2013-03-19 08:10:07 +08:00
( unsigned long long ) m_size ,
2013-04-05 10:22:57 +08:00
( unsigned long long ) m_process_address ,
2013-03-19 08:10:07 +08:00
( unsigned ) m_alignment ,
( unsigned ) m_section_id ) ;
}