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.
//
//===----------------------------------------------------------------------===//
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
2016-07-23 16:50:09 -04:00
# include "CommandObjectArgs.h"
2017-01-02 14:26:05 -05:00
# include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Core/Debugger.h"
# include "lldb/Core/Module.h"
# include "lldb/Core/Value.h"
# include "lldb/Host/Host.h"
2017-04-16 12:04:10 -04:00
# include "lldb/Host/OptionParser.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"
2015-07-03 12:57:06 -04:00
# include "lldb/Symbol/ClangASTContext.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Symbol/ObjectFile.h"
# include "lldb/Symbol/Variable.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"
2017-01-02 14:26:05 -05:00
# include "lldb/Target/StackFrame.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Target/Target.h"
# include "lldb/Target/Thread.h"
2017-01-02 14:26:05 -05:00
# include "llvm/ADT/StringSwitch.h"
2013-08-23 13:46:38 -04:00
using namespace lldb ;
using namespace lldb_private ;
2017-01-02 14:26:05 -05:00
// This command is a toy. I'm just using it to have a way to construct the
// arguments to
2013-08-23 13:46:38 -04:00
// calling functions.
//
2017-01-02 14:26:05 -05:00
static OptionDefinition g_arg_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_1 , false , " debug " , ' g ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Enable verbose debug logging of the expression parsing and evaluation. " } ,
// clang-format on
} ;
CommandObjectArgs : : CommandOptions : : CommandOptions (
CommandInterpreter & interpreter )
: Options ( ) {
// Keep only one place to reset the values to their defaults
OptionParsingStarting ( nullptr ) ;
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
CommandObjectArgs : : CommandOptions : : ~ CommandOptions ( ) = default ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
Error CommandObjectArgs : : CommandOptions : : SetOptionValue (
uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) {
Error error ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
const int short_option = m_getopt_table [ option_idx ] . val ;
error . SetErrorStringWithFormat ( " invalid short option character '%c' " ,
short_option ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
return error ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
void CommandObjectArgs : : CommandOptions : : OptionParsingStarting (
ExecutionContext * execution_context ) { }
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition >
CommandObjectArgs : : CommandOptions : : GetDefinitions ( ) {
return llvm : : makeArrayRef ( g_arg_options ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
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 ) { }
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
CommandObjectArgs : : ~ CommandObjectArgs ( ) = default ;
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 ;
}
if ( args . empty ( ) ) {
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 ;
}
TypeSystem * type_system =
thread_module_sp - > GetTypeSystemForLanguage ( eLanguageTypeC ) ;
if ( type_system = = nullptr ) {
result . AppendError ( " Unable to create C type system. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
ValueList value_list ;
for ( auto & arg_entry : args . entries ( ) ) {
llvm : : StringRef arg_type = arg_entry . ref ;
Value value ;
value . SetValueType ( Value : : eValueTypeScalar ) ;
CompilerType compiler_type ;
std : : size_t int_pos = arg_type . find ( " int " ) ;
if ( int_pos ! = llvm : : StringRef : : npos ) {
Encoding encoding = eEncodingSint ;
int width = 0 ;
if ( int_pos > 1 ) {
result . AppendErrorWithFormat ( " Invalid format: %s. \n " ,
arg_entry . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
return false ;
2017-01-02 14:26:05 -05:00
}
if ( int_pos = = 1 & & arg_type [ 0 ] ! = ' u ' ) {
result . AppendErrorWithFormat ( " Invalid format: %s. \n " ,
arg_entry . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
return false ;
2017-01-02 14:26:05 -05:00
}
if ( arg_type [ 0 ] = = ' u ' ) {
encoding = eEncodingUint ;
}
llvm : : StringRef width_spec = arg_type . drop_front ( int_pos + 3 ) ;
auto exp_result = llvm : : StringSwitch < llvm : : Optional < int > > ( width_spec )
. Case ( " 8_t " , 8 )
. Case ( " 16_t " , 16 )
. Case ( " 32_t " , 32 )
. Case ( " 64_t " , 64 )
. Default ( llvm : : None ) ;
if ( ! exp_result . hasValue ( ) ) {
result . AppendErrorWithFormat ( " Invalid format: %s. \n " ,
arg_entry . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
return false ;
2017-01-02 14:26:05 -05:00
}
width = * exp_result ;
2015-12-30 06:55:28 -05:00
2017-01-02 14:26:05 -05:00
compiler_type =
type_system - > GetBuiltinTypeForEncodingAndBitSize ( encoding , width ) ;
if ( ! compiler_type . IsValid ( ) ) {
result . AppendErrorWithFormat (
" Couldn't get Clang type for format %s (%s integer, width %d). \n " ,
arg_entry . c_str ( ) ,
( encoding = = eEncodingSint ? " signed " : " unsigned " ) , width ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
return false ;
2017-01-02 14:26:05 -05:00
}
} else if ( arg_type = = " void* " ) {
compiler_type =
type_system - > GetBasicTypeFromAST ( eBasicTypeVoid ) . GetPointerType ( ) ;
} else if ( arg_type = = " char* " ) {
compiler_type =
type_system - > GetBasicTypeFromAST ( eBasicTypeChar ) . GetPointerType ( ) ;
} else {
result . AppendErrorWithFormat ( " Invalid format: %s. \n " , arg_entry . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
value . SetCompilerType ( compiler_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 ( auto entry : llvm : : enumerate ( args . entries ( ) ) ) {
2017-04-16 12:04:10 -04:00
result . GetOutputStream ( ) . Printf (
" % " PRIu64 " (%s): " , ( uint64_t ) entry . index ( ) , entry . value ( ) . c_str ( ) ) ;
value_list . GetValueAtIndex ( entry . index ( ) ) - > Dump ( & result . GetOutputStream ( ) ) ;
2017-01-02 14:26:05 -05:00
result . GetOutputStream ( ) . Printf ( " \n " ) ;
}
return result . Succeeded ( ) ;
}