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"
2016-02-13 05:11:25 +08:00
# include "lldb/Symbol/CompileUnit.h"
2015-03-04 07:11:11 +08:00
# include "lldb/Symbol/SymbolContext.h"
2016-02-13 05:11:25 +08:00
# include "lldb/Symbol/SymbolVendor.h"
# include "lldb/Symbol/SymbolFile.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
2016-02-13 05:11:25 +08:00
# include "lldb/../../source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.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 ,
2016-02-13 05:11:25 +08:00
const SymbolContext & sym_ctx ,
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 ) ,
2016-02-13 05:11:25 +08:00
m_sym_ctx ( sym_ctx ) ,
2013-03-19 08:10:07 +08:00
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
{
2015-11-05 04:32:27 +08:00
const bool zero_memory = false ;
2013-04-05 10:22:57 +08:00
lldb : : addr_t allocation_process_addr = Malloc ( size ,
8 ,
lldb : : ePermissionsWritable | lldb : : ePermissionsReadable ,
eAllocationPolicyMirror ,
2015-11-05 04:32:27 +08:00
zero_memory ,
2013-04-05 10:22:57 +08:00
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 ) ;
2016-02-24 11:15:21 +08:00
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 ;
}
else
{
relocModel = llvm : : Reloc : : PIC_ ;
}
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
// This will be small for 32-bit and large for 64-bit.
codeModel = llvm : : CodeModel : : JITDefault ;
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 ) ) ;
2016-02-24 11:15:21 +08:00
2016-02-13 07:55:13 +08:00
m_strip_underscore = ( m_execution_engine_ap - > getDataLayout ( ) . getGlobalPrefix ( ) = = ' _ ' ) ;
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 ;
2016-02-24 11:15:21 +08:00
2015-01-28 02:03:05 +08:00
ss . PutCString ( " Couldn't lookup symbols: \n " ) ;
2016-02-24 11:15:21 +08:00
2015-01-28 02:03:05 +08:00
bool emitNewLine = false ;
2016-02-24 11:15:21 +08:00
2015-01-28 02:03:05 +08:00
for ( const ConstString & failed_lookup : m_failed_lookups )
{
if ( emitNewLine )
ss . PutCString ( " \n " ) ;
emitNewLine = true ;
ss . PutCString ( " " ) ;
2015-07-09 06:32:23 +08:00
ss . PutCString ( Mangled ( failed_lookup ) . GetDemangledName ( lldb : : eLanguageTypeObjC_plus_plus ) . AsCString ( ) ) ;
2015-01-28 02:03:05 +08:00
}
2016-02-24 11:15:21 +08:00
2015-01-28 02:03:05 +08:00
m_failed_lookups . clear ( ) ;
2016-02-24 11:15:21 +08:00
2015-01-28 02:03:05 +08:00
error . SetErrorString ( ss . GetData ( ) ) ;
2016-02-24 11:15:21 +08:00
2015-01-28 02:03:05 +08:00
return ;
}
2016-02-24 11:15:21 +08:00
2015-01-28 02:03:05 +08:00
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 ) ;
}
}
2015-10-23 08:39:09 +08:00
else
{
record . dump ( log ) ;
2016-02-24 11:15:21 +08:00
2015-10-23 08:39:09 +08:00
DataExtractor my_extractor ( ( const void * ) record . m_host_address , record . m_size , lldb : : eByteOrderBig , 8 ) ;
my_extractor . PutToLog ( log , 0 , record . m_size , record . m_host_address , 16 , DataExtractor : : TypeUInt8 ) ;
}
2014-01-21 08:54:48 +08:00
}
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 ;
2015-08-25 19:45:58 +08:00
else if ( dwarf_name . equals ( " addr " ) )
sect_type = lldb : : eSectionTypeDWARFDebugAddr ;
2014-03-25 07:10:19 +08:00
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 ;
2015-08-25 19:45:58 +08:00
else if ( dwarf_name . equals ( " str_offsets " ) )
sect_type = lldb : : eSectionTypeDWARFDebugStrOffsets ;
2014-03-25 07:10:19 +08:00
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
2015-05-13 08:25:54 +08:00
uint32_t permissions = lldb : : ePermissionsReadable ;
if ( ! IsReadOnly )
permissions | = lldb : : ePermissionsWritable ;
2013-04-05 10:22:57 +08:00
m_parent . m_records . push_back ( AllocationRecord ( ( uintptr_t ) return_value ,
2015-05-13 08:25:54 +08:00
permissions ,
2014-03-25 07:10:19 +08:00
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
}
2016-02-13 05:11:25 +08:00
static ConstString
FindBestAlternateMangledName ( const ConstString & demangled ,
const lldb : : LanguageType & lang_type ,
const SymbolContext & sym_ctx )
{
CPlusPlusLanguage : : MethodName cpp_name ( demangled ) ;
std : : string scope_qualified_name = cpp_name . GetScopeQualifiedName ( ) ;
if ( ! scope_qualified_name . size ( ) )
return ConstString ( ) ;
if ( ! sym_ctx . module_sp )
return ConstString ( ) ;
SymbolVendor * sym_vendor = sym_ctx . module_sp - > GetSymbolVendor ( ) ;
if ( ! sym_vendor )
return ConstString ( ) ;
lldb_private : : SymbolFile * sym_file = sym_vendor - > GetSymbolFile ( ) ;
if ( ! sym_file )
return ConstString ( ) ;
std : : vector < ConstString > alternates ;
sym_file - > GetMangledNamesForFunction ( scope_qualified_name , alternates ) ;
std : : vector < ConstString > param_and_qual_matches ;
std : : vector < ConstString > param_matches ;
for ( size_t i = 0 ; i < alternates . size ( ) ; i + + )
{
ConstString alternate_mangled_name = alternates [ i ] ;
Mangled mangled ( alternate_mangled_name , true ) ;
ConstString demangled = mangled . GetDemangledName ( lang_type ) ;
CPlusPlusLanguage : : MethodName alternate_cpp_name ( demangled ) ;
if ( ! cpp_name . IsValid ( ) )
continue ;
if ( alternate_cpp_name . GetArguments ( ) = = cpp_name . GetArguments ( ) )
{
if ( alternate_cpp_name . GetQualifiers ( ) = = cpp_name . GetQualifiers ( ) )
param_and_qual_matches . push_back ( alternate_mangled_name ) ;
else
param_matches . push_back ( alternate_mangled_name ) ;
}
}
if ( param_and_qual_matches . size ( ) )
return param_and_qual_matches [ 0 ] ; // It is assumed that there will be only one!
else if ( param_matches . size ( ) )
return param_matches [ 0 ] ; // Return one of them as a best match
else
return ConstString ( ) ;
}
2016-02-13 07:55:13 +08:00
struct IRExecutionUnit : : SearchSpec
2016-02-13 05:11:25 +08:00
{
ConstString name ;
uint32_t mask ;
SearchSpec ( ConstString n , uint32_t m = lldb : : eFunctionNameTypeAuto ) :
name ( n ) ,
mask ( m )
{
}
} ;
2016-02-13 07:55:13 +08:00
void
IRExecutionUnit : : CollectCandidateCNames ( std : : vector < IRExecutionUnit : : SearchSpec > & C_specs , const ConstString & name )
2016-02-13 05:11:25 +08:00
{
2016-02-13 07:55:13 +08:00
if ( m_strip_underscore & & name . AsCString ( ) [ 0 ] = = ' _ ' )
C_specs . insert ( C_specs . begin ( ) , ConstString ( & name . AsCString ( ) [ 1 ] ) ) ;
2016-02-13 05:11:25 +08:00
C_specs . push_back ( SearchSpec ( name ) ) ;
}
2016-02-13 07:55:13 +08:00
void
IRExecutionUnit : : CollectCandidateCPlusPlusNames ( std : : vector < IRExecutionUnit : : SearchSpec > & CPP_specs , const std : : vector < SearchSpec > & C_specs , const SymbolContext & sc )
2016-02-13 05:11:25 +08:00
{
for ( const SearchSpec & C_spec : C_specs )
{
const ConstString & name = C_spec . name ;
if ( CPlusPlusLanguage : : IsCPPMangledName ( name . GetCString ( ) ) )
{
Mangled mangled ( name , true ) ;
ConstString demangled = mangled . GetDemangledName ( lldb : : eLanguageTypeC_plus_plus ) ;
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
if ( demangled )
{
ConstString best_alternate_mangled_name = FindBestAlternateMangledName ( demangled , lldb : : eLanguageTypeC_plus_plus , sc ) ;
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
if ( best_alternate_mangled_name )
{
CPP_specs . push_back ( best_alternate_mangled_name ) ;
}
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
CPP_specs . push_back ( SearchSpec ( demangled , lldb : : eFunctionNameTypeFull ) ) ;
}
}
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
// Maybe we're looking for a const symbol but the debug info told us it was const...
if ( ! strncmp ( name . GetCString ( ) , " _ZN " , 3 ) & &
strncmp ( name . GetCString ( ) , " _ZNK " , 4 ) )
{
std : : string fixed_scratch ( " _ZNK " ) ;
fixed_scratch . append ( name . GetCString ( ) + 3 ) ;
CPP_specs . push_back ( ConstString ( fixed_scratch . c_str ( ) ) ) ;
}
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
// Maybe we're looking for a static symbol but we thought it was global...
if ( ! strncmp ( name . GetCString ( ) , " _Z " , 2 ) & &
strncmp ( name . GetCString ( ) , " _ZL " , 3 ) )
{
std : : string fixed_scratch ( " _ZL " ) ;
fixed_scratch . append ( name . GetCString ( ) + 2 ) ;
CPP_specs . push_back ( ConstString ( fixed_scratch . c_str ( ) ) ) ;
}
}
}
2016-02-13 07:55:13 +08:00
lldb : : addr_t
IRExecutionUnit : : FindInSymbols ( const std : : vector < IRExecutionUnit : : SearchSpec > & specs , const lldb_private : : SymbolContext & sc )
2016-02-13 05:11:25 +08:00
{
2016-02-24 07:09:06 +08:00
Target * target = sc . target_sp . get ( ) ;
if ( ! target )
{
// we shouldn't be doing any symbol lookup at all without a target
return LLDB_INVALID_ADDRESS ;
}
2016-02-13 05:11:25 +08:00
for ( const SearchSpec & spec : specs )
{
SymbolContextList sc_list ;
2016-02-24 07:09:06 +08:00
lldb : : addr_t best_internal_load_address = LLDB_INVALID_ADDRESS ;
std : : function < bool ( lldb : : addr_t & , SymbolContextList & , const lldb_private : : SymbolContext & ) > get_external_load_address =
[ & best_internal_load_address , target ] ( lldb : : addr_t & load_address ,
SymbolContextList & sc_list ,
const lldb_private : : SymbolContext & sc ) - > lldb : : addr_t
{
load_address = LLDB_INVALID_ADDRESS ;
for ( size_t si = 0 , se = sc_list . GetSize ( ) ; si < se ; + + si )
{
SymbolContext candidate_sc ;
sc_list . GetContextAtIndex ( si , candidate_sc ) ;
const bool is_external = ( candidate_sc . function ) | |
( candidate_sc . symbol & & candidate_sc . symbol - > IsExternal ( ) ) ;
2016-03-10 06:05:17 +08:00
if ( candidate_sc . symbol )
{
load_address = candidate_sc . symbol - > ResolveCallableAddress ( * target ) ;
2016-02-24 07:09:06 +08:00
2016-03-10 06:05:17 +08:00
if ( load_address = = LLDB_INVALID_ADDRESS )
{
if ( target - > GetProcessSP ( ) )
load_address = candidate_sc . symbol - > GetAddress ( ) . GetLoadAddress ( target ) ;
else
load_address = candidate_sc . symbol - > GetAddress ( ) . GetFileAddress ( ) ;
}
}
2016-02-24 07:09:06 +08:00
2016-03-10 06:05:17 +08:00
if ( load_address = = LLDB_INVALID_ADDRESS & & candidate_sc . function )
2016-03-04 19:26:56 +08:00
{
2016-03-10 06:05:17 +08:00
if ( target - > GetProcessSP ( ) )
load_address = candidate_sc . function - > GetAddressRange ( ) . GetBaseAddress ( ) . GetLoadAddress ( target ) ;
else
load_address = candidate_sc . function - > GetAddressRange ( ) . GetBaseAddress ( ) . GetFileAddress ( ) ;
2016-03-04 19:26:56 +08:00
}
2016-02-24 07:09:06 +08:00
2016-02-24 11:15:21 +08:00
if ( load_address ! = LLDB_INVALID_ADDRESS )
{
if ( is_external )
2016-02-24 07:09:06 +08:00
{
2016-02-24 11:15:21 +08:00
return true ;
}
else if ( best_internal_load_address = = LLDB_INVALID_ADDRESS )
{
best_internal_load_address = load_address ;
load_address = LLDB_INVALID_ADDRESS ;
2016-02-24 07:09:06 +08:00
}
}
}
return false ;
} ;
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
if ( sc . module_sp )
{
sc . module_sp - > FindFunctions ( spec . name ,
NULL ,
spec . mask ,
true , // include_symbols
false , // include_inlines
true , // append
sc_list ) ;
}
2016-02-24 07:09:06 +08:00
lldb : : addr_t load_address = LLDB_INVALID_ADDRESS ;
if ( get_external_load_address ( load_address , sc_list , sc ) )
{
return load_address ;
}
else
{
sc_list . Clear ( ) ;
}
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
if ( sc_list . GetSize ( ) = = 0 & & sc . target_sp )
{
sc . target_sp - > GetImages ( ) . FindFunctions ( spec . name ,
spec . mask ,
true , // include_symbols
false , // include_inlines
true , // append
sc_list ) ;
}
2016-02-24 11:15:21 +08:00
2016-02-24 07:09:06 +08:00
if ( get_external_load_address ( load_address , sc_list , sc ) )
{
return load_address ;
}
else
{
sc_list . Clear ( ) ;
}
2016-02-13 05:11:25 +08:00
if ( sc_list . GetSize ( ) = = 0 & & sc . target_sp )
{
sc . target_sp - > GetImages ( ) . FindSymbolsWithNameAndType ( spec . name , lldb : : eSymbolTypeAny , sc_list ) ;
}
2016-02-24 07:09:06 +08:00
if ( get_external_load_address ( load_address , sc_list , sc ) )
2016-02-13 05:11:25 +08:00
{
2016-02-24 07:09:06 +08:00
return load_address ;
2016-02-13 05:11:25 +08:00
}
2016-02-24 07:09:06 +08:00
// if there are any searches we try after this, add an sc_list.Clear() in an "else" clause here
2016-02-13 05:11:25 +08:00
if ( best_internal_load_address ! = LLDB_INVALID_ADDRESS )
{
return best_internal_load_address ;
}
}
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
return LLDB_INVALID_ADDRESS ;
}
2016-02-13 07:55:13 +08:00
lldb : : addr_t
IRExecutionUnit : : FindInRuntimes ( const std : : vector < SearchSpec > & specs , const lldb_private : : SymbolContext & sc )
2016-02-13 05:11:25 +08:00
{
lldb : : TargetSP target_sp = sc . target_sp ;
2016-02-24 11:15:21 +08:00
2015-01-28 02:03:05 +08:00
if ( ! target_sp )
{
2016-02-13 05:11:25 +08:00
return LLDB_INVALID_ADDRESS ;
2015-01-28 02:03:05 +08:00
}
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
lldb : : ProcessSP process_sp = sc . target_sp - > GetProcessSP ( ) ;
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
if ( ! process_sp )
2015-01-28 02:03:05 +08:00
{
2016-02-13 05:11:25 +08:00
return LLDB_INVALID_ADDRESS ;
2015-01-28 02:03:05 +08:00
}
2016-02-13 05:11:25 +08:00
ObjCLanguageRuntime * runtime = process_sp - > GetObjCLanguageRuntime ( ) ;
if ( runtime )
2015-01-28 02:03:05 +08:00
{
2016-02-13 05:11:25 +08:00
for ( const SearchSpec & spec : specs )
{
lldb : : addr_t symbol_load_addr = runtime - > LookupRuntimeSymbol ( spec . name ) ;
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
if ( symbol_load_addr ! = LLDB_INVALID_ADDRESS )
return symbol_load_addr ;
}
2015-01-28 02:03:05 +08:00
}
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
return LLDB_INVALID_ADDRESS ;
}
2015-07-03 00:43:49 +08:00
2016-02-13 05:11:25 +08:00
lldb : : addr_t
2016-02-13 07:55:13 +08:00
IRExecutionUnit : : FindSymbol ( const lldb_private : : ConstString & name )
2016-02-13 05:11:25 +08:00
{
std : : vector < SearchSpec > candidate_C_names ;
std : : vector < SearchSpec > candidate_CPlusPlus_names ;
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
CollectCandidateCNames ( candidate_C_names , name ) ;
2016-02-13 07:55:13 +08:00
lldb : : addr_t ret = FindInSymbols ( candidate_C_names , m_sym_ctx ) ;
2016-02-13 05:11:25 +08:00
if ( ret = = LLDB_INVALID_ADDRESS )
2016-02-13 07:55:13 +08:00
ret = FindInRuntimes ( candidate_C_names , m_sym_ctx ) ;
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
if ( ret = = LLDB_INVALID_ADDRESS )
2015-01-28 02:03:05 +08:00
{
2016-02-13 07:55:13 +08:00
CollectCandidateCPlusPlusNames ( candidate_CPlusPlus_names , candidate_C_names , m_sym_ctx ) ;
ret = FindInSymbols ( candidate_CPlusPlus_names , m_sym_ctx ) ;
2015-01-28 02:03:05 +08:00
}
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
return ret ;
}
uint64_t
IRExecutionUnit : : MemoryManager : : getSymbolAddress ( const std : : string & Name )
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
ConstString name_cs ( Name . c_str ( ) ) ;
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
lldb : : addr_t ret = m_parent . FindSymbol ( name_cs ) ;
2016-02-24 11:15:21 +08:00
2016-02-13 05:11:25 +08:00
if ( ret = = LLDB_INVALID_ADDRESS )
2015-01-28 02:03:05 +08:00
{
if ( log )
log - > Printf ( " IRExecutionUnit::getSymbolAddress(Name= \" %s \" ) = <not found> " ,
2016-02-13 05:11:25 +08:00
Name . c_str ( ) ) ;
m_parent . ReportSymbolLookupError ( name_cs ) ;
2015-01-28 02:03:05 +08:00
return 0xbad0bad0 ;
}
2016-02-13 05:11:25 +08:00
else
{
if ( log )
log - > Printf ( " IRExecutionUnit::getSymbolAddress(Name= \" %s \" ) = % " PRIx64 ,
Name . c_str ( ) ,
ret ) ;
return ret ;
}
2015-01-28 02:03:05 +08:00
}
void *
IRExecutionUnit : : MemoryManager : : getPointerToNamedFunction ( const std : : string & Name ,
bool AbortOnFailure ) {
assert ( sizeof ( void * ) = = 8 ) ;
2016-02-24 11:15:21 +08:00
2015-01-28 02:03:05 +08:00
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 :
2015-08-25 19:45:58 +08:00
case lldb : : eSectionTypeDWARFDebugAddr :
2014-03-25 07:10:19 +08:00
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 :
2015-08-25 19:45:58 +08:00
case lldb : : eSectionTypeDWARFDebugStrOffsets :
2014-03-25 07:10:19 +08:00
case lldb : : eSectionTypeDWARFAppleNames :
case lldb : : eSectionTypeDWARFAppleTypes :
case lldb : : eSectionTypeDWARFAppleNamespaces :
case lldb : : eSectionTypeDWARFAppleObjC :
err . Clear ( ) ;
break ;
default :
2015-11-05 04:32:27 +08:00
const bool zero_memory = false ;
2014-03-25 07:10:19 +08:00
record . m_process_address = Malloc ( record . m_size ,
record . m_alignment ,
record . m_permissions ,
eAllocationPolicyProcessOnly ,
2015-11-05 04:32:27 +08:00
zero_memory ,
2014-03-25 07:10:19 +08:00
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
2015-10-23 08:39:09 +08:00
log - > Printf ( " [0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d, name %s) " ,
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 ,
2015-10-23 08:39:09 +08:00
( unsigned ) m_section_id ,
m_name . c_str ( ) ) ;
2013-03-19 08:10:07 +08:00
}
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 ( ) ;
}