2013-08-23 13:46:38 -04:00
//===-- CommandObjectArgs.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "lldb/lldb-python.h"
# include "CommandObjectArgs.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
# include "lldb/Interpreter/Args.h"
# include "lldb/Core/Debugger.h"
# include "lldb/Core/Module.h"
# include "lldb/Core/Value.h"
# include "lldb/Expression/ClangExpression.h"
# include "lldb/Expression/ClangExpressionVariable.h"
# include "lldb/Expression/ClangFunction.h"
# include "lldb/Host/Host.h"
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Interpreter/CommandReturnObject.h"
# include "lldb/Symbol/ObjectFile.h"
# include "lldb/Symbol/Variable.h"
# include "lldb/Target/Process.h"
# include "lldb/Target/Target.h"
# include "lldb/Target/Thread.h"
# include "lldb/Target/StackFrame.h"
using namespace lldb ;
using namespace lldb_private ;
// This command is a toy. I'm just using it to have a way to construct the arguments to
// calling functions.
//
CommandObjectArgs : : CommandOptions : : CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter )
{
// Keep only one place to reset the values to their defaults
OptionParsingStarting ( ) ;
}
CommandObjectArgs : : CommandOptions : : ~ CommandOptions ( )
{
}
Error
CommandObjectArgs : : CommandOptions : : SetOptionValue ( uint32_t option_idx , const char * option_arg )
{
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
2014-11-25 16:00:58 -05:00
error . SetErrorStringWithFormat ( " invalid short option character '%c' " , short_option ) ;
2013-08-23 13:46:38 -04:00
return error ;
}
void
CommandObjectArgs : : CommandOptions : : OptionParsingStarting ( )
{
}
const OptionDefinition *
CommandObjectArgs : : CommandOptions : : GetDefinitions ( )
{
return g_option_table ;
}
CommandObjectArgs : : CommandObjectArgs ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" args " ,
" When stopped at the start of a function, reads function arguments of type (u?)int(8|16|32|64)_t, (void|char)* " ,
" args " ) ,
m_options ( interpreter )
{
}
CommandObjectArgs : : ~ CommandObjectArgs ( )
{
}
Options *
CommandObjectArgs : : GetOptions ( )
{
return & m_options ;
}
bool
CommandObjectArgs : : DoExecute ( Args & args , CommandReturnObject & result )
{
ConstString target_triple ;
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
if ( ! process )
{
result . AppendError ( " Args found no process. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
const ABI * abi = process - > GetABI ( ) . get ( ) ;
if ( ! abi )
{
result . AppendError ( " The current process has no ABI. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
const size_t num_args = args . GetArgumentCount ( ) ;
size_t arg_index ;
if ( ! num_args )
{
result . AppendError ( " args requires at least one argument " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
Thread * thread = m_exe_ctx . GetThreadPtr ( ) ;
if ( ! thread )
{
result . AppendError ( " args found no thread. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
lldb : : StackFrameSP thread_cur_frame = thread - > GetSelectedFrame ( ) ;
if ( ! thread_cur_frame )
{
result . AppendError ( " The current thread has no current frame. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
ModuleSP thread_module_sp ( thread_cur_frame - > GetFrameCodeAddress ( ) . GetModule ( ) ) ;
if ( ! thread_module_sp )
{
result . AppendError ( " The PC has no associated module. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
ClangASTContext & ast_context = thread_module_sp - > GetClangASTContext ( ) ;
ValueList value_list ;
for ( arg_index = 0 ; arg_index < num_args ; + + arg_index )
{
const char * arg_type_cstr = args . GetArgumentAtIndex ( arg_index ) ;
Value value ;
value . SetValueType ( Value : : eValueTypeScalar ) ;
ClangASTType clang_type ;
char * int_pos ;
if ( ( int_pos = strstr ( const_cast < char * > ( arg_type_cstr ) , " int " ) ) )
{
Encoding encoding = eEncodingSint ;
int width = 0 ;
if ( int_pos > arg_type_cstr + 1 )
{
result . AppendErrorWithFormat ( " Invalid format: %s. \n " , arg_type_cstr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( int_pos = = arg_type_cstr + 1 & & arg_type_cstr [ 0 ] ! = ' u ' )
{
result . AppendErrorWithFormat ( " Invalid format: %s. \n " , arg_type_cstr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( arg_type_cstr [ 0 ] = = ' u ' )
{
encoding = eEncodingUint ;
}
char * width_pos = int_pos + 3 ;
if ( ! strcmp ( width_pos , " 8_t " ) )
width = 8 ;
else if ( ! strcmp ( width_pos , " 16_t " ) )
width = 16 ;
else if ( ! strcmp ( width_pos , " 32_t " ) )
width = 32 ;
else if ( ! strcmp ( width_pos , " 64_t " ) )
width = 64 ;
else
{
result . AppendErrorWithFormat ( " Invalid format: %s. \n " , arg_type_cstr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
clang_type = ast_context . GetBuiltinTypeForEncodingAndBitSize ( encoding , width ) ;
if ( ! clang_type . IsValid ( ) )
{
result . AppendErrorWithFormat ( " Couldn't get Clang type for format %s (%s integer, width %d). \n " ,
arg_type_cstr ,
( encoding = = eEncodingSint ? " signed " : " unsigned " ) ,
width ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else if ( strchr ( arg_type_cstr , ' * ' ) )
{
if ( ! strcmp ( arg_type_cstr , " void* " ) )
clang_type = ast_context . GetBasicType ( eBasicTypeVoid ) . GetPointerType ( ) ;
else if ( ! strcmp ( arg_type_cstr , " char* " ) )
clang_type = ast_context . GetCStringType ( false ) ;
else
{
result . AppendErrorWithFormat ( " Invalid format: %s. \n " , arg_type_cstr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else
{
result . AppendErrorWithFormat ( " Invalid format: %s. \n " , arg_type_cstr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
value . SetClangType ( clang_type ) ;
value_list . PushValue ( value ) ;
}
if ( ! abi - > GetArgumentValues ( * thread , value_list ) )
{
result . AppendError ( " Couldn't get argument values " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
result . GetOutputStream ( ) . Printf ( " Arguments : \n " ) ;
for ( arg_index = 0 ; arg_index < num_args ; + + arg_index )
{
2014-11-25 16:00:58 -05:00
result . GetOutputStream ( ) . Printf ( " % " PRIu64 " (%s): " , ( uint64_t ) arg_index , args . GetArgumentAtIndex ( arg_index ) ) ;
2013-08-23 13:46:38 -04:00
value_list . GetValueAtIndex ( arg_index ) - > Dump ( & result . GetOutputStream ( ) ) ;
result . GetOutputStream ( ) . Printf ( " \n " ) ;
}
return result . Succeeded ( ) ;
}
OptionDefinition
CommandObjectArgs : : CommandOptions : : g_option_table [ ] =
{
2014-11-25 16:00:58 -05:00
{ LLDB_OPT_SET_1 , false , " debug " , ' g ' , OptionParser : : eNoArgument , NULL , NULL , 0 , eArgTypeNone , " Enable verbose debug logging of the expression parsing and evaluation. " } ,
{ 0 , false , NULL , 0 , 0 , NULL , NULL , 0 , eArgTypeNone , NULL }
2013-08-23 13:46:38 -04:00
} ;