2010-06-08 16:52:24 +00: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-15 19:49:27 +00:00
# include "lldb/Interpreter/Args.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Interpreter/CommandCompletions.h"
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Interpreter/CommandReturnObject.h"
# include "lldb/Core/Disassembler.h"
2010-06-15 19:49:27 +00:00
# include "lldb/Interpreter/Options.h"
2010-06-08 16:52:24 +00: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
2011-03-22 01:48:42 +00:00
# define DEFAULT_DISASM_NUM_INS 4
2010-06-08 16:52:24 +00:00
using namespace lldb ;
using namespace lldb_private ;
2011-04-07 22:46:35 +00:00
CommandObjectDisassemble : : CommandOptions : : CommandOptions ( CommandInterpreter & interpreter ) :
2011-04-08 22:15:29 +00:00
Options ( interpreter ) ,
2011-03-22 01:48:42 +00:00
num_lines_context ( 0 ) ,
num_instructions ( 0 ) ,
2011-03-30 18:16:51 +00:00
func_name ( ) ,
start_addr ( ) ,
end_addr ( ) ,
at_pc ( false ) ,
frame_line ( false ) ,
plugin_name ( ) ,
arch ( )
2010-06-08 16:52:24 +00:00
{
2011-04-13 00:18:08 +00:00
OptionParsingStarting ( ) ;
2010-06-08 16:52:24 +00:00
}
CommandObjectDisassemble : : CommandOptions : : ~ CommandOptions ( )
{
}
Error
2011-04-13 00:18:08 +00:00
CommandObjectDisassemble : : CommandOptions : : SetOptionValue ( uint32_t option_idx , const char * option_arg )
2010-06-08 16:52:24 +00:00
{
Error error ;
char short_option = ( char ) m_getopt_table [ option_idx ] . val ;
2011-03-22 01:48:42 +00:00
bool success ;
2010-06-08 16:52:24 +00:00
switch ( short_option )
{
case ' m ' :
show_mixed = true ;
break ;
2011-03-26 19:14:58 +00:00
case ' C ' :
2011-03-22 01:48:42 +00:00
num_lines_context = Args : : StringToUInt32 ( option_arg , 0 , 0 , & success ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " Invalid num context lines string: \" %s \" . \n " , option_arg ) ;
break ;
2010-06-08 16:52:24 +00:00
case ' c ' :
2011-03-22 01:48:42 +00:00
num_instructions = Args : : StringToUInt32 ( option_arg , 0 , 0 , & success ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " Invalid num of instructions string: \" %s \" . \n " , option_arg ) ;
2010-06-08 16:52:24 +00:00
break ;
case ' b ' :
show_bytes = true ;
break ;
2010-06-15 18:47:14 +00:00
case ' s ' :
2011-03-30 18:16:51 +00:00
start_addr = Args : : StringToUInt64 ( option_arg , LLDB_INVALID_ADDRESS , 0 ) ;
if ( start_addr = = LLDB_INVALID_ADDRESS )
start_addr = Args : : StringToUInt64 ( option_arg , LLDB_INVALID_ADDRESS , 16 ) ;
2010-06-08 16:52:24 +00:00
2011-03-30 18:16:51 +00:00
if ( start_addr = = LLDB_INVALID_ADDRESS )
2011-03-22 01:48:42 +00:00
error . SetErrorStringWithFormat ( " Invalid start address string '%s'. \n " , option_arg ) ;
2010-06-15 18:47:14 +00:00
break ;
case ' e ' :
2011-03-30 18:16:51 +00:00
end_addr = Args : : StringToUInt64 ( option_arg , LLDB_INVALID_ADDRESS , 0 ) ;
if ( end_addr = = LLDB_INVALID_ADDRESS )
end_addr = Args : : StringToUInt64 ( option_arg , LLDB_INVALID_ADDRESS , 16 ) ;
2010-06-15 18:47:14 +00:00
2011-03-30 18:16:51 +00:00
if ( end_addr = = LLDB_INVALID_ADDRESS )
2011-03-22 01:48:42 +00:00
error . SetErrorStringWithFormat ( " Invalid end address string '%s'. \n " , option_arg ) ;
2010-06-08 16:52:24 +00:00
break ;
case ' n ' :
2011-03-30 18:16:51 +00:00
func_name . assign ( option_arg ) ;
2010-06-08 16:52:24 +00:00
break ;
2011-03-22 01:48:42 +00:00
case ' p ' :
2011-03-30 18:16:51 +00:00
at_pc = true ;
break ;
case ' l ' :
frame_line = true ;
// Disassemble the current source line kind of implies showing mixed
// source code context.
show_mixed = true ;
2011-03-22 01:48:42 +00:00
break ;
2011-03-25 18:03:16 +00:00
case ' P ' :
2011-03-30 18:16:51 +00:00
plugin_name . assign ( option_arg ) ;
2011-03-25 18:03:16 +00:00
break ;
2010-06-08 16:52:24 +00:00
case ' r ' :
raw = true ;
break ;
2010-10-29 19:33:40 +00:00
case ' f ' :
// The default action is to disassemble the function for the current frame.
// There's no need to set any flag.
break ;
2011-03-26 19:14:58 +00:00
case ' a ' :
2011-04-12 05:54:46 +00:00
arch . SetTriple ( option_arg , m_interpreter . GetPlatform ( true ) . get ( ) ) ;
2011-03-26 19:14:58 +00:00
break ;
2010-06-08 16:52:24 +00:00
default :
error . SetErrorStringWithFormat ( " Unrecognized short option '%c'. \n " , short_option ) ;
break ;
}
return error ;
}
void
2011-04-13 00:18:08 +00:00
CommandObjectDisassemble : : CommandOptions : : OptionParsingStarting ( )
2010-06-08 16:52:24 +00:00
{
show_mixed = false ;
show_bytes = false ;
num_lines_context = 0 ;
2011-03-22 01:48:42 +00:00
num_instructions = 0 ;
2011-03-30 18:16:51 +00:00
func_name . clear ( ) ;
at_pc = false ;
frame_line = false ;
start_addr = LLDB_INVALID_ADDRESS ;
end_addr = LLDB_INVALID_ADDRESS ;
2010-06-17 00:32:05 +00:00
raw = false ;
2011-03-30 18:16:51 +00:00
plugin_name . clear ( ) ;
arch . Clear ( ) ;
2010-06-08 16:52:24 +00:00
}
2011-03-24 21:19:54 +00:00
const OptionDefinition *
2010-06-08 16:52:24 +00:00
CommandObjectDisassemble : : CommandOptions : : GetDefinitions ( )
{
return g_option_table ;
}
2011-03-24 21:19:54 +00:00
OptionDefinition
2010-06-08 16:52:24 +00:00
CommandObjectDisassemble : : CommandOptions : : g_option_table [ ] =
{
2011-03-26 19:14:58 +00: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. " } ,
{ LLDB_OPT_SET_ALL , false , " plugin " , ' P ' , required_argument , NULL , 0 , eArgTypePlugin , " Name of the disassembler plugin you want to use. " } ,
{ LLDB_OPT_SET_ALL , false , " arch " , ' a ' , required_argument , NULL , 0 , eArgTypeArchitecture , " Specify the architecture to use from cross disassembly. " } ,
{ LLDB_OPT_SET_1 |
LLDB_OPT_SET_2 , 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. " } ,
{ LLDB_OPT_SET_2 |
LLDB_OPT_SET_3 |
LLDB_OPT_SET_4 |
LLDB_OPT_SET_5 , false , " count " , ' c ' , required_argument , NULL , 0 , eArgTypeNumLines , " Number of instructions to display. " } ,
{ LLDB_OPT_SET_3 , true , " name " , ' n ' , required_argument , NULL , CommandCompletions : : eSymbolCompletion , eArgTypeFunctionName , " Disassemble entire contents of the given function name. " } ,
{ LLDB_OPT_SET_4 , true , " frame " , ' f ' , no_argument , NULL , 0 , eArgTypeNone , " Disassemble from the start of the current frame's function. " } ,
2011-03-30 18:16:51 +00:00
{ LLDB_OPT_SET_5 , true , " pc " , ' p ' , no_argument , NULL , 0 , eArgTypeNone , " Disassemble around the current pc. " } ,
{ LLDB_OPT_SET_6 , true , " line " , ' l ' , no_argument , NULL , 0 , eArgTypeNone , " Disassemble the current frame's current source line instructions if there debug line table information, else disasemble around the pc. " } ,
2011-03-26 19:14:58 +00:00
{ 0 , false , NULL , 0 , 0 , NULL , 0 , eArgTypeNone , NULL }
2010-06-08 16:52:24 +00:00
} ;
//-------------------------------------------------------------------------
// CommandObjectDisassemble
//-------------------------------------------------------------------------
2010-09-18 01:14:36 +00: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. " ,
2011-04-07 22:46:35 +00:00
" disassemble [<cmd-options>] " ) ,
m_options ( interpreter )
2010-06-08 16:52:24 +00:00
{
}
CommandObjectDisassemble : : ~ CommandObjectDisassemble ( )
{
}
bool
CommandObjectDisassemble : : Execute
(
Args & command ,
CommandReturnObject & result
)
{
2010-09-18 01:14:36 +00:00
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
2010-06-08 16:52:24 +00:00
if ( target = = NULL )
{
result . AppendError ( " invalid target, set executable file using 'file' command " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2011-03-30 18:16:51 +00:00
if ( ! m_options . arch . IsValid ( ) )
m_options . arch = target - > GetArchitecture ( ) ;
2010-06-08 16:52:24 +00:00
2011-03-30 18:16:51 +00:00
if ( ! m_options . arch . IsValid ( ) )
2010-06-08 16:52:24 +00:00
{
2011-03-26 19:14:58 +00:00
result . AppendError ( " use the --arch option or set the target architecure to disassemble " ) ;
2010-06-08 16:52:24 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2011-03-25 18:03:16 +00:00
const char * plugin_name = m_options . GetPluginName ( ) ;
2011-03-30 18:16:51 +00:00
Disassembler * disassembler = Disassembler : : FindPlugin ( m_options . arch , plugin_name ) ;
2010-06-08 16:52:24 +00:00
if ( disassembler = = NULL )
{
2011-03-25 18:03:16 +00:00
if ( plugin_name )
2011-03-26 19:14:58 +00:00
result . AppendErrorWithFormat ( " Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture. \n " ,
plugin_name ,
2011-03-30 18:16:51 +00:00
m_options . arch . GetArchitectureName ( ) ) ;
2011-03-25 18:03:16 +00:00
else
2011-03-26 19:14:58 +00:00
result . AppendErrorWithFormat ( " Unable to find Disassembler plug-in for the '%s' architecture. \n " ,
2011-03-30 18:16:51 +00:00
m_options . arch . GetArchitectureName ( ) ) ;
2010-06-08 16:52:24 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
2010-06-30 23:03:03 +00:00
if ( command . GetArgumentCount ( ) ! = 0 )
2010-06-08 16:52:24 +00:00
{
2010-09-18 01:14:36 +00:00
result . AppendErrorWithFormat ( " \" disassemble \" arguments are specified as options. \n " ) ;
2011-04-07 22:46:35 +00:00
GetOptions ( ) - > GenerateOptionUsage ( result . GetErrorStream ( ) , this ) ;
2010-06-15 18:47:14 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2011-03-22 01:48:42 +00:00
2010-06-30 23:03:03 +00:00
if ( m_options . show_mixed & & m_options . num_lines_context = = 0 )
2010-09-15 05:51:24 +00:00
m_options . num_lines_context = 1 ;
2010-06-08 16:52:24 +00:00
2011-04-12 05:54:46 +00:00
ExecutionContext exe_ctx ( m_interpreter . GetExecutionContext ( ) ) ;
2011-03-22 01:48:42 +00:00
2011-03-30 18:16:51 +00:00
if ( ! m_options . func_name . empty ( ) )
2010-06-30 23:03:03 +00:00
{
2011-03-30 18:16:51 +00:00
ConstString name ( m_options . func_name . c_str ( ) ) ;
2010-06-30 23:03:03 +00:00
2010-09-18 01:14:36 +00:00
if ( Disassembler : : Disassemble ( m_interpreter . GetDebugger ( ) ,
2011-03-30 18:16:51 +00:00
m_options . arch ,
2011-03-25 18:03:16 +00:00
plugin_name ,
2010-06-30 23:03:03 +00:00
exe_ctx ,
name ,
NULL , // Module *
2011-03-22 01:48:42 +00:00
m_options . num_instructions ,
2010-06-30 23:03:03 +00:00
m_options . show_mixed ? m_options . num_lines_context : 0 ,
m_options . show_bytes ,
2011-03-10 23:35:12 +00:00
m_options . raw ,
2010-06-30 23:03:03 +00:00
result . GetOutputStream ( ) ) )
2010-06-08 16:52:24 +00:00
{
2010-06-30 23:03:03 +00:00
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
2010-06-08 16:52:24 +00:00
}
else
{
result . AppendErrorWithFormat ( " Unable to find symbol with name '%s'. \n " , name . GetCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
2010-06-30 23:03:03 +00:00
}
2010-06-15 18:47:14 +00:00
else
2010-06-08 16:52:24 +00:00
{
2011-03-30 18:16:51 +00:00
AddressRange range ;
if ( m_options . frame_line )
2010-06-30 23:03:03 +00:00
{
2011-03-30 18:16:51 +00:00
LineEntry pc_line_entry ( exe_ctx . frame - > GetSymbolContext ( eSymbolContextLineEntry ) . line_entry ) ;
if ( pc_line_entry . IsValid ( ) )
2010-06-30 23:03:03 +00:00
{
2011-03-30 18:16:51 +00:00
range = pc_line_entry . range ;
2010-06-30 23:03:03 +00:00
}
2011-03-30 18:16:51 +00:00
else
2011-03-22 01:48:42 +00:00
{
2011-03-30 18:16:51 +00:00
m_options . at_pc = true ; // No line entry, so just disassemble around the current pc
m_options . show_mixed = false ;
2011-03-22 01:48:42 +00:00
}
2010-06-30 23:03:03 +00:00
}
2011-03-30 18:16:51 +00:00
// Did the "m_options.frame_line" find a valid range already? If so
// skip the rest...
if ( range . GetByteSize ( ) = = 0 )
2010-06-30 23:03:03 +00:00
{
2011-03-30 18:16:51 +00:00
if ( m_options . at_pc )
2011-03-22 01:48:42 +00:00
{
2011-03-30 18:16:51 +00:00
if ( exe_ctx . frame = = NULL )
2011-03-22 01:48:42 +00:00
{
2011-03-30 18:16:51 +00:00
result . AppendError ( " Cannot disassemble around the current PC without a selected frame. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
range . GetBaseAddress ( ) = exe_ctx . frame - > GetFrameCodeAddress ( ) ;
if ( m_options . num_instructions = = 0 )
{
// Disassembling at the PC always disassembles some number of instructions (not the whole function).
m_options . num_instructions = DEFAULT_DISASM_NUM_INS ;
}
}
else
{
range . GetBaseAddress ( ) . SetOffset ( m_options . start_addr ) ;
if ( range . GetBaseAddress ( ) . IsValid ( ) )
{
if ( m_options . end_addr ! = LLDB_INVALID_ADDRESS )
2011-03-22 01:48:42 +00:00
{
2011-03-30 18:16:51 +00:00
if ( m_options . end_addr < = m_options . start_addr )
{
result . AppendErrorWithFormat ( " End address before start address. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
range . SetByteSize ( m_options . end_addr - m_options . start_addr ) ;
2011-03-22 01:48:42 +00:00
}
}
}
}
if ( m_options . num_instructions ! = 0 )
{
2011-03-30 18:16:51 +00:00
if ( ! range . GetBaseAddress ( ) . IsValid ( ) )
2011-03-22 01:48:42 +00:00
{
// The default action is to disassemble the current frame function.
if ( exe_ctx . frame )
{
SymbolContext sc ( exe_ctx . frame - > GetSymbolContext ( eSymbolContextFunction | eSymbolContextSymbol ) ) ;
if ( sc . function )
2011-03-30 18:16:51 +00:00
range . GetBaseAddress ( ) = sc . function - > GetAddressRange ( ) . GetBaseAddress ( ) ;
2011-03-22 01:48:42 +00:00
else if ( sc . symbol & & sc . symbol - > GetAddressRangePtr ( ) )
2011-03-30 18:16:51 +00:00
range . GetBaseAddress ( ) = sc . symbol - > GetAddressRangePtr ( ) - > GetBaseAddress ( ) ;
2011-03-22 01:48:42 +00:00
else
2011-03-30 18:16:51 +00:00
range . GetBaseAddress ( ) = exe_ctx . frame - > GetFrameCodeAddress ( ) ;
2011-03-22 01:48:42 +00:00
}
2011-03-30 18:16:51 +00:00
if ( ! range . GetBaseAddress ( ) . IsValid ( ) )
2011-03-22 01:48:42 +00:00
{
result . AppendError ( " invalid frame " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
if ( Disassembler : : Disassemble ( m_interpreter . GetDebugger ( ) ,
2011-03-30 18:16:51 +00:00
m_options . arch ,
2011-03-25 18:03:16 +00:00
plugin_name ,
2011-03-22 01:48:42 +00:00
exe_ctx ,
2011-03-30 18:16:51 +00:00
range . GetBaseAddress ( ) ,
2011-03-22 01:48:42 +00:00
m_options . num_instructions ,
m_options . show_mixed ? m_options . num_lines_context : 0 ,
m_options . show_bytes ,
m_options . raw ,
result . GetOutputStream ( ) ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
2011-03-30 18:16:51 +00:00
result . AppendErrorWithFormat ( " Failed to disassemble memory at 0x%8.8llx. \n " , m_options . start_addr ) ;
2011-03-22 01:48:42 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
2011-03-30 18:16:51 +00:00
if ( ! range . GetBaseAddress ( ) . IsValid ( ) )
2011-03-22 01:48:42 +00:00
{
// The default action is to disassemble the current frame function.
if ( exe_ctx . frame )
{
SymbolContext sc ( exe_ctx . frame - > GetSymbolContext ( eSymbolContextFunction | eSymbolContextSymbol ) ) ;
if ( sc . function )
range = sc . function - > GetAddressRange ( ) ;
else if ( sc . symbol & & sc . symbol - > GetAddressRangePtr ( ) )
range = * sc . symbol - > GetAddressRangePtr ( ) ;
else
range . GetBaseAddress ( ) = exe_ctx . frame - > GetFrameCodeAddress ( ) ;
}
else
{
result . AppendError ( " invalid frame " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
if ( range . GetByteSize ( ) = = 0 )
range . SetByteSize ( DEFAULT_DISASM_BYTE_SIZE ) ;
if ( Disassembler : : Disassemble ( m_interpreter . GetDebugger ( ) ,
2011-03-30 18:16:51 +00:00
m_options . arch ,
2011-03-25 18:03:16 +00:00
plugin_name ,
2011-03-22 01:48:42 +00:00
exe_ctx ,
range ,
m_options . num_instructions ,
m_options . show_mixed ? m_options . num_lines_context : 0 ,
m_options . show_bytes ,
m_options . raw ,
result . GetOutputStream ( ) ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
2011-03-30 18:16:51 +00:00
result . AppendErrorWithFormat ( " Failed to disassemble memory at 0x%8.8llx. \n " , m_options . start_addr ) ;
2011-03-22 01:48:42 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
}
2010-06-30 23:03:03 +00:00
}
2010-06-08 16:52:24 +00:00
}
2010-06-15 18:47:14 +00:00
return result . Succeeded ( ) ;
2010-06-08 16:52:24 +00:00
}