2010-06-09 00:52:24 +08:00
//===-- CommandObjectDisassemble.cpp ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "CommandObjectDisassemble.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
# include "lldb/Core/AddressRange.h"
2010-06-16 03:49:27 +08:00
# include "lldb/Interpreter/Args.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Interpreter/CommandCompletions.h"
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Interpreter/CommandReturnObject.h"
# include "lldb/Core/Disassembler.h"
2010-06-16 03:49:27 +08:00
# include "lldb/Interpreter/Options.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Core/SourceManager.h"
# include "lldb/Target/StackFrame.h"
# include "lldb/Symbol/Symbol.h"
# include "lldb/Target/Process.h"
# include "lldb/Target/Target.h"
# define DEFAULT_DISASM_BYTE_SIZE 32
using namespace lldb ;
using namespace lldb_private ;
CommandObjectDisassemble : : CommandOptions : : CommandOptions ( ) :
Options ( ) ,
m_func_name ( ) ,
2010-06-16 02:47:14 +08:00
m_start_addr ( ) ,
m_end_addr ( )
2010-06-09 00:52:24 +08:00
{
ResetOptionValues ( ) ;
}
CommandObjectDisassemble : : CommandOptions : : ~ CommandOptions ( )
{
}
Error
CommandObjectDisassemble : : CommandOptions : : SetOptionValue ( int option_idx , const char * option_arg )
{
Error error ;
char short_option = ( char ) m_getopt_table [ option_idx ] . val ;
switch ( short_option )
{
case ' m ' :
show_mixed = true ;
break ;
case ' c ' :
num_lines_context = Args : : StringToUInt32 ( option_arg , 0 , 0 ) ;
break ;
case ' b ' :
show_bytes = true ;
break ;
2010-06-16 02:47:14 +08:00
case ' s ' :
m_start_addr = Args : : StringToUInt64 ( optarg , LLDB_INVALID_ADDRESS , 0 ) ;
if ( m_start_addr = = LLDB_INVALID_ADDRESS )
m_start_addr = Args : : StringToUInt64 ( optarg , LLDB_INVALID_ADDRESS , 16 ) ;
2010-06-09 00:52:24 +08:00
2010-06-16 02:47:14 +08:00
if ( m_start_addr = = LLDB_INVALID_ADDRESS )
error . SetErrorStringWithFormat ( " Invalid start address string '%s'. \n " , optarg ) ;
break ;
case ' e ' :
m_end_addr = Args : : StringToUInt64 ( optarg , LLDB_INVALID_ADDRESS , 0 ) ;
if ( m_end_addr = = LLDB_INVALID_ADDRESS )
m_end_addr = Args : : StringToUInt64 ( optarg , LLDB_INVALID_ADDRESS , 16 ) ;
if ( m_end_addr = = LLDB_INVALID_ADDRESS )
error . SetErrorStringWithFormat ( " Invalid end address string '%s'. \n " , optarg ) ;
2010-06-09 00:52:24 +08:00
break ;
case ' n ' :
m_func_name = option_arg ;
break ;
case ' r ' :
raw = true ;
break ;
2010-10-30 03:33:40 +08:00
case ' f ' :
// The default action is to disassemble the function for the current frame.
// There's no need to set any flag.
break ;
2010-06-09 00:52:24 +08:00
default :
error . SetErrorStringWithFormat ( " Unrecognized short option '%c'. \n " , short_option ) ;
break ;
}
return error ;
}
void
CommandObjectDisassemble : : CommandOptions : : ResetOptionValues ( )
{
Options : : ResetOptionValues ( ) ;
show_mixed = false ;
show_bytes = false ;
num_lines_context = 0 ;
m_func_name . clear ( ) ;
2010-06-16 02:47:14 +08:00
m_start_addr = LLDB_INVALID_ADDRESS ;
m_end_addr = LLDB_INVALID_ADDRESS ;
2010-06-17 08:32:05 +08:00
raw = false ;
2010-06-09 00:52:24 +08:00
}
const lldb : : OptionDefinition *
CommandObjectDisassemble : : CommandOptions : : GetDefinitions ( )
{
return g_option_table ;
}
lldb : : OptionDefinition
CommandObjectDisassemble : : CommandOptions : : g_option_table [ ] =
{
2010-10-02 03:59:14 +08:00
{ LLDB_OPT_SET_ALL , false , " bytes " , ' b ' , no_argument , NULL , 0 , eArgTypeNone , " Show opcode bytes when disassembling. " } ,
{ LLDB_OPT_SET_ALL , false , " context " , ' c ' , required_argument , NULL , 0 , eArgTypeNumLines , " Number of context lines of source to show. " } ,
{ LLDB_OPT_SET_ALL , false , " mixed " , ' m ' , no_argument , NULL , 0 , eArgTypeNone , " Enable mixed source and assembly display. " } ,
{ LLDB_OPT_SET_ALL , false , " raw " , ' r ' , no_argument , NULL , 0 , eArgTypeNone , " Print raw disassembly with no symbol information. " } ,
2010-06-16 02:47:14 +08:00
2010-10-05 06:28:36 +08:00
{ LLDB_OPT_SET_1 , true , " start-address " , ' s ' , required_argument , NULL , 0 , eArgTypeStartAddress , " Address at which to start disassembling. " } ,
{ LLDB_OPT_SET_1 , false , " end-address " , ' e ' , required_argument , NULL , 0 , eArgTypeEndAddress , " Address at which to end disassembling. " } ,
2010-06-16 02:47:14 +08:00
2010-10-02 03:59:14 +08:00
{ LLDB_OPT_SET_2 , true , " name " , ' n ' , required_argument , NULL , CommandCompletions : : eSymbolCompletion , eArgTypeFunctionName , " Disassemble entire contents of the given function name. " } ,
2010-06-16 02:47:14 +08:00
2010-10-30 03:33:40 +08:00
{ LLDB_OPT_SET_3 , true , " current-frame " , ' f ' , no_argument , NULL , 0 , eArgTypeNone , " Disassemble entire contents of the current frame's function. " } ,
2010-06-09 00:52:24 +08:00
2010-10-02 03:59:14 +08:00
{ 0 , false , NULL , 0 , 0 , NULL , 0 , eArgTypeNone , NULL }
2010-06-09 00:52:24 +08:00
} ;
//-------------------------------------------------------------------------
// CommandObjectDisassemble
//-------------------------------------------------------------------------
2010-09-18 09:14:36 +08:00
CommandObjectDisassemble : : CommandObjectDisassemble ( CommandInterpreter & interpreter ) :
CommandObject ( interpreter ,
" disassemble " ,
" Disassemble bytes in the current function, or elsewhere in the executable program as specified by the user. " ,
" disassemble [<cmd-options>] " )
2010-06-09 00:52:24 +08:00
{
}
CommandObjectDisassemble : : ~ CommandObjectDisassemble ( )
{
}
bool
CommandObjectDisassemble : : Execute
(
Args & command ,
CommandReturnObject & result
)
{
2010-09-18 09:14:36 +08:00
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
2010-06-09 00:52:24 +08:00
if ( target = = NULL )
{
result . AppendError ( " invalid target, set executable file using 'file' command " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
ArchSpec arch ( target - > GetArchitecture ( ) ) ;
if ( ! arch . IsValid ( ) )
{
result . AppendError ( " target needs valid architecure in order to be able to disassemble " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
Disassembler * disassembler = Disassembler : : FindPlugin ( arch ) ;
if ( disassembler = = NULL )
{
result . AppendErrorWithFormat ( " Unable to find Disassembler plug-in for %s architecture. \n " , arch . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
2010-07-01 07:03:03 +08:00
if ( command . GetArgumentCount ( ) ! = 0 )
2010-06-09 00:52:24 +08:00
{
2010-09-18 09:14:36 +08:00
result . AppendErrorWithFormat ( " \" disassemble \" arguments are specified as options. \n " ) ;
GetOptions ( ) - > GenerateOptionUsage ( m_interpreter ,
result . GetErrorStream ( ) ,
this ) ;
2010-06-16 02:47:14 +08:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-09-18 09:14:36 +08:00
ExecutionContext exe_ctx ( m_interpreter . GetDebugger ( ) . GetExecutionContext ( ) ) ;
2010-07-01 07:03:03 +08:00
if ( m_options . show_mixed & & m_options . num_lines_context = = 0 )
2010-09-15 13:51:24 +08:00
m_options . num_lines_context = 1 ;
2010-07-01 07:03:03 +08:00
if ( ! m_options . m_func_name . empty ( ) )
2010-06-16 02:47:14 +08:00
{
2010-07-01 07:03:03 +08:00
ConstString name ( m_options . m_func_name . c_str ( ) ) ;
2010-09-18 09:14:36 +08:00
if ( Disassembler : : Disassemble ( m_interpreter . GetDebugger ( ) ,
2010-07-01 07:03:03 +08:00
arch ,
exe_ctx ,
name ,
NULL , // Module *
m_options . show_mixed ? m_options . num_lines_context : 0 ,
m_options . show_bytes ,
result . GetOutputStream ( ) ) )
2010-06-16 02:47:14 +08:00
{
2010-07-01 07:03:03 +08:00
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
2010-06-16 02:47:14 +08:00
}
else
2010-07-01 07:03:03 +08:00
{
result . AppendErrorWithFormat ( " Unable to find symbol with name '%s'. \n " , name . GetCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
2010-06-16 02:47:14 +08:00
}
else
2010-06-09 00:52:24 +08:00
{
2010-07-01 07:03:03 +08:00
AddressRange range ;
if ( m_options . m_start_addr ! = LLDB_INVALID_ADDRESS )
2010-06-09 00:52:24 +08:00
{
2010-07-01 07:03:03 +08:00
range . GetBaseAddress ( ) . SetOffset ( m_options . m_start_addr ) ;
if ( m_options . m_end_addr ! = LLDB_INVALID_ADDRESS )
2010-06-09 00:52:24 +08:00
{
2010-07-01 07:03:03 +08:00
if ( m_options . m_end_addr < m_options . m_start_addr )
2010-06-09 00:52:24 +08:00
{
2010-07-01 07:03:03 +08:00
result . AppendErrorWithFormat ( " End address before start address. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2010-06-09 00:52:24 +08:00
}
2010-07-01 07:03:03 +08:00
range . SetByteSize ( m_options . m_end_addr - m_options . m_start_addr ) ;
2010-06-09 00:52:24 +08:00
}
else
2010-07-01 07:03:03 +08:00
range . SetByteSize ( DEFAULT_DISASM_BYTE_SIZE ) ;
}
2010-06-09 00:52:24 +08:00
else
{
2010-10-30 03:33:40 +08:00
// The default action is to disassemble the current frame function.
2010-07-01 07:03:03 +08:00
if ( exe_ctx . frame )
{
2010-11-04 17:43:27 +08:00
SymbolContext sc ( exe_ctx . frame - > GetSymbolContext ( eSymbolContextFunction | eSymbolContextSymbol ) ) ;
2010-07-01 07:03:03 +08:00
if ( sc . function )
range = sc . function - > GetAddressRange ( ) ;
else if ( sc . symbol & & sc . symbol - > GetAddressRangePtr ( ) )
range = * sc . symbol - > GetAddressRangePtr ( ) ;
else
2010-08-25 05:05:24 +08:00
range . GetBaseAddress ( ) = exe_ctx . frame - > GetFrameCodeAddress ( ) ;
2010-07-01 07:03:03 +08:00
}
else
{
result . AppendError ( " invalid frame " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-06-09 00:52:24 +08:00
}
2010-07-01 07:03:03 +08:00
if ( range . GetByteSize ( ) = = 0 )
range . SetByteSize ( DEFAULT_DISASM_BYTE_SIZE ) ;
2010-09-18 09:14:36 +08:00
if ( Disassembler : : Disassemble ( m_interpreter . GetDebugger ( ) ,
2010-07-01 07:03:03 +08:00
arch ,
exe_ctx ,
range ,
m_options . show_mixed ? m_options . num_lines_context : 0 ,
m_options . show_bytes ,
result . GetOutputStream ( ) ) )
2010-06-09 00:52:24 +08:00
{
2010-07-01 07:03:03 +08:00
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
2010-06-09 00:52:24 +08:00
}
else
{
2010-07-01 07:03:03 +08:00
result . AppendErrorWithFormat ( " Failed to disassemble memory at 0x%8.8llx. \n " , m_options . m_start_addr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2010-06-09 00:52:24 +08:00
}
}
2010-06-16 02:47:14 +08:00
return result . Succeeded ( ) ;
2010-06-09 00:52:24 +08:00
}