2010-06-09 00:52:24 +08:00
//===-- CommandObjectFrame.cpp ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "CommandObjectFrame.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
# include "lldb/Core/Debugger.h"
2010-09-02 08:18:39 +08:00
# include "lldb/Core/Module.h"
# include "lldb/Core/StreamFile.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Core/Timer.h"
2010-09-02 08:18:39 +08:00
# include "lldb/Core/Value.h"
# include "lldb/Core/ValueObject.h"
# include "lldb/Core/ValueObjectVariable.h"
# include "lldb/Interpreter/Args.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Interpreter/CommandReturnObject.h"
2010-09-02 08:18:39 +08:00
# include "lldb/Interpreter/Options.h"
# include "lldb/Symbol/ClangASTType.h"
# include "lldb/Symbol/ClangASTContext.h"
# include "lldb/Symbol/ObjectFile.h"
# include "lldb/Symbol/SymbolContext.h"
# include "lldb/Symbol/Type.h"
# include "lldb/Symbol/Variable.h"
# include "lldb/Symbol/VariableList.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Target/Process.h"
# include "lldb/Target/StackFrame.h"
# include "lldb/Target/Thread.h"
2010-09-02 08:18:39 +08:00
# include "lldb/Target/Target.h"
2010-06-09 00:52:24 +08:00
# include "CommandObjectThread.h"
using namespace lldb ;
using namespace lldb_private ;
# pragma mark CommandObjectFrameInfo
//-------------------------------------------------------------------------
// CommandObjectFrameInfo
//-------------------------------------------------------------------------
class CommandObjectFrameInfo : public CommandObject
{
public :
2010-09-18 09:14:36 +08:00
CommandObjectFrameInfo ( CommandInterpreter & interpreter ) :
CommandObject ( interpreter ,
" frame info " ,
" List information about the currently selected frame in the current thread. " ,
" frame info " ,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused )
2010-06-09 00:52:24 +08:00
{
}
~ CommandObjectFrameInfo ( )
{
}
bool
2010-09-18 09:14:36 +08:00
Execute ( Args & command ,
2010-06-09 00:52:24 +08:00
CommandReturnObject & result )
{
2010-09-18 09:14:36 +08:00
ExecutionContext exe_ctx ( m_interpreter . GetDebugger ( ) . GetExecutionContext ( ) ) ;
2010-06-09 00:52:24 +08:00
if ( exe_ctx . frame )
{
2010-10-04 09:05:56 +08:00
exe_ctx . frame - > DumpUsingSettingsFormat ( & result . GetOutputStream ( ) ) ;
2010-06-09 00:52:24 +08:00
result . GetOutputStream ( ) . EOL ( ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
result . AppendError ( " no current frame " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
} ;
# pragma mark CommandObjectFrameSelect
//-------------------------------------------------------------------------
// CommandObjectFrameSelect
//-------------------------------------------------------------------------
class CommandObjectFrameSelect : public CommandObject
{
public :
2010-10-11 06:28:11 +08:00
class CommandOptions : public Options
{
public :
CommandOptions ( ) :
Options ( )
{
ResetOptionValues ( ) ;
}
virtual
~ CommandOptions ( )
{
}
virtual Error
SetOptionValue ( int option_idx , const char * option_arg )
{
Error error ;
bool success = false ;
char short_option = ( char ) m_getopt_table [ option_idx ] . val ;
switch ( short_option )
{
case ' r ' :
relative_frame_offset = Args : : StringToSInt32 ( option_arg , INT32_MIN , 0 , & success ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " invalid frame offset argument '%s'. \n " , option_arg ) ;
break ;
default :
( " Invalid short option character '%c'. \n " , short_option ) ;
break ;
}
return error ;
}
void
ResetOptionValues ( )
{
Options : : ResetOptionValues ( ) ;
relative_frame_offset = INT32_MIN ;
}
const lldb : : OptionDefinition *
GetDefinitions ( )
{
return g_option_table ;
}
// Options table: Required for subclasses of Options.
static lldb : : OptionDefinition g_option_table [ ] ;
int32_t relative_frame_offset ;
} ;
2010-09-18 09:14:36 +08:00
CommandObjectFrameSelect ( CommandInterpreter & interpreter ) :
CommandObject ( interpreter ,
" frame select " ,
" Select a frame by index from within the current thread and make it the current frame. " ,
2010-10-05 06:28:36 +08:00
NULL ,
2010-09-18 09:14:36 +08:00
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused )
2010-06-09 00:52:24 +08:00
{
2010-10-05 06:28:36 +08:00
CommandArgumentEntry arg ;
CommandArgumentData index_arg ;
// Define the first (and only) variant of this arg.
index_arg . arg_type = eArgTypeFrameIndex ;
2010-10-11 06:28:11 +08:00
index_arg . arg_repetition = eArgRepeatOptional ;
2010-10-05 06:28:36 +08:00
// There is only one variant this argument could be; put it into the argument entry.
arg . push_back ( index_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
2010-06-09 00:52:24 +08:00
}
~ CommandObjectFrameSelect ( )
{
}
2010-10-11 06:28:11 +08:00
virtual
Options *
GetOptions ( )
{
return & m_options ;
}
2010-06-09 00:52:24 +08:00
bool
2010-09-18 09:14:36 +08:00
Execute ( Args & command ,
2010-06-09 00:52:24 +08:00
CommandReturnObject & result )
{
2010-09-18 09:14:36 +08:00
ExecutionContext exe_ctx ( m_interpreter . GetDebugger ( ) . GetExecutionContext ( ) ) ;
2010-06-09 00:52:24 +08:00
if ( exe_ctx . thread )
{
2010-10-11 06:28:11 +08:00
const uint32_t num_frames = exe_ctx . thread - > GetStackFrameCount ( ) ;
uint32_t frame_idx = UINT32_MAX ;
if ( m_options . relative_frame_offset ! = INT32_MIN )
2010-06-09 00:52:24 +08:00
{
2010-10-11 06:28:11 +08:00
// The one and only argument is a signed relative frame index
frame_idx = exe_ctx . thread - > GetSelectedFrameIndex ( ) ;
if ( frame_idx = = UINT32_MAX )
frame_idx = 0 ;
if ( m_options . relative_frame_offset < 0 )
{
if ( frame_idx > = - m_options . relative_frame_offset )
frame_idx + = m_options . relative_frame_offset ;
else
frame_idx = 0 ;
}
else if ( m_options . relative_frame_offset > 0 )
{
if ( num_frames - frame_idx > m_options . relative_frame_offset )
frame_idx + = m_options . relative_frame_offset ;
else
frame_idx = num_frames - 1 ;
}
}
else
{
if ( command . GetArgumentCount ( ) = = 1 )
{
const char * frame_idx_cstr = command . GetArgumentAtIndex ( 0 ) ;
frame_idx = Args : : StringToUInt32 ( frame_idx_cstr , UINT32_MAX , 0 ) ;
}
else
{
result . AppendError ( " invalid arguments. \n " ) ;
m_options . GenerateOptionUsage ( m_interpreter , result . GetErrorStream ( ) , this ) ;
}
}
if ( frame_idx < num_frames )
{
exe_ctx . thread - > SetSelectedFrameByIndex ( frame_idx ) ;
exe_ctx . frame = exe_ctx . thread - > GetSelectedFrame ( ) . get ( ) ;
2010-06-09 00:52:24 +08:00
2010-10-11 06:28:11 +08:00
if ( exe_ctx . frame )
2010-06-09 00:52:24 +08:00
{
2010-10-11 06:28:11 +08:00
bool already_shown = false ;
SymbolContext frame_sc ( exe_ctx . frame - > GetSymbolContext ( eSymbolContextLineEntry ) ) ;
if ( m_interpreter . GetDebugger ( ) . GetUseExternalEditor ( ) & & frame_sc . line_entry . file & & frame_sc . line_entry . line ! = 0 )
{
already_shown = Host : : OpenFileInExternalEditor ( frame_sc . line_entry . file , frame_sc . line_entry . line ) ;
}
2010-06-09 00:52:24 +08:00
2010-10-11 06:28:11 +08:00
if ( DisplayFrameForExecutionContext ( exe_ctx . thread ,
exe_ctx . frame ,
m_interpreter ,
result . GetOutputStream ( ) ,
true ,
! already_shown ,
3 ,
3 ) )
2010-06-09 00:52:24 +08:00
{
2010-10-11 06:28:11 +08:00
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return result . Succeeded ( ) ;
2010-06-09 00:52:24 +08:00
}
}
}
2010-10-11 06:28:11 +08:00
result . AppendErrorWithFormat ( " Frame index (%u) out of range. \n " , frame_idx ) ;
2010-06-09 00:52:24 +08:00
}
else
{
result . AppendError ( " no current thread " ) ;
}
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-10-11 06:28:11 +08:00
protected :
CommandOptions m_options ;
} ;
lldb : : OptionDefinition
CommandObjectFrameSelect : : CommandOptions : : g_option_table [ ] =
{
{ LLDB_OPT_SET_1 , false , " relative " , ' r ' , required_argument , NULL , 0 , eArgTypeOffset , " A relative frame index offset from the current frame index. " } ,
{ 0 , false , NULL , 0 , 0 , NULL , NULL , eArgTypeNone , NULL }
2010-06-09 00:52:24 +08:00
} ;
2010-09-02 08:18:39 +08:00
# pragma mark CommandObjectFrameVariable
//----------------------------------------------------------------------
// List images with associated information
//----------------------------------------------------------------------
class CommandObjectFrameVariable : public CommandObject
{
public :
class CommandOptions : public Options
{
public :
CommandOptions ( ) :
Options ( )
{
ResetOptionValues ( ) ;
}
virtual
~ CommandOptions ( )
{
}
virtual Error
SetOptionValue ( int option_idx , const char * option_arg )
{
Error error ;
bool success ;
char short_option = ( char ) m_getopt_table [ option_idx ] . val ;
switch ( short_option )
{
case ' o ' : use_objc = true ; break ;
case ' r ' : use_regex = true ; break ;
case ' a ' : show_args = false ; break ;
case ' l ' : show_locals = false ; break ;
2010-09-13 10:37:44 +08:00
case ' g ' : show_globals = true ; break ;
2010-10-14 02:56:36 +08:00
case ' t ' : show_types = true ; break ;
2010-09-02 08:18:39 +08:00
case ' y ' : show_summary = false ; break ;
case ' L ' : show_location = true ; break ;
2010-09-13 10:37:44 +08:00
case ' c ' : show_decl = true ; break ;
2010-09-02 08:18:39 +08:00
case ' D ' : debug = true ; break ;
2010-10-15 06:52:14 +08:00
case ' f ' : flat_output = true ; break ;
2010-09-02 08:18:39 +08:00
case ' d ' :
max_depth = Args : : StringToUInt32 ( option_arg , UINT32_MAX , 0 , & success ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " Invalid max depth '%s'. \n " , option_arg ) ;
break ;
case ' p ' :
ptr_depth = Args : : StringToUInt32 ( option_arg , 0 , 0 , & success ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " Invalid pointer depth '%s'. \n " , option_arg ) ;
break ;
case ' G ' :
2010-09-13 10:37:44 +08:00
globals . push_back ( ConstString ( option_arg ) ) ;
2010-09-02 08:18:39 +08:00
break ;
case ' s ' :
show_scope = true ;
break ;
default :
error . SetErrorStringWithFormat ( " Invalid short option character '%c'. \n " , short_option ) ;
break ;
}
return error ;
}
void
ResetOptionValues ( )
{
Options : : ResetOptionValues ( ) ;
use_objc = false ;
use_regex = false ;
show_args = true ;
show_locals = true ;
2010-09-13 10:37:44 +08:00
show_globals = false ;
2010-10-14 02:56:36 +08:00
show_types = false ;
2010-09-02 08:18:39 +08:00
show_scope = false ;
show_summary = true ;
show_location = false ;
2010-09-13 10:37:44 +08:00
show_decl = false ;
2010-09-02 08:18:39 +08:00
debug = false ;
2010-10-15 06:52:14 +08:00
flat_output = false ;
2010-09-02 08:18:39 +08:00
max_depth = UINT32_MAX ;
ptr_depth = 0 ;
globals . clear ( ) ;
}
const lldb : : OptionDefinition *
GetDefinitions ( )
{
return g_option_table ;
}
// Options table: Required for subclasses of Options.
static lldb : : OptionDefinition g_option_table [ ] ;
2010-09-13 10:37:44 +08:00
bool use_objc : 1 ,
use_regex : 1 ,
show_args : 1 ,
show_locals : 1 ,
show_globals : 1 ,
show_types : 1 ,
show_scope : 1 ,
show_summary : 1 ,
show_location : 1 ,
show_decl : 1 ,
2010-10-15 06:52:14 +08:00
debug : 1 ,
flat_output : 1 ;
2010-09-02 08:18:39 +08:00
uint32_t max_depth ; // The depth to print when dumping concrete (not pointers) aggreate values
uint32_t ptr_depth ; // The default depth that is dumped when we find pointers
std : : vector < ConstString > globals ;
// Instance variables to hold the values for command options.
} ;
2010-09-18 09:14:36 +08:00
CommandObjectFrameVariable ( CommandInterpreter & interpreter ) :
CommandObject ( interpreter ,
" frame variable " ,
2010-09-18 11:37:20 +08:00
" Show frame variables. All argument and local variables "
" that are in scope will be shown when no arguments are given. "
" If any arguments are specified, they can be names of "
2010-10-26 07:57:26 +08:00
" argument, local, file static and file global variables. "
2010-09-18 11:37:20 +08:00
" Children of aggregate variables can be specified such as "
" 'var->child.x'. " ,
2010-10-05 06:28:36 +08:00
NULL )
2010-09-02 08:18:39 +08:00
{
2010-10-05 06:28:36 +08:00
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 = eArgRepeatStar ;
// 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 ) ;
2010-09-02 08:18:39 +08:00
}
virtual
~ CommandObjectFrameVariable ( )
{
}
virtual
Options *
GetOptions ( )
{
return & m_options ;
}
virtual bool
Execute
(
Args & command ,
CommandReturnObject & result
)
{
2010-09-18 09:14:36 +08:00
ExecutionContext exe_ctx ( m_interpreter . GetDebugger ( ) . GetExecutionContext ( ) ) ;
2010-09-02 08:18:39 +08:00
if ( exe_ctx . frame = = NULL )
{
2010-09-18 12:06:15 +08:00
result . AppendError ( " you must be stopped in a valid stack frame to view frame variables. " ) ;
2010-09-02 08:18:39 +08:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else
{
2010-09-13 10:37:44 +08:00
Stream & s = result . GetOutputStream ( ) ;
bool get_file_globals = true ;
VariableList * variable_list = exe_ctx . frame - > GetVariableList ( get_file_globals ) ;
2010-09-02 08:18:39 +08:00
VariableSP var_sp ;
ValueObjectSP valobj_sp ;
//ValueObjectList &valobj_list = exe_ctx.frame->GetValueObjectList();
const char * name_cstr = NULL ;
size_t idx ;
if ( ! m_options . globals . empty ( ) )
{
uint32_t fail_count = 0 ;
if ( exe_ctx . target )
{
const size_t num_globals = m_options . globals . size ( ) ;
for ( idx = 0 ; idx < num_globals ; + + idx )
{
VariableList global_var_list ;
const uint32_t num_matching_globals = exe_ctx . target - > GetImages ( ) . FindGlobalVariables ( m_options . globals [ idx ] , true , UINT32_MAX , global_var_list ) ;
if ( num_matching_globals = = 0 )
{
+ + fail_count ;
result . GetErrorStream ( ) . Printf ( " error: can't find global variable '%s' \n " , m_options . globals [ idx ] . AsCString ( ) ) ;
}
else
{
for ( uint32_t global_idx = 0 ; global_idx < num_matching_globals ; + + global_idx )
{
var_sp = global_var_list . GetVariableAtIndex ( global_idx ) ;
if ( var_sp )
{
2010-09-02 10:59:18 +08:00
valobj_sp = exe_ctx . frame - > GetValueObjectForFrameVariable ( var_sp ) ;
2010-09-02 08:18:39 +08:00
if ( ! valobj_sp )
2010-09-02 10:59:18 +08:00
valobj_sp = exe_ctx . frame - > TrackGlobalVariable ( var_sp ) ;
2010-09-02 08:18:39 +08:00
if ( valobj_sp )
{
2010-09-13 10:37:44 +08:00
if ( m_options . show_decl & & var_sp - > GetDeclaration ( ) . GetFile ( ) )
{
2010-09-14 11:16:58 +08:00
var_sp - > GetDeclaration ( ) . DumpStopContext ( & s , false ) ;
s . PutCString ( " : " ) ;
2010-09-13 10:37:44 +08:00
}
2010-10-05 08:00:42 +08:00
ValueObject : : DumpValueObject ( result . GetOutputStream ( ) ,
exe_ctx . frame ,
valobj_sp . get ( ) ,
name_cstr ,
m_options . ptr_depth ,
0 ,
m_options . max_depth ,
m_options . show_types ,
m_options . show_location ,
m_options . use_objc ,
2010-10-15 06:52:14 +08:00
false ,
m_options . flat_output ) ;
2010-09-02 08:18:39 +08:00
}
}
}
}
}
}
if ( fail_count )
result . SetStatus ( eReturnStatusFailed ) ;
}
2010-09-13 11:44:33 +08:00
else if ( variable_list )
2010-09-02 08:18:39 +08:00
{
2010-09-13 11:44:33 +08:00
if ( command . GetArgumentCount ( ) > 0 )
2010-09-02 08:18:39 +08:00
{
2010-10-11 07:55:27 +08:00
VariableList regex_var_list ;
2010-09-13 11:44:33 +08:00
// If we have any args to the variable command, we will make
// variable objects from them...
for ( idx = 0 ; ( name_cstr = command . GetArgumentAtIndex ( idx ) ) ! = NULL ; + + idx )
2010-09-02 08:18:39 +08:00
{
2010-09-13 11:44:33 +08:00
uint32_t ptr_depth = m_options . ptr_depth ;
2010-10-11 07:55:27 +08:00
if ( m_options . use_regex )
2010-09-13 11:44:33 +08:00
{
2010-10-11 07:55:27 +08:00
const uint32_t regex_start_index = regex_var_list . GetSize ( ) ;
RegularExpression regex ( name_cstr ) ;
if ( regex . Compile ( name_cstr ) )
{
size_t num_matches = 0 ;
const size_t num_new_regex_vars = variable_list - > AppendVariablesIfUnique ( regex , regex_var_list , num_matches ) ;
if ( num_new_regex_vars > 0 )
{
for ( uint32_t regex_idx = regex_start_index , end_index = regex_var_list . GetSize ( ) ;
regex_idx < end_index ;
+ + regex_idx )
{
var_sp = regex_var_list . GetVariableAtIndex ( regex_idx ) ;
if ( var_sp )
{
valobj_sp = exe_ctx . frame - > GetValueObjectForFrameVariable ( var_sp ) ;
if ( valobj_sp )
{
if ( m_options . show_decl & & var_sp - > GetDeclaration ( ) . GetFile ( ) )
{
var_sp - > GetDeclaration ( ) . DumpStopContext ( & s , false ) ;
s . PutCString ( " : " ) ;
}
ValueObject : : DumpValueObject ( result . GetOutputStream ( ) ,
exe_ctx . frame ,
valobj_sp . get ( ) ,
var_sp - > GetName ( ) . AsCString ( ) ,
m_options . ptr_depth ,
0 ,
m_options . max_depth ,
m_options . show_types ,
m_options . show_location ,
m_options . use_objc ,
2010-10-15 06:52:14 +08:00
false ,
m_options . flat_output ) ;
2010-10-11 07:55:27 +08:00
}
}
}
}
else if ( num_matches = = 0 )
{
result . GetErrorStream ( ) . Printf ( " error: no variables matched the regular expression '%s'. \n " , name_cstr ) ;
}
}
else
{
char regex_error [ 1024 ] ;
if ( regex . GetErrorAsCString ( regex_error , sizeof ( regex_error ) ) )
result . GetErrorStream ( ) . Printf ( " error: %s \n " , regex_error ) ;
else
result . GetErrorStream ( ) . Printf ( " error: unkown regex error when compiling '%s' \n " , name_cstr ) ;
}
2010-09-13 11:44:33 +08:00
}
else
2010-09-02 08:18:39 +08:00
{
2010-10-11 07:55:27 +08:00
// If first character is a '*', then show pointer contents
if ( name_cstr [ 0 ] = = ' * ' )
{
+ + ptr_depth ;
name_cstr + + ; // Skip the '*'
}
2010-09-02 08:18:39 +08:00
2010-10-11 07:55:27 +08:00
std : : string var_path ( name_cstr ) ;
size_t separator_idx = var_path . find_first_of ( " .-[ " ) ;
ConstString name_const_string ;
if ( separator_idx = = std : : string : : npos )
name_const_string . SetCString ( var_path . c_str ( ) ) ;
else
name_const_string . SetCStringWithLength ( var_path . c_str ( ) , separator_idx ) ;
var_sp = variable_list - > FindVariable ( name_const_string ) ;
if ( var_sp )
2010-09-13 11:44:33 +08:00
{
2010-10-11 07:55:27 +08:00
valobj_sp = exe_ctx . frame - > GetValueObjectForFrameVariable ( var_sp ) ;
2010-09-13 11:44:33 +08:00
2010-10-11 07:55:27 +08:00
var_path . erase ( 0 , name_const_string . GetLength ( ) ) ;
// We are dumping at least one child
while ( separator_idx ! = std : : string : : npos )
{
// Calculate the next separator index ahead of time
ValueObjectSP child_valobj_sp ;
const char separator_type = var_path [ 0 ] ;
switch ( separator_type )
2010-09-02 08:18:39 +08:00
{
2010-10-11 07:55:27 +08:00
case ' - ' :
if ( var_path . size ( ) > = 2 & & var_path [ 1 ] ! = ' > ' )
2010-09-02 08:18:39 +08:00
{
2010-10-11 07:55:27 +08:00
result . GetErrorStream ( ) . Printf ( " error: invalid character in variable path starting at '%s' \n " ,
var_path . c_str ( ) ) ;
2010-09-02 08:18:39 +08:00
var_path . clear ( ) ;
valobj_sp . reset ( ) ;
break ;
}
2010-10-11 07:55:27 +08:00
var_path . erase ( 0 , 1 ) ; // Remove the '-'
// Fall through
case ' . ' :
2010-09-13 11:44:33 +08:00
{
2010-10-11 07:55:27 +08:00
var_path . erase ( 0 , 1 ) ; // Remove the '.' or '>'
separator_idx = var_path . find_first_of ( " .-[ " ) ;
ConstString child_name ;
if ( separator_idx = = std : : string : : npos )
child_name . SetCString ( var_path . c_str ( ) ) ;
2010-09-13 11:44:33 +08:00
else
2010-10-11 07:55:27 +08:00
child_name . SetCStringWithLength ( var_path . c_str ( ) , separator_idx ) ;
2010-09-13 11:44:33 +08:00
2010-10-11 07:55:27 +08:00
child_valobj_sp = valobj_sp - > GetChildMemberWithName ( child_name , true ) ;
2010-09-13 11:44:33 +08:00
if ( ! child_valobj_sp )
{
2010-10-11 07:55:27 +08:00
result . GetErrorStream ( ) . Printf ( " error: can't find child of '%s' named '%s' \n " ,
valobj_sp - > GetName ( ) . AsCString ( ) ,
child_name . GetCString ( ) ) ;
2010-09-13 11:44:33 +08:00
var_path . clear ( ) ;
valobj_sp . reset ( ) ;
break ;
}
2010-10-11 07:55:27 +08:00
// Remove the child name from the path
var_path . erase ( 0 , child_name . GetLength ( ) ) ;
}
break ;
2010-09-13 11:44:33 +08:00
2010-10-11 07:55:27 +08:00
case ' [ ' :
// Array member access, or treating pointer as an array
if ( var_path . size ( ) > 2 ) // Need at least two brackets and a number
{
char * end = NULL ;
int32_t child_index = : : strtol ( & var_path [ 1 ] , & end , 0 ) ;
if ( end & & * end = = ' ] ' )
{
2010-09-13 11:44:33 +08:00
2010-10-11 07:55:27 +08:00
if ( valobj_sp - > IsPointerType ( ) )
{
child_valobj_sp = valobj_sp - > GetSyntheticArrayMemberFromPointer ( child_index , true ) ;
}
else
{
child_valobj_sp = valobj_sp - > GetChildAtIndex ( child_index , true ) ;
}
if ( ! child_valobj_sp )
{
result . GetErrorStream ( ) . Printf ( " error: invalid array index %u in '%s' \n " ,
child_index ,
valobj_sp - > GetName ( ) . AsCString ( ) ) ;
var_path . clear ( ) ;
valobj_sp . reset ( ) ;
break ;
}
// Erase the array member specification '[%i]' where %i is the array index
var_path . erase ( 0 , ( end - var_path . c_str ( ) ) + 1 ) ;
separator_idx = var_path . find_first_of ( " .-[ " ) ;
// Break out early from the switch since we were able to find the child member
break ;
}
2010-09-13 11:44:33 +08:00
}
2010-10-11 07:55:27 +08:00
result . GetErrorStream ( ) . Printf ( " error: invalid array member specification for '%s' starting at '%s' \n " ,
valobj_sp - > GetName ( ) . AsCString ( ) ,
var_path . c_str ( ) ) ;
var_path . clear ( ) ;
valobj_sp . reset ( ) ;
break ;
2010-09-02 08:18:39 +08:00
2010-10-11 07:55:27 +08:00
break ;
2010-09-02 08:18:39 +08:00
2010-10-11 07:55:27 +08:00
default :
result . GetErrorStream ( ) . Printf ( " error: invalid character in variable path starting at '%s' \n " ,
var_path . c_str ( ) ) ;
var_path . clear ( ) ;
valobj_sp . reset ( ) ;
separator_idx = std : : string : : npos ;
break ;
}
2010-09-02 08:18:39 +08:00
2010-10-11 07:55:27 +08:00
if ( child_valobj_sp )
valobj_sp = child_valobj_sp ;
2010-09-02 08:18:39 +08:00
2010-10-11 07:55:27 +08:00
if ( var_path . empty ( ) )
break ;
2010-09-13 10:37:44 +08:00
2010-10-11 07:55:27 +08:00
}
2010-09-13 10:37:44 +08:00
2010-10-11 07:55:27 +08:00
if ( valobj_sp )
2010-09-13 10:37:44 +08:00
{
2010-10-11 07:55:27 +08:00
if ( m_options . show_decl & & var_sp - > GetDeclaration ( ) . GetFile ( ) )
{
var_sp - > GetDeclaration ( ) . DumpStopContext ( & s , false ) ;
s . PutCString ( " : " ) ;
}
2010-09-13 11:44:33 +08:00
2010-10-05 08:00:42 +08:00
2010-10-11 07:55:27 +08:00
ValueObject : : DumpValueObject ( result . GetOutputStream ( ) ,
exe_ctx . frame ,
valobj_sp . get ( ) ,
name_cstr ,
ptr_depth ,
0 ,
m_options . max_depth ,
m_options . show_types ,
m_options . show_location ,
m_options . use_objc ,
2010-10-15 06:52:14 +08:00
false ,
m_options . flat_output ) ;
2010-10-11 07:55:27 +08:00
}
}
else
{
result . GetErrorStream ( ) . Printf ( " error: unable to find any variables named '%s' \n " , name_cstr ) ;
var_path . clear ( ) ;
2010-09-13 10:37:44 +08:00
}
2010-09-13 11:44:33 +08:00
}
2010-09-02 08:18:39 +08:00
}
}
2010-09-13 11:44:33 +08:00
else
{
const uint32_t num_variables = variable_list - > GetSize ( ) ;
if ( num_variables > 0 )
{
for ( uint32_t i = 0 ; i < num_variables ; i + + )
{
VariableSP var_sp ( variable_list - > GetVariableAtIndex ( i ) ) ;
bool dump_variable = true ;
switch ( var_sp - > GetScope ( ) )
{
case eValueTypeVariableGlobal :
dump_variable = m_options . show_globals ;
if ( dump_variable & & m_options . show_scope )
s . PutCString ( " GLOBAL: " ) ;
break ;
case eValueTypeVariableStatic :
dump_variable = m_options . show_globals ;
if ( dump_variable & & m_options . show_scope )
s . PutCString ( " STATIC: " ) ;
break ;
case eValueTypeVariableArgument :
dump_variable = m_options . show_args ;
if ( dump_variable & & m_options . show_scope )
s . PutCString ( " ARG: " ) ;
break ;
case eValueTypeVariableLocal :
dump_variable = m_options . show_locals ;
if ( dump_variable & & m_options . show_scope )
s . PutCString ( " LOCAL: " ) ;
break ;
default :
break ;
}
if ( dump_variable )
{
// Use the variable object code to make sure we are
// using the same APIs as the the public API will be
// using...
valobj_sp = exe_ctx . frame - > GetValueObjectForFrameVariable ( var_sp ) ;
if ( valobj_sp )
{
2010-09-14 11:16:58 +08:00
// When dumping all variables, don't print any variables
// that are not in scope to avoid extra unneeded output
if ( valobj_sp - > IsInScope ( exe_ctx . frame ) )
2010-09-13 11:44:33 +08:00
{
2010-09-14 11:16:58 +08:00
if ( m_options . show_decl & & var_sp - > GetDeclaration ( ) . GetFile ( ) )
{
var_sp - > GetDeclaration ( ) . DumpStopContext ( & s , false ) ;
s . PutCString ( " : " ) ;
}
2010-10-05 08:00:42 +08:00
ValueObject : : DumpValueObject ( result . GetOutputStream ( ) ,
exe_ctx . frame ,
valobj_sp . get ( ) ,
name_cstr ,
m_options . ptr_depth ,
0 ,
m_options . max_depth ,
m_options . show_types ,
m_options . show_location ,
m_options . use_objc ,
2010-10-15 06:52:14 +08:00
false ,
m_options . flat_output ) ;
2010-09-13 11:44:33 +08:00
}
}
}
}
}
}
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
2010-09-02 08:18:39 +08:00
}
}
return result . Succeeded ( ) ;
}
protected :
CommandOptions m_options ;
} ;
lldb : : OptionDefinition
CommandObjectFrameVariable : : CommandOptions : : g_option_table [ ] =
{
2010-10-02 03:59:14 +08:00
{ LLDB_OPT_SET_1 , false , " debug " , ' D ' , no_argument , NULL , 0 , eArgTypeNone , " Enable verbose debug information. " } ,
{ LLDB_OPT_SET_1 , false , " depth " , ' d ' , required_argument , NULL , 0 , eArgTypeCount , " Set the max recurse depth when dumping aggregate types (default is infinity). " } ,
{ LLDB_OPT_SET_1 , false , " show-globals " , ' g ' , no_argument , NULL , 0 , eArgTypeNone , " Show the current frame source file global and static variables. " } ,
{ LLDB_OPT_SET_1 , false , " find-global " , ' G ' , required_argument , NULL , 0 , eArgTypeVarName , " Find a global variable by name (which might not be in the current stack frame source file). " } ,
{ LLDB_OPT_SET_1 , false , " location " , ' L ' , no_argument , NULL , 0 , eArgTypeNone , " Show variable location information. " } ,
{ LLDB_OPT_SET_1 , false , " show-declaration " , ' c ' , no_argument , NULL , 0 , eArgTypeNone , " Show variable declaration information (source file and line where the variable was declared). " } ,
{ LLDB_OPT_SET_1 , false , " no-args " , ' a ' , no_argument , NULL , 0 , eArgTypeNone , " Omit function arguments. " } ,
{ LLDB_OPT_SET_1 , false , " no-locals " , ' l ' , no_argument , NULL , 0 , eArgTypeNone , " Omit local variables. " } ,
2010-10-14 02:56:36 +08:00
{ LLDB_OPT_SET_1 , false , " show-types " , ' t ' , no_argument , NULL , 0 , eArgTypeNone , " Show variable types when dumping values. " } ,
2010-10-02 03:59:14 +08:00
{ LLDB_OPT_SET_1 , false , " no-summary " , ' y ' , no_argument , NULL , 0 , eArgTypeNone , " Omit summary information. " } ,
{ LLDB_OPT_SET_1 , false , " scope " , ' s ' , no_argument , NULL , 0 , eArgTypeNone , " Show variable scope (argument, local, global, static). " } ,
2010-10-28 08:56:11 +08:00
{ LLDB_OPT_SET_1 , false , " objc " , ' o ' , no_argument , NULL , 0 , eArgTypeNone , " When looking up a variable by name, print as an Objective-C object. " } ,
2010-10-02 03:59:14 +08:00
{ LLDB_OPT_SET_1 , false , " ptr-depth " , ' p ' , required_argument , NULL , 0 , eArgTypeCount , " The number of pointers to be traversed when dumping values (default is zero). " } ,
2010-10-11 07:55:27 +08:00
{ LLDB_OPT_SET_1 , false , " regex " , ' r ' , no_argument , NULL , 0 , eArgTypeRegularExpression , " The <variable-name> argument for name lookups are regular expressions. " } ,
2010-10-15 06:52:14 +08:00
{ LLDB_OPT_SET_1 , false , " flat " , ' f ' , no_argument , NULL , 0 , eArgTypeNone , " Display results in a flat format that uses expression paths for each variable or member. " } ,
2010-10-02 03:59:14 +08:00
{ 0 , false , NULL , 0 , 0 , NULL , NULL , eArgTypeNone , NULL }
2010-09-02 08:18:39 +08:00
} ;
2010-06-09 00:52:24 +08:00
# pragma mark CommandObjectMultiwordFrame
//-------------------------------------------------------------------------
// CommandObjectMultiwordFrame
//-------------------------------------------------------------------------
2010-06-23 09:19:29 +08:00
CommandObjectMultiwordFrame : : CommandObjectMultiwordFrame ( CommandInterpreter & interpreter ) :
2010-09-18 09:14:36 +08:00
CommandObjectMultiword ( interpreter ,
" frame " ,
2010-06-09 00:52:24 +08:00
" A set of commands for operating on the current thread's frames. " ,
" frame <subcommand> [<subcommand-options>] " )
{
2010-09-18 09:14:36 +08:00
LoadSubCommand ( " info " , CommandObjectSP ( new CommandObjectFrameInfo ( interpreter ) ) ) ;
LoadSubCommand ( " select " , CommandObjectSP ( new CommandObjectFrameSelect ( interpreter ) ) ) ;
LoadSubCommand ( " variable " , CommandObjectSP ( new CommandObjectFrameVariable ( interpreter ) ) ) ;
2010-06-09 00:52:24 +08:00
}
CommandObjectMultiwordFrame : : ~ CommandObjectMultiwordFrame ( )
{
}