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.
//
//===----------------------------------------------------------------------===//
# 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"
2015-03-04 07:11:11 +08:00
# include "llvm/Support/raw_ostream.h"
2013-03-19 08:10:07 +08:00
# include "lldb/Core/DataBufferHeap.h"
# include "lldb/Core/DataExtractor.h"
2014-10-11 07:07:36 +08:00
# include "lldb/Core/Debugger.h"
2013-03-19 08:10:07 +08:00
# include "lldb/Core/Disassembler.h"
# include "lldb/Core/Log.h"
2014-03-25 07:10:19 +08:00
# include "lldb/Core/Module.h"
# include "lldb/Core/Section.h"
2015-03-04 07:11:11 +08:00
# include "lldb/Symbol/SymbolContext.h"
2013-03-19 08:10:07 +08:00
# include "lldb/Expression/IRExecutionUnit.h"
# include "lldb/Target/ExecutionContext.h"
# include "lldb/Target/Target.h"
2015-03-04 07:11:11 +08:00
# include "lldb/Target/ObjCLanguageRuntime.h"
2013-03-19 08:10:07 +08:00
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 )
2014-07-07 01:54:58 +08:00
{
2013-04-05 10:22:57 +08:00
lldb : : addr_t allocation_process_addr = Malloc ( size ,
8 ,
lldb : : ePermissionsWritable | lldb : : ePermissionsReadable ,
eAllocationPolicyMirror ,
error ) ;
2014-07-07 01:54:58 +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 ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
WriteMemory ( allocation_process_addr , bytes , size , error ) ;
2014-07-07 01:54:58 +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 ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
return LLDB_INVALID_ADDRESS ;
}
2014-07-07 01:54:58 +08:00
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 ) ;
2014-07-07 01:54:58 +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
}
}
2014-07-07 01:54:58 +08:00
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 ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
Error err ;
2014-07-07 01:54:58 +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 ) ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
ExecutionContext exe_ctx ( process_wp ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
Error ret ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
ret . Clear ( ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
lldb : : addr_t func_local_addr = LLDB_INVALID_ADDRESS ;
lldb : : addr_t func_remote_addr = LLDB_INVALID_ADDRESS ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
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 ;
}
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
if ( func_local_addr = = LLDB_INVALID_ADDRESS )
{
ret . SetErrorToGenericError ( ) ;
ret . SetErrorStringWithFormat ( " Couldn't find function %s for disassembly " , m_name . AsCString ( ) ) ;
return ret ;
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
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 ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
std : : pair < lldb : : addr_t , lldb : : addr_t > func_range ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
func_range = GetRemoteRangeForLocal ( func_local_addr ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
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 ;
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
if ( log )
log - > Printf ( " Function's code range is [0x% " PRIx64 " +0x% " PRIx64 " ] " , func_range . first , func_range . second ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
Target * target = exe_ctx . GetTargetPtr ( ) ;
if ( ! target )
{
ret . SetErrorToGenericError ( ) ;
ret . SetErrorString ( " Couldn't find the target " ) ;
return ret ;
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
lldb : : DataBufferSP buffer_sp ( new DataBufferHeap ( func_range . second , 0 ) ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
Process * process = exe_ctx . GetProcessPtr ( ) ;
Error err ;
process - > ReadMemory ( func_remote_addr , buffer_sp - > GetBytes ( ) , buffer_sp - > GetByteSize ( ) , err ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
if ( ! err . Success ( ) )
{
ret . SetErrorToGenericError ( ) ;
ret . SetErrorStringWithFormat ( " Couldn't read from process: %s " , err . AsCString ( " unknown error " ) ) ;
return ret ;
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
ArchSpec arch ( target - > GetArchitecture ( ) ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
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 ) ;
2014-07-07 01:54:58 +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 ;
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
if ( ! process )
{
ret . SetErrorToGenericError ( ) ;
ret . SetErrorString ( " Couldn't find the process " ) ;
return ret ;
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
DataExtractor extractor ( buffer_sp ,
process - > GetByteOrder ( ) ,
target - > GetArchitecture ( ) . GetAddressByteSize ( ) ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
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 ) ;
}
2014-07-07 01:54:58 +08:00
2013-07-31 10:19:15 +08:00
disassembler_sp - > DecodeInstructions ( Address ( func_remote_addr ) , extractor , 0 , UINT32_MAX , false , false ) ;
2014-07-07 01:54:58 +08:00
2013-07-31 10:19:15 +08:00
InstructionList & instruction_list = disassembler_sp - > GetInstructionList ( ) ;
2015-02-05 06:00:53 +08:00
instruction_list . Dump ( & stream , true , true , & exe_ctx ) ;
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 ) ;
2014-07-07 01:54:58 +08:00
2013-03-27 11:09:55 +08:00
if ( err & & err - > Success ( ) )
{
err - > SetErrorToGenericError ( ) ;
err - > SetErrorStringWithFormat ( " Inline assembly error: %s " , diagnostic . getMessage ( ) . str ( ) . c_str ( ) ) ;
}
}
2015-01-28 02:03:05 +08:00
void
IRExecutionUnit : : ReportSymbolLookupError ( const ConstString & name )
{
m_failed_lookups . push_back ( name ) ;
}
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 ( ) ) ;
2014-07-07 01:54:58 +08:00
2014-02-07 06:25:20 +08:00
static Mutex s_runnable_info_mutex ( Mutex : : Type : : eMutexTypeRecursive ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
func_addr = LLDB_INVALID_ADDRESS ;
func_end = LLDB_INVALID_ADDRESS ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
if ( ! process_sp )
{
error . SetErrorToGenericError ( ) ;
error . SetErrorString ( " Couldn't write the JIT compiled code into the process because the process is invalid " ) ;
return ;
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
if ( m_did_jit )
{
func_addr = m_function_load_addr ;
func_end = m_function_end_load_addr ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
return ;
2013-04-05 10:22:57 +08:00
} ;
2014-07-07 01:54:58 +08:00
2014-02-07 06:25:20 +08:00
Mutex : : Locker runnable_info_mutex_locker ( s_runnable_info_mutex ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
m_did_jit = true ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
std : : string error_string ;
2014-07-07 01:54:58 +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 ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
m_module - > print ( oss , NULL ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
oss . flush ( ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
log - > Printf ( " Module being sent to JIT: \n %s " , s . c_str ( ) ) ;
}
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
llvm : : Triple triple ( m_module - > getTargetTriple ( ) ) ;
llvm : : Function * function = m_module - > getFunction ( m_name . AsCString ( ) ) ;
llvm : : Reloc : : Model relocModel ;
llvm : : CodeModel : : Model codeModel ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
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 ;
}
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
m_module_ap - > getContext ( ) . setInlineAsmDiagnosticHandler ( ReportInlineAsmError , & error ) ;
2014-07-07 01:54:58 +08:00
2014-08-19 12:27:03 +08:00
llvm : : EngineBuilder builder ( std : : move ( m_module_ap ) ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
builder . setEngineKind ( llvm : : EngineKind : : JIT )
. setErrorStr ( & error_string )
. setRelocationModel ( relocModel )
2014-12-05 05:26:25 +08:00
. setMCJITMemoryManager ( std : : unique_ptr < MemoryManager > ( new MemoryManager ( * this ) ) )
2014-09-16 14:34:29 +08:00
. setCodeModel ( codeModel )
2014-09-03 08:40:36 +08:00
. setOptLevel ( llvm : : CodeGenOpt : : Less ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
llvm : : StringRef mArch ;
llvm : : StringRef mCPU ;
llvm : : SmallVector < std : : string , 0 > mAttrs ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
for ( std : : string & feature : m_cpu_features )
mAttrs . push_back ( feature ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
llvm : : TargetMachine * target_machine = builder . selectTarget ( triple ,
mArch ,
mCPU ,
mAttrs ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
m_execution_engine_ap . reset ( builder . create ( target_machine ) ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
if ( ! m_execution_engine_ap . get ( ) )
{
error . SetErrorToGenericError ( ) ;
error . SetErrorStringWithFormat ( " Couldn't JIT the function: %s " , error_string . c_str ( ) ) ;
return ;
}
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
// Make sure we see all sections, including ones that don't have relocations...
m_execution_engine_ap - > setProcessAllSections ( true ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
m_execution_engine_ap - > DisableLazyCompilation ( ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
// We don't actually need the function pointer here, this just forces it to get resolved.
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
void * fun_ptr = m_execution_engine_ap - > getPointerToFunction ( function ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
if ( ! error . Success ( ) )
{
// We got an error through our callback!
return ;
}
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
if ( ! function )
{
error . SetErrorToGenericError ( ) ;
error . SetErrorStringWithFormat ( " Couldn't find '%s' in the JITted module " , m_name . AsCString ( ) ) ;
return ;
}
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
if ( ! fun_ptr )
{
error . SetErrorToGenericError ( ) ;
error . SetErrorStringWithFormat ( " '%s' was in the JITted module but wasn't lowered " , m_name . AsCString ( ) ) ;
return ;
}
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
m_jitted_functions . push_back ( JittedFunction ( m_name . AsCString ( ) , ( lldb : : addr_t ) fun_ptr ) ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
CommitAllocations ( process_sp ) ;
ReportAllocations ( * m_execution_engine_ap ) ;
WriteData ( process_sp ) ;
2014-07-07 01:54:58 +08:00
2015-01-28 02:03:05 +08:00
if ( m_failed_lookups . size ( ) )
{
StreamString ss ;
ss . PutCString ( " Couldn't lookup symbols: \n " ) ;
bool emitNewLine = false ;
for ( const ConstString & failed_lookup : m_failed_lookups )
{
if ( emitNewLine )
ss . PutCString ( " \n " ) ;
emitNewLine = true ;
ss . PutCString ( " " ) ;
ss . PutCString ( Mangled ( failed_lookup ) . GetDemangledName ( ) . AsCString ( ) ) ;
}
m_failed_lookups . clear ( ) ;
error . SetErrorString ( ss . GetData ( ) ) ;
return ;
}
m_function_load_addr = LLDB_INVALID_ADDRESS ;
m_function_end_load_addr = LLDB_INVALID_ADDRESS ;
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 ) ;
2014-07-07 01:54:58 +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
}
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
if ( log )
{
log - > Printf ( " Code can be run in the target. " ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
StreamString disassembly_stream ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
Error err = DisassembleFunction ( disassembly_stream , process_sp ) ;
2014-07-07 01:54:58 +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-07-07 01:54:58 +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 ) ;
2014-07-07 01:54:58 +08:00
2014-01-21 08:54:48 +08:00
DataBufferHeap my_buffer ( record . m_size , 0 ) ;
Error err ;
ReadMemory ( my_buffer . GetBytes ( ) , record . m_process_address , record . m_size , err ) ;
2014-07-07 01:54:58 +08:00
2014-01-21 08:54:48 +08:00
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
}
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
func_addr = m_function_load_addr ;
func_end = m_function_end_load_addr ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
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 ) :
2014-09-24 23:55:47 +08:00
m_default_mm_ap ( new llvm : : SectionMemoryManager ( ) ) ,
2013-03-19 08:10:07 +08:00
m_parent ( parent )
{
}
2014-03-25 07:10:19 +08:00
IRExecutionUnit : : MemoryManager : : ~ MemoryManager ( )
{
}
2013-03-19 08:10:07 +08:00
2014-03-25 07:10:19 +08:00
lldb : : SectionType
IRExecutionUnit : : GetSectionTypeFromSectionName ( const llvm : : StringRef & name , IRExecutionUnit : : AllocationKind alloc_kind )
{
lldb : : SectionType sect_type = lldb : : eSectionTypeCode ;
switch ( alloc_kind )
{
case AllocationKind : : Stub : sect_type = lldb : : eSectionTypeCode ; break ;
case AllocationKind : : Code : sect_type = lldb : : eSectionTypeCode ; break ;
case AllocationKind : : Data : sect_type = lldb : : eSectionTypeData ; break ;
case AllocationKind : : Global : sect_type = lldb : : eSectionTypeData ; break ;
case AllocationKind : : Bytes : sect_type = lldb : : eSectionTypeOther ; break ;
}
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
if ( ! name . empty ( ) )
{
if ( name . equals ( " __text " ) | | name . equals ( " .text " ) )
sect_type = lldb : : eSectionTypeCode ;
else if ( name . equals ( " __data " ) | | name . equals ( " .data " ) )
sect_type = lldb : : eSectionTypeCode ;
else if ( name . startswith ( " __debug_ " ) | | name . startswith ( " .debug_ " ) )
{
const uint32_t name_idx = name [ 0 ] = = ' _ ' ? 8 : 7 ;
llvm : : StringRef dwarf_name ( name . substr ( name_idx ) ) ;
switch ( dwarf_name [ 0 ] )
{
case ' a ' :
if ( dwarf_name . equals ( " abbrev " ) )
sect_type = lldb : : eSectionTypeDWARFDebugAbbrev ;
else if ( dwarf_name . equals ( " aranges " ) )
sect_type = lldb : : eSectionTypeDWARFDebugAranges ;
break ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
case ' f ' :
if ( dwarf_name . equals ( " frame " ) )
sect_type = lldb : : eSectionTypeDWARFDebugFrame ;
break ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
case ' i ' :
if ( dwarf_name . equals ( " info " ) )
sect_type = lldb : : eSectionTypeDWARFDebugInfo ;
break ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
case ' l ' :
if ( dwarf_name . equals ( " line " ) )
sect_type = lldb : : eSectionTypeDWARFDebugLine ;
else if ( dwarf_name . equals ( " loc " ) )
sect_type = lldb : : eSectionTypeDWARFDebugLoc ;
break ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
case ' m ' :
if ( dwarf_name . equals ( " macinfo " ) )
sect_type = lldb : : eSectionTypeDWARFDebugMacInfo ;
break ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
case ' p ' :
if ( dwarf_name . equals ( " pubnames " ) )
sect_type = lldb : : eSectionTypeDWARFDebugPubNames ;
else if ( dwarf_name . equals ( " pubtypes " ) )
sect_type = lldb : : eSectionTypeDWARFDebugPubTypes ;
break ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
case ' s ' :
if ( dwarf_name . equals ( " str " ) )
sect_type = lldb : : eSectionTypeDWARFDebugStr ;
break ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
case ' r ' :
if ( dwarf_name . equals ( " ranges " ) )
sect_type = lldb : : eSectionTypeDWARFDebugRanges ;
break ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
default :
break ;
}
}
else if ( name . startswith ( " __apple_ " ) | | name . startswith ( " .apple_ " ) )
{
#if 0
const uint32_t name_idx = name [ 0 ] = = ' _ ' ? 8 : 7 ;
llvm : : StringRef apple_name ( name . substr ( name_idx ) ) ;
switch ( apple_name [ 0 ] )
{
case ' n ' :
if ( apple_name . equals ( " names " ) )
sect_type = lldb : : eSectionTypeDWARFAppleNames ;
else if ( apple_name . equals ( " namespac " ) | | apple_name . equals ( " namespaces " ) )
sect_type = lldb : : eSectionTypeDWARFAppleNamespaces ;
break ;
case ' t ' :
if ( apple_name . equals ( " types " ) )
sect_type = lldb : : eSectionTypeDWARFAppleTypes ;
break ;
case ' o ' :
if ( apple_name . equals ( " objc " ) )
sect_type = lldb : : eSectionTypeDWARFAppleObjC ;
break ;
default :
break ;
}
# else
sect_type = lldb : : eSectionTypeInvalid ;
# endif
}
else if ( name . equals ( " __objc_imageinfo " ) )
sect_type = lldb : : eSectionTypeOther ;
}
return sect_type ;
}
2013-03-19 08:10:07 +08:00
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 ) ) ;
2014-07-07 01:54:58 +08:00
2013-10-02 09:43:46 +08:00
uint8_t * return_value = m_default_mm_ap - > allocateCodeSection ( Size , Alignment , SectionID , SectionName ) ;
2014-07-07 01:54:58 +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 ,
2014-03-25 07:10:19 +08:00
GetSectionTypeFromSectionName ( SectionName , AllocationKind : : Code ) ,
2013-04-05 10:22:57 +08:00
Size ,
Alignment ,
2014-03-25 07:10:19 +08:00
SectionID ,
SectionName . str ( ) . c_str ( ) ) ) ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
if ( log )
{
log - > Printf ( " IRExecutionUnit::allocateCodeSection(Size=0x% " PRIx64 " , Alignment=%u, SectionID=%u) = %p " ,
2015-04-09 04:23:52 +08:00
( uint64_t ) Size , Alignment , SectionID , ( void * ) return_value ) ;
2013-03-19 08:10:07 +08:00
}
2014-07-07 01:54:58 +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 ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
m_parent . m_records . push_back ( AllocationRecord ( ( uintptr_t ) return_value ,
2014-03-25 07:10:19 +08:00
lldb : : ePermissionsReadable | ( IsReadOnly ? 0 : lldb : : ePermissionsWritable ) ,
GetSectionTypeFromSectionName ( SectionName , AllocationKind : : Data ) ,
2013-04-05 10:22:57 +08:00
Size ,
Alignment ,
2014-03-25 07:10:19 +08:00
SectionID ,
SectionName . str ( ) . c_str ( ) ) ) ;
2013-03-19 08:10:07 +08:00
if ( log )
{
log - > Printf ( " IRExecutionUnit::allocateDataSection(Size=0x% " PRIx64 " , Alignment=%u, SectionID=%u) = %p " ,
2015-04-09 04:23:52 +08:00
( uint64_t ) Size , Alignment , SectionID , ( void * ) return_value ) ;
2013-03-19 08:10:07 +08:00
}
2014-07-07 01:54:58 +08:00
return return_value ;
2013-03-19 08:10:07 +08:00
}
2015-01-28 02:03:05 +08:00
uint64_t
IRExecutionUnit : : MemoryManager : : getSymbolAddress ( const std : : string & Name )
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
SymbolContextList sc_list ;
ExecutionContextScope * exe_scope = m_parent . GetBestExecutionContextScope ( ) ;
lldb : : TargetSP target_sp = exe_scope - > CalculateTarget ( ) ;
const char * name = Name . c_str ( ) ;
ConstString bare_name_cs ( name ) ;
ConstString name_cs ;
if ( name [ 0 ] = = ' _ ' )
name_cs = ConstString ( name + 1 ) ;
if ( ! target_sp )
{
if ( log )
log - > Printf ( " IRExecutionUnit::getSymbolAddress(Name= \" %s \" ) = <no target> " ,
Name . c_str ( ) ) ;
m_parent . ReportSymbolLookupError ( name_cs ) ;
return 0xbad0bad0 ;
}
uint32_t num_matches = 0 ;
lldb : : ProcessSP process_sp = exe_scope - > CalculateProcess ( ) ;
if ( ! name_cs . IsEmpty ( ) )
{
target_sp - > GetImages ( ) . FindSymbolsWithNameAndType ( name_cs , lldb : : eSymbolTypeAny , sc_list ) ;
num_matches = sc_list . GetSize ( ) ;
}
if ( ! num_matches )
{
target_sp - > GetImages ( ) . FindSymbolsWithNameAndType ( bare_name_cs , lldb : : eSymbolTypeAny , sc_list ) ;
num_matches = sc_list . GetSize ( ) ;
}
lldb : : addr_t symbol_load_addr = LLDB_INVALID_ADDRESS ;
for ( uint32_t i = 0 ; i < num_matches & & ( symbol_load_addr = = 0 | | symbol_load_addr = = LLDB_INVALID_ADDRESS ) ; i + + )
{
SymbolContext sym_ctx ;
sc_list . GetContextAtIndex ( i , sym_ctx ) ;
if ( sym_ctx . symbol - > GetType ( ) = = lldb : : eSymbolTypeUndefined )
continue ;
const Address * sym_address = & sym_ctx . symbol - > GetAddress ( ) ;
if ( ! sym_address | | ! sym_address - > IsValid ( ) )
continue ;
symbol_load_addr = sym_ctx . symbol - > ResolveCallableAddress ( * target_sp ) ;
if ( symbol_load_addr = = LLDB_INVALID_ADDRESS )
{
symbol_load_addr = sym_ctx . symbol - > GetAddress ( ) . GetLoadAddress ( target_sp . get ( ) ) ;
}
}
if ( symbol_load_addr = = LLDB_INVALID_ADDRESS & & process_sp & & name_cs )
{
// Try the Objective-C language runtime.
ObjCLanguageRuntime * runtime = process_sp - > GetObjCLanguageRuntime ( ) ;
if ( runtime )
symbol_load_addr = runtime - > LookupRuntimeSymbol ( name_cs ) ;
}
if ( symbol_load_addr = = LLDB_INVALID_ADDRESS )
{
if ( log )
log - > Printf ( " IRExecutionUnit::getSymbolAddress(Name= \" %s \" ) = <not found> " ,
name ) ;
m_parent . ReportSymbolLookupError ( bare_name_cs ) ;
return 0xbad0bad0 ;
}
if ( log )
log - > Printf ( " IRExecutionUnit::getSymbolAddress(Name= \" %s \" ) = % " PRIx64 ,
name ,
symbol_load_addr ) ;
if ( symbol_load_addr = = 0 )
return 0xbad00add ;
return symbol_load_addr ;
}
void *
IRExecutionUnit : : MemoryManager : : getPointerToNamedFunction ( const std : : string & Name ,
bool AbortOnFailure ) {
assert ( sizeof ( void * ) = = 8 ) ;
return ( void * ) getSymbolAddress ( Name ) ;
}
2013-03-19 08:10:07 +08:00
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 ;
2014-07-07 01:54:58 +08:00
2013-06-27 09:42:47 +08:00
lldb : : addr_t ret = record . m_process_address + ( local_address - record . m_host_address ) ;
2014-07-07 01:54:58 +08:00
2013-06-27 09:42:47 +08:00
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 ) ;
}
2014-07-07 01:54:58 +08:00
2013-06-27 09:42:47 +08:00
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 ) ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
return AddrRange ( record . m_process_address , record . m_size ) ;
}
2013-03-19 08:10:07 +08:00
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
return AddrRange ( 0 , 0 ) ;
}
bool
IRExecutionUnit : : CommitAllocations ( lldb : : ProcessSP & process_sp )
{
bool ret = true ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
lldb_private : : Error err ;
2014-07-07 01:54:58 +08:00
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 ;
2014-07-07 01:54:58 +08:00
2014-03-25 07:10:19 +08:00
switch ( record . m_sect_type )
{
case lldb : : eSectionTypeInvalid :
case lldb : : eSectionTypeDWARFDebugAbbrev :
case lldb : : eSectionTypeDWARFDebugAranges :
case lldb : : eSectionTypeDWARFDebugFrame :
case lldb : : eSectionTypeDWARFDebugInfo :
case lldb : : eSectionTypeDWARFDebugLine :
case lldb : : eSectionTypeDWARFDebugLoc :
case lldb : : eSectionTypeDWARFDebugMacInfo :
case lldb : : eSectionTypeDWARFDebugPubNames :
case lldb : : eSectionTypeDWARFDebugPubTypes :
case lldb : : eSectionTypeDWARFDebugRanges :
case lldb : : eSectionTypeDWARFDebugStr :
case lldb : : eSectionTypeDWARFAppleNames :
case lldb : : eSectionTypeDWARFAppleTypes :
case lldb : : eSectionTypeDWARFAppleNamespaces :
case lldb : : eSectionTypeDWARFAppleObjC :
err . Clear ( ) ;
break ;
default :
record . m_process_address = Malloc ( record . m_size ,
record . m_alignment ,
record . m_permissions ,
eAllocationPolicyProcessOnly ,
err ) ;
break ;
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
if ( ! err . Success ( ) )
{
ret = false ;
break ;
}
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
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
}
}
2014-07-07 01:54:58 +08:00
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 ;
2014-07-07 01:54:58 +08:00
2013-04-05 10:22:57 +08:00
if ( record . m_section_id = = eSectionIDInvalid )
2013-03-19 08:10:07 +08:00
continue ;
2014-07-07 01:54:58 +08:00
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
}
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
// Trigger re-application of relocations.
engine . finalizeObject ( ) ;
}
bool
IRExecutionUnit : : WriteData ( lldb : : ProcessSP & process_sp )
{
2014-03-25 07:10:19 +08:00
bool wrote_something = false ;
2013-04-05 10:22:57 +08:00
for ( AllocationRecord & record : m_records )
2013-03-19 08:10:07 +08:00
{
2014-03-25 07:10:19 +08:00
if ( record . m_process_address ! = LLDB_INVALID_ADDRESS )
{
lldb_private : : Error err ;
WriteMemory ( record . m_process_address , ( uint8_t * ) record . m_host_address , record . m_size , err ) ;
if ( err . Success ( ) )
wrote_something = true ;
}
2013-03-19 08:10:07 +08:00
}
2014-03-25 07:10:19 +08:00
return wrote_something ;
2013-03-19 08:10:07 +08:00
}
2014-07-07 01:54:58 +08:00
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 ;
2014-07-07 01:54:58 +08:00
2013-03-19 08:10:07 +08:00
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 ) ;
}
2014-03-25 07:10:19 +08:00
lldb : : ByteOrder
IRExecutionUnit : : GetByteOrder ( ) const
{
ExecutionContext exe_ctx ( GetBestExecutionContextScope ( ) ) ;
return exe_ctx . GetByteOrder ( ) ;
}
uint32_t
IRExecutionUnit : : GetAddressByteSize ( ) const
{
ExecutionContext exe_ctx ( GetBestExecutionContextScope ( ) ) ;
return exe_ctx . GetAddressByteSize ( ) ;
}
void
IRExecutionUnit : : PopulateSymtab ( lldb_private : : ObjectFile * obj_file ,
lldb_private : : Symtab & symtab )
{
// No symbols yet...
}
void
IRExecutionUnit : : PopulateSectionList ( lldb_private : : ObjectFile * obj_file ,
lldb_private : : SectionList & section_list )
{
for ( AllocationRecord & record : m_records )
{
if ( record . m_size > 0 )
{
lldb : : SectionSP section_sp ( new lldb_private : : Section ( obj_file - > GetModule ( ) ,
obj_file ,
record . m_section_id ,
ConstString ( record . m_name ) ,
record . m_sect_type ,
record . m_process_address ,
record . m_size ,
record . m_host_address , // file_offset (which is the host address for the data)
record . m_size , // file_size
2014-06-25 06:22:43 +08:00
0 ,
2014-03-25 07:10:19 +08:00
record . m_permissions ) ) ; // flags
section_list . AddSection ( section_sp ) ;
}
}
}
bool
IRExecutionUnit : : GetArchitecture ( lldb_private : : ArchSpec & arch )
{
ExecutionContext exe_ctx ( GetBestExecutionContextScope ( ) ) ;
Target * target = exe_ctx . GetTargetPtr ( ) ;
if ( target )
arch = target - > GetArchitecture ( ) ;
else
arch . Clear ( ) ;
return arch . IsValid ( ) ;
}
lldb : : ModuleSP
IRExecutionUnit : : GetJITModule ( )
{
ExecutionContext exe_ctx ( GetBestExecutionContextScope ( ) ) ;
Target * target = exe_ctx . GetTargetPtr ( ) ;
if ( target )
{
lldb : : ModuleSP jit_module_sp = lldb_private : : Module : : CreateJITModule ( std : : static_pointer_cast < lldb_private : : ObjectFileJITDelegate > ( shared_from_this ( ) ) ) ;
if ( jit_module_sp )
{
bool changed = false ;
jit_module_sp - > SetLoadAddress ( * target , 0 , true , changed ) ;
}
return jit_module_sp ;
}
return lldb : : ModuleSP ( ) ;
}