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 "CommandObjectTarget.h"
// Project includes
# 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"
2015-02-08 20:44:09 -05:00
# include "lldb/Host/StringConvert.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Host/Symbols.h"
2017-01-02 14:26:05 -05:00
# include "lldb/Interpreter/Args.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Interpreter/CommandReturnObject.h"
# include "lldb/Interpreter/OptionGroupArchitecture.h"
# include "lldb/Interpreter/OptionGroupBoolean.h"
# include "lldb/Interpreter/OptionGroupFile.h"
# include "lldb/Interpreter/OptionGroupFormat.h"
# include "lldb/Interpreter/OptionGroupPlatform.h"
2017-01-02 14:26:05 -05:00
# include "lldb/Interpreter/OptionGroupString.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Interpreter/OptionGroupUInt64.h"
# include "lldb/Interpreter/OptionGroupUUID.h"
# include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
2017-01-02 14:26:05 -05:00
# include "lldb/Interpreter/OptionGroupVariable.h"
# include "lldb/Interpreter/Options.h"
2013-08-23 13:46:38 -04:00
# 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"
2015-07-03 12:57:06 -04:00
# include "lldb/Target/ABI.h"
2013-08-23 13:46:38 -04:00
# 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"
2017-01-02 14:26:05 -05:00
// C Includes
// C++ Includes
# include <cerrno>
2013-08-23 13:46:38 -04:00
using namespace lldb ;
using namespace lldb_private ;
2017-01-02 14:26:05 -05:00
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= " , properties + + > 0 ? " , " : " ( " ) ;
target_arch . DumpTriple ( strm ) ;
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 ;
const bool stop_format = false ;
process_sp - > GetStatus ( strm ) ;
process_sp - > GetThreadStatus ( strm , only_threads_with_stop_reason ,
start_frame , num_frames ,
num_frames_with_source , stop_format ) ;
}
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
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 ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
return num_targets ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
// TODO: Remove this once llvm can pretty-print time points
static void DumpTimePoint ( llvm : : sys : : TimePoint < > tp , Stream & s , uint32_t width ) {
# ifndef LLDB_DISABLE_POSIX
char time_buf [ 32 ] ;
time_t time = llvm : : sys : : toTimeT ( tp ) ;
char * time_cstr = : : ctime_r ( & time , time_buf ) ;
if ( time_cstr ) {
char * newline = : : strpbrk ( time_cstr , " \n \r " ) ;
if ( newline )
* newline = ' \0 ' ;
if ( width > 0 )
s . Printf ( " %-*s " , width , time_cstr ) ;
else
s . PutCString ( time_cstr ) ;
} else if ( width > 0 )
s . Printf ( " %-*s " , width , " " ) ;
# endif
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
# pragma mark CommandObjectTargetCreate
//-------------------------------------------------------------------------
// "target create"
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetCreate : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetCreate ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " target create " ,
" Create a target using the argument as the main executable. " ,
nullptr ) ,
m_option_group ( ) , m_arch_option ( ) ,
m_core_file ( LLDB_OPT_SET_1 , false , " core " , ' c ' , 0 , eArgTypeFilename ,
" Fullpath to a core file to use for this target. " ) ,
m_platform_path ( LLDB_OPT_SET_1 , false , " platform-path " , ' P ' , 0 ,
eArgTypePath ,
" Path to the remote file to use for this target. " ) ,
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_core_file , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_platform_path , 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 . 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 ( ) override = default ;
Options * GetOptions ( ) override { return & m_option_group ; }
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 ) override {
std : : string completion_str ( input . GetArgumentAtIndex ( cursor_index ) ) ;
completion_str . erase ( cursor_char_position ) ;
CommandCompletions : : InvokeCommonCompletionCallbacks (
GetCommandInterpreter ( ) , CommandCompletions : : eDiskFileCompletion ,
completion_str . c_str ( ) , match_start_point , max_return_elements , nullptr ,
word_complete , matches ) ;
return matches . GetSize ( ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
protected :
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
const size_t argc = command . GetArgumentCount ( ) ;
FileSpec core_file ( m_core_file . GetOptionValue ( ) . GetCurrentValue ( ) ) ;
FileSpec remote_file ( m_remote_file . GetOptionValue ( ) . GetCurrentValue ( ) ) ;
if ( core_file ) {
if ( ! core_file . Exists ( ) ) {
result . AppendErrorWithFormat ( " core file '%s' doesn't exist " ,
core_file . GetPath ( ) . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( ! core_file . Readable ( ) ) {
result . AppendErrorWithFormat ( " core file '%s' is not readable " ,
core_file . GetPath ( ) . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( argc = = 1 | | core_file | | remote_file ) {
FileSpec symfile ( m_symbol_file . GetOptionValue ( ) . GetCurrentValue ( ) ) ;
if ( symfile ) {
if ( symfile . Exists ( ) ) {
if ( ! symfile . Readable ( ) ) {
result . AppendErrorWithFormat ( " symbol file '%s' is not readable " ,
symfile . GetPath ( ) . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
} else {
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 ( LLVM_PRETTY_FUNCTION , " (lldb) target create '%s' " ,
file_path ) ;
FileSpec file_spec ;
if ( file_path )
file_spec . SetFile ( file_path , true ) ;
bool must_set_platform_path = false ;
Debugger & debugger = m_interpreter . GetDebugger ( ) ;
TargetSP target_sp ;
llvm : : StringRef arch_cstr = m_arch_option . GetArchitectureName ( ) ;
const bool get_dependent_files =
m_add_dependents . GetOptionValue ( ) . GetCurrentValue ( ) ;
Error error ( debugger . GetTargetList ( ) . CreateTarget (
debugger , file_path , arch_cstr , get_dependent_files , nullptr ,
target_sp ) ) ;
if ( target_sp ) {
// Only get the platform after we create the target because we might
// have
// switched platforms depending on what the arguments were to
// CreateTarget()
// we can't rely on the selected platform.
PlatformSP platform_sp = target_sp - > GetPlatform ( ) ;
if ( remote_file ) {
if ( platform_sp ) {
// 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 ) ;
2014-11-25 16:00:58 -05:00
return false ;
2017-01-02 14:26:05 -05:00
}
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 ) ;
2014-11-25 16:00:58 -05:00
return false ;
2017-01-02 14:26:05 -05:00
}
2014-11-25 16:00:58 -05:00
}
2017-01-02 14:26:05 -05:00
} else {
result . AppendError ( " no platform found for target " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2014-11-25 16:00:58 -05:00
}
2017-01-02 14:26:05 -05:00
if ( symfile | | remote_file ) {
ModuleSP module_sp ( target_sp - > GetExecutableModule ( ) ) ;
if ( module_sp ) {
2013-08-23 13:46:38 -04:00
if ( symfile )
2017-01-02 14:26:05 -05:00
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 ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
debugger . GetTargetList ( ) . SetSelectedTarget ( target_sp . get ( ) ) ;
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 ) ;
}
if ( core_file ) {
char core_path [ PATH_MAX ] ;
core_file . GetPath ( core_path , sizeof ( core_path ) ) ;
if ( core_file . Exists ( ) ) {
if ( ! core_file . Readable ( ) ) {
result . AppendMessageWithFormat (
" Core file '%s' is not readable. \n " , core_path ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ( ) , llvm : : StringRef ( ) ,
& core_file ) ) ;
if ( process_sp ) {
// Seems weird 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 ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} 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 ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} else {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
result . AppendErrorWithFormat ( " '%s' takes exactly one executable path "
" argument, or use the --core option. \n " ,
m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
private :
2017-01-02 14:26:05 -05:00
OptionGroupOptions m_option_group ;
OptionGroupArchitecture m_arch_option ;
OptionGroupFile m_core_file ;
OptionGroupFile m_platform_path ;
OptionGroupFile m_symbol_file ;
OptionGroupFile m_remote_file ;
OptionGroupBoolean m_add_dependents ;
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetList
//----------------------------------------------------------------------
// "target list"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetList : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetList ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " target list " ,
" List all current targets in the current debug session. " , nullptr ) {
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetList ( ) override = default ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
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 ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetSelect
//----------------------------------------------------------------------
// "target select"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetSelect : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetSelect ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " target select " ,
" Select a target as the current target by target index. " , nullptr ) {
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetSelect ( ) override = default ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
if ( args . GetArgumentCount ( ) = = 1 ) {
bool success = false ;
const char * target_idx_arg = args . GetArgumentAtIndex ( 0 ) ;
uint32_t target_idx =
StringConvert : : ToUInt32 ( 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 {
if ( num_targets > 0 ) {
result . AppendErrorWithFormat (
" index %u is out of range, valid target indexes are 0 - %u \n " ,
target_idx , num_targets - 1 ) ;
} else {
result . AppendErrorWithFormat (
" index %u is out of range since there are no active targets \n " ,
target_idx ) ;
}
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} 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 ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetSelect
//----------------------------------------------------------------------
// "target delete"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetDelete : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetDelete ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " target delete " ,
2016-07-23 16:50:09 -04:00
" Delete one or more targets by target index. " ,
nullptr ) ,
2017-01-02 14:26:05 -05:00
m_option_group ( ) , m_all_option ( LLDB_OPT_SET_1 , false , " all " , ' a ' ,
" Delete all targets. " , false , true ) ,
2015-07-03 12:57:06 -04:00
m_cleanup_option (
2017-01-02 14:26:05 -05:00
LLDB_OPT_SET_1 , false , " clean " , ' c ' ,
" Perform extra cleanup to minimize memory consumption after "
" deleting the target. "
" By default, LLDB will keep in memory any modules previously "
" loaded by the target as well "
" as all of its debug info. Specifying --clean will unload all of "
" these shared modules and "
2015-07-03 12:57:06 -04:00
" cause them to be reparsed again the next time the target is run " ,
2017-01-02 14:26:05 -05:00
false , true ) {
m_option_group . Append ( & m_all_option , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_cleanup_option , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Finalize ( ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetDelete ( ) override = default ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
Options * GetOptions ( ) override { return & m_option_group ; }
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
const size_t argc = args . GetArgumentCount ( ) ;
std : : vector < TargetSP > delete_target_list ;
TargetList & target_list = m_interpreter . GetDebugger ( ) . GetTargetList ( ) ;
TargetSP target_sp ;
if ( m_all_option . GetOptionValue ( ) ) {
for ( int i = 0 ; i < target_list . GetNumTargets ( ) ; + + i )
delete_target_list . push_back ( target_list . GetTargetAtIndex ( i ) ) ;
} else 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 ) ;
return false ;
}
for ( auto & entry : args . entries ( ) ) {
uint32_t target_idx ;
if ( entry . ref . getAsInteger ( 0 , target_idx ) ) {
result . AppendErrorWithFormat ( " invalid target index '%s' \n " ,
entry . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2015-07-03 12:57:06 -04:00
}
2017-01-02 14:26:05 -05:00
if ( target_idx < num_targets ) {
target_sp = target_list . GetTargetAtIndex ( target_idx ) ;
if ( target_sp ) {
delete_target_list . push_back ( target_sp ) ;
continue ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ) ;
2013-08-23 13:46:38 -04:00
else
2017-01-02 14:26:05 -05:00
result . AppendErrorWithFormat (
" target index %u is out of range, the only valid index is 0 \n " ,
target_idx ) ;
2015-07-03 12:57:06 -04:00
2017-01-02 14:26:05 -05:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
} else {
target_sp = target_list . GetSelectedTarget ( ) ;
if ( ! target_sp ) {
result . AppendErrorWithFormat ( " no target is currently selected \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
delete_target_list . push_back ( target_sp ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
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 ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
// 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 true ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
OptionGroupOptions m_option_group ;
OptionGroupBoolean m_all_option ;
OptionGroupBoolean m_cleanup_option ;
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetVariable
//----------------------------------------------------------------------
// "target variable"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetVariable : public CommandObjectParsed {
static const uint32_t SHORT_OPTION_FILE = 0x66696c65 ; // 'file'
static const uint32_t SHORT_OPTION_SHLB = 0x73686c62 ; // 'shlb'
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetVariable ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " target variable " ,
" Read global variables for the current target, "
" before or while running a process. " ,
nullptr , eCommandRequiresTarget ) ,
m_option_group ( ) ,
m_option_variable ( false ) , // Don't include frame options
m_option_format ( eFormatDefault ) ,
m_option_compile_units ( LLDB_OPT_SET_1 , false , " file " , SHORT_OPTION_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 " , SHORT_OPTION_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 ( ) ;
}
~ CommandObjectTargetVariable ( ) override = default ;
void DumpValueObject ( Stream & s , VariableSP & var_sp , ValueObjectSP & valobj_sp ,
const char * root_name ) {
DumpValueObjectOptions options ( m_varobj_options . GetAsDumpOptions ( ) ) ;
if ( ! valobj_sp - > GetTargetSP ( ) - > GetDisplayRuntimeSupportValues ( ) & &
valobj_sp - > IsRuntimeSupportValue ( ) )
return ;
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 ;
case eValueTypeVariableThreadLocal :
if ( m_option_variable . show_scope )
s . PutCString ( " THREAD: " ) ;
break ;
default :
break ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
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 ( " : " ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
const Format format = m_option_format . GetFormat ( ) ;
if ( format ! = eFormatDefault )
options . SetFormat ( format ) ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
options . SetRootValueObjectName ( root_name ) ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
valobj_sp - > Dump ( s , options ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05: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 ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
Options * GetOptions ( ) override { return & m_option_group ; }
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
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 ( ) ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} 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 ( ) ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
Target * target = m_exe_ctx . GetTargetPtr ( ) ;
const size_t argc = args . GetArgumentCount ( ) ;
Stream & s = result . GetOutputStream ( ) ;
if ( argc > 0 ) {
// TODO: Convert to entry-based iteration. Requires converting
// DumpValueObject.
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 ( llvm : : StringRef : : withNullAsEmpty ( 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 ( ) ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
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 ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
} 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 = nullptr ;
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 ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( ! success ) {
if ( frame ) {
if ( comp_unit )
result . AppendErrorWithFormat (
" no global variables in current compile unit: %s \n " ,
comp_unit - > GetPath ( ) . c_str ( ) ) ;
2013-08-23 13:46:38 -04:00
else
2017-01-02 14:26:05 -05:00
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 ( ) ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
} 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 ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 (
llvm : : StringRef (
" . " ) ) ; // 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 ) ;
}
}
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
if ( m_interpreter . TruncationWarningNecessary ( ) ) {
result . GetOutputStream ( ) . Printf ( m_interpreter . TruncationWarningText ( ) ,
m_cmd_name . c_str ( ) ) ;
m_interpreter . TruncationWarningGiven ( ) ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
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 ;
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetModulesSearchPathsAdd
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesSearchPathsAdd : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetModulesSearchPathsAdd ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " target modules search-paths add " ,
" Add new image search paths substitution pairs to "
" the current target. " ,
nullptr ) {
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 ( ) override = default ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
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 ] ) {
Log * log = lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_HOST ) ;
if ( log ) {
log - > Printf ( " target modules search path adding ImageSearchPath "
" pair: '%s' -> '%s' " ,
from , to ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 " ) ;
2013-08-23 13:46:38 -04:00
else
2017-01-02 14:26:05 -05:00
result . AppendError ( " <new-path-prefix> can't be empty \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
} else {
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetModulesSearchPathsClear
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesSearchPathsClear : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
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 " ) { }
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetModulesSearchPathsClear ( ) override = default ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
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 ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetModulesSearchPathsInsert
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
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. " ,
nullptr ) {
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 ( ) override = default ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target ) {
size_t argc = command . GetArgumentCount ( ) ;
// check for at least 3 arguments and an odd number of parameters
if ( argc > = 3 & & argc & 1 ) {
bool success = false ;
uint32_t insert_idx = StringConvert : : ToUInt32 (
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 ( ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// 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 " ) ;
2013-08-23 13:46:38 -04:00
else
2017-01-02 14:26:05 -05:00
result . AppendError ( " <new-path-prefix> can't be empty \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} else {
result . AppendError ( " insert requires at least three arguments \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
return result . Succeeded ( ) ;
2017-01-02 14:26:05 -05:00
}
} else {
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetModulesSearchPathsList
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesSearchPathsList : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
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 " ) { }
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetModulesSearchPathsList ( ) override = default ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target ) {
if ( command . GetArgumentCount ( ) ! = 0 ) {
result . AppendError ( " list takes no arguments \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
return result . Succeeded ( ) ;
2017-01-02 14:26:05 -05:00
}
target - > GetImageSearchPathList ( ) . Dump ( & result . GetOutputStream ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetModulesSearchPathsQuery
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesSearchPathsQuery : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetModulesSearchPathsQuery ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " target modules search-paths query " ,
" Transform a path using the first applicable image search path. " ,
nullptr ) {
CommandArgumentEntry arg ;
CommandArgumentData path_arg ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Define the first (and only) variant of this arg.
path_arg . arg_type = eArgTypeDirectoryName ;
path_arg . arg_repetition = eArgRepeatPlain ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// There is only one variant this argument could be; put it into the
// argument entry.
arg . push_back ( path_arg ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetModulesSearchPathsQuery ( ) override = default ;
protected :
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target ) {
if ( command . GetArgumentCount ( ) ! = 1 ) {
result . AppendError ( " query requires one argument \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
return result . Succeeded ( ) ;
2017-01-02 14:26:05 -05:00
}
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 ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
//----------------------------------------------------------------------
// Static Helper functions
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
static void DumpModuleArchitecture ( Stream & strm , Module * module ,
bool full_triple , uint32_t width ) {
if ( module ) {
StreamString arch_strm ;
2015-12-30 06:55:28 -05:00
2017-01-02 14:26:05 -05:00
if ( full_triple )
module - > GetArchitecture ( ) . DumpTriple ( arch_strm ) ;
else
arch_strm . PutCString ( module - > GetArchitecture ( ) . GetArchitectureName ( ) ) ;
std : : string arch_str = arch_strm . GetString ( ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( width )
strm . Printf ( " %-*s " , width , arch_str . c_str ( ) ) ;
2013-08-23 13:46:38 -04:00
else
2017-01-02 14:26:05 -05:00
strm . PutCString ( arch_str ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
static void DumpModuleUUID ( Stream & strm , Module * module ) {
if ( module & & module - > GetUUID ( ) . IsValid ( ) )
module - > GetUUID ( ) . Dump ( & strm ) ;
else
strm . PutCString ( " " ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ) ;
2013-08-23 13:46:38 -04:00
else
2017-01-02 14:26:05 -05:00
strm < < " No line table " ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
return num_matches ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
// Keep the width spacing correct if things go wrong...
if ( width > 0 )
strm . Printf ( " %-*s " , width , " " ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
static void DumpDirectory ( Stream & strm , const FileSpec * file_spec_ptr ,
uint32_t width ) {
if ( file_spec_ptr ) {
2013-08-23 13:46:38 -04:00
if ( width > 0 )
2017-01-02 14:26:05 -05:00
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 , " " ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 , " " ) ;
2016-07-23 16:50:09 -04:00
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
static size_t DumpModuleObjfileHeaders ( Stream & strm , ModuleList & module_list ) {
size_t num_dumped = 0 ;
std : : lock_guard < std : : recursive_mutex > guard ( module_list . GetMutex ( ) ) ;
const size_t num_modules = module_list . GetSize ( ) ;
if ( num_modules > 0 ) {
strm . Printf ( " Dumping headers for % " PRIu64 " module(s). \n " ,
static_cast < uint64_t > ( num_modules ) ) ;
strm . IndentMore ( ) ;
for ( size_t image_idx = 0 ; image_idx < num_modules ; + + image_idx ) {
Module * module = module_list . GetModulePointerAtIndexUnlocked ( image_idx ) ;
if ( module ) {
if ( num_dumped + + > 0 ) {
strm . EOL ( ) ;
strm . EOL ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
ObjectFile * objfile = module - > GetObjectFile ( ) ;
objfile - > Dump ( & strm ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
strm . IndentLess ( ) ;
}
return num_dumped ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
static bool DumpModuleSymbolVendor ( Stream & strm , Module * module ) {
if ( module ) {
SymbolVendor * symbol_vendor = module - > GetSymbolVendor ( true ) ;
if ( symbol_vendor ) {
symbol_vendor - > Dump ( & strm ) ;
return true ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ( ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
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 ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ) {
std : : vector < uint32_t > match_indexes ;
ConstString symbol_name ( name ) ;
uint32_t num_matches = 0 ;
if ( name_is_regex ) {
RegularExpression name_regexp ( symbol_name . GetStringRef ( ) ) ;
num_matches = symtab - > AppendSymbolIndexesMatchingRegExAndType (
name_regexp , eSymbolTypeAny , match_indexes ) ;
} else {
num_matches =
symtab - > AppendSymbolIndexesWithName ( symbol_name , match_indexes ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
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 ( ) ;
for ( uint32_t i = 0 ; i < num_matches ; + + i ) {
Symbol * symbol = symtab - > SymbolAtIndex ( match_indexes [ i ] ) ;
if ( symbol & & symbol - > ValueIsAddress ( ) ) {
DumpAddress ( interpreter . GetExecutionContext ( )
. GetBestExecutionContextScope ( ) ,
symbol - > GetAddressRef ( ) , verbose , strm ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
strm . IndentLess ( ) ;
return num_matches ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
return 0 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
static void DumpSymbolContextList ( ExecutionContextScope * exe_scope ,
Stream & strm , SymbolContextList & sc_list ,
bool verbose ) {
strm . IndentMore ( ) ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
const uint32_t num_matches = sc_list . GetSize ( ) ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
for ( uint32_t i = 0 ; i < num_matches ; + + i ) {
SymbolContext sc ;
if ( sc_list . GetContextAtIndex ( i , sc ) ) {
AddressRange range ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
sc . GetAddressRange ( eSymbolContextEverything , 0 , true , range ) ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
DumpAddress ( exe_scope , range . GetBaseAddress ( ) , verbose , strm ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
strm . IndentLess ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ( ( llvm : : StringRef ( 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 , nullptr , eFunctionNameTypeAuto , include_symbols ,
include_inlines , append , sc_list ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( num_matches ) {
strm . Indent ( ) ;
strm . Printf ( " % " PRIu64 " match%s found in " , ( uint64_t ) num_matches ,
num_matches > 1 ? " es " : " " ) ;
DumpFullpath ( strm , & module - > GetFileSpec ( ) , 0 ) ;
strm . PutCString ( " : \n " ) ;
DumpSymbolContextList (
interpreter . GetExecutionContext ( ) . GetBestExecutionContextScope ( ) ,
strm , sc_list , verbose ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return num_matches ;
}
return 0 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ] ) {
2013-08-23 13:46:38 -04:00
TypeList type_list ;
const uint32_t max_num_matches = UINT32_MAX ;
2017-01-02 14:26:05 -05:00
size_t num_matches = 0 ;
2013-08-23 13:46:38 -04:00
bool name_is_fully_qualified = false ;
2017-01-02 14:26:05 -05:00
SymbolContext sc ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
ConstString name ( name_cstr ) ;
2017-01-02 14:26:05 -05:00
llvm : : DenseSet < lldb_private : : SymbolFile * > searched_symbol_files ;
num_matches =
module - > FindTypes ( sc , name , name_is_fully_qualified , max_num_matches ,
searched_symbol_files , type_list ) ;
if ( num_matches ) {
strm . Indent ( ) ;
strm . Printf ( " % " PRIu64 " match%s found in " , ( uint64_t ) num_matches ,
num_matches > 1 ? " es " : " " ) ;
DumpFullpath ( strm , & module - > GetFileSpec ( ) , 0 ) ;
strm . PutCString ( " : \n " ) ;
for ( TypeSP type_sp : type_list . Types ( ) ) {
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 - > GetFullCompilerType ( ) ;
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 - > GetFullCompilerType ( ) ;
typedefed_type_sp - > GetDescription ( & strm , eDescriptionLevelFull ,
true ) ;
typedef_type_sp = typedefed_type_sp ;
typedefed_type_sp = typedef_type_sp - > GetTypedefType ( ) ;
}
2013-08-23 13:46:38 -04:00
}
strm . EOL ( ) ;
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
}
return num_matches ;
2017-01-02 14:26:05 -05:00
}
return 0 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 )
2013-08-23 13:46:38 -04:00
return 0 ;
2017-01-02 14:26:05 -05:00
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 ) ;
llvm : : DenseSet < SymbolFile * > searched_symbol_files ;
num_matches = sym_ctx . module_sp - > FindTypes (
sym_ctx , name , name_is_fully_qualified , max_num_matches ,
searched_symbol_files , 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 - > GetFullCompilerType ( ) ;
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 - > GetFullCompilerType ( ) ;
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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
return 0 ;
}
static size_t FindModulesByName ( Target * target , const char * module_name ,
ModuleList & module_list ,
bool check_global_list ) {
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
std : : lock_guard < std : : recursive_mutex > guard (
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 ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} 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 ) ;
}
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
return module_list . GetSize ( ) - initial_size ;
2013-08-23 13:46:38 -04:00
}
# pragma mark CommandObjectTargetModulesModuleAutoComplete
//----------------------------------------------------------------------
// A base command object class that can auto complete with module file
// paths
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesModuleAutoComplete
: public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
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 ) ;
}
~ CommandObjectTargetModulesModuleAutoComplete ( ) override = default ;
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 ) override {
// Arguments are the standard module completer.
std : : string completion_str ( input . GetArgumentAtIndex ( cursor_index ) ) ;
completion_str . erase ( cursor_char_position ) ;
CommandCompletions : : InvokeCommonCompletionCallbacks (
GetCommandInterpreter ( ) , CommandCompletions : : eModuleCompletion ,
completion_str . c_str ( ) , match_start_point , max_return_elements , nullptr ,
word_complete , matches ) ;
return matches . GetSize ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetModulesSourceFileAutoComplete
//----------------------------------------------------------------------
// A base command object class that can auto complete with module source
// file paths
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesSourceFileAutoComplete
: public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
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 ) ;
}
~ CommandObjectTargetModulesSourceFileAutoComplete ( ) override = default ;
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 ) override {
// Arguments are the standard source file completer.
std : : string completion_str ( input . GetArgumentAtIndex ( cursor_index ) ) ;
completion_str . erase ( cursor_char_position ) ;
CommandCompletions : : InvokeCommonCompletionCallbacks (
GetCommandInterpreter ( ) , CommandCompletions : : eSourceFileCompletion ,
completion_str . c_str ( ) , match_start_point , max_return_elements , nullptr ,
word_complete , matches ) ;
return matches . GetSize ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
2016-07-23 16:50:09 -04:00
# pragma mark CommandObjectTargetModulesDumpObjfile
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesDumpObjfile
: public CommandObjectTargetModulesModuleAutoComplete {
2016-07-23 16:50:09 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetModulesDumpObjfile ( CommandInterpreter & interpreter )
: CommandObjectTargetModulesModuleAutoComplete (
interpreter , " target modules dump objfile " ,
" Dump the object file headers from one or more target modules. " ,
nullptr ) { }
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetModulesDumpObjfile ( ) override = default ;
2016-07-23 16:50:09 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = nullptr ) {
result . AppendError ( " invalid target, create a debug target using the "
" 'target create' command " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
uint32_t addr_byte_size = target - > GetArchitecture ( ) . GetAddressByteSize ( ) ;
result . GetOutputStream ( ) . SetAddressByteSize ( addr_byte_size ) ;
result . GetErrorStream ( ) . SetAddressByteSize ( addr_byte_size ) ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
size_t num_dumped = 0 ;
if ( command . GetArgumentCount ( ) = = 0 ) {
// Dump all headers for all modules images
num_dumped = DumpModuleObjfileHeaders ( result . GetOutputStream ( ) ,
target - > GetImages ( ) ) ;
if ( num_dumped = = 0 ) {
result . AppendError ( " the target has no associated executable images " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
// Find the modules that match the basename or full path.
ModuleList module_list ;
const char * arg_cstr ;
for ( int arg_idx = 0 ;
( arg_cstr = command . GetArgumentAtIndex ( arg_idx ) ) ! = nullptr ;
+ + arg_idx ) {
size_t num_matched =
FindModulesByName ( target , arg_cstr , module_list , true ) ;
if ( num_matched = = 0 ) {
result . AppendWarningWithFormat (
" Unable to find an image that matches '%s'. \n " , arg_cstr ) ;
2016-07-23 16:50:09 -04:00
}
2017-01-02 14:26:05 -05:00
}
// Dump all the modules we found.
num_dumped =
DumpModuleObjfileHeaders ( result . GetOutputStream ( ) , module_list ) ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
if ( num_dumped > 0 ) {
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendError ( " no matching executable images found " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2016-07-23 16:50:09 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2016-07-23 16:50:09 -04:00
} ;
# pragma mark CommandObjectTargetModulesDumpSymtab
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
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 , nullptr , nullptr } } ;
static OptionDefinition g_target_modules_dump_symtab_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_1 , false , " sort " , ' s ' , OptionParser : : eRequiredArgument , nullptr , g_sort_option_enumeration , 0 , eArgTypeSortOrder , " Supply a sort order when dumping the symbol table. " }
// clang-format on
} ;
class CommandObjectTargetModulesDumpSymtab
: public CommandObjectTargetModulesModuleAutoComplete {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetModulesDumpSymtab ( CommandInterpreter & interpreter )
: CommandObjectTargetModulesModuleAutoComplete (
interpreter , " target modules dump symtab " ,
" Dump the symbol table from one or more target modules. " , nullptr ) ,
m_options ( ) { }
~ CommandObjectTargetModulesDumpSymtab ( ) override = default ;
Options * GetOptions ( ) override { return & m_options ; }
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) , m_sort_order ( eSortOrderNone ) { }
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
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 , GetDefinitions ( ) [ option_idx ] . enum_values ,
eSortOrderNone , error ) ;
break ;
default :
error . SetErrorStringWithFormat ( " invalid short option character '%c' " ,
short_option ) ;
break ;
}
return error ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_sort_order = eSortOrderNone ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_target_modules_dump_symtab_options ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
SortOrder m_sort_order ;
} ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = nullptr ) {
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
std : : lock_guard < std : : recursive_mutex > guard (
target - > GetImages ( ) . GetMutex ( ) ) ;
const size_t num_modules = target - > GetImages ( ) . GetSize ( ) ;
if ( num_modules > 0 ) {
result . GetOutputStream ( ) . Printf ( " Dumping symbol table for % " PRIu64
" modules. \n " ,
( uint64_t ) num_modules ) ;
for ( size_t image_idx = 0 ; image_idx < num_modules ; + + image_idx ) {
if ( num_dumped > 0 ) {
result . GetOutputStream ( ) . EOL ( ) ;
result . GetOutputStream ( ) . EOL ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ) ) ! = nullptr ;
+ + 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 ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
num_dumped + + ;
DumpModuleSymtab ( m_interpreter , result . GetOutputStream ( ) ,
module , m_options . m_sort_order ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} else
result . AppendWarningWithFormat (
" Unable to find an image that matches '%s'. \n " , arg_cstr ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( num_dumped > 0 )
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
else {
result . AppendError ( " no matching executable images found " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
CommandOptions m_options ;
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetModulesDumpSections
//----------------------------------------------------------------------
// Image section dumping command
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesDumpSections
: public CommandObjectTargetModulesModuleAutoComplete {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetModulesDumpSections ( CommandInterpreter & interpreter )
: CommandObjectTargetModulesModuleAutoComplete (
interpreter , " target modules dump sections " ,
" Dump the sections from one or more target modules. " ,
//"target modules dump sections [<file1> ...]")
nullptr ) { }
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetModulesDumpSections ( ) override = default ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = nullptr ) {
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 % " PRIu64
" modules. \n " ,
( uint64_t ) 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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} else {
// Dump specified images (by basename or fullpath)
const char * arg_cstr ;
for ( int arg_idx = 0 ;
( arg_cstr = command . GetArgumentAtIndex ( arg_idx ) ) ! = nullptr ;
+ + 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 ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} else {
// Check the global list
std : : lock_guard < std : : recursive_mutex > guard (
Module : : GetAllocationModuleCollectionMutex ( ) ) ;
result . AppendWarningWithFormat (
" Unable to find an image that matches '%s'. \n " , arg_cstr ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
if ( num_dumped > 0 )
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
else {
result . AppendError ( " no matching executable images found " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetModulesDumpSymfile
//----------------------------------------------------------------------
// Image debug symbol dumping command
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesDumpSymfile
: public CommandObjectTargetModulesModuleAutoComplete {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
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> ...]")
nullptr ) { }
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetModulesDumpSymfile ( ) override = default ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = nullptr ) {
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 ( ) ;
std : : lock_guard < std : : recursive_mutex > guard ( target_modules . GetMutex ( ) ) ;
const size_t num_modules = target_modules . GetSize ( ) ;
if ( num_modules > 0 ) {
result . GetOutputStream ( ) . Printf ( " Dumping debug symbols for % " PRIu64
" modules. \n " ,
( uint64_t ) 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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} else {
// Dump specified images (by basename or fullpath)
const char * arg_cstr ;
for ( int arg_idx = 0 ;
( arg_cstr = command . GetArgumentAtIndex ( arg_idx ) ) ! = nullptr ;
+ + 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 + + ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} else
result . AppendWarningWithFormat (
" Unable to find an image that matches '%s'. \n " , arg_cstr ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
if ( num_dumped > 0 )
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
else {
result . AppendError ( " no matching executable images found " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetModulesDumpLineTable
//----------------------------------------------------------------------
// Image debug line table dumping command
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesDumpLineTable
: public CommandObjectTargetModulesSourceFileAutoComplete {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetModulesDumpLineTable ( CommandInterpreter & interpreter )
: CommandObjectTargetModulesSourceFileAutoComplete (
interpreter , " target modules dump line-table " ,
" Dump the line table for one or more compilation units. " , nullptr ,
eCommandRequiresTarget ) { }
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetModulesDumpLineTable ( ) override = default ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
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 . AppendError ( " file option must be specified. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return result . Succeeded ( ) ;
} else {
// Dump specified images (by basename or fullpath)
const char * arg_cstr ;
for ( int arg_idx = 0 ;
( arg_cstr = command . GetArgumentAtIndex ( arg_idx ) ) ! = nullptr ;
+ + arg_idx ) {
FileSpec file_spec ( arg_cstr , false ) ;
const ModuleList & target_modules = target - > GetImages ( ) ;
std : : lock_guard < std : : recursive_mutex > guard ( 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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
if ( total_num_dumped > 0 )
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
else {
result . AppendError ( " no source filenames matched any command arguments " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetModulesDump
//----------------------------------------------------------------------
// Dump multi-word command for target modules
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesDump : public CommandObjectMultiword {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
CommandObjectTargetModulesDump ( CommandInterpreter & interpreter )
: CommandObjectMultiword ( interpreter , " target modules dump " ,
" Commands for dumping information about one or "
" more target modules. " ,
" target modules dump "
" [headers|symtab|sections|symfile|line-table] "
" [<file1> <file2> ...] " ) {
LoadSubCommand ( " objfile " ,
CommandObjectSP (
new CommandObjectTargetModulesDumpObjfile ( interpreter ) ) ) ;
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 ) ) ) ;
}
~ CommandObjectTargetModulesDump ( ) override = default ;
2013-08-23 13:46:38 -04:00
} ;
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesAdd : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
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 ( ) ,
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 ( ) ;
}
~ CommandObjectTargetModulesAdd ( ) override = default ;
Options * GetOptions ( ) override { return & m_option_group ; }
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 ) override {
std : : string completion_str ( input . GetArgumentAtIndex ( cursor_index ) ) ;
completion_str . erase ( cursor_char_position ) ;
CommandCompletions : : InvokeCommonCompletionCallbacks (
GetCommandInterpreter ( ) , CommandCompletions : : eDiskFileCompletion ,
completion_str . c_str ( ) , match_start_point , max_return_elements , nullptr ,
word_complete , matches ) ;
return matches . GetSize ( ) ;
}
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
OptionGroupOptions m_option_group ;
OptionGroupUUID m_uuid_option_group ;
OptionGroupFile m_symbol_file ;
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = nullptr ) {
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 {
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 . GetData ( ) ,
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 . GetData ( ) ,
module_spec . GetFileSpec ( ) . GetPath ( ) . c_str ( ) ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} else {
result . AppendErrorWithFormat ( " Unable to create the executable "
" or symbol file with UUID %s " ,
strm . GetData ( ) ) ;
}
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} else {
StreamString strm ;
module_spec . GetUUID ( ) . Dump ( & strm ) ;
result . AppendErrorWithFormat (
" Unable to locate the executable or symbol file with UUID %s " ,
strm . GetData ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
} else {
result . AppendError (
" one or more executable image paths must be specified " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
} else {
for ( auto & entry : args . entries ( ) ) {
if ( entry . ref . empty ( ) )
continue ;
FileSpec file_spec ( entry . ref , 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 ( ) ;
if ( ! module_spec . GetArchitecture ( ) . IsValid ( ) )
module_spec . GetArchitecture ( ) = target - > GetArchitecture ( ) ;
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 " ,
entry . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
} else {
flush = true ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
std : : string resolved_path = file_spec . GetPath ( ) ;
result . SetStatus ( eReturnStatusFailed ) ;
if ( resolved_path ! = entry . ref ) {
result . AppendErrorWithFormat (
" invalid module path '%s' with resolved path '%s' \n " ,
entry . ref . str ( ) . c_str ( ) , resolved_path . c_str ( ) ) ;
break ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
result . AppendErrorWithFormat ( " invalid module path '%s' \n " ,
entry . c_str ( ) ) ;
break ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
if ( flush ) {
ProcessSP process = target - > GetProcessSP ( ) ;
if ( process )
process - > Flush ( ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesLoad
: public CommandObjectTargetModulesModuleAutoComplete {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
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 ( ) ,
m_file_option ( LLDB_OPT_SET_1 , false , " file " , ' f ' , 0 , eArgTypeName ,
" 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 ( ) ;
}
~ CommandObjectTargetModulesLoad ( ) override = default ;
Options * GetOptions ( ) override { return & m_option_group ; }
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = nullptr ) {
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 ;
const char * arg_cstr = m_file_option . GetOptionValue ( ) . GetCurrentValue ( ) ;
const bool use_global_module_list = true ;
ModuleList module_list ;
const size_t num_matches = FindModulesByName (
target , arg_cstr , module_list , use_global_module_list ) ;
if ( num_matches = = 1 ) {
module_spec . GetFileSpec ( ) =
module_list . GetModuleAtIndex ( 0 ) - > GetFileSpec ( ) ;
} else if ( num_matches > 1 ) {
search_using_module_spec = false ;
result . AppendErrorWithFormat (
" more than 1 module matched by name '%s' \n " , arg_cstr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
} else {
search_using_module_spec = false ;
result . AppendErrorWithFormat ( " no object file for module '%s' \n " ,
arg_cstr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
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 ( ) ;
const bool slide_is_offset = true ;
module - > SetLoadAddress ( * target , slide , slide_is_offset ,
changed ) ;
} 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 = StringConvert : : ToUInt64 (
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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} 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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( changed ) {
target - > ModulesDidLoad ( matching_modules ) ;
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
if ( process )
process - > Flush ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} 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 ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} 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 ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} 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 ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} else {
result . AppendError ( " either the \" --file <module> \" or the \" --uuid "
" <uuid> \" option must be specified. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2014-11-25 16:00:58 -05:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
OptionGroupOptions m_option_group ;
OptionGroupUUID m_uuid_option_group ;
OptionGroupString m_file_option ;
OptionGroupUInt64 m_slide_option ;
2013-08-23 13:46:38 -04:00
} ;
//----------------------------------------------------------------------
// List images with associated information
//----------------------------------------------------------------------
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
static OptionDefinition g_target_modules_list_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_1 , false , " address " , ' a ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeAddressOrExpression , " Display the image at this address. " } ,
{ LLDB_OPT_SET_1 , false , " arch " , ' A ' , OptionParser : : eOptionalArgument , nullptr , nullptr , 0 , eArgTypeWidth , " Display the architecture when listing images. " } ,
{ LLDB_OPT_SET_1 , false , " triple " , ' t ' , OptionParser : : eOptionalArgument , nullptr , nullptr , 0 , eArgTypeWidth , " Display the triple when listing images. " } ,
{ LLDB_OPT_SET_1 , false , " header " , ' h ' , OptionParser : : eNoArgument , nullptr , nullptr , 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 , nullptr , nullptr , 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 , nullptr , nullptr , 0 , eArgTypeNone , " Display the UUID when listing images. " } ,
{ LLDB_OPT_SET_1 , false , " fullpath " , ' f ' , OptionParser : : eOptionalArgument , nullptr , nullptr , 0 , eArgTypeWidth , " Display the fullpath to the image object file. " } ,
{ LLDB_OPT_SET_1 , false , " directory " , ' d ' , OptionParser : : eOptionalArgument , nullptr , nullptr , 0 , eArgTypeWidth , " Display the directory with optional width for the image object file. " } ,
{ LLDB_OPT_SET_1 , false , " basename " , ' b ' , OptionParser : : eOptionalArgument , nullptr , nullptr , 0 , eArgTypeWidth , " Display the basename with optional width for the image object file. " } ,
{ LLDB_OPT_SET_1 , false , " symfile " , ' s ' , OptionParser : : eOptionalArgument , nullptr , nullptr , 0 , eArgTypeWidth , " Display the fullpath to the image symbol file with optional width. " } ,
{ LLDB_OPT_SET_1 , false , " symfile-unique " , ' S ' , OptionParser : : eOptionalArgument , nullptr , nullptr , 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 , nullptr , nullptr , 0 , eArgTypeWidth , " Display the modification time with optional width of the module. " } ,
{ LLDB_OPT_SET_1 , false , " ref-count " , ' r ' , OptionParser : : eOptionalArgument , nullptr , nullptr , 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 , nullptr , nullptr , 0 , eArgTypeNone , " Display the module pointer. " } ,
{ LLDB_OPT_SET_1 , false , " global " , ' g ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Display the modules from the global module list, not just the current target. " }
// clang-format on
} ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesList : public CommandObjectParsed {
public :
class CommandOptions : public Options {
public :
CommandOptions ( )
: Options ( ) , m_format_array ( ) , m_use_global_module_list ( false ) ,
m_module_addr ( LLDB_INVALID_ADDRESS ) { }
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
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 ' ) {
m_module_addr = Args : : StringToAddress ( execution_context , option_arg ,
LLDB_INVALID_ADDRESS , & error ) ;
} else {
unsigned long width = 0 ;
option_arg . getAsInteger ( 0 , width ) ;
m_format_array . push_back ( std : : make_pair ( short_option , width ) ) ;
}
return error ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_format_array . clear ( ) ;
m_use_global_module_list = false ;
m_module_addr = LLDB_INVALID_ADDRESS ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_target_modules_list_options ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
// 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 ;
} ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
CommandObjectTargetModulesList ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " target modules list " ,
" List current executable and dependent shared library images. " ,
" target modules list [<cmd-options>] " ) ,
m_options ( ) { }
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetModulesList ( ) override = default ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
Options * GetOptions ( ) override { return & m_options ; }
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
protected :
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
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 = = nullptr & & ! use_global_module_list ) {
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 ;
// This locker will be locked on the mutex in module_list_ptr if it is
// non-nullptr.
// Otherwise it will lock the AllocationModuleCollectionMutex when
// accessing
// the global module list directly.
std : : unique_lock < std : : recursive_mutex > guard (
Module : : GetAllocationModuleCollectionMutex ( ) , std : : defer_lock ) ;
const ModuleList * module_list_ptr = nullptr ;
const size_t argc = command . GetArgumentCount ( ) ;
if ( argc = = 0 ) {
if ( use_global_module_list ) {
guard . lock ( ) ;
num_modules = Module : : GetNumberAllocatedModules ( ) ;
} else {
module_list_ptr = & target - > GetImages ( ) ;
}
} else {
// TODO: Convert to entry based iteration. Requires converting
// FindModulesByName.
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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
module_list_ptr = & module_list ;
}
std : : unique_lock < std : : recursive_mutex > lock ;
if ( module_list_ptr ! = nullptr ) {
lock =
std : : unique_lock < std : : recursive_mutex > ( 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 ( ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
void PrintModule ( Target * target , Module * module , int indent , Stream & strm ) {
if ( module = = nullptr ) {
strm . PutCString ( " Null module " ) ;
return ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
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 ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
strm . Printf ( " %*s " , addr_nibble_width + 2 , " " ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( width )
strm . Printf ( " {%* " PRIu64 " } " , width , ( uint64_t ) ref_count ) ;
else
strm . Printf ( " {% " PRIu64 " } " , ( uint64_t ) ref_count ) ;
} break ;
case ' s ' :
case ' S ' : {
const SymbolVendor * symbol_vendor = module - > GetSymbolVendor ( ) ;
if ( symbol_vendor ) {
const FileSpec symfile_spec = symbol_vendor - > GetMainFileSpec ( ) ;
if ( format_char = = ' S ' ) {
// 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 , & symfile_spec , width ) ;
dump_object_name = true ;
break ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
strm . Printf ( " %.*s " , width , " <NONE> " ) ;
} break ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
case ' m ' :
DumpTimePoint ( module - > GetModificationTime ( ) , strm , width ) ;
break ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
case ' p ' :
strm . Printf ( " %p " , static_cast < void * > ( module ) ) ;
break ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
case ' u ' :
DumpModuleUUID ( strm , module ) ;
break ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
default :
break ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( dump_object_name ) {
const char * object_name = module - > GetObjectName ( ) . GetCString ( ) ;
if ( object_name )
strm . Printf ( " (%s) " , object_name ) ;
}
strm . EOL ( ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
CommandOptions m_options ;
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetModulesShowUnwind
//----------------------------------------------------------------------
// Lookup unwind information in images
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
static OptionDefinition g_target_modules_show_unwind_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_1 , false , " name " , ' n ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeFunctionName , " Show unwind instructions for a function or symbol name. " } ,
{ LLDB_OPT_SET_2 , false , " address " , ' a ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeAddressOrExpression , " Show unwind instructions for a function or symbol containing an address " }
// clang-format on
} ;
2013-11-06 11:48:53 -05:00
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed {
public :
enum {
eLookupTypeInvalid = - 1 ,
eLookupTypeAddress = 0 ,
eLookupTypeSymbol ,
eLookupTypeFunction ,
eLookupTypeFunctionOrSymbol ,
kNumLookupTypes
} ;
class CommandOptions : public Options {
public :
CommandOptions ( )
: Options ( ) , m_type ( eLookupTypeInvalid ) , m_str ( ) ,
m_addr ( LLDB_INVALID_ADDRESS ) { }
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option ) {
case ' a ' : {
m_str = option_arg ;
m_type = eLookupTypeAddress ;
m_addr = Args : : StringToAddress ( execution_context , option_arg ,
LLDB_INVALID_ADDRESS , & error ) ;
if ( m_addr = = LLDB_INVALID_ADDRESS )
error . SetErrorStringWithFormat ( " invalid address string '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
}
case ' n ' :
m_str = option_arg ;
m_type = eLookupTypeFunctionOrSymbol ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option %c. " , short_option ) ;
break ;
}
return error ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_type = eLookupTypeInvalid ;
m_str . clear ( ) ;
m_addr = LLDB_INVALID_ADDRESS ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_target_modules_show_unwind_options ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Instance variables to hold the values for command options.
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
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
} ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
CommandObjectTargetModulesShowUnwind ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " target modules show-unwind " ,
" Show synthesized unwind instructions for a function. " , nullptr ,
eCommandRequiresTarget | eCommandRequiresProcess |
eCommandProcessMustBeLaunched | eCommandProcessMustBePaused ) ,
m_options ( ) { }
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetModulesShowUnwind ( ) override = default ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
Options * GetOptions ( ) override { return & m_options ; }
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
protected :
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_exe_ctx . GetTargetPtr ( ) ;
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
ABI * abi = nullptr ;
if ( process )
abi = process - > GetABI ( ) . get ( ) ;
if ( process = = nullptr ) {
result . AppendError (
" You must have a process running to use this command. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
ThreadList threads ( process - > GetThreadList ( ) ) ;
if ( threads . GetSize ( ) = = 0 ) {
result . AppendError ( " The process must be paused to use this command. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
ThreadSP thread ( threads . GetThreadAtIndex ( 0 ) ) ;
if ( ! thread ) {
result . AppendError ( " The process must be paused to use this command. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
SymbolContextList sc_list ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
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-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -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
2017-01-02 14:26:05 -05:00
size_t num_matches = sc_list . GetSize ( ) ;
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
2017-01-02 14:26:05 -05:00
for ( uint32_t idx = 0 ; idx < num_matches ; idx + + ) {
SymbolContext sc ;
sc_list . GetContextAtIndex ( idx , sc ) ;
if ( sc . symbol = = nullptr & & sc . function = = nullptr )
continue ;
if ( ! sc . module_sp | | sc . module_sp - > GetObjectFile ( ) = = nullptr )
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 )
continue ;
result . GetOutputStream ( ) . Printf (
" UNWIND PLANS for %s`%s (start addr 0x% " PRIx64 " ) \n \n " ,
sc . module_sp - > GetPlatformFileSpec ( ) . GetFilename ( ) . AsCString ( ) ,
funcname . AsCString ( ) , start_addr ) ;
UnwindPlanSP non_callsite_unwind_plan =
func_unwinders_sp - > GetUnwindPlanAtNonCallSite ( * target , * thread , - 1 ) ;
if ( non_callsite_unwind_plan ) {
result . GetOutputStream ( ) . Printf (
" Asynchronous (not restricted to call-sites) UnwindPlan is '%s' \n " ,
non_callsite_unwind_plan - > GetSourceName ( ) . AsCString ( ) ) ;
}
UnwindPlanSP callsite_unwind_plan =
func_unwinders_sp - > GetUnwindPlanAtCallSite ( * target , - 1 ) ;
if ( callsite_unwind_plan ) {
result . GetOutputStream ( ) . Printf (
" Synchronous (restricted to call-sites) UnwindPlan is '%s' \n " ,
callsite_unwind_plan - > GetSourceName ( ) . AsCString ( ) ) ;
}
UnwindPlanSP fast_unwind_plan =
func_unwinders_sp - > GetUnwindPlanFastUnwind ( * target , * thread ) ;
if ( fast_unwind_plan ) {
result . GetOutputStream ( ) . Printf (
" Fast UnwindPlan is '%s' \n " ,
fast_unwind_plan - > GetSourceName ( ) . AsCString ( ) ) ;
}
result . GetOutputStream ( ) . Printf ( " \n " ) ;
UnwindPlanSP assembly_sp =
func_unwinders_sp - > GetAssemblyUnwindPlan ( * target , * thread , 0 ) ;
if ( assembly_sp ) {
result . GetOutputStream ( ) . Printf (
" Assembly language inspection UnwindPlan: \n " ) ;
assembly_sp - > Dump ( result . GetOutputStream ( ) , thread . get ( ) ,
LLDB_INVALID_ADDRESS ) ;
result . GetOutputStream ( ) . Printf ( " \n " ) ;
}
UnwindPlanSP ehframe_sp =
func_unwinders_sp - > GetEHFrameUnwindPlan ( * target , 0 ) ;
if ( ehframe_sp ) {
result . GetOutputStream ( ) . Printf ( " eh_frame UnwindPlan: \n " ) ;
ehframe_sp - > Dump ( result . GetOutputStream ( ) , thread . get ( ) ,
LLDB_INVALID_ADDRESS ) ;
result . GetOutputStream ( ) . Printf ( " \n " ) ;
}
UnwindPlanSP ehframe_augmented_sp =
func_unwinders_sp - > GetEHFrameAugmentedUnwindPlan ( * target , * thread , 0 ) ;
if ( ehframe_augmented_sp ) {
result . GetOutputStream ( ) . Printf ( " eh_frame augmented UnwindPlan: \n " ) ;
ehframe_augmented_sp - > Dump ( result . GetOutputStream ( ) , thread . get ( ) ,
LLDB_INVALID_ADDRESS ) ;
result . GetOutputStream ( ) . Printf ( " \n " ) ;
}
UnwindPlanSP arm_unwind_sp =
func_unwinders_sp - > GetArmUnwindUnwindPlan ( * target , 0 ) ;
if ( arm_unwind_sp ) {
result . GetOutputStream ( ) . Printf ( " ARM.exidx unwind UnwindPlan: \n " ) ;
arm_unwind_sp - > Dump ( result . GetOutputStream ( ) , thread . get ( ) ,
LLDB_INVALID_ADDRESS ) ;
result . GetOutputStream ( ) . Printf ( " \n " ) ;
}
UnwindPlanSP compact_unwind_sp =
func_unwinders_sp - > GetCompactUnwindUnwindPlan ( * target , 0 ) ;
if ( compact_unwind_sp ) {
result . GetOutputStream ( ) . Printf ( " Compact unwind UnwindPlan: \n " ) ;
compact_unwind_sp - > Dump ( result . GetOutputStream ( ) , thread . get ( ) ,
LLDB_INVALID_ADDRESS ) ;
result . GetOutputStream ( ) . Printf ( " \n " ) ;
}
if ( fast_unwind_plan ) {
result . GetOutputStream ( ) . Printf ( " Fast UnwindPlan: \n " ) ;
fast_unwind_plan - > Dump ( result . GetOutputStream ( ) , thread . get ( ) ,
LLDB_INVALID_ADDRESS ) ;
result . GetOutputStream ( ) . Printf ( " \n " ) ;
}
ABISP abi_sp = process - > GetABI ( ) ;
if ( abi_sp ) {
UnwindPlan arch_default ( lldb : : eRegisterKindGeneric ) ;
if ( abi_sp - > CreateDefaultUnwindPlan ( arch_default ) ) {
result . GetOutputStream ( ) . Printf ( " Arch default UnwindPlan: \n " ) ;
arch_default . Dump ( result . GetOutputStream ( ) , thread . get ( ) ,
LLDB_INVALID_ADDRESS ) ;
result . GetOutputStream ( ) . Printf ( " \n " ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
UnwindPlan arch_entry ( lldb : : eRegisterKindGeneric ) ;
if ( abi_sp - > CreateFunctionEntryUnwindPlan ( arch_entry ) ) {
result . GetOutputStream ( ) . Printf (
" Arch default at entry point UnwindPlan: \n " ) ;
arch_entry . Dump ( result . GetOutputStream ( ) , thread . get ( ) ,
LLDB_INVALID_ADDRESS ) ;
result . GetOutputStream ( ) . Printf ( " \n " ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2015-02-06 16:38:51 -05:00
2017-01-02 14:26:05 -05:00
result . GetOutputStream ( ) . Printf ( " \n " ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
CommandOptions m_options ;
2013-08-23 13:46:38 -04:00
} ;
//----------------------------------------------------------------------
// Lookup information in images
//----------------------------------------------------------------------
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
static OptionDefinition g_target_modules_lookup_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_1 , true , " address " , ' a ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeAddressOrExpression , " Lookup an address in one or more target modules. " } ,
{ LLDB_OPT_SET_1 , false , " offset " , ' o ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeOffset , " When looking up an address subtract <offset> from any addresses before doing the lookup. " } ,
/* FIXME: re-enable regex for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_6 */
{ LLDB_OPT_SET_2 | LLDB_OPT_SET_4 | LLDB_OPT_SET_5 , false , " regex " , ' r ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " The <name> argument for name lookups are regular expressions. " } ,
{ LLDB_OPT_SET_2 , true , " symbol " , ' s ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 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 , nullptr , nullptr , 0 , eArgTypeFilename , " Lookup a file by fullpath or basename in one or more target modules. " } ,
{ LLDB_OPT_SET_3 , false , " line " , ' l ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLineNum , " Lookup a line number in a file (must be used in conjunction with --file). " } ,
{ LLDB_OPT_SET_FROM_TO ( 3 , 5 ) , false , " no-inlines " , ' i ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Ignore inline entries (must be used in conjunction with --file or --function). " } ,
{ LLDB_OPT_SET_4 , true , " function " , ' F ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 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 , nullptr , nullptr , 0 , eArgTypeFunctionOrSymbol , " Lookup a function or symbol by name in one or more target modules. " } ,
{ LLDB_OPT_SET_6 , true , " type " , ' t ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 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 , nullptr , nullptr , 0 , eArgTypeNone , " Enable verbose lookup information. " } ,
{ LLDB_OPT_SET_ALL , false , " all " , ' A ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Print all matches, not just the best match, if a best match is available. " } ,
// clang-format on
} ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
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 ( ) : Options ( ) { OptionParsingStarting ( nullptr ) ; }
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option ) {
case ' a ' : {
m_type = eLookupTypeAddress ;
m_addr = Args : : StringToAddress ( execution_context , option_arg ,
LLDB_INVALID_ADDRESS , & error ) ;
} break ;
case ' o ' :
if ( option_arg . getAsInteger ( 0 , m_offset ) )
error . SetErrorStringWithFormat ( " invalid offset string '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
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 ' :
if ( option_arg . getAsInteger ( 0 , m_line_number ) )
error . SetErrorStringWithFormat ( " invalid line number string '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
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 ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
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 ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_target_modules_lookup_options ) ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
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. " ,
nullptr , eCommandRequiresTarget ) ,
m_options ( ) {
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 ) ;
}
~ CommandObjectTargetModulesLookup ( ) override = default ;
Options * GetOptions ( ) override { 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 ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
StackFrameSP frame = m_exe_ctx . GetFrameSP ( ) ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
if ( ! frame )
return false ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
break ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
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_verbose
? static_cast < int > ( eSymbolContextVariable )
: 0 ) ,
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 ,
GetCommandInterpreter ( ) . GetDebugger ( ) . GetTerminalWidth ( ) ) ;
syntax_error = true ;
break ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = nullptr ) {
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 ( ) ;
}
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
// Dump all sections for all other modules
const ModuleList & target_modules = target - > GetImages ( ) ;
std : : lock_guard < std : : recursive_mutex > guard ( target_modules . GetMutex ( ) ) ;
const size_t num_modules = target_modules . GetSize ( ) ;
if ( num_modules > 0 ) {
for ( i = 0 ; i < num_modules & & ! syntax_error ; + + 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 + + ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
} 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 ) ) ! = nullptr & &
! syntax_error ;
+ + 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 + + ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} else
result . AppendWarningWithFormat (
" Unable to find an image that matches '%s'. \n " , arg_cstr ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
if ( num_successful_lookups > 0 )
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
else
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
CommandOptions m_options ;
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectMultiwordImageSearchPaths
//-------------------------------------------------------------------------
// CommandObjectMultiwordImageSearchPaths
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModulesImageSearchPaths
: public CommandObjectMultiword {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetModulesImageSearchPaths ( CommandInterpreter & interpreter )
: CommandObjectMultiword (
interpreter , " target modules search-paths " ,
" Commands for managing module search paths for a target. " ,
" 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 ( ) override = default ;
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetModules
//-------------------------------------------------------------------------
// CommandObjectTargetModules
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetModules : public CommandObjectMultiword {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
CommandObjectTargetModules ( CommandInterpreter & interpreter )
: CommandObjectMultiword ( interpreter , " target modules " ,
" 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 ) ) ) ;
}
~ CommandObjectTargetModules ( ) override = default ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
private :
2017-01-02 14:26:05 -05:00
//------------------------------------------------------------------
// For CommandObjectTargetModules only
//------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN ( CommandObjectTargetModules ) ;
2013-08-23 13:46:38 -04:00
} ;
2017-01-02 14:26:05 -05:00
class CommandObjectTargetSymbolsAdd : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
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>] " , eCommandRequiresTarget ) ,
m_option_group ( ) ,
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 ( ) ;
}
~ CommandObjectTargetSymbolsAdd ( ) override = default ;
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 ) override {
std : : string completion_str ( input . GetArgumentAtIndex ( cursor_index ) ) ;
completion_str . erase ( cursor_char_position ) ;
CommandCompletions : : InvokeCommonCompletionCallbacks (
GetCommandInterpreter ( ) , CommandCompletions : : eDiskFileCompletion ,
completion_str . c_str ( ) , match_start_point , max_return_elements , nullptr ,
word_complete , matches ) ;
return matches . GetSize ( ) ;
}
Options * GetOptions ( ) override { return & m_option_group ; }
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
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 ) ;
}
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
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 ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
}
}
// 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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
}
// 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 ;
}
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} else {
result . AppendError ( " invalid current frame " ) ;
error_set = true ;
}
} else {
result . AppendErrorWithFormat ( " process is not stopped: %s " ,
StateAsCString ( process_state ) ) ;
error_set = true ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} 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 ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
success | = module_spec . GetUUID ( ) . IsValid ( ) | |
module_spec . GetFileSpec ( ) . Exists ( ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( success ) {
if ( Symbols : : DownloadObjectAndSymbolFile ( module_spec ) ) {
if ( module_spec . GetSymbolFileSpec ( ) )
success = AddModuleSymbols ( target , module_spec , flush , result ) ;
}
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
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 . GetString ( ) ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} 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 ( auto & entry : args . entries ( ) ) {
if ( ! entry . ref . empty ( ) ) {
module_spec . GetSymbolFileSpec ( ) . SetFile ( entry . ref , true ) ;
if ( platform_sp ) {
FileSpec symfile_spec ;
if ( platform_sp
- > ResolveSymbolFile ( * target , module_spec , symfile_spec )
. Success ( ) )
module_spec . GetSymbolFileSpec ( ) = symfile_spec ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
ArchSpec arch ;
bool symfile_exists = module_spec . GetSymbolFileSpec ( ) . Exists ( ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( symfile_exists ) {
if ( ! AddModuleSymbols ( target , module_spec , flush , result ) )
break ;
} else {
std : : string resolved_symfile_path =
module_spec . GetSymbolFileSpec ( ) . GetPath ( ) ;
if ( resolved_symfile_path ! = entry . ref ) {
result . AppendErrorWithFormat (
" invalid module path '%s' with resolved path '%s' \n " ,
entry . c_str ( ) , resolved_symfile_path . c_str ( ) ) ;
break ;
}
result . AppendErrorWithFormat ( " invalid module path '%s' \n " ,
entry . c_str ( ) ) ;
break ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( flush ) {
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
if ( process )
process - > Flush ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
OptionGroupOptions m_option_group ;
OptionGroupUUID m_uuid_option_group ;
OptionGroupFile m_file_option ;
OptionGroupBoolean m_current_frame_option ;
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetSymbols
//-------------------------------------------------------------------------
// CommandObjectTargetSymbols
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetSymbols : public CommandObjectMultiword {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
CommandObjectTargetSymbols ( CommandInterpreter & interpreter )
: CommandObjectMultiword (
interpreter , " target symbols " ,
" Commands for adding and managing debug symbol files. " ,
" target symbols <sub-command> ... " ) {
LoadSubCommand (
" add " , CommandObjectSP ( new CommandObjectTargetSymbolsAdd ( interpreter ) ) ) ;
}
~ CommandObjectTargetSymbols ( ) override = default ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
private :
2017-01-02 14:26:05 -05:00
//------------------------------------------------------------------
// For CommandObjectTargetModules only
//------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN ( CommandObjectTargetSymbols ) ;
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetStopHookAdd
//-------------------------------------------------------------------------
// CommandObjectTargetStopHookAdd
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
static OptionDefinition g_target_stop_hook_add_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , false , " one-liner " , ' o ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeOneLiner , " Specify a one-line breakpoint command inline. Be sure to surround it with quotes. " } ,
{ LLDB_OPT_SET_ALL , false , " shlib " , ' s ' , OptionParser : : eRequiredArgument , nullptr , nullptr , CommandCompletions : : eModuleCompletion , eArgTypeShlibName , " Set the module within which the stop-hook is to be run. " } ,
{ LLDB_OPT_SET_ALL , false , " thread-index " , ' x ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeThreadIndex , " The stop hook is run only for the thread whose index matches this argument. " } ,
{ LLDB_OPT_SET_ALL , false , " thread-id " , ' t ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeThreadID , " The stop hook is run only for the thread whose TID matches this argument. " } ,
{ LLDB_OPT_SET_ALL , false , " thread-name " , ' T ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeThreadName , " The stop hook is run only for the thread whose thread name matches this argument. " } ,
{ LLDB_OPT_SET_ALL , false , " queue-name " , ' q ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeQueueName , " The stop hook is run only for threads in the queue whose name is given by this argument. " } ,
{ LLDB_OPT_SET_1 , false , " file " , ' f ' , OptionParser : : eRequiredArgument , nullptr , nullptr , CommandCompletions : : eSourceFileCompletion , eArgTypeFilename , " Specify the source file within which the stop-hook is to be run. " } ,
{ LLDB_OPT_SET_1 , false , " start-line " , ' l ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLineNum , " Set the start of the line range for which the stop-hook is to be run. " } ,
{ LLDB_OPT_SET_1 , false , " end-line " , ' e ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLineNum , " Set the end of the line range for which the stop-hook is to be run. " } ,
{ LLDB_OPT_SET_2 , false , " classname " , ' c ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeClassName , " Specify the class within which the stop-hook is to be run. " } ,
{ LLDB_OPT_SET_3 , false , " name " , ' n ' , OptionParser : : eRequiredArgument , nullptr , nullptr , CommandCompletions : : eSymbolCompletion , eArgTypeFunctionName , " Set the function name within which the stop hook will be run. " } ,
// clang-format on
} ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
class CommandObjectTargetStopHookAdd : public CommandObjectParsed ,
public IOHandlerDelegateMultiline {
public :
class CommandOptions : public Options {
public :
CommandOptions ( )
: Options ( ) , 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 ( ) override = default ;
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_target_stop_hook_add_options ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option ) {
case ' c ' :
m_class_name = option_arg ;
m_sym_ctx_specified = true ;
break ;
case ' e ' :
if ( option_arg . getAsInteger ( 0 , m_line_end ) ) {
error . SetErrorStringWithFormat ( " invalid end line number: \" %s \" " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
m_sym_ctx_specified = true ;
break ;
case ' l ' :
if ( option_arg . getAsInteger ( 0 , m_line_start ) ) {
error . SetErrorStringWithFormat ( " invalid start line number: \" %s \" " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ' :
if ( option_arg . getAsInteger ( 0 , m_thread_id ) )
error . SetErrorStringWithFormat ( " invalid thread id string '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
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 ' :
if ( option_arg . getAsInteger ( 0 , m_thread_index ) )
error . SetErrorStringWithFormat ( " invalid thread index string '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
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 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
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 ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ;
} ;
CommandObjectTargetStopHookAdd ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " target stop-hook add " ,
" Add a hook to be executed when the target stops. " ,
" target stop-hook add " ) ,
IOHandlerDelegateMultiline ( " DONE " ,
IOHandlerDelegate : : Completion : : LLDBCommand ) ,
m_options ( ) { }
~ CommandObjectTargetStopHookAdd ( ) override = default ;
Options * GetOptions ( ) override { return & m_options ; }
2014-02-18 11:23:10 -05:00
protected :
2017-01-02 14:26:05 -05:00
void IOHandlerActivated ( IOHandler & io_handler ) override {
StreamFileSP output_sp ( io_handler . GetOutputStreamFile ( ) ) ;
if ( output_sp ) {
output_sp - > PutCString (
" Enter your stop hook command(s). Type 'DONE' to end. \n " ) ;
output_sp - > Flush ( ) ;
}
}
void IOHandlerInputComplete ( IOHandler & io_handler ,
std : : string & line ) override {
if ( m_stop_hook_sp ) {
if ( line . empty ( ) ) {
StreamFileSP error_sp ( io_handler . GetErrorStreamFile ( ) ) ;
if ( error_sp ) {
error_sp - > Printf ( " error: stop hook #% " PRIu64
" aborted, no commands. \n " ,
m_stop_hook_sp - > GetID ( ) ) ;
error_sp - > Flush ( ) ;
}
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target )
target - > RemoveStopHookByID ( m_stop_hook_sp - > GetID ( ) ) ;
} else {
m_stop_hook_sp - > GetCommandPointer ( ) - > SplitIntoLines ( line ) ;
2014-02-18 11:23:10 -05:00
StreamFileSP output_sp ( io_handler . GetOutputStreamFile ( ) ) ;
2017-01-02 14:26:05 -05:00
if ( output_sp ) {
output_sp - > Printf ( " Stop hook #% " PRIu64 " added. \n " ,
m_stop_hook_sp - > GetID ( ) ) ;
output_sp - > Flush ( ) ;
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
}
m_stop_hook_sp . reset ( ) ;
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
io_handler . SetIsDone ( true ) ;
}
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
m_stop_hook_sp . reset ( ) ;
Target * target = GetSelectedOrDummyTarget ( ) ;
if ( target ) {
Target : : StopHookSP new_hook_sp = target - > CreateStopHook ( ) ;
// 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 ) ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
if ( ! m_options . m_class_name . empty ( ) ) {
specifier_ap - > AddSpecification (
m_options . m_class_name . c_str ( ) ,
SymbolContextSpecifier : : eClassOrNamespaceSpecified ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
if ( ! m_options . m_file_name . empty ( ) ) {
specifier_ap - > AddSpecification (
m_options . m_file_name . c_str ( ) ,
SymbolContextSpecifier : : eFileSpecified ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
if ( m_options . m_line_start ! = 0 ) {
specifier_ap - > AddLineSpecification (
m_options . m_line_start ,
SymbolContextSpecifier : : eLineStartSpecified ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
if ( m_options . m_line_end ! = UINT_MAX ) {
specifier_ap - > AddLineSpecification (
m_options . m_line_end , SymbolContextSpecifier : : eLineEndSpecified ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
if ( ! m_options . m_function_name . empty ( ) ) {
specifier_ap - > AddSpecification (
m_options . m_function_name . c_str ( ) ,
SymbolContextSpecifier : : eFunctionSpecified ) ;
}
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
if ( specifier_ap )
new_hook_sp - > SetSpecifier ( specifier_ap . release ( ) ) ;
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
// Next see if any of the thread options have been entered:
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
if ( m_options . m_thread_specified ) {
ThreadSpec * thread_spec = new ThreadSpec ( ) ;
2014-02-18 11:23:10 -05:00
2017-01-02 14:26:05 -05:00
if ( m_options . m_thread_id ! = LLDB_INVALID_THREAD_ID ) {
thread_spec - > SetTID ( m_options . m_thread_id ) ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
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 {
m_stop_hook_sp = new_hook_sp ;
m_interpreter . GetLLDBCommandsFromIOHandler (
" > " , // Prompt
* this , // IOHandlerDelegate
true , // Run IOHandler in async mode
nullptr ) ; // Baton for the "io_handler" that will be passed back
// into our IOHandlerDelegate functions
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
private :
CommandOptions m_options ;
Target : : StopHookSP m_stop_hook_sp ;
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetStopHookDelete
//-------------------------------------------------------------------------
// CommandObjectTargetStopHookDelete
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetStopHookDelete : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetStopHookDelete ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " target stop-hook delete " ,
" Delete a stop-hook. " ,
" target stop-hook delete [<idx>] " ) { }
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetStopHookDelete ( ) override = default ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = GetSelectedOrDummyTarget ( ) ;
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 ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} else {
bool success ;
for ( size_t i = 0 ; i < num_args ; i + + ) {
lldb : : user_id_t user_id = StringConvert : : ToUInt32 (
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 ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
# pragma mark CommandObjectTargetStopHookEnableDisable
//-------------------------------------------------------------------------
// CommandObjectTargetStopHookEnableDisable
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetStopHookEnableDisable ( CommandInterpreter & interpreter ,
bool enable , const char * name ,
const char * help , const char * syntax )
: CommandObjectParsed ( interpreter , name , help , syntax ) , m_enable ( enable ) {
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetStopHookEnableDisable ( ) override = default ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = GetSelectedOrDummyTarget ( ) ;
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 = StringConvert : : ToUInt32 (
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 ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
private :
2017-01-02 14:26:05 -05:00
bool m_enable ;
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectTargetStopHookList
//-------------------------------------------------------------------------
// CommandObjectTargetStopHookList
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTargetStopHookList : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTargetStopHookList ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " target stop-hook list " ,
" List all stop-hooks. " ,
" target stop-hook list [<type>] " ) { }
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTargetStopHookList ( ) override = default ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = GetSelectedOrDummyTarget ( ) ;
if ( ! target ) {
result . AppendError ( " invalid target \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return result . Succeeded ( ) ;
}
2014-11-25 16:00:58 -05:00
2017-01-02 14:26:05 -05:00
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 ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectMultiwordTargetStopHooks
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
//-------------------------------------------------------------------------
// CommandObjectMultiwordTargetStopHooks
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectMultiwordTargetStopHooks ( CommandInterpreter & interpreter )
: CommandObjectMultiword (
interpreter , " target stop-hook " ,
" 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 ( ) override = default ;
2013-08-23 13:46:38 -04:00
} ;
# pragma mark CommandObjectMultiwordTarget
//-------------------------------------------------------------------------
// CommandObjectMultiwordTarget
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
CommandObjectMultiwordTarget : : CommandObjectMultiwordTarget (
CommandInterpreter & interpreter )
: CommandObjectMultiword ( interpreter , " target " ,
" 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 ) ) ) ;
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
CommandObjectMultiwordTarget : : ~ CommandObjectMultiwordTarget ( ) = default ;