2013-08-23 13:46:38 -04:00
//===-- CommandObjectTarget.cpp ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "lldb/lldb-python.h"
# include "CommandObjectTarget.h"
// C Includes
# include <errno.h>
// C++ Includes
// Other libraries and framework includes
// Project includes
# include "lldb/Interpreter/Args.h"
# include "lldb/Core/Debugger.h"
2014-02-18 11:23:10 -05:00
# include "lldb/Core/IOHandler.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Core/Module.h"
# include "lldb/Core/ModuleSpec.h"
# include "lldb/Core/Section.h"
# include "lldb/Core/State.h"
# include "lldb/Core/Timer.h"
# include "lldb/Core/ValueObjectVariable.h"
2013-11-06 11:48:53 -05:00
# include "lldb/DataFormatters/ValueObjectPrinter.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Host/Symbols.h"
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Interpreter/CommandReturnObject.h"
# include "lldb/Interpreter/Options.h"
# include "lldb/Interpreter/OptionGroupArchitecture.h"
# include "lldb/Interpreter/OptionGroupBoolean.h"
# include "lldb/Interpreter/OptionGroupFile.h"
# include "lldb/Interpreter/OptionGroupFormat.h"
# include "lldb/Interpreter/OptionGroupVariable.h"
# include "lldb/Interpreter/OptionGroupPlatform.h"
# include "lldb/Interpreter/OptionGroupUInt64.h"
# include "lldb/Interpreter/OptionGroupUUID.h"
# include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
# include "lldb/Symbol/CompileUnit.h"
# include "lldb/Symbol/FuncUnwinders.h"
# include "lldb/Symbol/LineTable.h"
# include "lldb/Symbol/ObjectFile.h"
# include "lldb/Symbol/SymbolFile.h"
# include "lldb/Symbol/SymbolVendor.h"
# include "lldb/Symbol/UnwindPlan.h"
# include "lldb/Symbol/VariableList.h"
# include "lldb/Target/Process.h"
2014-02-18 11:23:10 -05:00
# include "lldb/Target/SectionLoadList.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Target/StackFrame.h"
# include "lldb/Target/Thread.h"
# include "lldb/Target/ThreadSpec.h"
using namespace lldb ;
using namespace lldb_private ;
static void
DumpTargetInfo ( uint32_t target_idx , Target * target , const char * prefix_cstr , bool show_stopped_process_status , Stream & strm )
{
const ArchSpec & target_arch = target - > GetArchitecture ( ) ;
Module * exe_module = target - > GetExecutableModulePointer ( ) ;
char exe_path [ PATH_MAX ] ;
bool exe_valid = false ;
if ( exe_module )
exe_valid = exe_module - > GetFileSpec ( ) . GetPath ( exe_path , sizeof ( exe_path ) ) ;
if ( ! exe_valid )
: : strcpy ( exe_path , " <none> " ) ;
strm . Printf ( " %starget #%u: %s " , prefix_cstr ? prefix_cstr : " " , target_idx , exe_path ) ;
uint32_t properties = 0 ;
if ( target_arch . IsValid ( ) )
{
strm . Printf ( " %sarch=%s " , properties + + > 0 ? " , " : " ( " , target_arch . GetTriple ( ) . str ( ) . c_str ( ) ) ;
properties + + ;
}
PlatformSP platform_sp ( target - > GetPlatform ( ) ) ;
if ( platform_sp )
strm . Printf ( " %splatform=%s " , properties + + > 0 ? " , " : " ( " , platform_sp - > GetName ( ) . GetCString ( ) ) ;
ProcessSP process_sp ( target - > GetProcessSP ( ) ) ;
bool show_process_status = false ;
if ( process_sp )
{
lldb : : pid_t pid = process_sp - > GetID ( ) ;
StateType state = process_sp - > GetState ( ) ;
if ( show_stopped_process_status )
show_process_status = StateIsStoppedState ( state , true ) ;
const char * state_cstr = StateAsCString ( state ) ;
if ( pid ! = LLDB_INVALID_PROCESS_ID )
strm . Printf ( " %spid=% " PRIu64 , properties + + > 0 ? " , " : " ( " , pid ) ;
strm . Printf ( " %sstate=%s " , properties + + > 0 ? " , " : " ( " , state_cstr ) ;
}
if ( properties > 0 )
strm . PutCString ( " ) \n " ) ;
else
strm . EOL ( ) ;
if ( show_process_status )
{
const bool only_threads_with_stop_reason = true ;
const uint32_t start_frame = 0 ;
const uint32_t num_frames = 1 ;
const uint32_t num_frames_with_source = 1 ;
process_sp - > GetStatus ( strm ) ;
process_sp - > GetThreadStatus ( strm ,
only_threads_with_stop_reason ,
start_frame ,
num_frames ,
num_frames_with_source ) ;
}
}
static uint32_t
DumpTargetList ( TargetList & target_list , bool show_stopped_process_status , Stream & strm )
{
const uint32_t num_targets = target_list . GetNumTargets ( ) ;
if ( num_targets )
{
TargetSP selected_target_sp ( target_list . GetSelectedTarget ( ) ) ;
strm . PutCString ( " Current targets: \n " ) ;
for ( uint32_t i = 0 ; i < num_targets ; + + i )
{
TargetSP target_sp ( target_list . GetTargetAtIndex ( i ) ) ;
if ( target_sp )
{
bool is_selected = target_sp . get ( ) = = selected_target_sp . get ( ) ;
DumpTargetInfo ( i ,
target_sp . get ( ) ,
is_selected ? " * " : " " ,
show_stopped_process_status ,
strm ) ;
}
}
}
return num_targets ;
}
# pragma mark CommandObjectTargetCreate
//-------------------------------------------------------------------------
// "target create"
//-------------------------------------------------------------------------
class CommandObjectTargetCreate : public CommandObjectParsed
{
public :
CommandObjectTargetCreate ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target create " ,
" Create a target using the argument as the main executable. " ,
NULL ) ,
m_option_group ( interpreter ) ,
m_arch_option ( ) ,
m_platform_options ( true ) , // Do include the "--platform" option in the platform settings by passing true
m_core_file ( LLDB_OPT_SET_1 , false , " core " , ' c ' , 0 , eArgTypeFilename , " Fullpath to a core file to use for this target. " ) ,
2013-11-06 11:48:53 -05:00
m_platform_path ( LLDB_OPT_SET_1 , false , " platform-path " , ' P ' , 0 , eArgTypePath , " Path to the remote file to use for this target. " ) ,
2013-08-23 13:46:38 -04:00
m_symbol_file ( LLDB_OPT_SET_1 , false , " symfile " , ' s ' , 0 , eArgTypeFilename , " Fullpath to a stand alone debug symbols file for when debug symbols are not in the executable. " ) ,
m_remote_file ( LLDB_OPT_SET_1 , false , " remote-file " , ' r ' , 0 , eArgTypeFilename , " Fullpath to the file on the remote host if debugging remotely. " ) ,
m_add_dependents ( LLDB_OPT_SET_1 , false , " no-dependents " , ' d ' , " Don't load dependent files when creating the target, just add the specified executable. " , true , true )
{
CommandArgumentEntry arg ;
CommandArgumentData file_arg ;
// Define the first (and only) variant of this arg.
file_arg . arg_type = eArgTypeFilename ;
file_arg . arg_repetition = eArgRepeatPlain ;
// There is only one variant this argument could be; put it into the argument entry.
arg . push_back ( file_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
m_option_group . Append ( & m_arch_option , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_platform_options , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_core_file , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
2013-11-06 11:48:53 -05:00
m_option_group . Append ( & m_platform_path , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
2013-08-23 13:46:38 -04:00
m_option_group . Append ( & m_symbol_file , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_remote_file , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_add_dependents , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Finalize ( ) ;
}
~ CommandObjectTargetCreate ( )
{
}
Options *
GetOptions ( )
{
return & m_option_group ;
}
virtual int
HandleArgumentCompletion ( Args & input ,
int & cursor_index ,
int & cursor_char_position ,
OptionElementVector & opt_element_vector ,
int match_start_point ,
int max_return_elements ,
bool & word_complete ,
StringList & matches )
{
std : : string completion_str ( input . GetArgumentAtIndex ( cursor_index ) ) ;
completion_str . erase ( cursor_char_position ) ;
CommandCompletions : : InvokeCommonCompletionCallbacks ( m_interpreter ,
CommandCompletions : : eDiskFileCompletion ,
completion_str . c_str ( ) ,
match_start_point ,
max_return_elements ,
NULL ,
word_complete ,
matches ) ;
return matches . GetSize ( ) ;
}
protected :
bool
DoExecute ( Args & command , CommandReturnObject & result )
{
const size_t argc = command . GetArgumentCount ( ) ;
FileSpec core_file ( m_core_file . GetOptionValue ( ) . GetCurrentValue ( ) ) ;
FileSpec remote_file ( m_remote_file . GetOptionValue ( ) . GetCurrentValue ( ) ) ;
2013-11-06 11:48:53 -05:00
if ( argc = = 1 | | core_file | | remote_file )
2013-08-23 13:46:38 -04:00
{
FileSpec symfile ( m_symbol_file . GetOptionValue ( ) . GetCurrentValue ( ) ) ;
if ( symfile )
{
if ( ! symfile . Exists ( ) )
{
char symfile_path [ PATH_MAX ] ;
symfile . GetPath ( symfile_path , sizeof ( symfile_path ) ) ;
result . AppendErrorWithFormat ( " invalid symbol file path '%s' " , symfile_path ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
const char * file_path = command . GetArgumentAtIndex ( 0 ) ;
Timer scoped_timer ( __PRETTY_FUNCTION__ , " (lldb) target create ' % s ' " , file_path) ;
2013-11-06 11:48:53 -05:00
FileSpec file_spec ;
if ( file_path )
file_spec . SetFile ( file_path , true ) ;
bool must_set_platform_path = false ;
2013-08-23 13:46:38 -04:00
Debugger & debugger = m_interpreter . GetDebugger ( ) ;
2013-11-06 11:48:53 -05:00
PlatformSP platform_sp ( debugger . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
if ( remote_file )
{
// I have a remote file.. two possible cases
if ( file_spec & & file_spec . Exists ( ) )
{
// if the remote file does not exist, push it there
if ( ! platform_sp - > GetFileExists ( remote_file ) )
{
Error err = platform_sp - > PutFile ( file_spec , remote_file ) ;
if ( err . Fail ( ) )
{
result . AppendError ( err . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
}
else
{
// there is no local file and we need one
// in order to make the remote ---> local transfer we need a platform
// TODO: if the user has passed in a --platform argument, use it to fetch the right platform
if ( ! platform_sp )
{
result . AppendError ( " unable to perform remote debugging without a platform " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( file_path )
{
// copy the remote file to the local file
Error err = platform_sp - > GetFile ( remote_file , file_spec ) ;
if ( err . Fail ( ) )
{
result . AppendError ( err . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else
{
// make up a local file
result . AppendError ( " remote --> local transfer without local path is not implemented yet " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
}
TargetSP target_sp ;
2013-08-23 13:46:38 -04:00
const char * arch_cstr = m_arch_option . GetArchitectureName ( ) ;
const bool get_dependent_files = m_add_dependents . GetOptionValue ( ) . GetCurrentValue ( ) ;
Error error ( debugger . GetTargetList ( ) . CreateTarget ( debugger ,
2013-11-06 11:48:53 -05:00
// remote_file ? remote_file : file_spec,
2013-08-23 13:46:38 -04:00
file_path ,
arch_cstr ,
get_dependent_files ,
& m_platform_options ,
target_sp ) ) ;
if ( target_sp )
{
if ( symfile | | remote_file )
{
ModuleSP module_sp ( target_sp - > GetExecutableModule ( ) ) ;
if ( module_sp )
{
if ( symfile )
module_sp - > SetSymbolFileFileSpec ( symfile ) ;
if ( remote_file )
{
std : : string remote_path = remote_file . GetPath ( ) ;
target_sp - > SetArg0 ( remote_path . c_str ( ) ) ;
module_sp - > SetPlatformFileSpec ( remote_file ) ;
}
}
}
debugger . GetTargetList ( ) . SetSelectedTarget ( target_sp . get ( ) ) ;
2013-11-06 11:48:53 -05:00
if ( must_set_platform_path )
{
ModuleSpec main_module_spec ( file_spec ) ;
ModuleSP module_sp = target_sp - > GetSharedModule ( main_module_spec ) ;
if ( module_sp )
module_sp - > SetPlatformFileSpec ( remote_file ) ;
}
2013-08-23 13:46:38 -04:00
if ( core_file )
{
char core_path [ PATH_MAX ] ;
core_file . GetPath ( core_path , sizeof ( core_path ) ) ;
if ( core_file . Exists ( ) )
{
FileSpec core_file_dir ;
core_file_dir . GetDirectory ( ) = core_file . GetDirectory ( ) ;
target_sp - > GetExecutableSearchPaths ( ) . Append ( core_file_dir ) ;
ProcessSP process_sp ( target_sp - > CreateProcess ( m_interpreter . GetDebugger ( ) . GetListener ( ) , NULL , & core_file ) ) ;
if ( process_sp )
{
// Seems wierd that we Launch a core file, but that is
// what we do!
error = process_sp - > LoadCore ( ) ;
if ( error . Fail ( ) )
{
result . AppendError ( error . AsCString ( " can't find plug-in for core file " ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else
{
result . AppendMessageWithFormat ( " Core file '%s' (%s) was loaded. \n " , core_path , target_sp - > GetArchitecture ( ) . GetArchitectureName ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
}
else
{
result . AppendErrorWithFormat ( " Unable to find process plug-in for core file '%s' \n " , core_path ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendErrorWithFormat ( " Core file '%s' does not exist \n " , core_path ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendMessageWithFormat ( " Current executable set to '%s' (%s). \n " , file_path , target_sp - > GetArchitecture ( ) . GetArchitectureName ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
}
else
{
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendErrorWithFormat ( " '%s' takes exactly one executable path argument, or use the --core-file option. \n " , m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
private :
OptionGroupOptions m_option_group ;
OptionGroupArchitecture m_arch_option ;
OptionGroupPlatform m_platform_options ;
OptionGroupFile m_core_file ;
2013-11-06 11:48:53 -05:00
OptionGroupFile m_platform_path ;
2013-08-23 13:46:38 -04:00
OptionGroupFile m_symbol_file ;
OptionGroupFile m_remote_file ;
OptionGroupBoolean m_add_dependents ;
} ;
# pragma mark CommandObjectTargetList
//----------------------------------------------------------------------
// "target list"
//----------------------------------------------------------------------
class CommandObjectTargetList : public CommandObjectParsed
{
public :
CommandObjectTargetList ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target list " ,
" List all current targets in the current debug session. " ,
NULL ,
0 )
{
}
virtual
~ CommandObjectTargetList ( )
{
}
protected :
virtual bool
DoExecute ( Args & args , CommandReturnObject & result )
{
if ( args . GetArgumentCount ( ) = = 0 )
{
Stream & strm = result . GetOutputStream ( ) ;
bool show_stopped_process_status = false ;
if ( DumpTargetList ( m_interpreter . GetDebugger ( ) . GetTargetList ( ) , show_stopped_process_status , strm ) = = 0 )
{
strm . PutCString ( " No targets. \n " ) ;
}
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
result . AppendError ( " the 'target list' command takes no arguments \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
} ;
# pragma mark CommandObjectTargetSelect
//----------------------------------------------------------------------
// "target select"
//----------------------------------------------------------------------
class CommandObjectTargetSelect : public CommandObjectParsed
{
public :
CommandObjectTargetSelect ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target select " ,
" Select a target as the current target by target index. " ,
NULL ,
0 )
{
}
virtual
~ CommandObjectTargetSelect ( )
{
}
protected :
virtual bool
DoExecute ( Args & args , CommandReturnObject & result )
{
if ( args . GetArgumentCount ( ) = = 1 )
{
bool success = false ;
const char * target_idx_arg = args . GetArgumentAtIndex ( 0 ) ;
uint32_t target_idx = Args : : StringToUInt32 ( target_idx_arg , UINT32_MAX , 0 , & success ) ;
if ( success )
{
TargetList & target_list = m_interpreter . GetDebugger ( ) . GetTargetList ( ) ;
const uint32_t num_targets = target_list . GetNumTargets ( ) ;
if ( target_idx < num_targets )
{
TargetSP target_sp ( target_list . GetTargetAtIndex ( target_idx ) ) ;
if ( target_sp )
{
Stream & strm = result . GetOutputStream ( ) ;
target_list . SetSelectedTarget ( target_sp . get ( ) ) ;
bool show_stopped_process_status = false ;
DumpTargetList ( target_list , show_stopped_process_status , strm ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
result . AppendErrorWithFormat ( " target #%u is NULL in target list \n " , target_idx ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendErrorWithFormat ( " index %u is out of range, valid target indexes are 0 - %u \n " ,
target_idx ,
num_targets - 1 ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendErrorWithFormat ( " invalid index string value '%s' \n " , target_idx_arg ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendError ( " 'target select' takes a single argument: a target index \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
} ;
# pragma mark CommandObjectTargetSelect
//----------------------------------------------------------------------
// "target delete"
//----------------------------------------------------------------------
class CommandObjectTargetDelete : public CommandObjectParsed
{
public :
CommandObjectTargetDelete ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target delete " ,
" Delete one or more targets by target index. " ,
NULL ,
0 ) ,
m_option_group ( interpreter ) ,
m_cleanup_option ( LLDB_OPT_SET_1 , false , " clean " , ' c ' , " Perform extra cleanup to minimize memory consumption after deleting the target. " , false , false )
{
m_option_group . Append ( & m_cleanup_option , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Finalize ( ) ;
}
virtual
~ CommandObjectTargetDelete ( )
{
}
Options *
GetOptions ( )
{
return & m_option_group ;
}
protected :
virtual bool
DoExecute ( Args & args , CommandReturnObject & result )
{
const size_t argc = args . GetArgumentCount ( ) ;
std : : vector < TargetSP > delete_target_list ;
TargetList & target_list = m_interpreter . GetDebugger ( ) . GetTargetList ( ) ;
bool success = true ;
TargetSP target_sp ;
if ( argc > 0 )
{
const uint32_t num_targets = target_list . GetNumTargets ( ) ;
// Bail out if don't have any targets.
if ( num_targets = = 0 ) {
result . AppendError ( " no targets to delete " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
success = false ;
}
for ( uint32_t arg_idx = 0 ; success & & arg_idx < argc ; + + arg_idx )
{
const char * target_idx_arg = args . GetArgumentAtIndex ( arg_idx ) ;
uint32_t target_idx = Args : : StringToUInt32 ( target_idx_arg , UINT32_MAX , 0 , & success ) ;
if ( success )
{
if ( target_idx < num_targets )
{
target_sp = target_list . GetTargetAtIndex ( target_idx ) ;
if ( target_sp )
{
delete_target_list . push_back ( target_sp ) ;
continue ;
}
}
if ( num_targets > 1 )
result . AppendErrorWithFormat ( " target index %u is out of range, valid target indexes are 0 - %u \n " ,
target_idx ,
num_targets - 1 ) ;
else
result . AppendErrorWithFormat ( " target index %u is out of range, the only valid index is 0 \n " ,
target_idx ) ;
result . SetStatus ( eReturnStatusFailed ) ;
success = false ;
}
else
{
result . AppendErrorWithFormat ( " invalid target index '%s' \n " , target_idx_arg ) ;
result . SetStatus ( eReturnStatusFailed ) ;
success = false ;
}
}
}
else
{
target_sp = target_list . GetSelectedTarget ( ) ;
if ( target_sp )
{
delete_target_list . push_back ( target_sp ) ;
}
else
{
result . AppendErrorWithFormat ( " no target is currently selected \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
success = false ;
}
}
if ( success )
{
const size_t num_targets_to_delete = delete_target_list . size ( ) ;
for ( size_t idx = 0 ; idx < num_targets_to_delete ; + + idx )
{
target_sp = delete_target_list [ idx ] ;
target_list . DeleteTarget ( target_sp ) ;
target_sp - > Destroy ( ) ;
}
// If "--clean" was specified, prune any orphaned shared modules from
// the global shared module list
if ( m_cleanup_option . GetOptionValue ( ) )
{
const bool mandatory = true ;
ModuleList : : RemoveOrphanSharedModules ( mandatory ) ;
}
result . GetOutputStream ( ) . Printf ( " %u targets deleted. \n " , ( uint32_t ) num_targets_to_delete ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
return result . Succeeded ( ) ;
}
OptionGroupOptions m_option_group ;
OptionGroupBoolean m_cleanup_option ;
} ;
# pragma mark CommandObjectTargetVariable
//----------------------------------------------------------------------
// "target variable"
//----------------------------------------------------------------------
class CommandObjectTargetVariable : public CommandObjectParsed
{
public :
CommandObjectTargetVariable ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target variable " ,
" Read global variable(s) prior to, or while running your binary. " ,
NULL ,
eFlagRequiresTarget ) ,
m_option_group ( interpreter ) ,
m_option_variable ( false ) , // Don't include frame options
m_option_format ( eFormatDefault ) ,
m_option_compile_units ( LLDB_OPT_SET_1 , false , " file " , ' file ' , 0 , eArgTypeFilename , " A basename or fullpath to a file that contains global variables. This option can be specified multiple times. " ) ,
m_option_shared_libraries ( LLDB_OPT_SET_1 , false , " shlib " , ' shlb ' , 0 , eArgTypeFilename , " A basename or fullpath to a shared library to use in the search for global variables. This option can be specified multiple times. " ) ,
m_varobj_options ( )
{
CommandArgumentEntry arg ;
CommandArgumentData var_name_arg ;
// Define the first (and only) variant of this arg.
var_name_arg . arg_type = eArgTypeVarName ;
var_name_arg . arg_repetition = eArgRepeatPlus ;
// There is only one variant this argument could be; put it into the argument entry.
arg . push_back ( var_name_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
m_option_group . Append ( & m_varobj_options , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_option_variable , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_option_format , OptionGroupFormat : : OPTION_GROUP_FORMAT | OptionGroupFormat : : OPTION_GROUP_GDB_FMT , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_option_compile_units , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_option_shared_libraries , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Finalize ( ) ;
}
virtual
~ CommandObjectTargetVariable ( )
{
}
void
DumpValueObject ( Stream & s , VariableSP & var_sp , ValueObjectSP & valobj_sp , const char * root_name )
{
2013-11-06 11:48:53 -05:00
DumpValueObjectOptions options ( m_varobj_options . GetAsDumpOptions ( ) ) ;
2013-08-23 13:46:38 -04:00
switch ( var_sp - > GetScope ( ) )
{
case eValueTypeVariableGlobal :
if ( m_option_variable . show_scope )
s . PutCString ( " GLOBAL: " ) ;
break ;
case eValueTypeVariableStatic :
if ( m_option_variable . show_scope )
s . PutCString ( " STATIC: " ) ;
break ;
case eValueTypeVariableArgument :
if ( m_option_variable . show_scope )
s . PutCString ( " ARG: " ) ;
break ;
case eValueTypeVariableLocal :
if ( m_option_variable . show_scope )
s . PutCString ( " LOCAL: " ) ;
break ;
default :
break ;
}
if ( m_option_variable . show_decl )
{
bool show_fullpaths = false ;
bool show_module = true ;
if ( var_sp - > DumpDeclaration ( & s , show_fullpaths , show_module ) )
s . PutCString ( " : " ) ;
}
const Format format = m_option_format . GetFormat ( ) ;
if ( format ! = eFormatDefault )
options . SetFormat ( format ) ;
options . SetRootValueObjectName ( root_name ) ;
2013-11-06 11:48:53 -05:00
valobj_sp - > Dump ( s , options ) ;
2013-08-23 13:46:38 -04:00
}
static size_t GetVariableCallback ( void * baton ,
const char * name ,
VariableList & variable_list )
{
Target * target = static_cast < Target * > ( baton ) ;
if ( target )
{
return target - > GetImages ( ) . FindGlobalVariables ( ConstString ( name ) ,
true ,
UINT32_MAX ,
variable_list ) ;
}
return 0 ;
}
Options *
GetOptions ( )
{
return & m_option_group ;
}
protected :
void
DumpGlobalVariableList ( const ExecutionContext & exe_ctx , const SymbolContext & sc , const VariableList & variable_list , Stream & s )
{
size_t count = variable_list . GetSize ( ) ;
if ( count > 0 )
{
if ( sc . module_sp )
{
if ( sc . comp_unit )
{
s . Printf ( " Global variables for %s in %s: \n " ,
sc . comp_unit - > GetPath ( ) . c_str ( ) ,
sc . module_sp - > GetFileSpec ( ) . GetPath ( ) . c_str ( ) ) ;
}
else
{
s . Printf ( " Global variables for %s \n " ,
sc . module_sp - > GetFileSpec ( ) . GetPath ( ) . c_str ( ) ) ;
}
}
else if ( sc . comp_unit )
{
s . Printf ( " Global variables for %s \n " ,
sc . comp_unit - > GetPath ( ) . c_str ( ) ) ;
}
for ( uint32_t i = 0 ; i < count ; + + i )
{
VariableSP var_sp ( variable_list . GetVariableAtIndex ( i ) ) ;
if ( var_sp )
{
ValueObjectSP valobj_sp ( ValueObjectVariable : : Create ( exe_ctx . GetBestExecutionContextScope ( ) , var_sp ) ) ;
if ( valobj_sp )
DumpValueObject ( s , var_sp , valobj_sp , var_sp - > GetName ( ) . GetCString ( ) ) ;
}
}
}
}
virtual bool
DoExecute ( Args & args , CommandReturnObject & result )
{
Target * target = m_exe_ctx . GetTargetPtr ( ) ;
const size_t argc = args . GetArgumentCount ( ) ;
Stream & s = result . GetOutputStream ( ) ;
if ( argc > 0 )
{
for ( size_t idx = 0 ; idx < argc ; + + idx )
{
VariableList variable_list ;
ValueObjectList valobj_list ;
const char * arg = args . GetArgumentAtIndex ( idx ) ;
size_t matches = 0 ;
bool use_var_name = false ;
if ( m_option_variable . use_regex )
{
RegularExpression regex ( arg ) ;
if ( ! regex . IsValid ( ) )
{
result . GetErrorStream ( ) . Printf ( " error: invalid regular expression: '%s' \n " , arg ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
use_var_name = true ;
matches = target - > GetImages ( ) . FindGlobalVariables ( regex ,
true ,
UINT32_MAX ,
variable_list ) ;
}
else
{
Error error ( Variable : : GetValuesForVariableExpressionPath ( arg ,
m_exe_ctx . GetBestExecutionContextScope ( ) ,
GetVariableCallback ,
target ,
variable_list ,
valobj_list ) ) ;
matches = variable_list . GetSize ( ) ;
}
if ( matches = = 0 )
{
result . GetErrorStream ( ) . Printf ( " error: can't find global variable '%s' \n " , arg ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else
{
for ( uint32_t global_idx = 0 ; global_idx < matches ; + + global_idx )
{
VariableSP var_sp ( variable_list . GetVariableAtIndex ( global_idx ) ) ;
if ( var_sp )
{
ValueObjectSP valobj_sp ( valobj_list . GetValueObjectAtIndex ( global_idx ) ) ;
if ( ! valobj_sp )
valobj_sp = ValueObjectVariable : : Create ( m_exe_ctx . GetBestExecutionContextScope ( ) , var_sp ) ;
if ( valobj_sp )
DumpValueObject ( s , var_sp , valobj_sp , use_var_name ? var_sp - > GetName ( ) . GetCString ( ) : arg ) ;
}
}
}
}
}
else
{
const FileSpecList & compile_units = m_option_compile_units . GetOptionValue ( ) . GetCurrentValue ( ) ;
const FileSpecList & shlibs = m_option_shared_libraries . GetOptionValue ( ) . GetCurrentValue ( ) ;
SymbolContextList sc_list ;
const size_t num_compile_units = compile_units . GetSize ( ) ;
const size_t num_shlibs = shlibs . GetSize ( ) ;
if ( num_compile_units = = 0 & & num_shlibs = = 0 )
{
bool success = false ;
StackFrame * frame = m_exe_ctx . GetFramePtr ( ) ;
CompileUnit * comp_unit = NULL ;
if ( frame )
{
SymbolContext sc = frame - > GetSymbolContext ( eSymbolContextCompUnit ) ;
if ( sc . comp_unit )
{
const bool can_create = true ;
VariableListSP comp_unit_varlist_sp ( sc . comp_unit - > GetVariableList ( can_create ) ) ;
if ( comp_unit_varlist_sp )
{
size_t count = comp_unit_varlist_sp - > GetSize ( ) ;
if ( count > 0 )
{
DumpGlobalVariableList ( m_exe_ctx , sc , * comp_unit_varlist_sp , s ) ;
success = true ;
}
}
}
}
if ( ! success )
{
if ( frame )
{
if ( comp_unit )
result . AppendErrorWithFormat ( " no global variables in current compile unit: %s \n " ,
comp_unit - > GetPath ( ) . c_str ( ) ) ;
else
result . AppendErrorWithFormat ( " no debug information for frame %u \n " , frame - > GetFrameIndex ( ) ) ;
}
else
result . AppendError ( " 'target variable' takes one or more global variable names as arguments \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
SymbolContextList sc_list ;
const bool append = true ;
// We have one or more compile unit or shlib
if ( num_shlibs > 0 )
{
for ( size_t shlib_idx = 0 ; shlib_idx < num_shlibs ; + + shlib_idx )
{
const FileSpec module_file ( shlibs . GetFileSpecAtIndex ( shlib_idx ) ) ;
ModuleSpec module_spec ( module_file ) ;
ModuleSP module_sp ( target - > GetImages ( ) . FindFirstModule ( module_spec ) ) ;
if ( module_sp )
{
if ( num_compile_units > 0 )
{
for ( size_t cu_idx = 0 ; cu_idx < num_compile_units ; + + cu_idx )
module_sp - > FindCompileUnits ( compile_units . GetFileSpecAtIndex ( cu_idx ) , append , sc_list ) ;
}
else
{
SymbolContext sc ;
sc . module_sp = module_sp ;
sc_list . Append ( sc ) ;
}
}
else
{
// Didn't find matching shlib/module in target...
result . AppendErrorWithFormat ( " target doesn't contain the specified shared library: %s \n " ,
module_file . GetPath ( ) . c_str ( ) ) ;
}
}
}
else
{
// No shared libraries, we just want to find globals for the compile units files that were specified
for ( size_t cu_idx = 0 ; cu_idx < num_compile_units ; + + cu_idx )
target - > GetImages ( ) . FindCompileUnits ( compile_units . GetFileSpecAtIndex ( cu_idx ) , append , sc_list ) ;
}
const uint32_t num_scs = sc_list . GetSize ( ) ;
if ( num_scs > 0 )
{
SymbolContext sc ;
for ( uint32_t sc_idx = 0 ; sc_idx < num_scs ; + + sc_idx )
{
if ( sc_list . GetContextAtIndex ( sc_idx , sc ) )
{
if ( sc . comp_unit )
{
const bool can_create = true ;
VariableListSP comp_unit_varlist_sp ( sc . comp_unit - > GetVariableList ( can_create ) ) ;
if ( comp_unit_varlist_sp )
DumpGlobalVariableList ( m_exe_ctx , sc , * comp_unit_varlist_sp , s ) ;
}
else if ( sc . module_sp )
{
// Get all global variables for this module
lldb_private : : RegularExpression all_globals_regex ( " . " ) ; // Any global with at least one character
VariableList variable_list ;
sc . module_sp - > FindGlobalVariables ( all_globals_regex , append , UINT32_MAX , variable_list ) ;
DumpGlobalVariableList ( m_exe_ctx , sc , variable_list , s ) ;
}
}
}
}
}
}
if ( m_interpreter . TruncationWarningNecessary ( ) )
{
result . GetOutputStream ( ) . Printf ( m_interpreter . TruncationWarningText ( ) ,
m_cmd_name . c_str ( ) ) ;
m_interpreter . TruncationWarningGiven ( ) ;
}
return result . Succeeded ( ) ;
}
OptionGroupOptions m_option_group ;
OptionGroupVariable m_option_variable ;
OptionGroupFormat m_option_format ;
OptionGroupFileList m_option_compile_units ;
OptionGroupFileList m_option_shared_libraries ;
OptionGroupValueObjectDisplay m_varobj_options ;
} ;
# pragma mark CommandObjectTargetModulesSearchPathsAdd
class CommandObjectTargetModulesSearchPathsAdd : public CommandObjectParsed
{
public :
CommandObjectTargetModulesSearchPathsAdd ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target modules search-paths add " ,
" Add new image search paths substitution pairs to the current target. " ,
NULL )
{
CommandArgumentEntry arg ;
CommandArgumentData old_prefix_arg ;
CommandArgumentData new_prefix_arg ;
// Define the first variant of this arg pair.
old_prefix_arg . arg_type = eArgTypeOldPathPrefix ;
old_prefix_arg . arg_repetition = eArgRepeatPairPlus ;
// Define the first variant of this arg pair.
new_prefix_arg . arg_type = eArgTypeNewPathPrefix ;
new_prefix_arg . arg_repetition = eArgRepeatPairPlus ;
// There are two required arguments that must always occur together, i.e. an argument "pair". Because they
// must always occur together, they are treated as two variants of one argument rather than two independent
// arguments. Push them both into the first argument position for m_arguments...
arg . push_back ( old_prefix_arg ) ;
arg . push_back ( new_prefix_arg ) ;
m_arguments . push_back ( arg ) ;
}
~ CommandObjectTargetModulesSearchPathsAdd ( )
{
}
protected :
bool
DoExecute ( Args & command ,
CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target )
{
const size_t argc = command . GetArgumentCount ( ) ;
if ( argc & 1 )
{
result . AppendError ( " add requires an even number of arguments \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
else
{
for ( size_t i = 0 ; i < argc ; i + = 2 )
{
const char * from = command . GetArgumentAtIndex ( i ) ;
const char * to = command . GetArgumentAtIndex ( i + 1 ) ;
if ( from [ 0 ] & & to [ 0 ] )
{
bool last_pair = ( ( argc - i ) = = 2 ) ;
target - > GetImageSearchPathList ( ) . Append ( ConstString ( from ) ,
ConstString ( to ) ,
last_pair ) ; // Notify if this is the last pair
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
{
if ( from [ 0 ] )
result . AppendError ( " <path-prefix> can't be empty \n " ) ;
else
result . AppendError ( " <new-path-prefix> can't be empty \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
}
}
else
{
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
} ;
# pragma mark CommandObjectTargetModulesSearchPathsClear
class CommandObjectTargetModulesSearchPathsClear : public CommandObjectParsed
{
public :
CommandObjectTargetModulesSearchPathsClear ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target modules search-paths clear " ,
" Clear all current image search path substitution pairs from the current target. " ,
" target modules search-paths clear " )
{
}
~ CommandObjectTargetModulesSearchPathsClear ( )
{
}
protected :
bool
DoExecute ( Args & command ,
CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target )
{
bool notify = true ;
target - > GetImageSearchPathList ( ) . Clear ( notify ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
{
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
} ;
# pragma mark CommandObjectTargetModulesSearchPathsInsert
class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed
{
public :
CommandObjectTargetModulesSearchPathsInsert ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target modules search-paths insert " ,
" Insert a new image search path substitution pair into the current target at the specified index. " ,
NULL )
{
CommandArgumentEntry arg1 ;
CommandArgumentEntry arg2 ;
CommandArgumentData index_arg ;
CommandArgumentData old_prefix_arg ;
CommandArgumentData new_prefix_arg ;
// Define the first and only variant of this arg.
index_arg . arg_type = eArgTypeIndex ;
index_arg . arg_repetition = eArgRepeatPlain ;
// Put the one and only variant into the first arg for m_arguments:
arg1 . push_back ( index_arg ) ;
// Define the first variant of this arg pair.
old_prefix_arg . arg_type = eArgTypeOldPathPrefix ;
old_prefix_arg . arg_repetition = eArgRepeatPairPlus ;
// Define the first variant of this arg pair.
new_prefix_arg . arg_type = eArgTypeNewPathPrefix ;
new_prefix_arg . arg_repetition = eArgRepeatPairPlus ;
// There are two required arguments that must always occur together, i.e. an argument "pair". Because they
// must always occur together, they are treated as two variants of one argument rather than two independent
// arguments. Push them both into the same argument position for m_arguments...
arg2 . push_back ( old_prefix_arg ) ;
arg2 . push_back ( new_prefix_arg ) ;
// Add arguments to m_arguments.
m_arguments . push_back ( arg1 ) ;
m_arguments . push_back ( arg2 ) ;
}
~ CommandObjectTargetModulesSearchPathsInsert ( )
{
}
protected :
bool
DoExecute ( Args & command ,
CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target )
{
size_t argc = command . GetArgumentCount ( ) ;
// check for at least 3 arguments and an odd nubmer of parameters
if ( argc > = 3 & & argc & 1 )
{
bool success = false ;
uint32_t insert_idx = Args : : StringToUInt32 ( command . GetArgumentAtIndex ( 0 ) , UINT32_MAX , 0 , & success ) ;
if ( ! success )
{
result . AppendErrorWithFormat ( " <index> parameter is not an integer: '%s'. \n " , command . GetArgumentAtIndex ( 0 ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return result . Succeeded ( ) ;
}
// shift off the index
command . Shift ( ) ;
argc = command . GetArgumentCount ( ) ;
for ( uint32_t i = 0 ; i < argc ; i + = 2 , + + insert_idx )
{
const char * from = command . GetArgumentAtIndex ( i ) ;
const char * to = command . GetArgumentAtIndex ( i + 1 ) ;
if ( from [ 0 ] & & to [ 0 ] )
{
bool last_pair = ( ( argc - i ) = = 2 ) ;
target - > GetImageSearchPathList ( ) . Insert ( ConstString ( from ) ,
ConstString ( to ) ,
insert_idx ,
last_pair ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
{
if ( from [ 0 ] )
result . AppendError ( " <path-prefix> can't be empty \n " ) ;
else
result . AppendError ( " <new-path-prefix> can't be empty \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
}
else
{
result . AppendError ( " insert requires at least three arguments \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return result . Succeeded ( ) ;
}
}
else
{
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
} ;
# pragma mark CommandObjectTargetModulesSearchPathsList
class CommandObjectTargetModulesSearchPathsList : public CommandObjectParsed
{
public :
CommandObjectTargetModulesSearchPathsList ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target modules search-paths list " ,
" List all current image search path substitution pairs in the current target. " ,
" target modules search-paths list " )
{
}
~ CommandObjectTargetModulesSearchPathsList ( )
{
}
protected :
bool
DoExecute ( Args & command ,
CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target )
{
if ( command . GetArgumentCount ( ) ! = 0 )
{
result . AppendError ( " list takes no arguments \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return result . Succeeded ( ) ;
}
target - > GetImageSearchPathList ( ) . Dump ( & result . GetOutputStream ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
} ;
# pragma mark CommandObjectTargetModulesSearchPathsQuery
class CommandObjectTargetModulesSearchPathsQuery : public CommandObjectParsed
{
public :
CommandObjectTargetModulesSearchPathsQuery ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target modules search-paths query " ,
" Transform a path using the first applicable image search path. " ,
NULL )
{
CommandArgumentEntry arg ;
CommandArgumentData path_arg ;
// Define the first (and only) variant of this arg.
path_arg . arg_type = eArgTypeDirectoryName ;
path_arg . arg_repetition = eArgRepeatPlain ;
// There is only one variant this argument could be; put it into the argument entry.
arg . push_back ( path_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
}
~ CommandObjectTargetModulesSearchPathsQuery ( )
{
}
protected :
bool
DoExecute ( Args & command ,
CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target )
{
if ( command . GetArgumentCount ( ) ! = 1 )
{
result . AppendError ( " query requires one argument \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return result . Succeeded ( ) ;
}
ConstString orig ( command . GetArgumentAtIndex ( 0 ) ) ;
ConstString transformed ;
if ( target - > GetImageSearchPathList ( ) . RemapPath ( orig , transformed ) )
result . GetOutputStream ( ) . Printf ( " %s \n " , transformed . GetCString ( ) ) ;
else
result . GetOutputStream ( ) . Printf ( " %s \n " , orig . GetCString ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
} ;
//----------------------------------------------------------------------
// Static Helper functions
//----------------------------------------------------------------------
static void
DumpModuleArchitecture ( Stream & strm , Module * module , bool full_triple , uint32_t width )
{
if ( module )
{
const char * arch_cstr ;
if ( full_triple )
arch_cstr = module - > GetArchitecture ( ) . GetTriple ( ) . str ( ) . c_str ( ) ;
else
arch_cstr = module - > GetArchitecture ( ) . GetArchitectureName ( ) ;
if ( width )
strm . Printf ( " %-*s " , width , arch_cstr ) ;
else
strm . PutCString ( arch_cstr ) ;
}
}
static void
DumpModuleUUID ( Stream & strm , Module * module )
{
if ( module & & module - > GetUUID ( ) . IsValid ( ) )
module - > GetUUID ( ) . Dump ( & strm ) ;
else
strm . PutCString ( " " ) ;
}
static uint32_t
DumpCompileUnitLineTable ( CommandInterpreter & interpreter ,
Stream & strm ,
Module * module ,
const FileSpec & file_spec ,
bool load_addresses )
{
uint32_t num_matches = 0 ;
if ( module )
{
SymbolContextList sc_list ;
num_matches = module - > ResolveSymbolContextsForFileSpec ( file_spec ,
0 ,
false ,
eSymbolContextCompUnit ,
sc_list ) ;
for ( uint32_t i = 0 ; i < num_matches ; + + i )
{
SymbolContext sc ;
if ( sc_list . GetContextAtIndex ( i , sc ) )
{
if ( i > 0 )
strm < < " \n \n " ;
strm < < " Line table for " < < * static_cast < FileSpec * > ( sc . comp_unit ) < < " in ` "
< < module - > GetFileSpec ( ) . GetFilename ( ) < < " \n " ;
LineTable * line_table = sc . comp_unit - > GetLineTable ( ) ;
if ( line_table )
line_table - > GetDescription ( & strm ,
interpreter . GetExecutionContext ( ) . GetTargetPtr ( ) ,
lldb : : eDescriptionLevelBrief ) ;
else
strm < < " No line table " ;
}
}
}
return num_matches ;
}
static void
DumpFullpath ( Stream & strm , const FileSpec * file_spec_ptr , uint32_t width )
{
if ( file_spec_ptr )
{
if ( width > 0 )
{
std : : string fullpath = file_spec_ptr - > GetPath ( ) ;
strm . Printf ( " %-*s " , width , fullpath . c_str ( ) ) ;
return ;
}
else
{
file_spec_ptr - > Dump ( & strm ) ;
return ;
}
}
// Keep the width spacing correct if things go wrong...
if ( width > 0 )
strm . Printf ( " %-*s " , width , " " ) ;
}
static void
DumpDirectory ( Stream & strm , const FileSpec * file_spec_ptr , uint32_t width )
{
if ( file_spec_ptr )
{
if ( width > 0 )
strm . Printf ( " %-*s " , width , file_spec_ptr - > GetDirectory ( ) . AsCString ( " " ) ) ;
else
file_spec_ptr - > GetDirectory ( ) . Dump ( & strm ) ;
return ;
}
// Keep the width spacing correct if things go wrong...
if ( width > 0 )
strm . Printf ( " %-*s " , width , " " ) ;
}
static void
DumpBasename ( Stream & strm , const FileSpec * file_spec_ptr , uint32_t width )
{
if ( file_spec_ptr )
{
if ( width > 0 )
strm . Printf ( " %-*s " , width , file_spec_ptr - > GetFilename ( ) . AsCString ( " " ) ) ;
else
file_spec_ptr - > GetFilename ( ) . Dump ( & strm ) ;
return ;
}
// Keep the width spacing correct if things go wrong...
if ( width > 0 )
strm . Printf ( " %-*s " , width , " " ) ;
}
static void
DumpModuleSymtab ( CommandInterpreter & interpreter , Stream & strm , Module * module , SortOrder sort_order )
{
if ( module )
{
SymbolVendor * sym_vendor = module - > GetSymbolVendor ( ) ;
if ( sym_vendor )
{
Symtab * symtab = sym_vendor - > GetSymtab ( ) ;
if ( symtab )
symtab - > Dump ( & strm , interpreter . GetExecutionContext ( ) . GetTargetPtr ( ) , sort_order ) ;
}
}
}
static void
DumpModuleSections ( CommandInterpreter & interpreter , Stream & strm , Module * module )
{
if ( module )
{
SectionList * section_list = module - > GetSectionList ( ) ;
if ( section_list )
{
strm . Printf ( " Sections for '%s' (%s): \n " ,
module - > GetSpecificationDescription ( ) . c_str ( ) ,
module - > GetArchitecture ( ) . GetArchitectureName ( ) ) ;
strm . IndentMore ( ) ;
section_list - > Dump ( & strm , interpreter . GetExecutionContext ( ) . GetTargetPtr ( ) , true , UINT32_MAX ) ;
strm . IndentLess ( ) ;
}
}
}
static bool
DumpModuleSymbolVendor ( Stream & strm , Module * module )
{
if ( module )
{
SymbolVendor * symbol_vendor = module - > GetSymbolVendor ( true ) ;
if ( symbol_vendor )
{
symbol_vendor - > Dump ( & strm ) ;
return true ;
}
}
return false ;
}
static void
DumpAddress ( ExecutionContextScope * exe_scope , const Address & so_addr , bool verbose , Stream & strm )
{
strm . IndentMore ( ) ;
strm . Indent ( " Address: " ) ;
so_addr . Dump ( & strm , exe_scope , Address : : DumpStyleModuleWithFileAddress ) ;
strm . PutCString ( " ( " ) ;
so_addr . Dump ( & strm , exe_scope , Address : : DumpStyleSectionNameOffset ) ;
strm . PutCString ( " ) \n " ) ;
strm . Indent ( " Summary: " ) ;
const uint32_t save_indent = strm . GetIndentLevel ( ) ;
strm . SetIndentLevel ( save_indent + 13 ) ;
so_addr . Dump ( & strm , exe_scope , Address : : DumpStyleResolvedDescription ) ;
strm . SetIndentLevel ( save_indent ) ;
// Print out detailed address information when verbose is enabled
if ( verbose )
{
strm . EOL ( ) ;
so_addr . Dump ( & strm , exe_scope , Address : : DumpStyleDetailedSymbolContext ) ;
}
strm . IndentLess ( ) ;
}
static bool
LookupAddressInModule ( CommandInterpreter & interpreter ,
Stream & strm ,
Module * module ,
uint32_t resolve_mask ,
lldb : : addr_t raw_addr ,
lldb : : addr_t offset ,
bool verbose )
{
if ( module )
{
lldb : : addr_t addr = raw_addr - offset ;
Address so_addr ;
SymbolContext sc ;
Target * target = interpreter . GetExecutionContext ( ) . GetTargetPtr ( ) ;
if ( target & & ! target - > GetSectionLoadList ( ) . IsEmpty ( ) )
{
if ( ! target - > GetSectionLoadList ( ) . ResolveLoadAddress ( addr , so_addr ) )
return false ;
else if ( so_addr . GetModule ( ) . get ( ) ! = module )
return false ;
}
else
{
if ( ! module - > ResolveFileAddress ( addr , so_addr ) )
return false ;
}
ExecutionContextScope * exe_scope = interpreter . GetExecutionContext ( ) . GetBestExecutionContextScope ( ) ;
DumpAddress ( exe_scope , so_addr , verbose , strm ) ;
// strm.IndentMore();
// strm.Indent (" Address: ");
// so_addr.Dump (&strm, exe_scope, Address::DumpStyleModuleWithFileAddress);
// strm.PutCString (" (");
// so_addr.Dump (&strm, exe_scope, Address::DumpStyleSectionNameOffset);
// strm.PutCString (")\n");
// strm.Indent (" Summary: ");
// const uint32_t save_indent = strm.GetIndentLevel ();
// strm.SetIndentLevel (save_indent + 13);
// so_addr.Dump (&strm, exe_scope, Address::DumpStyleResolvedDescription);
// strm.SetIndentLevel (save_indent);
// // Print out detailed address information when verbose is enabled
// if (verbose)
// {
// strm.EOL();
// so_addr.Dump (&strm, exe_scope, Address::DumpStyleDetailedSymbolContext);
// }
// strm.IndentLess();
return true ;
}
return false ;
}
static uint32_t
LookupSymbolInModule ( CommandInterpreter & interpreter , Stream & strm , Module * module , const char * name , bool name_is_regex , bool verbose )
{
if ( module )
{
SymbolContext sc ;
SymbolVendor * sym_vendor = module - > GetSymbolVendor ( ) ;
if ( sym_vendor )
{
Symtab * symtab = sym_vendor - > GetSymtab ( ) ;
if ( symtab )
{
uint32_t i ;
std : : vector < uint32_t > match_indexes ;
ConstString symbol_name ( name ) ;
uint32_t num_matches = 0 ;
if ( name_is_regex )
{
RegularExpression name_regexp ( name ) ;
num_matches = symtab - > AppendSymbolIndexesMatchingRegExAndType ( name_regexp ,
eSymbolTypeAny ,
match_indexes ) ;
}
else
{
num_matches = symtab - > AppendSymbolIndexesWithName ( symbol_name , match_indexes ) ;
}
if ( num_matches > 0 )
{
strm . Indent ( ) ;
strm . Printf ( " %u symbols match %s'%s' in " , num_matches ,
name_is_regex ? " the regular expression " : " " , name ) ;
DumpFullpath ( strm , & module - > GetFileSpec ( ) , 0 ) ;
strm . PutCString ( " : \n " ) ;
strm . IndentMore ( ) ;
//Symtab::DumpSymbolHeader (&strm);
for ( i = 0 ; i < num_matches ; + + i )
{
Symbol * symbol = symtab - > SymbolAtIndex ( match_indexes [ i ] ) ;
DumpAddress ( interpreter . GetExecutionContext ( ) . GetBestExecutionContextScope ( ) ,
symbol - > GetAddress ( ) ,
verbose ,
strm ) ;
// strm.Indent ();
// symbol->Dump (&strm, interpreter.GetExecutionContext().GetTargetPtr(), i);
}
strm . IndentLess ( ) ;
return num_matches ;
}
}
}
}
return 0 ;
}
static void
DumpSymbolContextList ( ExecutionContextScope * exe_scope , Stream & strm , SymbolContextList & sc_list , bool verbose )
{
strm . IndentMore ( ) ;
uint32_t i ;
const uint32_t num_matches = sc_list . GetSize ( ) ;
for ( i = 0 ; i < num_matches ; + + i )
{
SymbolContext sc ;
if ( sc_list . GetContextAtIndex ( i , sc ) )
{
AddressRange range ;
sc . GetAddressRange ( eSymbolContextEverything ,
0 ,
true ,
range ) ;
DumpAddress ( exe_scope , range . GetBaseAddress ( ) , verbose , strm ) ;
}
}
strm . IndentLess ( ) ;
}
static size_t
LookupFunctionInModule ( CommandInterpreter & interpreter ,
Stream & strm ,
Module * module ,
const char * name ,
bool name_is_regex ,
bool include_inlines ,
bool include_symbols ,
bool verbose )
{
if ( module & & name & & name [ 0 ] )
{
SymbolContextList sc_list ;
const bool append = true ;
size_t num_matches = 0 ;
if ( name_is_regex )
{
RegularExpression function_name_regex ( name ) ;
num_matches = module - > FindFunctions ( function_name_regex ,
include_symbols ,
include_inlines ,
append ,
sc_list ) ;
}
else
{
ConstString function_name ( name ) ;
num_matches = module - > FindFunctions ( function_name ,
NULL ,
eFunctionNameTypeAuto ,
include_symbols ,
include_inlines ,
append ,
sc_list ) ;
}
if ( num_matches )
{
strm . Indent ( ) ;
strm . Printf ( " %zu match%s found in " , num_matches , num_matches > 1 ? " es " : " " ) ;
DumpFullpath ( strm , & module - > GetFileSpec ( ) , 0 ) ;
strm . PutCString ( " : \n " ) ;
DumpSymbolContextList ( interpreter . GetExecutionContext ( ) . GetBestExecutionContextScope ( ) , strm , sc_list , verbose ) ;
}
return num_matches ;
}
return 0 ;
}
static size_t
LookupTypeInModule ( CommandInterpreter & interpreter ,
Stream & strm ,
Module * module ,
const char * name_cstr ,
bool name_is_regex )
{
if ( module & & name_cstr & & name_cstr [ 0 ] )
{
TypeList type_list ;
const uint32_t max_num_matches = UINT32_MAX ;
size_t num_matches = 0 ;
bool name_is_fully_qualified = false ;
SymbolContext sc ;
ConstString name ( name_cstr ) ;
num_matches = module - > FindTypes ( sc , name , name_is_fully_qualified , max_num_matches , type_list ) ;
if ( num_matches )
{
strm . Indent ( ) ;
strm . Printf ( " %zu match%s found in " , num_matches , num_matches > 1 ? " es " : " " ) ;
DumpFullpath ( strm , & module - > GetFileSpec ( ) , 0 ) ;
strm . PutCString ( " : \n " ) ;
2013-12-03 13:51:59 -05:00
for ( TypeSP type_sp : type_list . Types ( ) )
2013-08-23 13:46:38 -04:00
{
if ( type_sp )
{
// Resolve the clang type so that any forward references
// to types that haven't yet been parsed will get parsed.
type_sp - > GetClangFullType ( ) ;
type_sp - > GetDescription ( & strm , eDescriptionLevelFull , true ) ;
// Print all typedef chains
TypeSP typedef_type_sp ( type_sp ) ;
TypeSP typedefed_type_sp ( typedef_type_sp - > GetTypedefType ( ) ) ;
while ( typedefed_type_sp )
{
strm . EOL ( ) ;
strm . Printf ( " typedef '%s': " , typedef_type_sp - > GetName ( ) . GetCString ( ) ) ;
typedefed_type_sp - > GetClangFullType ( ) ;
typedefed_type_sp - > GetDescription ( & strm , eDescriptionLevelFull , true ) ;
typedef_type_sp = typedefed_type_sp ;
typedefed_type_sp = typedef_type_sp - > GetTypedefType ( ) ;
}
}
strm . EOL ( ) ;
}
}
return num_matches ;
}
return 0 ;
}
static size_t
LookupTypeHere ( CommandInterpreter & interpreter ,
Stream & strm ,
const SymbolContext & sym_ctx ,
const char * name_cstr ,
bool name_is_regex )
{
if ( ! sym_ctx . module_sp )
return 0 ;
TypeList type_list ;
const uint32_t max_num_matches = UINT32_MAX ;
size_t num_matches = 1 ;
bool name_is_fully_qualified = false ;
ConstString name ( name_cstr ) ;
num_matches = sym_ctx . module_sp - > FindTypes ( sym_ctx , name , name_is_fully_qualified , max_num_matches , type_list ) ;
if ( num_matches )
{
strm . Indent ( ) ;
strm . PutCString ( " Best match found in " ) ;
DumpFullpath ( strm , & sym_ctx . module_sp - > GetFileSpec ( ) , 0 ) ;
strm . PutCString ( " : \n " ) ;
TypeSP type_sp ( type_list . GetTypeAtIndex ( 0 ) ) ;
if ( type_sp )
{
// Resolve the clang type so that any forward references
// to types that haven't yet been parsed will get parsed.
type_sp - > GetClangFullType ( ) ;
type_sp - > GetDescription ( & strm , eDescriptionLevelFull , true ) ;
// Print all typedef chains
TypeSP typedef_type_sp ( type_sp ) ;
TypeSP typedefed_type_sp ( typedef_type_sp - > GetTypedefType ( ) ) ;
while ( typedefed_type_sp )
{
strm . EOL ( ) ;
strm . Printf ( " typedef '%s': " , typedef_type_sp - > GetName ( ) . GetCString ( ) ) ;
typedefed_type_sp - > GetClangFullType ( ) ;
typedefed_type_sp - > GetDescription ( & strm , eDescriptionLevelFull , true ) ;
typedef_type_sp = typedefed_type_sp ;
typedefed_type_sp = typedef_type_sp - > GetTypedefType ( ) ;
}
}
strm . EOL ( ) ;
}
return num_matches ;
}
static uint32_t
LookupFileAndLineInModule ( CommandInterpreter & interpreter ,
Stream & strm ,
Module * module ,
const FileSpec & file_spec ,
uint32_t line ,
bool check_inlines ,
bool verbose )
{
if ( module & & file_spec )
{
SymbolContextList sc_list ;
const uint32_t num_matches = module - > ResolveSymbolContextsForFileSpec ( file_spec , line , check_inlines ,
eSymbolContextEverything , sc_list ) ;
if ( num_matches > 0 )
{
strm . Indent ( ) ;
strm . Printf ( " %u match%s found in " , num_matches , num_matches > 1 ? " es " : " " ) ;
strm < < file_spec ;
if ( line > 0 )
strm . Printf ( " :%u " , line ) ;
strm < < " in " ;
DumpFullpath ( strm , & module - > GetFileSpec ( ) , 0 ) ;
strm . PutCString ( " : \n " ) ;
DumpSymbolContextList ( interpreter . GetExecutionContext ( ) . GetBestExecutionContextScope ( ) , strm , sc_list , verbose ) ;
return num_matches ;
}
}
return 0 ;
}
static size_t
FindModulesByName ( Target * target ,
const char * module_name ,
ModuleList & module_list ,
bool check_global_list )
{
// Dump specified images (by basename or fullpath)
FileSpec module_file_spec ( module_name , false ) ;
ModuleSpec module_spec ( module_file_spec ) ;
const size_t initial_size = module_list . GetSize ( ) ;
if ( check_global_list )
{
// Check the global list
Mutex : : Locker locker ( Module : : GetAllocationModuleCollectionMutex ( ) ) ;
const size_t num_modules = Module : : GetNumberAllocatedModules ( ) ;
ModuleSP module_sp ;
for ( size_t image_idx = 0 ; image_idx < num_modules ; + + image_idx )
{
Module * module = Module : : GetAllocatedModuleAtIndex ( image_idx ) ;
if ( module )
{
if ( module - > MatchesModuleSpec ( module_spec ) )
{
module_sp = module - > shared_from_this ( ) ;
module_list . AppendIfNeeded ( module_sp ) ;
}
}
}
}
else
{
if ( target )
{
const size_t num_matches = target - > GetImages ( ) . FindModules ( module_spec , module_list ) ;
// Not found in our module list for our target, check the main
// shared module list in case it is a extra file used somewhere
// else
if ( num_matches = = 0 )
{
module_spec . GetArchitecture ( ) = target - > GetArchitecture ( ) ;
ModuleList : : FindSharedModules ( module_spec , module_list ) ;
}
}
else
{
ModuleList : : FindSharedModules ( module_spec , module_list ) ;
}
}
return module_list . GetSize ( ) - initial_size ;
}
# pragma mark CommandObjectTargetModulesModuleAutoComplete
//----------------------------------------------------------------------
// A base command object class that can auto complete with module file
// paths
//----------------------------------------------------------------------
class CommandObjectTargetModulesModuleAutoComplete : public CommandObjectParsed
{
public :
CommandObjectTargetModulesModuleAutoComplete ( CommandInterpreter & interpreter ,
const char * name ,
const char * help ,
const char * syntax ) :
CommandObjectParsed ( interpreter , name , help , syntax )
{
CommandArgumentEntry arg ;
CommandArgumentData file_arg ;
// Define the first (and only) variant of this arg.
file_arg . arg_type = eArgTypeFilename ;
file_arg . arg_repetition = eArgRepeatStar ;
// There is only one variant this argument could be; put it into the argument entry.
arg . push_back ( file_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
}
virtual
~ CommandObjectTargetModulesModuleAutoComplete ( )
{
}
virtual int
HandleArgumentCompletion ( Args & input ,
int & cursor_index ,
int & cursor_char_position ,
OptionElementVector & opt_element_vector ,
int match_start_point ,
int max_return_elements ,
bool & word_complete ,
StringList & matches )
{
// Arguments are the standard module completer.
std : : string completion_str ( input . GetArgumentAtIndex ( cursor_index ) ) ;
completion_str . erase ( cursor_char_position ) ;
CommandCompletions : : InvokeCommonCompletionCallbacks ( m_interpreter ,
CommandCompletions : : eModuleCompletion ,
completion_str . c_str ( ) ,
match_start_point ,
max_return_elements ,
NULL ,
word_complete ,
matches ) ;
return matches . GetSize ( ) ;
}
} ;
# pragma mark CommandObjectTargetModulesSourceFileAutoComplete
//----------------------------------------------------------------------
// A base command object class that can auto complete with module source
// file paths
//----------------------------------------------------------------------
class CommandObjectTargetModulesSourceFileAutoComplete : public CommandObjectParsed
{
public :
CommandObjectTargetModulesSourceFileAutoComplete ( CommandInterpreter & interpreter ,
const char * name ,
const char * help ,
const char * syntax ,
uint32_t flags ) :
CommandObjectParsed ( interpreter , name , help , syntax , flags )
{
CommandArgumentEntry arg ;
CommandArgumentData source_file_arg ;
// Define the first (and only) variant of this arg.
source_file_arg . arg_type = eArgTypeSourceFile ;
source_file_arg . arg_repetition = eArgRepeatPlus ;
// There is only one variant this argument could be; put it into the argument entry.
arg . push_back ( source_file_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
}
virtual
~ CommandObjectTargetModulesSourceFileAutoComplete ( )
{
}
virtual int
HandleArgumentCompletion ( Args & input ,
int & cursor_index ,
int & cursor_char_position ,
OptionElementVector & opt_element_vector ,
int match_start_point ,
int max_return_elements ,
bool & word_complete ,
StringList & matches )
{
// Arguments are the standard source file completer.
std : : string completion_str ( input . GetArgumentAtIndex ( cursor_index ) ) ;
completion_str . erase ( cursor_char_position ) ;
CommandCompletions : : InvokeCommonCompletionCallbacks ( m_interpreter ,
CommandCompletions : : eSourceFileCompletion ,
completion_str . c_str ( ) ,
match_start_point ,
max_return_elements ,
NULL ,
word_complete ,
matches ) ;
return matches . GetSize ( ) ;
}
} ;
# pragma mark CommandObjectTargetModulesDumpSymtab
class CommandObjectTargetModulesDumpSymtab : public CommandObjectTargetModulesModuleAutoComplete
{
public :
CommandObjectTargetModulesDumpSymtab ( CommandInterpreter & interpreter ) :
CommandObjectTargetModulesModuleAutoComplete ( interpreter ,
" target modules dump symtab " ,
" Dump the symbol table from one or more target modules. " ,
NULL ) ,
m_options ( interpreter )
{
}
virtual
~ CommandObjectTargetModulesDumpSymtab ( )
{
}
virtual Options *
GetOptions ( )
{
return & m_options ;
}
class CommandOptions : public Options
{
public :
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter ) ,
m_sort_order ( eSortOrderNone )
{
}
virtual
~ CommandOptions ( )
{
}
virtual Error
SetOptionValue ( uint32_t option_idx , const char * option_arg )
{
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option )
{
case ' s ' :
m_sort_order = ( SortOrder ) Args : : StringToOptionEnum ( option_arg ,
g_option_table [ option_idx ] . enum_values ,
eSortOrderNone ,
error ) ;
break ;
default :
error . SetErrorStringWithFormat ( " invalid short option character '%c' " , short_option ) ;
break ;
}
return error ;
}
void
OptionParsingStarting ( )
{
m_sort_order = eSortOrderNone ;
}
const OptionDefinition *
GetDefinitions ( )
{
return g_option_table ;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table [ ] ;
SortOrder m_sort_order ;
} ;
protected :
virtual bool
DoExecute ( Args & command ,
CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = NULL )
{
result . AppendError ( " invalid target, create a debug target using the 'target create' command " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else
{
uint32_t num_dumped = 0 ;
uint32_t addr_byte_size = target - > GetArchitecture ( ) . GetAddressByteSize ( ) ;
result . GetOutputStream ( ) . SetAddressByteSize ( addr_byte_size ) ;
result . GetErrorStream ( ) . SetAddressByteSize ( addr_byte_size ) ;
if ( command . GetArgumentCount ( ) = = 0 )
{
// Dump all sections for all modules images
Mutex : : Locker modules_locker ( target - > GetImages ( ) . GetMutex ( ) ) ;
const size_t num_modules = target - > GetImages ( ) . GetSize ( ) ;
if ( num_modules > 0 )
{
result . GetOutputStream ( ) . Printf ( " Dumping symbol table for %zu modules. \n " , num_modules ) ;
for ( size_t image_idx = 0 ; image_idx < num_modules ; + + image_idx )
{
if ( num_dumped > 0 )
{
result . GetOutputStream ( ) . EOL ( ) ;
result . GetOutputStream ( ) . EOL ( ) ;
}
num_dumped + + ;
DumpModuleSymtab ( m_interpreter ,
result . GetOutputStream ( ) ,
target - > GetImages ( ) . GetModulePointerAtIndexUnlocked ( image_idx ) ,
m_options . m_sort_order ) ;
}
}
else
{
result . AppendError ( " the target has no associated executable images " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else
{
// Dump specified images (by basename or fullpath)
const char * arg_cstr ;
for ( int arg_idx = 0 ; ( arg_cstr = command . GetArgumentAtIndex ( arg_idx ) ) ! = NULL ; + + arg_idx )
{
ModuleList module_list ;
const size_t num_matches = FindModulesByName ( target , arg_cstr , module_list , true ) ;
if ( num_matches > 0 )
{
for ( size_t i = 0 ; i < num_matches ; + + i )
{
Module * module = module_list . GetModulePointerAtIndex ( i ) ;
if ( module )
{
if ( num_dumped > 0 )
{
result . GetOutputStream ( ) . EOL ( ) ;
result . GetOutputStream ( ) . EOL ( ) ;
}
num_dumped + + ;
DumpModuleSymtab ( m_interpreter , result . GetOutputStream ( ) , module , m_options . m_sort_order ) ;
}
}
}
else
result . AppendWarningWithFormat ( " Unable to find an image that matches '%s'. \n " , arg_cstr ) ;
}
}
if ( num_dumped > 0 )
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
else
{
result . AppendError ( " no matching executable images found " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
return result . Succeeded ( ) ;
}
CommandOptions m_options ;
} ;
static OptionEnumValueElement
g_sort_option_enumeration [ 4 ] =
{
{ eSortOrderNone , " none " , " No sorting, use the original symbol table order. " } ,
{ eSortOrderByAddress , " address " , " Sort output by symbol address. " } ,
{ eSortOrderByName , " name " , " Sort output by symbol name. " } ,
{ 0 , NULL , NULL }
} ;
OptionDefinition
CommandObjectTargetModulesDumpSymtab : : CommandOptions : : g_option_table [ ] =
{
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_1 , false , " sort " , ' s ' , OptionParser : : eRequiredArgument , g_sort_option_enumeration , 0 , eArgTypeSortOrder , " Supply a sort order when dumping the symbol table. " } ,
2013-08-23 13:46:38 -04:00
{ 0 , false , NULL , 0 , 0 , NULL , 0 , eArgTypeNone , NULL }
} ;
# pragma mark CommandObjectTargetModulesDumpSections
//----------------------------------------------------------------------
// Image section dumping command
//----------------------------------------------------------------------
class CommandObjectTargetModulesDumpSections : public CommandObjectTargetModulesModuleAutoComplete
{
public :
CommandObjectTargetModulesDumpSections ( CommandInterpreter & interpreter ) :
CommandObjectTargetModulesModuleAutoComplete ( interpreter ,
" target modules dump sections " ,
" Dump the sections from one or more target modules. " ,
//"target modules dump sections [<file1> ...]")
NULL )
{
}
virtual
~ CommandObjectTargetModulesDumpSections ( )
{
}
protected :
virtual bool
DoExecute ( Args & command ,
CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = NULL )
{
result . AppendError ( " invalid target, create a debug target using the 'target create' command " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else
{
uint32_t num_dumped = 0 ;
uint32_t addr_byte_size = target - > GetArchitecture ( ) . GetAddressByteSize ( ) ;
result . GetOutputStream ( ) . SetAddressByteSize ( addr_byte_size ) ;
result . GetErrorStream ( ) . SetAddressByteSize ( addr_byte_size ) ;
if ( command . GetArgumentCount ( ) = = 0 )
{
// Dump all sections for all modules images
const size_t num_modules = target - > GetImages ( ) . GetSize ( ) ;
if ( num_modules > 0 )
{
result . GetOutputStream ( ) . Printf ( " Dumping sections for %zu modules. \n " , num_modules ) ;
for ( size_t image_idx = 0 ; image_idx < num_modules ; + + image_idx )
{
num_dumped + + ;
DumpModuleSections ( m_interpreter , result . GetOutputStream ( ) , target - > GetImages ( ) . GetModulePointerAtIndex ( image_idx ) ) ;
}
}
else
{
result . AppendError ( " the target has no associated executable images " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else
{
// Dump specified images (by basename or fullpath)
const char * arg_cstr ;
for ( int arg_idx = 0 ; ( arg_cstr = command . GetArgumentAtIndex ( arg_idx ) ) ! = NULL ; + + arg_idx )
{
ModuleList module_list ;
const size_t num_matches = FindModulesByName ( target , arg_cstr , module_list , true ) ;
if ( num_matches > 0 )
{
for ( size_t i = 0 ; i < num_matches ; + + i )
{
Module * module = module_list . GetModulePointerAtIndex ( i ) ;
if ( module )
{
num_dumped + + ;
DumpModuleSections ( m_interpreter , result . GetOutputStream ( ) , module ) ;
}
}
}
else
{
// Check the global list
Mutex : : Locker locker ( Module : : GetAllocationModuleCollectionMutex ( ) ) ;
result . AppendWarningWithFormat ( " Unable to find an image that matches '%s'. \n " , arg_cstr ) ;
}
}
}
if ( num_dumped > 0 )
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
else
{
result . AppendError ( " no matching executable images found " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
return result . Succeeded ( ) ;
}
} ;
# pragma mark CommandObjectTargetModulesDumpSymfile
//----------------------------------------------------------------------
// Image debug symbol dumping command
//----------------------------------------------------------------------
class CommandObjectTargetModulesDumpSymfile : public CommandObjectTargetModulesModuleAutoComplete
{
public :
CommandObjectTargetModulesDumpSymfile ( CommandInterpreter & interpreter ) :
CommandObjectTargetModulesModuleAutoComplete ( interpreter ,
" target modules dump symfile " ,
" Dump the debug symbol file for one or more target modules. " ,
//"target modules dump symfile [<file1> ...]")
NULL )
{
}
virtual
~ CommandObjectTargetModulesDumpSymfile ( )
{
}
protected :
virtual bool
DoExecute ( Args & command ,
CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = NULL )
{
result . AppendError ( " invalid target, create a debug target using the 'target create' command " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else
{
uint32_t num_dumped = 0 ;
uint32_t addr_byte_size = target - > GetArchitecture ( ) . GetAddressByteSize ( ) ;
result . GetOutputStream ( ) . SetAddressByteSize ( addr_byte_size ) ;
result . GetErrorStream ( ) . SetAddressByteSize ( addr_byte_size ) ;
if ( command . GetArgumentCount ( ) = = 0 )
{
// Dump all sections for all modules images
const ModuleList & target_modules = target - > GetImages ( ) ;
Mutex : : Locker modules_locker ( target_modules . GetMutex ( ) ) ;
const size_t num_modules = target_modules . GetSize ( ) ;
if ( num_modules > 0 )
{
result . GetOutputStream ( ) . Printf ( " Dumping debug symbols for %zu modules. \n " , num_modules ) ;
for ( uint32_t image_idx = 0 ; image_idx < num_modules ; + + image_idx )
{
if ( DumpModuleSymbolVendor ( result . GetOutputStream ( ) , target_modules . GetModulePointerAtIndexUnlocked ( image_idx ) ) )
num_dumped + + ;
}
}
else
{
result . AppendError ( " the target has no associated executable images " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else
{
// Dump specified images (by basename or fullpath)
const char * arg_cstr ;
for ( int arg_idx = 0 ; ( arg_cstr = command . GetArgumentAtIndex ( arg_idx ) ) ! = NULL ; + + arg_idx )
{
ModuleList module_list ;
const size_t num_matches = FindModulesByName ( target , arg_cstr , module_list , true ) ;
if ( num_matches > 0 )
{
for ( size_t i = 0 ; i < num_matches ; + + i )
{
Module * module = module_list . GetModulePointerAtIndex ( i ) ;
if ( module )
{
if ( DumpModuleSymbolVendor ( result . GetOutputStream ( ) , module ) )
num_dumped + + ;
}
}
}
else
result . AppendWarningWithFormat ( " Unable to find an image that matches '%s'. \n " , arg_cstr ) ;
}
}
if ( num_dumped > 0 )
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
else
{
result . AppendError ( " no matching executable images found " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
return result . Succeeded ( ) ;
}
} ;
# pragma mark CommandObjectTargetModulesDumpLineTable
//----------------------------------------------------------------------
// Image debug line table dumping command
//----------------------------------------------------------------------
class CommandObjectTargetModulesDumpLineTable : public CommandObjectTargetModulesSourceFileAutoComplete
{
public :
CommandObjectTargetModulesDumpLineTable ( CommandInterpreter & interpreter ) :
CommandObjectTargetModulesSourceFileAutoComplete ( interpreter ,
" target modules dump line-table " ,
" Dump the line table for one or more compilation units. " ,
NULL ,
eFlagRequiresTarget )
{
}
virtual
~ CommandObjectTargetModulesDumpLineTable ( )
{
}
protected :
virtual bool
DoExecute ( Args & command ,
CommandReturnObject & result )
{
Target * target = m_exe_ctx . GetTargetPtr ( ) ;
uint32_t total_num_dumped = 0 ;
uint32_t addr_byte_size = target - > GetArchitecture ( ) . GetAddressByteSize ( ) ;
result . GetOutputStream ( ) . SetAddressByteSize ( addr_byte_size ) ;
result . GetErrorStream ( ) . SetAddressByteSize ( addr_byte_size ) ;
if ( command . GetArgumentCount ( ) = = 0 )
{
result . AppendErrorWithFormat ( " \n Syntax: %s \n " , m_cmd_syntax . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
else
{
// Dump specified images (by basename or fullpath)
const char * arg_cstr ;
for ( int arg_idx = 0 ; ( arg_cstr = command . GetArgumentAtIndex ( arg_idx ) ) ! = NULL ; + + arg_idx )
{
FileSpec file_spec ( arg_cstr , false ) ;
const ModuleList & target_modules = target - > GetImages ( ) ;
Mutex : : Locker modules_locker ( target_modules . GetMutex ( ) ) ;
const size_t num_modules = target_modules . GetSize ( ) ;
if ( num_modules > 0 )
{
uint32_t num_dumped = 0 ;
for ( uint32_t i = 0 ; i < num_modules ; + + i )
{
if ( DumpCompileUnitLineTable ( m_interpreter ,
result . GetOutputStream ( ) ,
target_modules . GetModulePointerAtIndexUnlocked ( i ) ,
file_spec ,
m_exe_ctx . GetProcessPtr ( ) & & m_exe_ctx . GetProcessRef ( ) . IsAlive ( ) ) )
num_dumped + + ;
}
if ( num_dumped = = 0 )
result . AppendWarningWithFormat ( " No source filenames matched '%s'. \n " , arg_cstr ) ;
else
total_num_dumped + = num_dumped ;
}
}
}
if ( total_num_dumped > 0 )
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
else
{
result . AppendError ( " no source filenames matched any command arguments " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
} ;
# pragma mark CommandObjectTargetModulesDump
//----------------------------------------------------------------------
// Dump multi-word command for target modules
//----------------------------------------------------------------------
class CommandObjectTargetModulesDump : public CommandObjectMultiword
{
public :
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
CommandObjectTargetModulesDump ( CommandInterpreter & interpreter ) :
CommandObjectMultiword ( interpreter ,
" target modules dump " ,
" A set of commands for dumping information about one or more target modules. " ,
" target modules dump [symtab|sections|symfile|line-table] [<file1> <file2> ...] " )
{
LoadSubCommand ( " symtab " , CommandObjectSP ( new CommandObjectTargetModulesDumpSymtab ( interpreter ) ) ) ;
LoadSubCommand ( " sections " , CommandObjectSP ( new CommandObjectTargetModulesDumpSections ( interpreter ) ) ) ;
LoadSubCommand ( " symfile " , CommandObjectSP ( new CommandObjectTargetModulesDumpSymfile ( interpreter ) ) ) ;
LoadSubCommand ( " line-table " , CommandObjectSP ( new CommandObjectTargetModulesDumpLineTable ( interpreter ) ) ) ;
}
virtual
~ CommandObjectTargetModulesDump ( )
{
}
} ;
class CommandObjectTargetModulesAdd : public CommandObjectParsed
{
public :
CommandObjectTargetModulesAdd ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target modules add " ,
" Add a new module to the current target's modules. " ,
" target modules add [<module>] " ) ,
m_option_group ( interpreter ) ,
m_symbol_file ( LLDB_OPT_SET_1 , false , " symfile " , ' s ' , 0 , eArgTypeFilename , " Fullpath to a stand alone debug symbols file for when debug symbols are not in the executable. " )
{
m_option_group . Append ( & m_uuid_option_group , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_symbol_file , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Finalize ( ) ;
}
virtual
~ CommandObjectTargetModulesAdd ( )
{
}
virtual Options *
GetOptions ( )
{
return & m_option_group ;
}
virtual int
HandleArgumentCompletion ( Args & input ,
int & cursor_index ,
int & cursor_char_position ,
OptionElementVector & opt_element_vector ,
int match_start_point ,
int max_return_elements ,
bool & word_complete ,
StringList & matches )
{
std : : string completion_str ( input . GetArgumentAtIndex ( cursor_index ) ) ;
completion_str . erase ( cursor_char_position ) ;
CommandCompletions : : InvokeCommonCompletionCallbacks ( m_interpreter ,
CommandCompletions : : eDiskFileCompletion ,
completion_str . c_str ( ) ,
match_start_point ,
max_return_elements ,
NULL ,
word_complete ,
matches ) ;
return matches . GetSize ( ) ;
}
protected :
OptionGroupOptions m_option_group ;
OptionGroupUUID m_uuid_option_group ;
OptionGroupFile m_symbol_file ;
virtual bool
DoExecute ( Args & args ,
CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = NULL )
{
result . AppendError ( " invalid target, create a debug target using the 'target create' command " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else
{
bool flush = false ;
const size_t argc = args . GetArgumentCount ( ) ;
if ( argc = = 0 )
{
if ( m_uuid_option_group . GetOptionValue ( ) . OptionWasSet ( ) )
{
// We are given a UUID only, go locate the file
ModuleSpec module_spec ;
module_spec . GetUUID ( ) = m_uuid_option_group . GetOptionValue ( ) . GetCurrentValue ( ) ;
if ( m_symbol_file . GetOptionValue ( ) . OptionWasSet ( ) )
module_spec . GetSymbolFileSpec ( ) = m_symbol_file . GetOptionValue ( ) . GetCurrentValue ( ) ;
if ( Symbols : : DownloadObjectAndSymbolFile ( module_spec ) )
{
ModuleSP module_sp ( target - > GetSharedModule ( module_spec ) ) ;
if ( module_sp )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return true ;
}
else
{
flush = true ;
StreamString strm ;
module_spec . GetUUID ( ) . Dump ( & strm ) ;
if ( module_spec . GetFileSpec ( ) )
{
if ( module_spec . GetSymbolFileSpec ( ) )
{
result . AppendErrorWithFormat ( " Unable to create the executable or symbol file with UUID %s with path %s and symbol file %s " ,
strm . GetString ( ) . c_str ( ) ,
module_spec . GetFileSpec ( ) . GetPath ( ) . c_str ( ) ,
module_spec . GetSymbolFileSpec ( ) . GetPath ( ) . c_str ( ) ) ;
}
else
{
result . AppendErrorWithFormat ( " Unable to create the executable or symbol file with UUID %s with path %s " ,
strm . GetString ( ) . c_str ( ) ,
module_spec . GetFileSpec ( ) . GetPath ( ) . c_str ( ) ) ;
}
}
else
{
result . AppendErrorWithFormat ( " Unable to create the executable or symbol file with UUID %s " ,
strm . GetString ( ) . c_str ( ) ) ;
}
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else
{
StreamString strm ;
module_spec . GetUUID ( ) . Dump ( & strm ) ;
result . AppendErrorWithFormat ( " Unable to locate the executable or symbol file with UUID %s " , strm . GetString ( ) . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else
{
result . AppendError ( " one or more executable image paths must be specified " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else
{
for ( size_t i = 0 ; i < argc ; + + i )
{
const char * path = args . GetArgumentAtIndex ( i ) ;
if ( path )
{
FileSpec file_spec ( path , true ) ;
if ( file_spec . Exists ( ) )
{
ModuleSpec module_spec ( file_spec ) ;
if ( m_uuid_option_group . GetOptionValue ( ) . OptionWasSet ( ) )
module_spec . GetUUID ( ) = m_uuid_option_group . GetOptionValue ( ) . GetCurrentValue ( ) ;
if ( m_symbol_file . GetOptionValue ( ) . OptionWasSet ( ) )
module_spec . GetSymbolFileSpec ( ) = m_symbol_file . GetOptionValue ( ) . GetCurrentValue ( ) ;
2013-11-06 11:48:53 -05:00
if ( ! module_spec . GetArchitecture ( ) . IsValid ( ) )
module_spec . GetArchitecture ( ) = target - > GetArchitecture ( ) ;
2013-08-23 13:46:38 -04:00
Error error ;
ModuleSP module_sp ( target - > GetSharedModule ( module_spec , & error ) ) ;
if ( ! module_sp )
{
const char * error_cstr = error . AsCString ( ) ;
if ( error_cstr )
result . AppendError ( error_cstr ) ;
else
result . AppendErrorWithFormat ( " unsupported module: %s " , path ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else
{
flush = true ;
}
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
char resolved_path [ PATH_MAX ] ;
result . SetStatus ( eReturnStatusFailed ) ;
if ( file_spec . GetPath ( resolved_path , sizeof ( resolved_path ) ) )
{
if ( strcmp ( resolved_path , path ) ! = 0 )
{
result . AppendErrorWithFormat ( " invalid module path '%s' with resolved path '%s' \n " , path , resolved_path ) ;
break ;
}
}
result . AppendErrorWithFormat ( " invalid module path '%s' \n " , path ) ;
break ;
}
}
}
}
if ( flush )
{
ProcessSP process = target - > GetProcessSP ( ) ;
if ( process )
process - > Flush ( ) ;
}
}
return result . Succeeded ( ) ;
}
} ;
class CommandObjectTargetModulesLoad : public CommandObjectTargetModulesModuleAutoComplete
{
public :
CommandObjectTargetModulesLoad ( CommandInterpreter & interpreter ) :
CommandObjectTargetModulesModuleAutoComplete ( interpreter ,
" target modules load " ,
" Set the load addresses for one or more sections in a target module. " ,
" target modules load [--file <module> --uuid <uuid>] <sect-name> <address> [<sect-name> <address> ....] " ) ,
m_option_group ( interpreter ) ,
m_file_option ( LLDB_OPT_SET_1 , false , " file " , ' f ' , 0 , eArgTypeFilename , " Fullpath or basename for module to load. " ) ,
m_slide_option ( LLDB_OPT_SET_1 , false , " slide " , ' s ' , 0 , eArgTypeOffset , " Set the load address for all sections to be the virtual address in the file plus the offset. " , 0 )
{
m_option_group . Append ( & m_uuid_option_group , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_file_option , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_slide_option , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Finalize ( ) ;
}
virtual
~ CommandObjectTargetModulesLoad ( )
{
}
virtual Options *
GetOptions ( )
{
return & m_option_group ;
}
protected :
virtual bool
DoExecute ( Args & args ,
CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = NULL )
{
result . AppendError ( " invalid target, create a debug target using the 'target create' command " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else
{
const size_t argc = args . GetArgumentCount ( ) ;
ModuleSpec module_spec ;
bool search_using_module_spec = false ;
if ( m_file_option . GetOptionValue ( ) . OptionWasSet ( ) )
{
search_using_module_spec = true ;
module_spec . GetFileSpec ( ) = m_file_option . GetOptionValue ( ) . GetCurrentValue ( ) ;
}
if ( m_uuid_option_group . GetOptionValue ( ) . OptionWasSet ( ) )
{
search_using_module_spec = true ;
module_spec . GetUUID ( ) = m_uuid_option_group . GetOptionValue ( ) . GetCurrentValue ( ) ;
}
if ( search_using_module_spec )
{
ModuleList matching_modules ;
const size_t num_matches = target - > GetImages ( ) . FindModules ( module_spec , matching_modules ) ;
char path [ PATH_MAX ] ;
if ( num_matches = = 1 )
{
Module * module = matching_modules . GetModulePointerAtIndex ( 0 ) ;
if ( module )
{
ObjectFile * objfile = module - > GetObjectFile ( ) ;
if ( objfile )
{
SectionList * section_list = module - > GetSectionList ( ) ;
if ( section_list )
{
bool changed = false ;
if ( argc = = 0 )
{
if ( m_slide_option . GetOptionValue ( ) . OptionWasSet ( ) )
{
const addr_t slide = m_slide_option . GetOptionValue ( ) . GetCurrentValue ( ) ;
2014-02-18 11:23:10 -05:00
const bool slide_is_offset = true ;
module - > SetLoadAddress ( * target , slide , slide_is_offset , changed ) ;
2013-08-23 13:46:38 -04:00
}
else
{
result . AppendError ( " one or more section name + load address pair must be specified " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else
{
if ( m_slide_option . GetOptionValue ( ) . OptionWasSet ( ) )
{
result . AppendError ( " The \" --slide <offset> \" option can't be used in conjunction with setting section load addresses. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
for ( size_t i = 0 ; i < argc ; i + = 2 )
{
const char * sect_name = args . GetArgumentAtIndex ( i ) ;
const char * load_addr_cstr = args . GetArgumentAtIndex ( i + 1 ) ;
if ( sect_name & & load_addr_cstr )
{
ConstString const_sect_name ( sect_name ) ;
bool success = false ;
addr_t load_addr = Args : : StringToUInt64 ( load_addr_cstr , LLDB_INVALID_ADDRESS , 0 , & success ) ;
if ( success )
{
SectionSP section_sp ( section_list - > FindSectionByName ( const_sect_name ) ) ;
if ( section_sp )
{
if ( section_sp - > IsThreadSpecific ( ) )
{
result . AppendErrorWithFormat ( " thread specific sections are not yet supported (section '%s') \n " , sect_name ) ;
result . SetStatus ( eReturnStatusFailed ) ;
break ;
}
else
{
if ( target - > GetSectionLoadList ( ) . SetSectionLoadAddress ( section_sp , load_addr ) )
changed = true ;
result . AppendMessageWithFormat ( " section '%s' loaded at 0x% " PRIx64 " \n " , sect_name , load_addr ) ;
}
}
else
{
result . AppendErrorWithFormat ( " no section found that matches the section name '%s' \n " , sect_name ) ;
result . SetStatus ( eReturnStatusFailed ) ;
break ;
}
}
else
{
result . AppendErrorWithFormat ( " invalid load address string '%s' \n " , load_addr_cstr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
break ;
}
}
else
{
if ( sect_name )
result . AppendError ( " section names must be followed by a load address. \n " ) ;
else
result . AppendError ( " one or more section name + load address pair must be specified. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
break ;
}
}
}
if ( changed )
{
target - > ModulesDidLoad ( matching_modules ) ;
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
if ( process )
process - > Flush ( ) ;
}
}
else
{
module - > GetFileSpec ( ) . GetPath ( path , sizeof ( path ) ) ;
result . AppendErrorWithFormat ( " no sections in object file '%s' \n " , path ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
module - > GetFileSpec ( ) . GetPath ( path , sizeof ( path ) ) ;
result . AppendErrorWithFormat ( " no object file for module '%s' \n " , path ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
FileSpec * module_spec_file = module_spec . GetFileSpecPtr ( ) ;
if ( module_spec_file )
{
module_spec_file - > GetPath ( path , sizeof ( path ) ) ;
result . AppendErrorWithFormat ( " invalid module '%s'. \n " , path ) ;
}
else
result . AppendError ( " no module spec " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
std : : string uuid_str ;
if ( module_spec . GetFileSpec ( ) )
module_spec . GetFileSpec ( ) . GetPath ( path , sizeof ( path ) ) ;
else
path [ 0 ] = ' \0 ' ;
if ( module_spec . GetUUIDPtr ( ) )
uuid_str = module_spec . GetUUID ( ) . GetAsString ( ) ;
if ( num_matches > 1 )
{
result . AppendErrorWithFormat ( " multiple modules match%s%s%s%s: \n " ,
path [ 0 ] ? " file= " : " " ,
path ,
! uuid_str . empty ( ) ? " uuid= " : " " ,
uuid_str . c_str ( ) ) ;
for ( size_t i = 0 ; i < num_matches ; + + i )
{
if ( matching_modules . GetModulePointerAtIndex ( i ) - > GetFileSpec ( ) . GetPath ( path , sizeof ( path ) ) )
result . AppendMessageWithFormat ( " %s \n " , path ) ;
}
}
else
{
result . AppendErrorWithFormat ( " no modules were found that match%s%s%s%s. \n " ,
path [ 0 ] ? " file= " : " " ,
path ,
! uuid_str . empty ( ) ? " uuid= " : " " ,
uuid_str . c_str ( ) ) ;
}
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendError ( " either the \" --file <module> \" or the \" --uuid <uuid> \" option must be specified. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
return result . Succeeded ( ) ;
}
OptionGroupOptions m_option_group ;
OptionGroupUUID m_uuid_option_group ;
OptionGroupFile m_file_option ;
OptionGroupUInt64 m_slide_option ;
} ;
//----------------------------------------------------------------------
// List images with associated information
//----------------------------------------------------------------------
class CommandObjectTargetModulesList : public CommandObjectParsed
{
public :
class CommandOptions : public Options
{
public :
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter ) ,
m_format_array ( ) ,
m_use_global_module_list ( false ) ,
m_module_addr ( LLDB_INVALID_ADDRESS )
{
}
virtual
~ CommandOptions ( )
{
}
virtual Error
SetOptionValue ( uint32_t option_idx , const char * option_arg )
{
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
if ( short_option = = ' g ' )
{
m_use_global_module_list = true ;
}
else if ( short_option = = ' a ' )
{
ExecutionContext exe_ctx ( m_interpreter . GetExecutionContext ( ) ) ;
m_module_addr = Args : : StringToAddress ( & exe_ctx , option_arg , LLDB_INVALID_ADDRESS , & error ) ;
}
else
{
unsigned long width = 0 ;
if ( option_arg )
width = strtoul ( option_arg , NULL , 0 ) ;
m_format_array . push_back ( std : : make_pair ( short_option , width ) ) ;
}
return error ;
}
void
OptionParsingStarting ( )
{
m_format_array . clear ( ) ;
m_use_global_module_list = false ;
m_module_addr = LLDB_INVALID_ADDRESS ;
}
const OptionDefinition *
GetDefinitions ( )
{
return g_option_table ;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table [ ] ;
// Instance variables to hold the values for command options.
typedef std : : vector < std : : pair < char , uint32_t > > FormatWidthCollection ;
FormatWidthCollection m_format_array ;
bool m_use_global_module_list ;
lldb : : addr_t m_module_addr ;
} ;
CommandObjectTargetModulesList ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target modules list " ,
" List current executable and dependent shared library images. " ,
" target modules list [<cmd-options>] " ) ,
m_options ( interpreter )
{
}
virtual
~ CommandObjectTargetModulesList ( )
{
}
virtual
Options *
GetOptions ( )
{
return & m_options ;
}
protected :
virtual bool
DoExecute ( Args & command ,
CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
const bool use_global_module_list = m_options . m_use_global_module_list ;
// Define a local module list here to ensure it lives longer than any "locker"
// object which might lock its contents below (through the "module_list_ptr"
// variable).
ModuleList module_list ;
if ( target = = NULL & & use_global_module_list = = false )
{
result . AppendError ( " invalid target, create a debug target using the 'target create' command " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else
{
if ( target )
{
uint32_t addr_byte_size = target - > GetArchitecture ( ) . GetAddressByteSize ( ) ;
result . GetOutputStream ( ) . SetAddressByteSize ( addr_byte_size ) ;
result . GetErrorStream ( ) . SetAddressByteSize ( addr_byte_size ) ;
}
// Dump all sections for all modules images
Stream & strm = result . GetOutputStream ( ) ;
if ( m_options . m_module_addr ! = LLDB_INVALID_ADDRESS )
{
if ( target )
{
Address module_address ;
if ( module_address . SetLoadAddress ( m_options . m_module_addr , target ) )
{
ModuleSP module_sp ( module_address . GetModule ( ) ) ;
if ( module_sp )
{
PrintModule ( target , module_sp . get ( ) , 0 , strm ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
result . AppendErrorWithFormat ( " Couldn't find module matching address: 0x% " PRIx64 " . " , m_options . m_module_addr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendErrorWithFormat ( " Couldn't find module containing address: 0x% " PRIx64 " . " , m_options . m_module_addr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendError ( " Can only look up modules by address with a valid target. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
size_t num_modules = 0 ;
Mutex : : Locker locker ; // This locker will be locked on the mutex in module_list_ptr if it is non-NULL.
// Otherwise it will lock the AllocationModuleCollectionMutex when accessing
// the global module list directly.
const ModuleList * module_list_ptr = NULL ;
const size_t argc = command . GetArgumentCount ( ) ;
if ( argc = = 0 )
{
if ( use_global_module_list )
{
locker . Lock ( Module : : GetAllocationModuleCollectionMutex ( ) ) ;
num_modules = Module : : GetNumberAllocatedModules ( ) ;
}
else
{
module_list_ptr = & target - > GetImages ( ) ;
}
}
else
{
for ( size_t i = 0 ; i < argc ; + + i )
{
// Dump specified images (by basename or fullpath)
const char * arg_cstr = command . GetArgumentAtIndex ( i ) ;
const size_t num_matches = FindModulesByName ( target , arg_cstr , module_list , use_global_module_list ) ;
if ( num_matches = = 0 )
{
if ( argc = = 1 )
{
result . AppendErrorWithFormat ( " no modules found that match '%s' " , arg_cstr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
}
module_list_ptr = & module_list ;
}
if ( module_list_ptr ! = NULL )
{
locker . Lock ( module_list_ptr - > GetMutex ( ) ) ;
num_modules = module_list_ptr - > GetSize ( ) ;
}
if ( num_modules > 0 )
{
for ( uint32_t image_idx = 0 ; image_idx < num_modules ; + + image_idx )
{
ModuleSP module_sp ;
Module * module ;
if ( module_list_ptr )
{
module_sp = module_list_ptr - > GetModuleAtIndexUnlocked ( image_idx ) ;
module = module_sp . get ( ) ;
}
else
{
module = Module : : GetAllocatedModuleAtIndex ( image_idx ) ;
module_sp = module - > shared_from_this ( ) ;
}
const size_t indent = strm . Printf ( " [%3u] " , image_idx ) ;
PrintModule ( target , module , indent , strm ) ;
}
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
if ( argc )
{
if ( use_global_module_list )
result . AppendError ( " the global module list has no matching modules " ) ;
else
result . AppendError ( " the target has no matching modules " ) ;
}
else
{
if ( use_global_module_list )
result . AppendError ( " the global module list is empty " ) ;
else
result . AppendError ( " the target has no associated executable images " ) ;
}
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
return result . Succeeded ( ) ;
}
void
PrintModule ( Target * target , Module * module , int indent , Stream & strm )
{
if ( module = = NULL )
{
strm . PutCString ( " Null module " ) ;
return ;
}
bool dump_object_name = false ;
if ( m_options . m_format_array . empty ( ) )
{
m_options . m_format_array . push_back ( std : : make_pair ( ' u ' , 0 ) ) ;
m_options . m_format_array . push_back ( std : : make_pair ( ' h ' , 0 ) ) ;
m_options . m_format_array . push_back ( std : : make_pair ( ' f ' , 0 ) ) ;
m_options . m_format_array . push_back ( std : : make_pair ( ' S ' , 0 ) ) ;
}
const size_t num_entries = m_options . m_format_array . size ( ) ;
bool print_space = false ;
for ( size_t i = 0 ; i < num_entries ; + + i )
{
if ( print_space )
strm . PutChar ( ' ' ) ;
print_space = true ;
const char format_char = m_options . m_format_array [ i ] . first ;
uint32_t width = m_options . m_format_array [ i ] . second ;
switch ( format_char )
{
case ' A ' :
DumpModuleArchitecture ( strm , module , false , width ) ;
break ;
case ' t ' :
DumpModuleArchitecture ( strm , module , true , width ) ;
break ;
case ' f ' :
DumpFullpath ( strm , & module - > GetFileSpec ( ) , width ) ;
dump_object_name = true ;
break ;
case ' d ' :
DumpDirectory ( strm , & module - > GetFileSpec ( ) , width ) ;
break ;
case ' b ' :
DumpBasename ( strm , & module - > GetFileSpec ( ) , width ) ;
dump_object_name = true ;
break ;
case ' h ' :
case ' o ' :
// Image header address
{
uint32_t addr_nibble_width = target ? ( target - > GetArchitecture ( ) . GetAddressByteSize ( ) * 2 ) : 16 ;
ObjectFile * objfile = module - > GetObjectFile ( ) ;
if ( objfile )
{
Address header_addr ( objfile - > GetHeaderAddress ( ) ) ;
if ( header_addr . IsValid ( ) )
{
if ( target & & ! target - > GetSectionLoadList ( ) . IsEmpty ( ) )
{
lldb : : addr_t header_load_addr = header_addr . GetLoadAddress ( target ) ;
if ( header_load_addr = = LLDB_INVALID_ADDRESS )
{
header_addr . Dump ( & strm , target , Address : : DumpStyleModuleWithFileAddress , Address : : DumpStyleFileAddress ) ;
}
else
{
if ( format_char = = ' o ' )
{
// Show the offset of slide for the image
strm . Printf ( " 0x%*.* " PRIx64 , addr_nibble_width , addr_nibble_width , header_load_addr - header_addr . GetFileAddress ( ) ) ;
}
else
{
// Show the load address of the image
strm . Printf ( " 0x%*.* " PRIx64 , addr_nibble_width , addr_nibble_width , header_load_addr ) ;
}
}
break ;
}
// The address was valid, but the image isn't loaded, output the address in an appropriate format
header_addr . Dump ( & strm , target , Address : : DumpStyleFileAddress ) ;
break ;
}
}
strm . Printf ( " %*s " , addr_nibble_width + 2 , " " ) ;
}
break ;
case ' r ' :
{
size_t ref_count = 0 ;
ModuleSP module_sp ( module - > shared_from_this ( ) ) ;
if ( module_sp )
{
// Take one away to make sure we don't count our local "module_sp"
ref_count = module_sp . use_count ( ) - 1 ;
}
if ( width )
strm . Printf ( " {%*zu} " , width , ref_count ) ;
else
strm . Printf ( " {%zu} " , ref_count ) ;
}
break ;
case ' s ' :
case ' S ' :
{
SymbolVendor * symbol_vendor = module - > GetSymbolVendor ( ) ;
if ( symbol_vendor )
{
SymbolFile * symbol_file = symbol_vendor - > GetSymbolFile ( ) ;
if ( symbol_file )
{
if ( format_char = = ' S ' )
{
FileSpec & symfile_spec = symbol_file - > GetObjectFile ( ) - > GetFileSpec ( ) ;
// Dump symbol file only if different from module file
if ( ! symfile_spec | | symfile_spec = = module - > GetFileSpec ( ) )
{
print_space = false ;
break ;
}
// Add a newline and indent past the index
strm . Printf ( " \n %*s " , indent , " " ) ;
}
DumpFullpath ( strm , & symbol_file - > GetObjectFile ( ) - > GetFileSpec ( ) , width ) ;
dump_object_name = true ;
break ;
}
}
strm . Printf ( " %.*s " , width , " <NONE> " ) ;
}
break ;
case ' m ' :
module - > GetModificationTime ( ) . Dump ( & strm , width ) ;
break ;
case ' p ' :
strm . Printf ( " %p " , module ) ;
break ;
case ' u ' :
DumpModuleUUID ( strm , module ) ;
break ;
default :
break ;
}
}
if ( dump_object_name )
{
const char * object_name = module - > GetObjectName ( ) . GetCString ( ) ;
if ( object_name )
strm . Printf ( " (%s) " , object_name ) ;
}
strm . EOL ( ) ;
}
CommandOptions m_options ;
} ;
OptionDefinition
CommandObjectTargetModulesList : : CommandOptions : : g_option_table [ ] =
{
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_1 , false , " address " , ' a ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeAddressOrExpression , " Display the image at this address. " } ,
{ LLDB_OPT_SET_1 , false , " arch " , ' A ' , OptionParser : : eOptionalArgument , NULL , 0 , eArgTypeWidth , " Display the architecture when listing images. " } ,
{ LLDB_OPT_SET_1 , false , " triple " , ' t ' , OptionParser : : eOptionalArgument , NULL , 0 , eArgTypeWidth , " Display the triple when listing images. " } ,
{ LLDB_OPT_SET_1 , false , " header " , ' h ' , OptionParser : : eNoArgument , NULL , 0 , eArgTypeNone , " Display the image header address as a load address if debugging, a file address otherwise. " } ,
{ LLDB_OPT_SET_1 , false , " offset " , ' o ' , OptionParser : : eNoArgument , NULL , 0 , eArgTypeNone , " Display the image header address offset from the header file address (the slide amount). " } ,
{ LLDB_OPT_SET_1 , false , " uuid " , ' u ' , OptionParser : : eNoArgument , NULL , 0 , eArgTypeNone , " Display the UUID when listing images. " } ,
{ LLDB_OPT_SET_1 , false , " fullpath " , ' f ' , OptionParser : : eOptionalArgument , NULL , 0 , eArgTypeWidth , " Display the fullpath to the image object file. " } ,
{ LLDB_OPT_SET_1 , false , " directory " , ' d ' , OptionParser : : eOptionalArgument , NULL , 0 , eArgTypeWidth , " Display the directory with optional width for the image object file. " } ,
{ LLDB_OPT_SET_1 , false , " basename " , ' b ' , OptionParser : : eOptionalArgument , NULL , 0 , eArgTypeWidth , " Display the basename with optional width for the image object file. " } ,
{ LLDB_OPT_SET_1 , false , " symfile " , ' s ' , OptionParser : : eOptionalArgument , NULL , 0 , eArgTypeWidth , " Display the fullpath to the image symbol file with optional width. " } ,
{ LLDB_OPT_SET_1 , false , " symfile-unique " , ' S ' , OptionParser : : eOptionalArgument , NULL , 0 , eArgTypeWidth , " Display the symbol file with optional width only if it is different from the executable object file. " } ,
{ LLDB_OPT_SET_1 , false , " mod-time " , ' m ' , OptionParser : : eOptionalArgument , NULL , 0 , eArgTypeWidth , " Display the modification time with optional width of the module. " } ,
{ LLDB_OPT_SET_1 , false , " ref-count " , ' r ' , OptionParser : : eOptionalArgument , NULL , 0 , eArgTypeWidth , " Display the reference count if the module is still in the shared module cache. " } ,
{ LLDB_OPT_SET_1 , false , " pointer " , ' p ' , OptionParser : : eOptionalArgument , NULL , 0 , eArgTypeNone , " Display the module pointer. " } ,
{ LLDB_OPT_SET_1 , false , " global " , ' g ' , OptionParser : : eNoArgument , NULL , 0 , eArgTypeNone , " Display the modules from the global module list, not just the current target. " } ,
2013-08-23 13:46:38 -04:00
{ 0 , false , NULL , 0 , 0 , NULL , 0 , eArgTypeNone , NULL }
} ;
# pragma mark CommandObjectTargetModulesShowUnwind
//----------------------------------------------------------------------
// Lookup unwind information in images
//----------------------------------------------------------------------
class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed
{
public :
enum
{
eLookupTypeInvalid = - 1 ,
eLookupTypeAddress = 0 ,
eLookupTypeSymbol ,
eLookupTypeFunction ,
eLookupTypeFunctionOrSymbol ,
kNumLookupTypes
} ;
class CommandOptions : public Options
{
public :
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter ) ,
m_type ( eLookupTypeInvalid ) ,
m_str ( ) ,
m_addr ( LLDB_INVALID_ADDRESS )
{
}
virtual
~ CommandOptions ( )
{
}
virtual Error
SetOptionValue ( uint32_t option_idx , const char * option_arg )
{
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option )
{
case ' a ' :
{
ExecutionContext exe_ctx ( m_interpreter . GetExecutionContext ( ) ) ;
2013-11-06 11:48:53 -05:00
m_str = option_arg ;
2013-08-23 13:46:38 -04:00
m_type = eLookupTypeAddress ;
m_addr = Args : : StringToAddress ( & exe_ctx , option_arg , LLDB_INVALID_ADDRESS , & error ) ;
if ( m_addr = = LLDB_INVALID_ADDRESS )
error . SetErrorStringWithFormat ( " invalid address string '%s' " , option_arg ) ;
break ;
}
case ' n ' :
{
m_str = option_arg ;
m_type = eLookupTypeFunctionOrSymbol ;
break ;
}
2013-11-06 11:48:53 -05:00
default :
error . SetErrorStringWithFormat ( " unrecognized option %c. " , short_option ) ;
break ;
2013-08-23 13:46:38 -04:00
}
return error ;
}
void
OptionParsingStarting ( )
{
m_type = eLookupTypeInvalid ;
m_str . clear ( ) ;
m_addr = LLDB_INVALID_ADDRESS ;
}
const OptionDefinition *
GetDefinitions ( )
{
return g_option_table ;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table [ ] ;
// Instance variables to hold the values for command options.
int m_type ; // Should be a eLookupTypeXXX enum after parsing options
std : : string m_str ; // Holds name lookup
lldb : : addr_t m_addr ; // Holds the address to lookup
} ;
CommandObjectTargetModulesShowUnwind ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target modules show-unwind " ,
" Show synthesized unwind instructions for a function. " ,
NULL ,
eFlagRequiresTarget |
eFlagRequiresProcess |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused ) ,
m_options ( interpreter )
{
}
virtual
~ CommandObjectTargetModulesShowUnwind ( )
{
}
virtual
Options *
GetOptions ( )
{
return & m_options ;
}
protected :
bool
DoExecute ( Args & command ,
CommandReturnObject & result )
{
Target * target = m_exe_ctx . GetTargetPtr ( ) ;
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
ABI * abi = NULL ;
if ( process )
abi = process - > GetABI ( ) . get ( ) ;
if ( process = = NULL )
{
result . AppendError ( " You must have a process running to use this command. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
ThreadList threads ( process - > GetThreadList ( ) ) ;
if ( threads . GetSize ( ) = = 0 )
{
result . AppendError ( " The process must be paused to use this command. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
ThreadSP thread ( threads . GetThreadAtIndex ( 0 ) ) ;
if ( thread . get ( ) = = NULL )
{
result . AppendError ( " The process must be paused to use this command. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
SymbolContextList sc_list ;
if ( m_options . m_type = = eLookupTypeFunctionOrSymbol )
{
ConstString function_name ( m_options . m_str . c_str ( ) ) ;
target - > GetImages ( ) . FindFunctions ( function_name , eFunctionNameTypeAuto , true , false , true , sc_list ) ;
}
else if ( m_options . m_type = = eLookupTypeAddress & & target )
{
Address addr ;
if ( target - > GetSectionLoadList ( ) . ResolveLoadAddress ( m_options . m_addr , addr ) )
{
SymbolContext sc ;
ModuleSP module_sp ( addr . GetModule ( ) ) ;
module_sp - > ResolveSymbolContextForAddress ( addr , eSymbolContextEverything , sc ) ;
if ( sc . function | | sc . symbol )
{
sc_list . Append ( sc ) ;
}
}
}
2013-11-06 11:48:53 -05:00
else
{
result . AppendError ( " address-expression or function name option must be specified. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2013-08-23 13:46:38 -04:00
size_t num_matches = sc_list . GetSize ( ) ;
2013-11-06 11:48:53 -05:00
if ( num_matches = = 0 )
{
result . AppendErrorWithFormat ( " no unwind data found that matches '%s'. " , m_options . m_str . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2013-08-23 13:46:38 -04:00
for ( uint32_t idx = 0 ; idx < num_matches ; idx + + )
{
SymbolContext sc ;
sc_list . GetContextAtIndex ( idx , sc ) ;
if ( sc . symbol = = NULL & & sc . function = = NULL )
continue ;
if ( sc . module_sp . get ( ) = = NULL | | sc . module_sp - > GetObjectFile ( ) = = NULL )
continue ;
AddressRange range ;
if ( ! sc . GetAddressRange ( eSymbolContextFunction | eSymbolContextSymbol , 0 , false , range ) )
continue ;
if ( ! range . GetBaseAddress ( ) . IsValid ( ) )
continue ;
ConstString funcname ( sc . GetFunctionName ( ) ) ;
if ( funcname . IsEmpty ( ) )
continue ;
addr_t start_addr = range . GetBaseAddress ( ) . GetLoadAddress ( target ) ;
if ( abi )
start_addr = abi - > FixCodeAddress ( start_addr ) ;
FuncUnwindersSP func_unwinders_sp ( sc . module_sp - > GetObjectFile ( ) - > GetUnwindTable ( ) . GetUncachedFuncUnwindersContainingAddress ( start_addr , sc ) ) ;
if ( func_unwinders_sp . get ( ) = = NULL )
continue ;
Address first_non_prologue_insn ( func_unwinders_sp - > GetFirstNonPrologueInsn ( * target ) ) ;
if ( first_non_prologue_insn . IsValid ( ) )
{
result . GetOutputStream ( ) . Printf ( " First non-prologue instruction is at address 0x% " PRIx64 " or offset % " PRId64 " into the function. \n " , first_non_prologue_insn . GetLoadAddress ( target ) , first_non_prologue_insn . GetLoadAddress ( target ) - start_addr ) ;
result . GetOutputStream ( ) . Printf ( " \n " ) ;
}
UnwindPlanSP non_callsite_unwind_plan = func_unwinders_sp - > GetUnwindPlanAtNonCallSite ( * thread . get ( ) ) ;
if ( non_callsite_unwind_plan . get ( ) )
{
result . GetOutputStream ( ) . Printf ( " Asynchronous (not restricted to call-sites) UnwindPlan for %s`%s (start addr 0x% " PRIx64 " ): \n " , sc . module_sp - > GetPlatformFileSpec ( ) . GetFilename ( ) . AsCString ( ) , funcname . AsCString ( ) , start_addr ) ;
non_callsite_unwind_plan - > Dump ( result . GetOutputStream ( ) , thread . get ( ) , LLDB_INVALID_ADDRESS ) ;
result . GetOutputStream ( ) . Printf ( " \n " ) ;
}
UnwindPlanSP callsite_unwind_plan = func_unwinders_sp - > GetUnwindPlanAtCallSite ( - 1 ) ;
if ( callsite_unwind_plan . get ( ) )
{
result . GetOutputStream ( ) . Printf ( " Synchronous (restricted to call-sites) UnwindPlan for %s`%s (start addr 0x% " PRIx64 " ): \n " , sc . module_sp - > GetPlatformFileSpec ( ) . GetFilename ( ) . AsCString ( ) , funcname . AsCString ( ) , start_addr ) ;
callsite_unwind_plan - > Dump ( result . GetOutputStream ( ) , thread . get ( ) , LLDB_INVALID_ADDRESS ) ;
result . GetOutputStream ( ) . Printf ( " \n " ) ;
}
UnwindPlanSP arch_default_unwind_plan = func_unwinders_sp - > GetUnwindPlanArchitectureDefault ( * thread . get ( ) ) ;
if ( arch_default_unwind_plan . get ( ) )
{
result . GetOutputStream ( ) . Printf ( " Architecture default UnwindPlan for %s`%s (start addr 0x% " PRIx64 " ): \n " , sc . module_sp - > GetPlatformFileSpec ( ) . GetFilename ( ) . AsCString ( ) , funcname . AsCString ( ) , start_addr ) ;
arch_default_unwind_plan - > Dump ( result . GetOutputStream ( ) , thread . get ( ) , LLDB_INVALID_ADDRESS ) ;
result . GetOutputStream ( ) . Printf ( " \n " ) ;
}
UnwindPlanSP fast_unwind_plan = func_unwinders_sp - > GetUnwindPlanFastUnwind ( * thread . get ( ) ) ;
if ( fast_unwind_plan . get ( ) )
{
result . GetOutputStream ( ) . Printf ( " Fast UnwindPlan for %s`%s (start addr 0x% " PRIx64 " ): \n " , sc . module_sp - > GetPlatformFileSpec ( ) . GetFilename ( ) . AsCString ( ) , funcname . AsCString ( ) , start_addr ) ;
fast_unwind_plan - > Dump ( result . GetOutputStream ( ) , thread . get ( ) , LLDB_INVALID_ADDRESS ) ;
result . GetOutputStream ( ) . Printf ( " \n " ) ;
}
result . GetOutputStream ( ) . Printf ( " \n " ) ;
}
return result . Succeeded ( ) ;
}
CommandOptions m_options ;
} ;
OptionDefinition
CommandObjectTargetModulesShowUnwind : : CommandOptions : : g_option_table [ ] =
{
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_1 , false , " name " , ' n ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeFunctionName , " Show unwind instructions for a function or symbol name. " } ,
{ LLDB_OPT_SET_2 , false , " address " , ' a ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeAddressOrExpression , " Show unwind instructions for a function or symbol containing an address " } ,
2013-08-23 13:46:38 -04:00
{ 0 , false , NULL , 0 , 0 , NULL , 0 , eArgTypeNone , NULL }
} ;
//----------------------------------------------------------------------
// Lookup information in images
//----------------------------------------------------------------------
class CommandObjectTargetModulesLookup : public CommandObjectParsed
{
public :
enum
{
eLookupTypeInvalid = - 1 ,
eLookupTypeAddress = 0 ,
eLookupTypeSymbol ,
eLookupTypeFileLine , // Line is optional
eLookupTypeFunction ,
eLookupTypeFunctionOrSymbol ,
eLookupTypeType ,
kNumLookupTypes
} ;
class CommandOptions : public Options
{
public :
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter )
{
OptionParsingStarting ( ) ;
}
virtual
~ CommandOptions ( )
{
}
virtual Error
SetOptionValue ( uint32_t option_idx , const char * option_arg )
{
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option )
{
case ' a ' :
{
m_type = eLookupTypeAddress ;
ExecutionContext exe_ctx ( m_interpreter . GetExecutionContext ( ) ) ;
m_addr = Args : : StringToAddress ( & exe_ctx , option_arg , LLDB_INVALID_ADDRESS , & error ) ;
}
break ;
case ' o ' :
m_offset = Args : : StringToUInt64 ( option_arg , LLDB_INVALID_ADDRESS ) ;
if ( m_offset = = LLDB_INVALID_ADDRESS )
error . SetErrorStringWithFormat ( " invalid offset string '%s' " , option_arg ) ;
break ;
case ' s ' :
m_str = option_arg ;
m_type = eLookupTypeSymbol ;
break ;
case ' f ' :
m_file . SetFile ( option_arg , false ) ;
m_type = eLookupTypeFileLine ;
break ;
case ' i ' :
m_include_inlines = false ;
break ;
case ' l ' :
m_line_number = Args : : StringToUInt32 ( option_arg , UINT32_MAX ) ;
if ( m_line_number = = UINT32_MAX )
error . SetErrorStringWithFormat ( " invalid line number string '%s' " , option_arg ) ;
else if ( m_line_number = = 0 )
error . SetErrorString ( " zero is an invalid line number " ) ;
m_type = eLookupTypeFileLine ;
break ;
case ' F ' :
m_str = option_arg ;
m_type = eLookupTypeFunction ;
break ;
case ' n ' :
m_str = option_arg ;
m_type = eLookupTypeFunctionOrSymbol ;
break ;
case ' t ' :
m_str = option_arg ;
m_type = eLookupTypeType ;
break ;
case ' v ' :
m_verbose = 1 ;
break ;
case ' A ' :
m_print_all = true ;
break ;
case ' r ' :
m_use_regex = true ;
break ;
}
return error ;
}
void
OptionParsingStarting ( )
{
m_type = eLookupTypeInvalid ;
m_str . clear ( ) ;
m_file . Clear ( ) ;
m_addr = LLDB_INVALID_ADDRESS ;
m_offset = 0 ;
m_line_number = 0 ;
m_use_regex = false ;
m_include_inlines = true ;
m_verbose = false ;
m_print_all = false ;
}
const OptionDefinition *
GetDefinitions ( )
{
return g_option_table ;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table [ ] ;
int m_type ; // Should be a eLookupTypeXXX enum after parsing options
std : : string m_str ; // Holds name lookup
FileSpec m_file ; // Files for file lookups
lldb : : addr_t m_addr ; // Holds the address to lookup
lldb : : addr_t m_offset ; // Subtract this offset from m_addr before doing lookups.
uint32_t m_line_number ; // Line number for file+line lookups
bool m_use_regex ; // Name lookups in m_str are regular expressions.
bool m_include_inlines ; // Check for inline entries when looking up by file/line.
bool m_verbose ; // Enable verbose lookup info
bool m_print_all ; // Print all matches, even in cases where there's a best match.
} ;
CommandObjectTargetModulesLookup ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target modules lookup " ,
" Look up information within executable and dependent shared library images. " ,
NULL ,
eFlagRequiresTarget ) ,
m_options ( interpreter )
{
CommandArgumentEntry arg ;
CommandArgumentData file_arg ;
// Define the first (and only) variant of this arg.
file_arg . arg_type = eArgTypeFilename ;
file_arg . arg_repetition = eArgRepeatStar ;
// There is only one variant this argument could be; put it into the argument entry.
arg . push_back ( file_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
}
virtual
~ CommandObjectTargetModulesLookup ( )
{
}
virtual Options *
GetOptions ( )
{
return & m_options ;
}
bool
LookupHere ( CommandInterpreter & interpreter , CommandReturnObject & result , bool & syntax_error )
{
switch ( m_options . m_type )
{
case eLookupTypeAddress :
case eLookupTypeFileLine :
case eLookupTypeFunction :
case eLookupTypeFunctionOrSymbol :
case eLookupTypeSymbol :
default :
return false ;
case eLookupTypeType :
break ;
}
StackFrameSP frame = m_exe_ctx . GetFrameSP ( ) ;
if ( ! frame )
return false ;
const SymbolContext & sym_ctx ( frame - > GetSymbolContext ( eSymbolContextModule ) ) ;
if ( ! sym_ctx . module_sp )
return false ;
switch ( m_options . m_type )
{
default :
return false ;
case eLookupTypeType :
if ( ! m_options . m_str . empty ( ) )
{
if ( LookupTypeHere ( m_interpreter ,
result . GetOutputStream ( ) ,
sym_ctx ,
m_options . m_str . c_str ( ) ,
m_options . m_use_regex ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return true ;
}
}
break ;
}
return true ;
}
bool
LookupInModule ( CommandInterpreter & interpreter , Module * module , CommandReturnObject & result , bool & syntax_error )
{
switch ( m_options . m_type )
{
case eLookupTypeAddress :
if ( m_options . m_addr ! = LLDB_INVALID_ADDRESS )
{
if ( LookupAddressInModule ( m_interpreter ,
result . GetOutputStream ( ) ,
module ,
eSymbolContextEverything ,
m_options . m_addr ,
m_options . m_offset ,
m_options . m_verbose ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return true ;
}
}
break ;
case eLookupTypeSymbol :
if ( ! m_options . m_str . empty ( ) )
{
if ( LookupSymbolInModule ( m_interpreter ,
result . GetOutputStream ( ) ,
module ,
m_options . m_str . c_str ( ) ,
m_options . m_use_regex ,
m_options . m_verbose ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return true ;
}
}
break ;
case eLookupTypeFileLine :
if ( m_options . m_file )
{
if ( LookupFileAndLineInModule ( m_interpreter ,
result . GetOutputStream ( ) ,
module ,
m_options . m_file ,
m_options . m_line_number ,
m_options . m_include_inlines ,
m_options . m_verbose ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return true ;
}
}
break ;
case eLookupTypeFunctionOrSymbol :
case eLookupTypeFunction :
if ( ! m_options . m_str . empty ( ) )
{
if ( LookupFunctionInModule ( m_interpreter ,
result . GetOutputStream ( ) ,
module ,
m_options . m_str . c_str ( ) ,
m_options . m_use_regex ,
m_options . m_include_inlines ,
m_options . m_type = = eLookupTypeFunctionOrSymbol , // include symbols
m_options . m_verbose ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return true ;
}
}
break ;
case eLookupTypeType :
if ( ! m_options . m_str . empty ( ) )
{
if ( LookupTypeInModule ( m_interpreter ,
result . GetOutputStream ( ) ,
module ,
m_options . m_str . c_str ( ) ,
m_options . m_use_regex ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return true ;
}
}
break ;
default :
m_options . GenerateOptionUsage ( result . GetErrorStream ( ) , this ) ;
syntax_error = true ;
break ;
}
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
protected :
virtual bool
DoExecute ( Args & command ,
CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = NULL )
{
result . AppendError ( " invalid target, create a debug target using the 'target create' command " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else
{
bool syntax_error = false ;
uint32_t i ;
uint32_t num_successful_lookups = 0 ;
uint32_t addr_byte_size = target - > GetArchitecture ( ) . GetAddressByteSize ( ) ;
result . GetOutputStream ( ) . SetAddressByteSize ( addr_byte_size ) ;
result . GetErrorStream ( ) . SetAddressByteSize ( addr_byte_size ) ;
// Dump all sections for all modules images
if ( command . GetArgumentCount ( ) = = 0 )
{
ModuleSP current_module ;
// Where it is possible to look in the current symbol context
// first, try that. If this search was successful and --all
// was not passed, don't print anything else.
if ( LookupHere ( m_interpreter , result , syntax_error ) )
{
result . GetOutputStream ( ) . EOL ( ) ;
num_successful_lookups + + ;
if ( ! m_options . m_print_all )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return result . Succeeded ( ) ;
}
}
// Dump all sections for all other modules
const ModuleList & target_modules = target - > GetImages ( ) ;
Mutex : : Locker modules_locker ( target_modules . GetMutex ( ) ) ;
const size_t num_modules = target_modules . GetSize ( ) ;
if ( num_modules > 0 )
{
for ( i = 0 ; i < num_modules & & syntax_error = = false ; + + i )
{
Module * module_pointer = target_modules . GetModulePointerAtIndexUnlocked ( i ) ;
if ( module_pointer ! = current_module . get ( ) & &
LookupInModule ( m_interpreter , target_modules . GetModulePointerAtIndexUnlocked ( i ) , result , syntax_error ) )
{
result . GetOutputStream ( ) . EOL ( ) ;
num_successful_lookups + + ;
}
}
}
else
{
result . AppendError ( " the target has no associated executable images " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else
{
// Dump specified images (by basename or fullpath)
const char * arg_cstr ;
for ( i = 0 ; ( arg_cstr = command . GetArgumentAtIndex ( i ) ) ! = NULL & & syntax_error = = false ; + + i )
{
ModuleList module_list ;
const size_t num_matches = FindModulesByName ( target , arg_cstr , module_list , false ) ;
if ( num_matches > 0 )
{
for ( size_t j = 0 ; j < num_matches ; + + j )
{
Module * module = module_list . GetModulePointerAtIndex ( j ) ;
if ( module )
{
if ( LookupInModule ( m_interpreter , module , result , syntax_error ) )
{
result . GetOutputStream ( ) . EOL ( ) ;
num_successful_lookups + + ;
}
}
}
}
else
result . AppendWarningWithFormat ( " Unable to find an image that matches '%s'. \n " , arg_cstr ) ;
}
}
if ( num_successful_lookups > 0 )
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
else
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
CommandOptions m_options ;
} ;
OptionDefinition
CommandObjectTargetModulesLookup : : CommandOptions : : g_option_table [ ] =
{
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_1 , true , " address " , ' a ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeAddressOrExpression , " Lookup an address in one or more target modules. " } ,
{ LLDB_OPT_SET_1 , false , " offset " , ' o ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeOffset , " When looking up an address subtract <offset> from any addresses before doing the lookup. " } ,
2013-08-23 13:46:38 -04:00
{ LLDB_OPT_SET_2 | LLDB_OPT_SET_4 | LLDB_OPT_SET_5
/* FIXME: re-enable this for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_6 */ ,
2013-11-06 11:48:53 -05:00
false , " regex " , ' r ' , OptionParser : : eNoArgument , NULL , 0 , eArgTypeNone , " The <name> argument for name lookups are regular expressions. " } ,
{ LLDB_OPT_SET_2 , true , " symbol " , ' s ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeSymbol , " Lookup a symbol by name in the symbol tables in one or more target modules. " } ,
{ LLDB_OPT_SET_3 , true , " file " , ' f ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeFilename , " Lookup a file by fullpath or basename in one or more target modules. " } ,
{ LLDB_OPT_SET_3 , false , " line " , ' l ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeLineNum , " Lookup a line number in a file (must be used in conjunction with --file). " } ,
2013-08-23 13:46:38 -04:00
{ LLDB_OPT_SET_FROM_TO ( 3 , 5 ) ,
2013-11-06 11:48:53 -05:00
false , " no-inlines " , ' i ' , OptionParser : : eNoArgument , NULL , 0 , eArgTypeNone , " Ignore inline entries (must be used in conjunction with --file or --function). " } ,
{ LLDB_OPT_SET_4 , true , " function " , ' F ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeFunctionName , " Lookup a function by name in the debug symbols in one or more target modules. " } ,
{ LLDB_OPT_SET_5 , true , " name " , ' n ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeFunctionOrSymbol , " Lookup a function or symbol by name in one or more target modules. " } ,
{ LLDB_OPT_SET_6 , true , " type " , ' t ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeName , " Lookup a type by name in the debug symbols in one or more target modules. " } ,
{ LLDB_OPT_SET_ALL , false , " verbose " , ' v ' , OptionParser : : eNoArgument , NULL , 0 , eArgTypeNone , " Enable verbose lookup information. " } ,
{ LLDB_OPT_SET_ALL , false , " all " , ' A ' , OptionParser : : eNoArgument , NULL , 0 , eArgTypeNone , " Print all matches, not just the best match, if a best match is available. " } ,
2013-08-23 13:46:38 -04:00
{ 0 , false , NULL , 0 , 0 , NULL , 0 , eArgTypeNone , NULL }
} ;
# pragma mark CommandObjectMultiwordImageSearchPaths
//-------------------------------------------------------------------------
// CommandObjectMultiwordImageSearchPaths
//-------------------------------------------------------------------------
class CommandObjectTargetModulesImageSearchPaths : public CommandObjectMultiword
{
public :
CommandObjectTargetModulesImageSearchPaths ( CommandInterpreter & interpreter ) :
CommandObjectMultiword ( interpreter ,
" target modules search-paths " ,
" A set of commands for operating on debugger target image search paths. " ,
" target modules search-paths <subcommand> [<subcommand-options>] " )
{
LoadSubCommand ( " add " , CommandObjectSP ( new CommandObjectTargetModulesSearchPathsAdd ( interpreter ) ) ) ;
LoadSubCommand ( " clear " , CommandObjectSP ( new CommandObjectTargetModulesSearchPathsClear ( interpreter ) ) ) ;
LoadSubCommand ( " insert " , CommandObjectSP ( new CommandObjectTargetModulesSearchPathsInsert ( interpreter ) ) ) ;
LoadSubCommand ( " list " , CommandObjectSP ( new CommandObjectTargetModulesSearchPathsList ( interpreter ) ) ) ;
LoadSubCommand ( " query " , CommandObjectSP ( new CommandObjectTargetModulesSearchPathsQuery ( interpreter ) ) ) ;
}
~ CommandObjectTargetModulesImageSearchPaths ( )
{
}
} ;
# pragma mark CommandObjectTargetModules
//-------------------------------------------------------------------------
// CommandObjectTargetModules
//-------------------------------------------------------------------------
class CommandObjectTargetModules : public CommandObjectMultiword
{
public :
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
CommandObjectTargetModules ( CommandInterpreter & interpreter ) :
CommandObjectMultiword ( interpreter ,
" target modules " ,
" A set of commands for accessing information for one or more target modules. " ,
" target modules <sub-command> ... " )
{
LoadSubCommand ( " add " , CommandObjectSP ( new CommandObjectTargetModulesAdd ( interpreter ) ) ) ;
LoadSubCommand ( " load " , CommandObjectSP ( new CommandObjectTargetModulesLoad ( interpreter ) ) ) ;
LoadSubCommand ( " dump " , CommandObjectSP ( new CommandObjectTargetModulesDump ( interpreter ) ) ) ;
LoadSubCommand ( " list " , CommandObjectSP ( new CommandObjectTargetModulesList ( interpreter ) ) ) ;
LoadSubCommand ( " lookup " , CommandObjectSP ( new CommandObjectTargetModulesLookup ( interpreter ) ) ) ;
LoadSubCommand ( " search-paths " , CommandObjectSP ( new CommandObjectTargetModulesImageSearchPaths ( interpreter ) ) ) ;
LoadSubCommand ( " show-unwind " , CommandObjectSP ( new CommandObjectTargetModulesShowUnwind ( interpreter ) ) ) ;
}
virtual
~ CommandObjectTargetModules ( )
{
}
private :
//------------------------------------------------------------------
// For CommandObjectTargetModules only
//------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN ( CommandObjectTargetModules ) ;
} ;
class CommandObjectTargetSymbolsAdd : public CommandObjectParsed
{
public :
CommandObjectTargetSymbolsAdd ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target symbols add " ,
" Add a debug symbol file to one of the target's current modules by specifying a path to a debug symbols file, or using the options to specify a module to download symbols for. " ,
" target symbols add [<symfile>] " , eFlagRequiresTarget ) ,
m_option_group ( interpreter ) ,
m_file_option ( LLDB_OPT_SET_1 , false , " shlib " , ' s ' , CommandCompletions : : eModuleCompletion , eArgTypeShlibName , " Fullpath or basename for module to find debug symbols for. " ) ,
m_current_frame_option ( LLDB_OPT_SET_2 , false , " frame " , ' F ' , " Locate the debug symbols the currently selected frame. " , false , true )
{
m_option_group . Append ( & m_uuid_option_group , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_file_option , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_current_frame_option , LLDB_OPT_SET_2 , LLDB_OPT_SET_2 ) ;
m_option_group . Finalize ( ) ;
}
virtual
~ CommandObjectTargetSymbolsAdd ( )
{
}
virtual int
HandleArgumentCompletion ( Args & input ,
int & cursor_index ,
int & cursor_char_position ,
OptionElementVector & opt_element_vector ,
int match_start_point ,
int max_return_elements ,
bool & word_complete ,
StringList & matches )
{
std : : string completion_str ( input . GetArgumentAtIndex ( cursor_index ) ) ;
completion_str . erase ( cursor_char_position ) ;
CommandCompletions : : InvokeCommonCompletionCallbacks ( m_interpreter ,
CommandCompletions : : eDiskFileCompletion ,
completion_str . c_str ( ) ,
match_start_point ,
max_return_elements ,
NULL ,
word_complete ,
matches ) ;
return matches . GetSize ( ) ;
}
virtual Options *
GetOptions ( )
{
return & m_option_group ;
}
protected :
bool
AddModuleSymbols ( Target * target ,
ModuleSpec & module_spec ,
bool & flush ,
CommandReturnObject & result )
{
const FileSpec & symbol_fspec = module_spec . GetSymbolFileSpec ( ) ;
if ( symbol_fspec )
{
char symfile_path [ PATH_MAX ] ;
symbol_fspec . GetPath ( symfile_path , sizeof ( symfile_path ) ) ;
if ( ! module_spec . GetUUID ( ) . IsValid ( ) )
{
if ( ! module_spec . GetFileSpec ( ) & & ! module_spec . GetPlatformFileSpec ( ) )
module_spec . GetFileSpec ( ) . GetFilename ( ) = symbol_fspec . GetFilename ( ) ;
}
// We now have a module that represents a symbol file
// that can be used for a module that might exist in the
// current target, so we need to find that module in the
// target
ModuleList matching_module_list ;
size_t num_matches = 0 ;
// First extract all module specs from the symbol file
lldb_private : : ModuleSpecList symfile_module_specs ;
if ( ObjectFile : : GetModuleSpecifications ( module_spec . GetSymbolFileSpec ( ) , 0 , 0 , symfile_module_specs ) )
{
// Now extract the module spec that matches the target architecture
ModuleSpec target_arch_module_spec ;
ModuleSpec symfile_module_spec ;
target_arch_module_spec . GetArchitecture ( ) = target - > GetArchitecture ( ) ;
if ( symfile_module_specs . FindMatchingModuleSpec ( target_arch_module_spec , symfile_module_spec ) )
{
// See if it has a UUID?
if ( symfile_module_spec . GetUUID ( ) . IsValid ( ) )
{
// It has a UUID, look for this UUID in the target modules
ModuleSpec symfile_uuid_module_spec ;
symfile_uuid_module_spec . GetUUID ( ) = symfile_module_spec . GetUUID ( ) ;
num_matches = target - > GetImages ( ) . FindModules ( symfile_uuid_module_spec , matching_module_list ) ;
}
}
if ( num_matches = = 0 )
{
// No matches yet, iterate through the module specs to find a UUID value that
// we can match up to an image in our target
const size_t num_symfile_module_specs = symfile_module_specs . GetSize ( ) ;
for ( size_t i = 0 ; i < num_symfile_module_specs & & num_matches = = 0 ; + + i )
{
if ( symfile_module_specs . GetModuleSpecAtIndex ( i , symfile_module_spec ) )
{
if ( symfile_module_spec . GetUUID ( ) . IsValid ( ) )
{
// It has a UUID, look for this UUID in the target modules
ModuleSpec symfile_uuid_module_spec ;
symfile_uuid_module_spec . GetUUID ( ) = symfile_module_spec . GetUUID ( ) ;
num_matches = target - > GetImages ( ) . FindModules ( symfile_uuid_module_spec , matching_module_list ) ;
}
}
}
}
}
// Just try to match up the file by basename if we have no matches at this point
if ( num_matches = = 0 )
num_matches = target - > GetImages ( ) . FindModules ( module_spec , matching_module_list ) ;
while ( num_matches = = 0 )
{
ConstString filename_no_extension ( module_spec . GetFileSpec ( ) . GetFileNameStrippingExtension ( ) ) ;
// Empty string returned, lets bail
if ( ! filename_no_extension )
break ;
// Check if there was no extension to strip and the basename is the same
if ( filename_no_extension = = module_spec . GetFileSpec ( ) . GetFilename ( ) )
break ;
// Replace basename with one less extension
module_spec . GetFileSpec ( ) . GetFilename ( ) = filename_no_extension ;
num_matches = target - > GetImages ( ) . FindModules ( module_spec , matching_module_list ) ;
}
if ( num_matches > 1 )
{
result . AppendErrorWithFormat ( " multiple modules match symbol file '%s', use the --uuid option to resolve the ambiguity. \n " , symfile_path ) ;
}
else if ( num_matches = = 1 )
{
ModuleSP module_sp ( matching_module_list . GetModuleAtIndex ( 0 ) ) ;
// The module has not yet created its symbol vendor, we can just
// give the existing target module the symfile path to use for
// when it decides to create it!
module_sp - > SetSymbolFileFileSpec ( symbol_fspec ) ;
SymbolVendor * symbol_vendor = module_sp - > GetSymbolVendor ( true , & result . GetErrorStream ( ) ) ;
if ( symbol_vendor )
{
SymbolFile * symbol_file = symbol_vendor - > GetSymbolFile ( ) ;
if ( symbol_file )
{
ObjectFile * object_file = symbol_file - > GetObjectFile ( ) ;
if ( object_file & & object_file - > GetFileSpec ( ) = = symbol_fspec )
{
// Provide feedback that the symfile has been successfully added.
const FileSpec & module_fs = module_sp - > GetFileSpec ( ) ;
result . AppendMessageWithFormat ( " symbol file '%s' has been added to '%s' \n " ,
symfile_path ,
module_fs . GetPath ( ) . c_str ( ) ) ;
// Let clients know something changed in the module
// if it is currently loaded
ModuleList module_list ;
module_list . Append ( module_sp ) ;
target - > SymbolsDidLoad ( module_list ) ;
// Make sure we load any scripting resources that may be embedded
// in the debug info files in case the platform supports that.
Error error ;
StreamString feedback_stream ;
module_sp - > LoadScriptingResourceInTarget ( target , error , & feedback_stream ) ;
if ( error . Fail ( ) & & error . AsCString ( ) )
result . AppendWarningWithFormat ( " unable to load scripting data for module %s - error reported was %s " ,
module_sp - > GetFileSpec ( ) . GetFileNameStrippingExtension ( ) . GetCString ( ) ,
error . AsCString ( ) ) ;
else if ( feedback_stream . GetSize ( ) )
result . AppendWarningWithFormat ( " %s " , feedback_stream . GetData ( ) ) ;
flush = true ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return true ;
}
}
}
// Clear the symbol file spec if anything went wrong
module_sp - > SetSymbolFileFileSpec ( FileSpec ( ) ) ;
}
if ( module_spec . GetUUID ( ) . IsValid ( ) )
{
StreamString ss_symfile_uuid ;
module_spec . GetUUID ( ) . Dump ( & ss_symfile_uuid ) ;
result . AppendErrorWithFormat ( " symbol file '%s' (%s) does not match any existing module%s \n " ,
symfile_path ,
ss_symfile_uuid . GetData ( ) ,
( symbol_fspec . GetFileType ( ) ! = FileSpec : : eFileTypeRegular )
? " \n please specify the full path to the symbol file "
: " " ) ;
}
else
{
result . AppendErrorWithFormat ( " symbol file '%s' does not match any existing module%s \n " ,
symfile_path ,
( symbol_fspec . GetFileType ( ) ! = FileSpec : : eFileTypeRegular )
? " \n please specify the full path to the symbol file "
: " " ) ;
}
}
else
{
result . AppendError ( " one or more executable image paths must be specified " ) ;
}
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
virtual bool
DoExecute ( Args & args ,
CommandReturnObject & result )
{
Target * target = m_exe_ctx . GetTargetPtr ( ) ;
result . SetStatus ( eReturnStatusFailed ) ;
bool flush = false ;
ModuleSpec module_spec ;
const bool uuid_option_set = m_uuid_option_group . GetOptionValue ( ) . OptionWasSet ( ) ;
const bool file_option_set = m_file_option . GetOptionValue ( ) . OptionWasSet ( ) ;
const bool frame_option_set = m_current_frame_option . GetOptionValue ( ) . OptionWasSet ( ) ;
const size_t argc = args . GetArgumentCount ( ) ;
if ( argc = = 0 )
{
if ( uuid_option_set | | file_option_set | | frame_option_set )
{
bool success = false ;
bool error_set = false ;
if ( frame_option_set )
{
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
if ( process )
{
const StateType process_state = process - > GetState ( ) ;
if ( StateIsStoppedState ( process_state , true ) )
{
StackFrame * frame = m_exe_ctx . GetFramePtr ( ) ;
if ( frame )
{
ModuleSP frame_module_sp ( frame - > GetSymbolContext ( eSymbolContextModule ) . module_sp ) ;
if ( frame_module_sp )
{
if ( frame_module_sp - > GetPlatformFileSpec ( ) . Exists ( ) )
{
module_spec . GetArchitecture ( ) = frame_module_sp - > GetArchitecture ( ) ;
module_spec . GetFileSpec ( ) = frame_module_sp - > GetPlatformFileSpec ( ) ;
}
module_spec . GetUUID ( ) = frame_module_sp - > GetUUID ( ) ;
success = module_spec . GetUUID ( ) . IsValid ( ) | | module_spec . GetFileSpec ( ) ;
}
else
{
result . AppendError ( " frame has no module " ) ;
error_set = true ;
}
}
else
{
result . AppendError ( " invalid current frame " ) ;
error_set = true ;
}
}
else
{
result . AppendErrorWithFormat ( " process is not stopped: %s " , StateAsCString ( process_state ) ) ;
error_set = true ;
}
}
else
{
result . AppendError ( " a process must exist in order to use the --frame option " ) ;
error_set = true ;
}
}
else
{
if ( uuid_option_set )
{
module_spec . GetUUID ( ) = m_uuid_option_group . GetOptionValue ( ) . GetCurrentValue ( ) ;
success | = module_spec . GetUUID ( ) . IsValid ( ) ;
}
else if ( file_option_set )
{
module_spec . GetFileSpec ( ) = m_file_option . GetOptionValue ( ) . GetCurrentValue ( ) ;
ModuleSP module_sp ( target - > GetImages ( ) . FindFirstModule ( module_spec ) ) ;
if ( module_sp )
{
module_spec . GetFileSpec ( ) = module_sp - > GetFileSpec ( ) ;
module_spec . GetPlatformFileSpec ( ) = module_sp - > GetPlatformFileSpec ( ) ;
module_spec . GetUUID ( ) = module_sp - > GetUUID ( ) ;
module_spec . GetArchitecture ( ) = module_sp - > GetArchitecture ( ) ;
}
else
{
module_spec . GetArchitecture ( ) = target - > GetArchitecture ( ) ;
}
success | = module_spec . GetFileSpec ( ) . Exists ( ) ;
}
}
if ( success )
{
if ( Symbols : : DownloadObjectAndSymbolFile ( module_spec ) )
{
if ( module_spec . GetSymbolFileSpec ( ) )
success = AddModuleSymbols ( target , module_spec , flush , result ) ;
}
}
if ( ! success & & ! error_set )
{
StreamString error_strm ;
if ( uuid_option_set )
{
error_strm . PutCString ( " unable to find debug symbols for UUID " ) ;
module_spec . GetUUID ( ) . Dump ( & error_strm ) ;
}
else if ( file_option_set )
{
error_strm . PutCString ( " unable to find debug symbols for the executable file " ) ;
error_strm < < module_spec . GetFileSpec ( ) ;
}
else if ( frame_option_set )
{
error_strm . PutCString ( " unable to find debug symbols for the current frame " ) ;
}
result . AppendError ( error_strm . GetData ( ) ) ;
}
}
else
{
result . AppendError ( " one or more symbol file paths must be specified, or options must be specified " ) ;
}
}
else
{
if ( uuid_option_set )
{
result . AppendError ( " specify either one or more paths to symbol files or use the --uuid option without arguments " ) ;
}
else if ( file_option_set )
{
result . AppendError ( " specify either one or more paths to symbol files or use the --file option without arguments " ) ;
}
else if ( frame_option_set )
{
result . AppendError ( " specify either one or more paths to symbol files or use the --frame option without arguments " ) ;
}
else
{
PlatformSP platform_sp ( target - > GetPlatform ( ) ) ;
for ( size_t i = 0 ; i < argc ; + + i )
{
const char * symfile_path = args . GetArgumentAtIndex ( i ) ;
if ( symfile_path )
{
module_spec . GetSymbolFileSpec ( ) . SetFile ( symfile_path , true ) ;
if ( platform_sp )
{
FileSpec symfile_spec ;
if ( platform_sp - > ResolveSymbolFile ( * target , module_spec , symfile_spec ) . Success ( ) )
module_spec . GetSymbolFileSpec ( ) = symfile_spec ;
}
ArchSpec arch ;
bool symfile_exists = module_spec . GetSymbolFileSpec ( ) . Exists ( ) ;
if ( symfile_exists )
{
if ( ! AddModuleSymbols ( target , module_spec , flush , result ) )
break ;
}
else
{
char resolved_symfile_path [ PATH_MAX ] ;
if ( module_spec . GetSymbolFileSpec ( ) . GetPath ( resolved_symfile_path , sizeof ( resolved_symfile_path ) ) )
{
if ( strcmp ( resolved_symfile_path , symfile_path ) ! = 0 )
{
result . AppendErrorWithFormat ( " invalid module path '%s' with resolved path '%s' \n " , symfile_path , resolved_symfile_path ) ;
break ;
}
}
result . AppendErrorWithFormat ( " invalid module path '%s' \n " , symfile_path ) ;
break ;
}
}
}
}
}
if ( flush )
{
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
if ( process )
process - > Flush ( ) ;
}
return result . Succeeded ( ) ;
}
OptionGroupOptions m_option_group ;
OptionGroupUUID m_uuid_option_group ;
OptionGroupFile m_file_option ;
OptionGroupBoolean m_current_frame_option ;
} ;
# pragma mark CommandObjectTargetSymbols
//-------------------------------------------------------------------------
// CommandObjectTargetSymbols
//-------------------------------------------------------------------------
class CommandObjectTargetSymbols : public CommandObjectMultiword
{
public :
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
CommandObjectTargetSymbols ( CommandInterpreter & interpreter ) :
CommandObjectMultiword ( interpreter ,
" target symbols " ,
" A set of commands for adding and managing debug symbol files. " ,
" target symbols <sub-command> ... " )
{
LoadSubCommand ( " add " , CommandObjectSP ( new CommandObjectTargetSymbolsAdd ( interpreter ) ) ) ;
}
virtual
~ CommandObjectTargetSymbols ( )
{
}
private :
//------------------------------------------------------------------
// For CommandObjectTargetModules only
//------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN ( CommandObjectTargetSymbols ) ;
} ;
# pragma mark CommandObjectTargetStopHookAdd
//-------------------------------------------------------------------------
// CommandObjectTargetStopHookAdd
//-------------------------------------------------------------------------
2014-02-18 11:23:10 -05:00
class CommandObjectTargetStopHookAdd :
public CommandObjectParsed ,
public IOHandlerDelegateMultiline
2013-08-23 13:46:38 -04:00
{
public :
class CommandOptions : public Options
{
public :
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter ) ,
m_line_start ( 0 ) ,
m_line_end ( UINT_MAX ) ,
m_func_name_type_mask ( eFunctionNameTypeAuto ) ,
m_sym_ctx_specified ( false ) ,
m_thread_specified ( false ) ,
m_use_one_liner ( false ) ,
m_one_liner ( )
{
}
~ CommandOptions ( ) { }
const OptionDefinition *
GetDefinitions ( )
{
return g_option_table ;
}
virtual Error
SetOptionValue ( uint32_t option_idx , const char * option_arg )
{
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
bool success ;
switch ( short_option )
{
case ' c ' :
m_class_name = option_arg ;
m_sym_ctx_specified = true ;
break ;
case ' e ' :
m_line_end = Args : : StringToUInt32 ( option_arg , UINT_MAX , 0 , & success ) ;
if ( ! success )
{
error . SetErrorStringWithFormat ( " invalid end line number: \" %s \" " , option_arg ) ;
break ;
}
m_sym_ctx_specified = true ;
break ;
case ' l ' :
m_line_start = Args : : StringToUInt32 ( option_arg , 0 , 0 , & success ) ;
if ( ! success )
{
error . SetErrorStringWithFormat ( " invalid start line number: \" %s \" " , option_arg ) ;
break ;
}
m_sym_ctx_specified = true ;
break ;
case ' i ' :
m_no_inlines = true ;
break ;
case ' n ' :
m_function_name = option_arg ;
m_func_name_type_mask | = eFunctionNameTypeAuto ;
m_sym_ctx_specified = true ;
break ;
case ' f ' :
m_file_name = option_arg ;
m_sym_ctx_specified = true ;
break ;
case ' s ' :
m_module_name = option_arg ;
m_sym_ctx_specified = true ;
break ;
case ' t ' :
{
m_thread_id = Args : : StringToUInt64 ( option_arg , LLDB_INVALID_THREAD_ID , 0 ) ;
if ( m_thread_id = = LLDB_INVALID_THREAD_ID )
error . SetErrorStringWithFormat ( " invalid thread id string '%s' " , option_arg ) ;
m_thread_specified = true ;
}
break ;
case ' T ' :
m_thread_name = option_arg ;
m_thread_specified = true ;
break ;
case ' q ' :
m_queue_name = option_arg ;
m_thread_specified = true ;
break ;
case ' x ' :
{
m_thread_index = Args : : StringToUInt32 ( option_arg , UINT32_MAX , 0 ) ;
if ( m_thread_id = = UINT32_MAX )
error . SetErrorStringWithFormat ( " invalid thread index string '%s' " , option_arg ) ;
m_thread_specified = true ;
}
break ;
case ' o ' :
m_use_one_liner = true ;
m_one_liner = option_arg ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option %c. " , short_option ) ;
break ;
}
return error ;
}
void
OptionParsingStarting ( )
{
m_class_name . clear ( ) ;
m_function_name . clear ( ) ;
m_line_start = 0 ;
m_line_end = UINT_MAX ;
m_file_name . clear ( ) ;
m_module_name . clear ( ) ;
m_func_name_type_mask = eFunctionNameTypeAuto ;
m_thread_id = LLDB_INVALID_THREAD_ID ;
m_thread_index = UINT32_MAX ;
m_thread_name . clear ( ) ;
m_queue_name . clear ( ) ;
m_no_inlines = false ;
m_sym_ctx_specified = false ;
m_thread_specified = false ;
m_use_one_liner = false ;
m_one_liner . clear ( ) ;
}
static OptionDefinition g_option_table [ ] ;
std : : string m_class_name ;
std : : string m_function_name ;
uint32_t m_line_start ;
uint32_t m_line_end ;
std : : string m_file_name ;
std : : string m_module_name ;
uint32_t m_func_name_type_mask ; // A pick from lldb::FunctionNameType.
lldb : : tid_t m_thread_id ;
uint32_t m_thread_index ;
std : : string m_thread_name ;
std : : string m_queue_name ;
bool m_sym_ctx_specified ;
bool m_no_inlines ;
bool m_thread_specified ;
// Instance variables to hold the values for one_liner options.
bool m_use_one_liner ;
std : : string m_one_liner ;
} ;
Options *
GetOptions ( )
{
return & m_options ;
}
CommandObjectTargetStopHookAdd ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
2014-02-18 11:23:10 -05:00
" target stop-hook add " ,
2013-08-23 13:46:38 -04:00
" Add a hook to be executed when the target stops. " ,
" target stop-hook add " ) ,
2014-02-18 11:23:10 -05:00
IOHandlerDelegateMultiline ( " DONE " , IOHandlerDelegate : : Completion : : LLDBCommand ) ,
2013-08-23 13:46:38 -04:00
m_options ( interpreter )
{
}
~ CommandObjectTargetStopHookAdd ( )
{
}
2014-02-18 11:23:10 -05:00
protected :
virtual void
IOHandlerActivated ( IOHandler & io_handler )
2013-08-23 13:46:38 -04:00
{
2014-02-18 11:23:10 -05:00
StreamFileSP output_sp ( io_handler . GetOutputStreamFile ( ) ) ;
if ( output_sp )
2013-08-23 13:46:38 -04:00
{
2014-02-18 11:23:10 -05:00
output_sp - > PutCString ( " Enter your stop hook command(s). Type 'DONE' to end. \n " ) ;
output_sp - > Flush ( ) ;
}
}
virtual void
IOHandlerInputComplete ( IOHandler & io_handler , std : : string & line )
{
if ( m_stop_hook_sp )
{
if ( line . empty ( ) )
2013-08-23 13:46:38 -04:00
{
2014-02-18 11:23:10 -05:00
StreamFileSP error_sp ( io_handler . GetErrorStreamFile ( ) ) ;
if ( error_sp )
2013-08-23 13:46:38 -04:00
{
2014-02-18 11:23:10 -05:00
error_sp - > Printf ( " error: stop hook #% " PRIu64 " aborted, no commands. \n " , m_stop_hook_sp - > GetID ( ) ) ;
error_sp - > Flush ( ) ;
2013-08-23 13:46:38 -04:00
}
2014-02-18 11:23:10 -05:00
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target )
target - > RemoveStopHookByID ( m_stop_hook_sp - > GetID ( ) ) ;
2013-08-23 13:46:38 -04:00
}
2014-02-18 11:23:10 -05:00
else
2013-08-23 13:46:38 -04:00
{
2014-02-18 11:23:10 -05:00
m_stop_hook_sp - > GetCommandPointer ( ) - > SplitIntoLines ( line ) ;
StreamFileSP output_sp ( io_handler . GetOutputStreamFile ( ) ) ;
if ( output_sp )
2013-08-23 13:46:38 -04:00
{
2014-02-18 11:23:10 -05:00
output_sp - > Printf ( " Stop hook #% " PRIu64 " added. \n " , m_stop_hook_sp - > GetID ( ) ) ;
output_sp - > Flush ( ) ;
2013-08-23 13:46:38 -04:00
}
}
2014-02-18 11:23:10 -05:00
m_stop_hook_sp . reset ( ) ;
2013-08-23 13:46:38 -04:00
}
2014-02-18 11:23:10 -05:00
io_handler . SetIsDone ( true ) ;
2013-08-23 13:46:38 -04:00
}
2014-02-18 11:23:10 -05:00
2013-08-23 13:46:38 -04:00
bool
DoExecute ( Args & command , CommandReturnObject & result )
{
2014-02-18 11:23:10 -05:00
m_stop_hook_sp . reset ( ) ;
2013-08-23 13:46:38 -04:00
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target )
{
2014-02-18 11:23:10 -05:00
Target : : StopHookSP new_hook_sp = target - > CreateStopHook ( ) ;
2013-08-23 13:46:38 -04:00
// First step, make the specifier.
std : : unique_ptr < SymbolContextSpecifier > specifier_ap ;
if ( m_options . m_sym_ctx_specified )
{
specifier_ap . reset ( new SymbolContextSpecifier ( m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) ) ) ;
if ( ! m_options . m_module_name . empty ( ) )
{
specifier_ap - > AddSpecification ( m_options . m_module_name . c_str ( ) , SymbolContextSpecifier : : eModuleSpecified ) ;
}
if ( ! m_options . m_class_name . empty ( ) )
{
specifier_ap - > AddSpecification ( m_options . m_class_name . c_str ( ) , SymbolContextSpecifier : : eClassOrNamespaceSpecified ) ;
}
if ( ! m_options . m_file_name . empty ( ) )
{
specifier_ap - > AddSpecification ( m_options . m_file_name . c_str ( ) , SymbolContextSpecifier : : eFileSpecified ) ;
}
if ( m_options . m_line_start ! = 0 )
{
specifier_ap - > AddLineSpecification ( m_options . m_line_start , SymbolContextSpecifier : : eLineStartSpecified ) ;
}
if ( m_options . m_line_end ! = UINT_MAX )
{
specifier_ap - > AddLineSpecification ( m_options . m_line_end , SymbolContextSpecifier : : eLineEndSpecified ) ;
}
if ( ! m_options . m_function_name . empty ( ) )
{
specifier_ap - > AddSpecification ( m_options . m_function_name . c_str ( ) , SymbolContextSpecifier : : eFunctionSpecified ) ;
}
}
if ( specifier_ap . get ( ) )
new_hook_sp - > SetSpecifier ( specifier_ap . release ( ) ) ;
// Next see if any of the thread options have been entered:
if ( m_options . m_thread_specified )
{
ThreadSpec * thread_spec = new ThreadSpec ( ) ;
if ( m_options . m_thread_id ! = LLDB_INVALID_THREAD_ID )
{
thread_spec - > SetTID ( m_options . m_thread_id ) ;
}
if ( m_options . m_thread_index ! = UINT32_MAX )
thread_spec - > SetIndex ( m_options . m_thread_index ) ;
if ( ! m_options . m_thread_name . empty ( ) )
thread_spec - > SetName ( m_options . m_thread_name . c_str ( ) ) ;
if ( ! m_options . m_queue_name . empty ( ) )
thread_spec - > SetQueueName ( m_options . m_queue_name . c_str ( ) ) ;
new_hook_sp - > SetThreadSpecifier ( thread_spec ) ;
}
if ( m_options . m_use_one_liner )
{
// Use one-liner.
new_hook_sp - > GetCommandPointer ( ) - > AppendString ( m_options . m_one_liner . c_str ( ) ) ;
result . AppendMessageWithFormat ( " Stop hook #% " PRIu64 " added. \n " , new_hook_sp - > GetID ( ) ) ;
}
else
{
2014-02-18 11:23:10 -05:00
m_stop_hook_sp = new_hook_sp ;
m_interpreter . GetLLDBCommandsFromIOHandler ( " > " , // Prompt
* this , // IOHandlerDelegate
true , // Run IOHandler in async mode
NULL ) ; // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
2013-08-23 13:46:38 -04:00
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
{
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
private :
CommandOptions m_options ;
2014-02-18 11:23:10 -05:00
Target : : StopHookSP m_stop_hook_sp ;
2013-08-23 13:46:38 -04:00
} ;
OptionDefinition
CommandObjectTargetStopHookAdd : : CommandOptions : : g_option_table [ ] =
{
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_ALL , false , " one-liner " , ' o ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeOneLiner ,
2013-08-23 13:46:38 -04:00
" Specify a one-line breakpoint command inline. Be sure to surround it with quotes. " } ,
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_ALL , false , " shlib " , ' s ' , OptionParser : : eRequiredArgument , NULL , CommandCompletions : : eModuleCompletion , eArgTypeShlibName ,
2013-08-23 13:46:38 -04:00
" Set the module within which the stop-hook is to be run. " } ,
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_ALL , false , " thread-index " , ' x ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeThreadIndex ,
2013-08-23 13:46:38 -04:00
" The stop hook is run only for the thread whose index matches this argument. " } ,
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_ALL , false , " thread-id " , ' t ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeThreadID ,
2013-08-23 13:46:38 -04:00
" The stop hook is run only for the thread whose TID matches this argument. " } ,
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_ALL , false , " thread-name " , ' T ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeThreadName ,
2013-08-23 13:46:38 -04:00
" The stop hook is run only for the thread whose thread name matches this argument. " } ,
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_ALL , false , " queue-name " , ' q ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeQueueName ,
2013-08-23 13:46:38 -04:00
" The stop hook is run only for threads in the queue whose name is given by this argument. " } ,
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_1 , false , " file " , ' f ' , OptionParser : : eRequiredArgument , NULL , CommandCompletions : : eSourceFileCompletion , eArgTypeFilename ,
2013-08-23 13:46:38 -04:00
" Specify the source file within which the stop-hook is to be run. " } ,
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_1 , false , " start-line " , ' l ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeLineNum ,
2013-08-23 13:46:38 -04:00
" Set the start of the line range for which the stop-hook is to be run. " } ,
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_1 , false , " end-line " , ' e ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeLineNum ,
2013-08-23 13:46:38 -04:00
" Set the end of the line range for which the stop-hook is to be run. " } ,
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_2 , false , " classname " , ' c ' , OptionParser : : eRequiredArgument , NULL , 0 , eArgTypeClassName ,
2013-08-23 13:46:38 -04:00
" Specify the class within which the stop-hook is to be run. " } ,
2013-11-06 11:48:53 -05:00
{ LLDB_OPT_SET_3 , false , " name " , ' n ' , OptionParser : : eRequiredArgument , NULL , CommandCompletions : : eSymbolCompletion , eArgTypeFunctionName ,
2013-08-23 13:46:38 -04:00
" Set the function name within which the stop hook will be run. " } ,
{ 0 , false , NULL , 0 , 0 , NULL , 0 , eArgTypeNone , NULL }
} ;
# pragma mark CommandObjectTargetStopHookDelete
//-------------------------------------------------------------------------
// CommandObjectTargetStopHookDelete
//-------------------------------------------------------------------------
class CommandObjectTargetStopHookDelete : public CommandObjectParsed
{
public :
CommandObjectTargetStopHookDelete ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target stop-hook delete " ,
" Delete a stop-hook. " ,
" target stop-hook delete [<idx>] " )
{
}
~ CommandObjectTargetStopHookDelete ( )
{
}
protected :
bool
DoExecute ( Args & command , CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target )
{
// FIXME: see if we can use the breakpoint id style parser?
size_t num_args = command . GetArgumentCount ( ) ;
if ( num_args = = 0 )
{
if ( ! m_interpreter . Confirm ( " Delete all stop hooks? " , true ) )
{
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else
{
target - > RemoveAllStopHooks ( ) ;
}
}
else
{
bool success ;
for ( size_t i = 0 ; i < num_args ; i + + )
{
lldb : : user_id_t user_id = Args : : StringToUInt32 ( command . GetArgumentAtIndex ( i ) , 0 , 0 , & success ) ;
if ( ! success )
{
result . AppendErrorWithFormat ( " invalid stop hook id: \" %s \" . \n " , command . GetArgumentAtIndex ( i ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
success = target - > RemoveStopHookByID ( user_id ) ;
if ( ! success )
{
result . AppendErrorWithFormat ( " unknown stop hook id: \" %s \" . \n " , command . GetArgumentAtIndex ( i ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
{
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
} ;
# pragma mark CommandObjectTargetStopHookEnableDisable
//-------------------------------------------------------------------------
// CommandObjectTargetStopHookEnableDisable
//-------------------------------------------------------------------------
class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed
{
public :
CommandObjectTargetStopHookEnableDisable ( CommandInterpreter & interpreter , bool enable , const char * name , const char * help , const char * syntax ) :
CommandObjectParsed ( interpreter ,
name ,
help ,
syntax ) ,
m_enable ( enable )
{
}
~ CommandObjectTargetStopHookEnableDisable ( )
{
}
protected :
bool
DoExecute ( Args & command , CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target )
{
// FIXME: see if we can use the breakpoint id style parser?
size_t num_args = command . GetArgumentCount ( ) ;
bool success ;
if ( num_args = = 0 )
{
target - > SetAllStopHooksActiveState ( m_enable ) ;
}
else
{
for ( size_t i = 0 ; i < num_args ; i + + )
{
lldb : : user_id_t user_id = Args : : StringToUInt32 ( command . GetArgumentAtIndex ( i ) , 0 , 0 , & success ) ;
if ( ! success )
{
result . AppendErrorWithFormat ( " invalid stop hook id: \" %s \" . \n " , command . GetArgumentAtIndex ( i ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
success = target - > SetStopHookActiveStateByID ( user_id , m_enable ) ;
if ( ! success )
{
result . AppendErrorWithFormat ( " unknown stop hook id: \" %s \" . \n " , command . GetArgumentAtIndex ( i ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
{
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
private :
bool m_enable ;
} ;
# pragma mark CommandObjectTargetStopHookList
//-------------------------------------------------------------------------
// CommandObjectTargetStopHookList
//-------------------------------------------------------------------------
class CommandObjectTargetStopHookList : public CommandObjectParsed
{
public :
CommandObjectTargetStopHookList ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" target stop-hook list " ,
" List all stop-hooks. " ,
" target stop-hook list [<type>] " )
{
}
~ CommandObjectTargetStopHookList ( )
{
}
protected :
bool
DoExecute ( Args & command , CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( ! target )
{
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return result . Succeeded ( ) ;
}
size_t num_hooks = target - > GetNumStopHooks ( ) ;
if ( num_hooks = = 0 )
{
result . GetOutputStream ( ) . PutCString ( " No stop hooks. \n " ) ;
}
else
{
for ( size_t i = 0 ; i < num_hooks ; i + + )
{
Target : : StopHookSP this_hook = target - > GetStopHookAtIndex ( i ) ;
if ( i > 0 )
result . GetOutputStream ( ) . PutCString ( " \n " ) ;
this_hook - > GetDescription ( & ( result . GetOutputStream ( ) ) , eDescriptionLevelFull ) ;
}
}
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return result . Succeeded ( ) ;
}
} ;
# pragma mark CommandObjectMultiwordTargetStopHooks
//-------------------------------------------------------------------------
// CommandObjectMultiwordTargetStopHooks
//-------------------------------------------------------------------------
class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword
{
public :
CommandObjectMultiwordTargetStopHooks ( CommandInterpreter & interpreter ) :
CommandObjectMultiword ( interpreter ,
" target stop-hook " ,
" A set of commands for operating on debugger target stop-hooks. " ,
" target stop-hook <subcommand> [<subcommand-options>] " )
{
LoadSubCommand ( " add " , CommandObjectSP ( new CommandObjectTargetStopHookAdd ( interpreter ) ) ) ;
LoadSubCommand ( " delete " , CommandObjectSP ( new CommandObjectTargetStopHookDelete ( interpreter ) ) ) ;
LoadSubCommand ( " disable " , CommandObjectSP ( new CommandObjectTargetStopHookEnableDisable ( interpreter ,
false ,
" target stop-hook disable [<id>] " ,
" Disable a stop-hook. " ,
" target stop-hook disable " ) ) ) ;
LoadSubCommand ( " enable " , CommandObjectSP ( new CommandObjectTargetStopHookEnableDisable ( interpreter ,
true ,
" target stop-hook enable [<id>] " ,
" Enable a stop-hook. " ,
" target stop-hook enable " ) ) ) ;
LoadSubCommand ( " list " , CommandObjectSP ( new CommandObjectTargetStopHookList ( interpreter ) ) ) ;
}
~ CommandObjectMultiwordTargetStopHooks ( )
{
}
} ;
# pragma mark CommandObjectMultiwordTarget
//-------------------------------------------------------------------------
// CommandObjectMultiwordTarget
//-------------------------------------------------------------------------
CommandObjectMultiwordTarget : : CommandObjectMultiwordTarget ( CommandInterpreter & interpreter ) :
CommandObjectMultiword ( interpreter ,
" target " ,
" A set of commands for operating on debugger targets. " ,
" target <subcommand> [<subcommand-options>] " )
{
LoadSubCommand ( " create " , CommandObjectSP ( new CommandObjectTargetCreate ( interpreter ) ) ) ;
LoadSubCommand ( " delete " , CommandObjectSP ( new CommandObjectTargetDelete ( interpreter ) ) ) ;
LoadSubCommand ( " list " , CommandObjectSP ( new CommandObjectTargetList ( interpreter ) ) ) ;
LoadSubCommand ( " select " , CommandObjectSP ( new CommandObjectTargetSelect ( interpreter ) ) ) ;
LoadSubCommand ( " stop-hook " , CommandObjectSP ( new CommandObjectMultiwordTargetStopHooks ( interpreter ) ) ) ;
LoadSubCommand ( " modules " , CommandObjectSP ( new CommandObjectTargetModules ( interpreter ) ) ) ;
LoadSubCommand ( " symbols " , CommandObjectSP ( new CommandObjectTargetSymbols ( interpreter ) ) ) ;
LoadSubCommand ( " variable " , CommandObjectSP ( new CommandObjectTargetVariable ( interpreter ) ) ) ;
}
CommandObjectMultiwordTarget : : ~ CommandObjectMultiwordTarget ( )
{
}