2010-06-08 16:52:24 +00:00
//===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "CommandObjectMemory.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
# include "lldb/Core/DataBufferHeap.h"
# include "lldb/Core/DataExtractor.h"
2010-06-23 01:19:29 +00:00
# include "lldb/Core/Debugger.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Core/StreamString.h"
2011-04-27 22:04:39 +00:00
# include "lldb/Core/ValueObjectMemory.h"
2010-06-23 01:19:29 +00:00
# include "lldb/Interpreter/Args.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Interpreter/CommandReturnObject.h"
2010-06-23 01:19:29 +00:00
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Interpreter/Options.h"
2011-04-27 22:04:39 +00:00
# include "lldb/Interpreter/OptionGroupFormat.h"
# include "lldb/Interpreter/OptionGroupOutputFile.h"
2011-04-28 20:55:26 +00:00
# include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
2011-10-12 02:08:07 +00:00
# include "lldb/Symbol/ClangNamespaceDecl.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Target/Process.h"
2011-04-27 22:04:39 +00:00
# include "lldb/Target/StackFrame.h"
2010-06-08 16:52:24 +00:00
using namespace lldb ;
using namespace lldb_private ;
2011-04-28 20:55:26 +00:00
static OptionDefinition
2011-04-27 22:04:39 +00:00
g_option_table [ ] =
2010-06-08 16:52:24 +00:00
{
2011-04-27 22:04:39 +00:00
{ LLDB_OPT_SET_1 , false , " num-per-line " , ' l ' , required_argument , NULL , 0 , eArgTypeNumberPerLine , " The number of items per line to display. " } ,
{ LLDB_OPT_SET_2 , false , " binary " , ' b ' , no_argument , NULL , 0 , eArgTypeNone , " If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings. " } ,
{ LLDB_OPT_SET_3 , true , " view-as " , ' t ' , required_argument , NULL , 0 , eArgTypeNone , " The name of a type to view memory as. " } ,
} ;
2010-06-08 16:52:24 +00:00
2011-04-27 22:04:39 +00:00
class OptionGroupReadMemory : public OptionGroup
{
public :
2010-06-08 16:52:24 +00:00
2011-04-27 22:04:39 +00:00
OptionGroupReadMemory ( ) :
2011-04-28 20:55:26 +00:00
m_num_per_line ( 1 , 1 ) ,
2011-04-27 22:04:39 +00:00
m_output_as_binary ( false ) ,
m_view_as_type ( )
{
}
2010-06-08 16:52:24 +00:00
2011-04-27 22:04:39 +00:00
virtual
~ OptionGroupReadMemory ( )
{
}
virtual uint32_t
GetNumDefinitions ( )
{
return sizeof ( g_option_table ) / sizeof ( OptionDefinition ) ;
}
virtual const OptionDefinition *
GetDefinitions ( )
{
return g_option_table ;
}
virtual Error
SetOptionValue ( CommandInterpreter & interpreter ,
uint32_t option_idx ,
const char * option_arg )
{
Error error ;
char short_option = ( char ) g_option_table [ option_idx ] . short_option ;
switch ( short_option )
{
2010-06-08 16:52:24 +00:00
case ' l ' :
2011-04-27 22:04:39 +00:00
error = m_num_per_line . SetValueFromCString ( option_arg ) ;
if ( m_num_per_line . GetCurrentValue ( ) = = 0 )
2010-06-08 16:52:24 +00:00
error . SetErrorStringWithFormat ( " Invalid value for --num-per-line option '%s'. Must be positive integer value. \n " , option_arg ) ;
break ;
2011-10-25 06:44:01 +00:00
2010-10-10 20:52:20 +00:00
case ' b ' :
m_output_as_binary = true ;
break ;
2011-04-27 22:04:39 +00:00
case ' t ' :
error = m_view_as_type . SetValueFromCString ( option_arg ) ;
2010-10-10 20:52:20 +00:00
break ;
2011-04-27 22:04:39 +00:00
2010-06-08 16:52:24 +00:00
default :
error . SetErrorStringWithFormat ( " Unrecognized short option '%c'. \n " , short_option ) ;
break ;
}
2011-04-27 22:04:39 +00:00
return error ;
}
virtual void
OptionParsingStarting ( CommandInterpreter & interpreter )
{
m_num_per_line . Clear ( ) ;
m_output_as_binary = false ;
m_view_as_type . Clear ( ) ;
}
2011-04-28 20:55:26 +00:00
Error
2011-10-25 06:44:01 +00:00
FinalizeSettings ( Target * target , OptionGroupFormat & format_options )
2011-04-27 22:04:39 +00:00
{
2011-04-28 20:55:26 +00:00
Error error ;
2011-10-25 06:44:01 +00:00
OptionValueUInt64 & byte_size_value = format_options . GetByteSizeValue ( ) ;
OptionValueUInt64 & count_value = format_options . GetCountValue ( ) ;
bool byte_size_option_set = byte_size_value . OptionWasSet ( ) ;
2011-04-28 20:55:26 +00:00
const bool num_per_line_option_set = m_num_per_line . OptionWasSet ( ) ;
2011-10-25 06:44:01 +00:00
const bool count_option_set = format_options . GetCountValue ( ) . OptionWasSet ( ) ;
2011-04-28 20:55:26 +00:00
2011-10-25 06:44:01 +00:00
uint32_t format_byte_size = byte_size_value . GetCurrentValue ( ) ;
2011-04-28 20:55:26 +00:00
if ( byte_size_option_set )
{
if ( format_byte_size > 0 )
{
error . SetErrorString ( " can't specify the byte size in both the '--size <num>' option and the '--format [<byte-size>]<format-char>' options. " ) ;
return error ;
}
}
else
{
if ( format_byte_size ! = 0 )
{
byte_size_option_set = true ;
2011-10-25 06:44:01 +00:00
byte_size_value = format_byte_size ;
2011-04-28 20:55:26 +00:00
}
}
switch ( format_options . GetFormat ( ) )
2010-06-08 16:52:24 +00:00
{
2011-04-27 22:04:39 +00:00
default :
break ;
case eFormatBoolean :
2011-04-28 20:55:26 +00:00
if ( ! byte_size_option_set )
2011-10-25 06:44:01 +00:00
byte_size_value = 1 ;
2011-04-28 20:55:26 +00:00
if ( ! num_per_line_option_set )
m_num_per_line = 1 ;
if ( ! count_option_set )
2011-10-25 06:44:01 +00:00
format_options . GetCountValue ( ) = 8 ;
2011-04-27 22:04:39 +00:00
break ;
case eFormatCString :
break ;
case eFormatPointer :
2011-10-25 06:44:01 +00:00
byte_size_value = target - > GetArchitecture ( ) . GetAddressByteSize ( ) ;
2011-04-28 20:55:26 +00:00
if ( ! num_per_line_option_set )
m_num_per_line = 4 ;
if ( ! count_option_set )
2011-10-25 06:44:01 +00:00
format_options . GetCountValue ( ) = 8 ;
2011-04-27 22:04:39 +00:00
break ;
case eFormatBinary :
case eFormatFloat :
case eFormatOctal :
case eFormatDecimal :
case eFormatEnum :
case eFormatUnicode16 :
case eFormatUnicode32 :
case eFormatUnsigned :
2011-04-28 20:55:26 +00:00
if ( ! byte_size_option_set )
2011-10-25 06:44:01 +00:00
byte_size_value = 4 ;
2011-04-28 20:55:26 +00:00
if ( ! num_per_line_option_set )
m_num_per_line = 1 ;
if ( ! count_option_set )
2011-10-25 06:44:01 +00:00
format_options . GetCountValue ( ) = 8 ;
2011-04-27 22:04:39 +00:00
break ;
case eFormatBytes :
case eFormatBytesWithASCII :
2011-10-25 06:44:01 +00:00
if ( byte_size_value . OptionWasSet ( ) )
2011-04-28 20:55:26 +00:00
{
2011-10-25 06:44:01 +00:00
if ( byte_size_value > 1 )
2011-04-28 20:55:26 +00:00
error . SetErrorString ( " use --count option to specify an end address to display a number of bytes " ) ;
}
else
2011-10-25 06:44:01 +00:00
byte_size_value = 1 ;
2011-04-28 20:55:26 +00:00
if ( ! num_per_line_option_set )
m_num_per_line = 16 ;
if ( ! count_option_set )
2011-10-25 06:44:01 +00:00
format_options . GetCountValue ( ) = 32 ;
2011-04-27 22:04:39 +00:00
break ;
2011-06-17 23:50:44 +00:00
case eFormatCharArray :
2011-04-27 22:04:39 +00:00
case eFormatChar :
case eFormatCharPrintable :
2011-04-28 20:55:26 +00:00
if ( ! byte_size_option_set )
2011-10-25 06:44:01 +00:00
byte_size_value = 1 ;
2011-04-28 20:55:26 +00:00
if ( ! num_per_line_option_set )
m_num_per_line = 32 ;
if ( ! count_option_set )
2011-10-25 06:44:01 +00:00
format_options . GetCountValue ( ) = 64 ;
2011-04-27 22:04:39 +00:00
break ;
case eFormatComplex :
2011-04-28 20:55:26 +00:00
if ( ! byte_size_option_set )
2011-10-25 06:44:01 +00:00
byte_size_value = 8 ;
2011-04-28 20:55:26 +00:00
if ( ! num_per_line_option_set )
m_num_per_line = 1 ;
if ( ! count_option_set )
2011-10-25 06:44:01 +00:00
format_options . GetCountValue ( ) = 8 ;
2011-04-27 22:04:39 +00:00
break ;
case eFormatHex :
2011-04-28 20:55:26 +00:00
if ( ! byte_size_option_set )
2011-10-25 06:44:01 +00:00
byte_size_value = 4 ;
2011-04-28 20:55:26 +00:00
if ( ! num_per_line_option_set )
{
2011-10-25 06:44:01 +00:00
switch ( byte_size_value )
2011-04-28 20:55:26 +00:00
{
case 1 :
case 2 :
m_num_per_line = 8 ;
break ;
case 4 :
m_num_per_line = 4 ;
break ;
case 8 :
m_num_per_line = 2 ;
break ;
default :
m_num_per_line = 1 ;
break ;
}
}
if ( ! count_option_set )
2011-10-25 06:44:01 +00:00
count_value = 8 ;
2011-04-27 22:04:39 +00:00
break ;
case eFormatVectorOfChar :
case eFormatVectorOfSInt8 :
case eFormatVectorOfUInt8 :
case eFormatVectorOfSInt16 :
case eFormatVectorOfUInt16 :
case eFormatVectorOfSInt32 :
case eFormatVectorOfUInt32 :
case eFormatVectorOfSInt64 :
case eFormatVectorOfUInt64 :
case eFormatVectorOfFloat32 :
case eFormatVectorOfFloat64 :
case eFormatVectorOfUInt128 :
2011-04-28 20:55:26 +00:00
if ( ! byte_size_option_set )
2011-10-25 06:44:01 +00:00
byte_size_value = 128 ;
2011-04-28 20:55:26 +00:00
if ( ! num_per_line_option_set )
m_num_per_line = 1 ;
if ( ! count_option_set )
2011-10-25 06:44:01 +00:00
count_value = 4 ;
2011-04-27 22:04:39 +00:00
break ;
2010-06-08 16:52:24 +00:00
}
2011-04-28 20:55:26 +00:00
return error ;
2011-04-27 22:04:39 +00:00
}
2010-06-08 16:52:24 +00:00
2011-04-27 22:04:39 +00:00
OptionValueUInt64 m_num_per_line ;
bool m_output_as_binary ;
OptionValueString m_view_as_type ;
} ;
2010-06-08 16:52:24 +00:00
2011-04-27 22:04:39 +00:00
//----------------------------------------------------------------------
// Read memory from the inferior process
//----------------------------------------------------------------------
class CommandObjectMemoryRead : public CommandObject
{
public :
2010-09-18 01:14:36 +00:00
CommandObjectMemoryRead ( CommandInterpreter & interpreter ) :
CommandObject ( interpreter ,
" memory read " ,
2010-09-08 21:06:11 +00:00
" Read from the memory of the process being debugged. " ,
2010-10-04 22:28:36 +00:00
NULL ,
2011-07-09 00:55:34 +00:00
eFlagProcessMustBePaused ) ,
2011-04-27 22:04:39 +00:00
m_option_group ( interpreter ) ,
2011-10-25 06:44:01 +00:00
m_format_options ( eFormatBytesWithASCII , 1 , 8 ) ,
2011-04-27 22:04:39 +00:00
m_memory_options ( ) ,
2011-04-28 20:55:26 +00:00
m_outfile_options ( ) ,
m_varobj_options ( )
2010-06-08 16:52:24 +00:00
{
2010-10-04 22:28:36 +00:00
CommandArgumentEntry arg1 ;
CommandArgumentEntry arg2 ;
CommandArgumentData start_addr_arg ;
CommandArgumentData end_addr_arg ;
// Define the first (and only) variant of this arg.
start_addr_arg . arg_type = eArgTypeStartAddress ;
start_addr_arg . arg_repetition = eArgRepeatPlain ;
// There is only one variant this argument could be; put it into the argument entry.
arg1 . push_back ( start_addr_arg ) ;
// Define the first (and only) variant of this arg.
end_addr_arg . arg_type = eArgTypeEndAddress ;
end_addr_arg . arg_repetition = eArgRepeatOptional ;
// There is only one variant this argument could be; put it into the argument entry.
arg2 . push_back ( end_addr_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg1 ) ;
m_arguments . push_back ( arg2 ) ;
2011-04-27 22:04:39 +00:00
2011-10-25 06:44:01 +00:00
// Add the "--format" and "--count" options to group 1 and 3
m_option_group . Append ( & m_format_options ,
OptionGroupFormat : : OPTION_GROUP_FORMAT | OptionGroupFormat : : OPTION_GROUP_COUNT ,
LLDB_OPT_SET_1 | LLDB_OPT_SET_3 ) ;
// Add the "--size" option to group 1 and 2
m_option_group . Append ( & m_format_options ,
OptionGroupFormat : : OPTION_GROUP_SIZE ,
LLDB_OPT_SET_1 | LLDB_OPT_SET_2 ) ;
2011-04-27 22:04:39 +00:00
m_option_group . Append ( & m_memory_options ) ;
m_option_group . Append ( & m_outfile_options , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3 ) ;
2011-04-28 20:55:26 +00:00
m_option_group . Append ( & m_varobj_options , LLDB_OPT_SET_ALL , LLDB_OPT_SET_3 ) ;
2011-04-27 22:04:39 +00:00
m_option_group . Finalize ( ) ;
2010-06-08 16:52:24 +00:00
}
virtual
~ CommandObjectMemoryRead ( )
{
}
Options *
GetOptions ( )
{
2011-04-27 22:04:39 +00:00
return & m_option_group ;
2010-06-08 16:52:24 +00:00
}
virtual bool
2010-09-18 01:14:36 +00:00
Execute ( Args & command ,
2010-06-08 16:52:24 +00:00
CommandReturnObject & result )
{
2011-04-27 22:04:39 +00:00
ExecutionContext exe_ctx ( m_interpreter . GetExecutionContext ( ) ) ;
2011-09-22 04:58:26 +00:00
Target * target = exe_ctx . GetTargetPtr ( ) ;
if ( target = = NULL )
2010-06-08 16:52:24 +00:00
{
2011-07-09 00:55:34 +00:00
result . AppendError ( " need at least a target to read memory " ) ;
2010-06-08 16:52:24 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
const size_t argc = command . GetArgumentCount ( ) ;
2011-04-27 22:04:39 +00:00
2010-06-08 16:52:24 +00:00
if ( argc = = 0 | | argc > 2 )
{
result . AppendErrorWithFormat ( " %s takes 1 or two args. \n " , m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2011-04-28 20:55:26 +00:00
ClangASTType clang_ast_type ;
Error error ;
Format format = m_format_options . GetFormat ( ) ;
2011-04-27 22:04:39 +00:00
const char * view_as_type_cstr = m_memory_options . m_view_as_type . GetCurrentValue ( ) ;
if ( view_as_type_cstr & & view_as_type_cstr [ 0 ] )
2010-06-08 16:52:24 +00:00
{
2011-04-27 22:04:39 +00:00
// We are viewing memory as a type
SymbolContext sc ;
const bool append = true ;
TypeList type_list ;
uint32_t reference_count = 0 ;
uint32_t pointer_count = 0 ;
size_t idx ;
static const char * g_keywords [ ] = { " const " , " volatile " , " restrict " , " struct " , " class " , " union " } ;
static size_t g_num_keywords = sizeof ( g_keywords ) / sizeof ( const char * ) ;
std : : string type_str ( view_as_type_cstr ) ;
// Remove all instances of g_keywords that are followed by spaces
for ( size_t i = 0 ; i < g_num_keywords ; + + i )
{
const char * keyword = g_keywords [ i ] ;
int keyword_len = : : strlen ( keyword ) ;
while ( ( idx = type_str . find ( keyword ) ) ! = std : : string : : npos )
{
if ( type_str [ idx + keyword_len ] = = ' ' | | type_str [ idx + keyword_len ] = = ' \t ' )
type_str . erase ( idx , keyword_len + 1 ) ;
}
}
bool done = type_str . empty ( ) ;
//
idx = type_str . find_first_not_of ( " \t " ) ;
if ( idx > 0 & & idx ! = std : : string : : npos )
type_str . erase ( 0 , idx ) ;
while ( ! done )
{
// Strip trailing spaces
if ( type_str . empty ( ) )
done = true ;
else
{
switch ( type_str [ type_str . size ( ) - 1 ] )
{
case ' * ' :
+ + pointer_count ;
// fall through...
case ' ' :
case ' \t ' :
type_str . erase ( type_str . size ( ) - 1 ) ;
break ;
case ' & ' :
if ( reference_count = = 0 )
{
reference_count = 1 ;
type_str . erase ( type_str . size ( ) - 1 ) ;
}
else
{
result . AppendErrorWithFormat ( " invalid type string: '%s' \n " , view_as_type_cstr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
break ;
default :
done = true ;
break ;
}
}
}
ConstString lookup_type_name ( type_str . c_str ( ) ) ;
2011-09-22 04:58:26 +00:00
StackFrame * frame = exe_ctx . GetFramePtr ( ) ;
if ( frame )
2011-04-27 22:04:39 +00:00
{
2011-09-22 04:58:26 +00:00
sc = frame - > GetSymbolContext ( eSymbolContextModule ) ;
2011-04-27 22:04:39 +00:00
if ( sc . module_sp )
{
2011-10-12 02:08:07 +00:00
sc . module_sp - > FindTypes ( sc ,
lookup_type_name ,
NULL ,
2011-04-27 22:04:39 +00:00
append ,
1 ,
type_list ) ;
}
}
if ( type_list . GetSize ( ) = = 0 )
{
2011-09-22 04:58:26 +00:00
target - > GetImages ( ) . FindTypes ( sc ,
lookup_type_name ,
append ,
1 ,
type_list ) ;
2011-04-27 22:04:39 +00:00
}
if ( type_list . GetSize ( ) = = 0 )
{
result . AppendErrorWithFormat ( " unable to find any types that match the raw type '%s' for full type '%s' \n " ,
lookup_type_name . GetCString ( ) ,
view_as_type_cstr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
TypeSP type_sp ( type_list . GetTypeAtIndex ( 0 ) ) ;
clang_ast_type . SetClangType ( type_sp - > GetClangAST ( ) , type_sp - > GetClangFullType ( ) ) ;
while ( pointer_count > 0 )
{
clang_type_t pointer_type = ClangASTContext : : CreatePointerType ( clang_ast_type . GetASTContext ( ) , clang_ast_type . GetOpaqueQualType ( ) ) ;
if ( pointer_type )
clang_ast_type . SetClangType ( clang_ast_type . GetASTContext ( ) , pointer_type ) ;
else
{
result . AppendError ( " unable make a pointer type \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
- - pointer_count ;
}
2011-10-25 06:44:01 +00:00
m_format_options . GetByteSizeValue ( ) = ( clang_ast_type . GetClangTypeBitWidth ( ) + 7 ) / 8 ;
2011-04-27 22:04:39 +00:00
2011-10-25 06:44:01 +00:00
if ( m_format_options . GetByteSizeValue ( ) = = 0 )
2011-04-27 22:04:39 +00:00
{
result . AppendErrorWithFormat ( " unable to get the byte size of the type '%s' \n " ,
view_as_type_cstr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2011-04-28 20:55:26 +00:00
2011-10-25 06:44:01 +00:00
if ( ! m_format_options . GetCountValue ( ) . OptionWasSet ( ) )
m_format_options . GetCountValue ( ) = 1 ;
2011-04-27 22:04:39 +00:00
}
else
{
2011-09-22 04:58:26 +00:00
error = m_memory_options . FinalizeSettings ( target , m_format_options ) ;
2010-06-08 16:52:24 +00:00
}
2011-04-28 20:55:26 +00:00
// Look for invalid combinations of settings
if ( error . Fail ( ) )
2010-06-08 16:52:24 +00:00
{
2011-04-28 20:55:26 +00:00
result . AppendErrorWithFormat ( " %s " , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2010-06-08 16:52:24 +00:00
}
2011-10-25 06:44:01 +00:00
size_t item_count = m_format_options . GetCountValue ( ) . GetCurrentValue ( ) ;
const size_t item_byte_size = m_format_options . GetByteSizeValue ( ) . GetCurrentValue ( ) ;
2011-04-28 20:55:26 +00:00
const size_t num_per_line = m_memory_options . m_num_per_line . GetCurrentValue ( ) ;
2011-04-27 22:04:39 +00:00
size_t total_byte_size = item_count * item_byte_size ;
2010-06-08 16:52:24 +00:00
if ( total_byte_size = = 0 )
total_byte_size = 32 ;
lldb : : addr_t addr = Args : : StringToUInt64 ( command . GetArgumentAtIndex ( 0 ) , LLDB_INVALID_ADDRESS , 0 ) ;
if ( addr = = LLDB_INVALID_ADDRESS )
{
result . AppendErrorWithFormat ( " invalid start address string '%s'. \n " , command . GetArgumentAtIndex ( 0 ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( argc = = 2 )
{
lldb : : addr_t end_addr = Args : : StringToUInt64 ( command . GetArgumentAtIndex ( 1 ) , LLDB_INVALID_ADDRESS , 0 ) ;
if ( end_addr = = LLDB_INVALID_ADDRESS )
{
2011-04-28 20:55:26 +00:00
result . AppendErrorWithFormat ( " invalid end address string '%s'. \n " , command . GetArgumentAtIndex ( 1 ) ) ;
2010-06-08 16:52:24 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else if ( end_addr < = addr )
{
2011-04-28 20:55:26 +00:00
result . AppendErrorWithFormat ( " end address (0x%llx) must be greater that the start address (0x%llx). \n " , end_addr , addr ) ;
2010-06-08 16:52:24 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2011-10-25 06:44:01 +00:00
else if ( m_format_options . GetCountValue ( ) . OptionWasSet ( ) )
2010-06-08 16:52:24 +00:00
{
2011-09-20 21:44:10 +00:00
result . AppendErrorWithFormat ( " specify either the end address (0x%llx) or the count (--count %lu), not both. \n " , end_addr , item_count ) ;
2010-06-08 16:52:24 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
total_byte_size = end_addr - addr ;
item_count = total_byte_size / item_byte_size ;
}
2011-04-27 22:04:39 +00:00
DataBufferSP data_sp ;
size_t bytes_read = 0 ;
if ( ! clang_ast_type . GetOpaqueQualType ( ) )
2010-06-08 16:52:24 +00:00
{
2011-04-27 22:04:39 +00:00
data_sp . reset ( new DataBufferHeap ( total_byte_size , ' \0 ' ) ) ;
2011-07-09 00:55:34 +00:00
Address address ( NULL , addr ) ;
2011-09-22 04:58:26 +00:00
bytes_read = target - > ReadMemory ( address , false , data_sp - > GetBytes ( ) , data_sp - > GetByteSize ( ) , error ) ;
2011-04-27 22:04:39 +00:00
if ( bytes_read = = 0 )
{
result . AppendWarningWithFormat ( " Read from 0x%llx failed. \n " , addr ) ;
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( bytes_read < total_byte_size )
2011-09-20 21:44:10 +00:00
result . AppendWarningWithFormat ( " Not all bytes (%lu/%lu) were able to be read from 0x%llx. \n " , bytes_read , total_byte_size , addr ) ;
2010-06-08 16:52:24 +00:00
}
2010-10-10 20:52:20 +00:00
StreamFile outfile_stream ;
Stream * output_stream = NULL ;
2011-04-27 22:04:39 +00:00
const FileSpec & outfile_spec = m_outfile_options . GetFile ( ) . GetCurrentValue ( ) ;
if ( outfile_spec )
2010-10-10 20:52:20 +00:00
{
char path [ PATH_MAX ] ;
2011-04-27 22:04:39 +00:00
outfile_spec . GetPath ( path , sizeof ( path ) ) ;
uint32_t open_options = File : : eOpenOptionWrite | File : : eOpenOptionCanCreate ;
const bool append = m_outfile_options . GetAppend ( ) . GetCurrentValue ( ) ;
if ( append )
open_options | = File : : eOpenOptionAppend ;
if ( outfile_stream . GetFile ( ) . Open ( path , open_options ) . Success ( ) )
2010-10-10 20:52:20 +00:00
{
2011-04-27 22:04:39 +00:00
if ( m_memory_options . m_output_as_binary )
2010-10-10 20:52:20 +00:00
{
int bytes_written = outfile_stream . Write ( data_sp - > GetBytes ( ) , bytes_read ) ;
if ( bytes_written > 0 )
{
result . GetOutputStream ( ) . Printf ( " %i bytes %s to '%s' \n " ,
bytes_written ,
2011-04-27 22:04:39 +00:00
append ? " appended " : " written " ,
2010-10-10 20:52:20 +00:00
path ) ;
return true ;
}
else
{
result . AppendErrorWithFormat ( " Failed to write %zu bytes to '%s'. \n " , bytes_read , path ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else
{
// We are going to write ASCII to the file just point the
// output_stream to our outfile_stream...
output_stream = & outfile_stream ;
}
}
else
{
2011-04-27 22:04:39 +00:00
result . AppendErrorWithFormat ( " Failed to open file '%s' for %s. \n " , path , append ? " append " : " write " ) ;
2010-10-10 20:52:20 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else
{
output_stream = & result . GetOutputStream ( ) ;
}
2011-04-27 22:04:39 +00:00
if ( clang_ast_type . GetOpaqueQualType ( ) )
{
for ( uint32_t i = 0 ; i < item_count ; + + i )
{
addr_t item_addr = addr + ( i * item_byte_size ) ;
Address address ( NULL , item_addr ) ;
StreamString name_strm ;
name_strm . Printf ( " 0x%llx " , item_addr ) ;
ValueObjectSP valobj_sp ( ValueObjectMemory : : Create ( exe_ctx . GetBestExecutionContextScope ( ) ,
name_strm . GetString ( ) . c_str ( ) ,
address ,
clang_ast_type ) ) ;
if ( valobj_sp )
{
2011-04-28 20:55:26 +00:00
if ( format ! = eFormatDefault )
valobj_sp - > SetFormat ( format ) ;
bool scope_already_checked = true ;
2011-04-27 22:04:39 +00:00
ValueObject : : DumpValueObject ( * output_stream ,
valobj_sp . get ( ) ,
NULL ,
2011-04-28 20:55:26 +00:00
m_varobj_options . ptr_depth ,
0 ,
m_varobj_options . max_depth ,
m_varobj_options . show_types ,
m_varobj_options . show_location ,
m_varobj_options . use_objc ,
2011-05-04 03:43:18 +00:00
m_varobj_options . use_dynamic ,
2011-08-09 23:50:01 +00:00
m_varobj_options . be_raw ? false : m_varobj_options . use_synth ,
2011-04-27 22:04:39 +00:00
scope_already_checked ,
2011-07-16 01:22:04 +00:00
m_varobj_options . flat_output ,
2011-08-12 02:00:06 +00:00
m_varobj_options . be_raw ? UINT32_MAX : m_varobj_options . no_summary_depth ,
m_varobj_options . be_raw ? true : m_varobj_options . ignore_cap ) ;
2011-04-27 22:04:39 +00:00
}
else
{
result . AppendErrorWithFormat ( " failed to create a value object for: (%s) %s \n " ,
view_as_type_cstr ,
name_strm . GetString ( ) . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
return true ;
}
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
DataExtractor data ( data_sp ,
2011-09-22 04:58:26 +00:00
target - > GetArchitecture ( ) . GetByteOrder ( ) ,
target - > GetArchitecture ( ) . GetAddressByteSize ( ) ) ;
2011-04-27 22:04:39 +00:00
2010-10-10 20:52:20 +00:00
assert ( output_stream ) ;
data . Dump ( output_stream ,
0 ,
2011-04-27 22:04:39 +00:00
m_format_options . GetFormat ( ) ,
2010-10-10 20:52:20 +00:00
item_byte_size ,
item_count ,
num_per_line ,
addr ,
0 ,
0 ) ;
output_stream - > EOL ( ) ;
2010-06-08 16:52:24 +00:00
return true ;
}
protected :
2011-04-27 22:04:39 +00:00
OptionGroupOptions m_option_group ;
OptionGroupFormat m_format_options ;
OptionGroupReadMemory m_memory_options ;
OptionGroupOutputFile m_outfile_options ;
2011-04-28 20:55:26 +00:00
OptionGroupValueObjectDisplay m_varobj_options ;
2010-10-10 20:52:20 +00:00
2010-06-08 16:52:24 +00:00
} ;
2011-10-25 06:44:01 +00:00
OptionDefinition
g_memory_write_option_table [ ] =
{
{ LLDB_OPT_SET_1 , true , " infile " , ' i ' , required_argument , NULL , 0 , eArgTypeFilename , " Write memory using the contents of a file. " } ,
{ LLDB_OPT_SET_1 , false , " offset " , ' o ' , required_argument , NULL , 0 , eArgTypeOffset , " Start writng bytes from an offset within the input file. " } ,
} ;
2010-06-08 16:52:24 +00:00
//----------------------------------------------------------------------
// Write memory to the inferior process
//----------------------------------------------------------------------
class CommandObjectMemoryWrite : public CommandObject
{
public :
2011-10-25 06:44:01 +00:00
class OptionGroupWriteMemory : public OptionGroup
2010-06-08 16:52:24 +00:00
{
public :
2011-10-25 06:44:01 +00:00
OptionGroupWriteMemory ( ) :
OptionGroup ( )
2010-06-08 16:52:24 +00:00
{
}
virtual
2011-10-25 06:44:01 +00:00
~ OptionGroupWriteMemory ( )
2010-06-08 16:52:24 +00:00
{
}
2011-10-25 06:44:01 +00:00
virtual uint32_t
GetNumDefinitions ( )
{
return sizeof ( g_memory_write_option_table ) / sizeof ( OptionDefinition ) ;
}
virtual const OptionDefinition *
GetDefinitions ( )
{
return g_memory_write_option_table ;
}
2010-06-08 16:52:24 +00:00
virtual Error
2011-10-25 06:44:01 +00:00
SetOptionValue ( CommandInterpreter & interpreter ,
uint32_t option_idx ,
const char * option_arg )
2010-06-08 16:52:24 +00:00
{
Error error ;
2011-10-25 06:44:01 +00:00
char short_option = ( char ) g_memory_write_option_table [ option_idx ] . short_option ;
2010-06-08 16:52:24 +00:00
switch ( short_option )
{
2011-10-25 06:44:01 +00:00
case ' i ' :
m_infile . SetFile ( option_arg , true ) ;
if ( ! m_infile . Exists ( ) )
2010-10-10 20:52:20 +00:00
{
2011-10-25 06:44:01 +00:00
m_infile . Clear ( ) ;
error . SetErrorStringWithFormat ( " Input file does not exist: '%s' \n " , option_arg ) ;
2010-10-10 20:52:20 +00:00
}
2011-10-25 06:44:01 +00:00
break ;
case ' o ' :
{
bool success ;
m_infile_offset = Args : : StringToUInt64 ( option_arg , 0 , 0 , & success ) ;
if ( ! success )
{
error . SetErrorStringWithFormat ( " Invalid offset string '%s' \n " , option_arg ) ;
}
}
break ;
default :
error . SetErrorStringWithFormat ( " Unrecognized short option '%c'. \n " , short_option ) ;
break ;
2010-06-08 16:52:24 +00:00
}
return error ;
}
2011-10-25 06:44:01 +00:00
virtual void
OptionParsingStarting ( CommandInterpreter & interpreter )
2010-06-08 16:52:24 +00:00
{
2010-10-10 20:52:20 +00:00
m_infile . Clear ( ) ;
m_infile_offset = 0 ;
2010-06-08 16:52:24 +00:00
}
2010-10-10 20:52:20 +00:00
FileSpec m_infile ;
off_t m_infile_offset ;
2010-06-08 16:52:24 +00:00
} ;
2010-09-18 01:14:36 +00:00
CommandObjectMemoryWrite ( CommandInterpreter & interpreter ) :
CommandObject ( interpreter ,
" memory write " ,
2010-09-08 21:06:11 +00:00
" Write to the memory of the process being debugged. " ,
2010-10-04 22:28:36 +00:00
//"memory write [<cmd-options>] <addr> [value1 value2 ...]",
NULL ,
2011-04-07 22:46:35 +00:00
eFlagProcessMustBeLaunched ) ,
2011-10-25 06:44:01 +00:00
m_option_group ( interpreter ) ,
m_format_options ( eFormatBytes , 1 , UINT64_MAX ) ,
m_memory_options ( )
2010-06-08 16:52:24 +00:00
{
2010-10-04 22:28:36 +00:00
CommandArgumentEntry arg1 ;
CommandArgumentEntry arg2 ;
CommandArgumentData addr_arg ;
CommandArgumentData value_arg ;
// Define the first (and only) variant of this arg.
addr_arg . arg_type = eArgTypeAddress ;
addr_arg . arg_repetition = eArgRepeatPlain ;
// There is only one variant this argument could be; put it into the argument entry.
arg1 . push_back ( addr_arg ) ;
// Define the first (and only) variant of this arg.
value_arg . arg_type = eArgTypeValue ;
value_arg . arg_repetition = eArgRepeatPlus ;
// There is only one variant this argument could be; put it into the argument entry.
arg2 . push_back ( value_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg1 ) ;
m_arguments . push_back ( arg2 ) ;
2011-10-25 06:44:01 +00:00
m_option_group . Append ( & m_format_options , OptionGroupFormat : : OPTION_GROUP_FORMAT , LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_format_options , OptionGroupFormat : : OPTION_GROUP_SIZE , LLDB_OPT_SET_1 | LLDB_OPT_SET_2 ) ;
m_option_group . Append ( & m_memory_options , LLDB_OPT_SET_ALL , LLDB_OPT_SET_2 ) ;
m_option_group . Finalize ( ) ;
2010-06-08 16:52:24 +00:00
}
virtual
~ CommandObjectMemoryWrite ( )
{
}
Options *
GetOptions ( )
{
2011-10-25 06:44:01 +00:00
return & m_option_group ;
2010-06-08 16:52:24 +00:00
}
bool
UIntValueIsValidForSize ( uint64_t uval64 , size_t total_byte_size )
{
if ( total_byte_size > 8 )
return false ;
if ( total_byte_size = = 8 )
return true ;
const uint64_t max = ( ( uint64_t ) 1 < < ( uint64_t ) ( total_byte_size * 8 ) ) - 1 ;
return uval64 < = max ;
}
bool
SIntValueIsValidForSize ( int64_t sval64 , size_t total_byte_size )
{
if ( total_byte_size > 8 )
return false ;
if ( total_byte_size = = 8 )
return true ;
const int64_t max = ( ( int64_t ) 1 < < ( uint64_t ) ( total_byte_size * 8 - 1 ) ) - 1 ;
const int64_t min = ~ ( max ) ;
return min < = sval64 & & sval64 < = max ;
}
virtual bool
2010-09-18 01:14:36 +00:00
Execute ( Args & command ,
2010-06-08 16:52:24 +00:00
CommandReturnObject & result )
{
2011-09-22 04:58:26 +00:00
Process * process = m_interpreter . GetExecutionContext ( ) . GetProcessPtr ( ) ;
2010-06-08 16:52:24 +00:00
if ( process = = NULL )
{
result . AppendError ( " need a process to read memory " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
const size_t argc = command . GetArgumentCount ( ) ;
2011-10-25 06:44:01 +00:00
if ( m_memory_options . m_infile )
2010-06-08 16:52:24 +00:00
{
2010-10-10 20:52:20 +00:00
if ( argc < 1 )
{
result . AppendErrorWithFormat ( " %s takes a destination address when writing file contents. \n " , m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
else if ( argc < 2 )
{
result . AppendErrorWithFormat ( " %s takes a destination address and at least one value. \n " , m_cmd_name . c_str ( ) ) ;
2010-06-08 16:52:24 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
StreamString buffer ( Stream : : eBinary ,
2011-02-15 21:59:32 +00:00
process - > GetTarget ( ) . GetArchitecture ( ) . GetAddressByteSize ( ) ,
process - > GetTarget ( ) . GetArchitecture ( ) . GetByteOrder ( ) ) ;
2010-06-08 16:52:24 +00:00
2011-10-25 06:44:01 +00:00
OptionValueUInt64 & byte_size_value = m_format_options . GetByteSizeValue ( ) ;
size_t item_byte_size = byte_size_value . GetCurrentValue ( ) ;
2010-07-09 20:39:50 +00:00
2010-06-08 16:52:24 +00:00
lldb : : addr_t addr = Args : : StringToUInt64 ( command . GetArgumentAtIndex ( 0 ) , LLDB_INVALID_ADDRESS , 0 ) ;
if ( addr = = LLDB_INVALID_ADDRESS )
{
result . AppendErrorWithFormat ( " Invalid address string '%s'. \n " , command . GetArgumentAtIndex ( 0 ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-10-10 20:52:20 +00:00
2011-10-25 06:44:01 +00:00
if ( m_memory_options . m_infile )
2010-10-10 20:52:20 +00:00
{
size_t length = SIZE_MAX ;
2011-10-25 06:44:01 +00:00
if ( item_byte_size > 0 )
length = item_byte_size ;
lldb : : DataBufferSP data_sp ( m_memory_options . m_infile . ReadFileContents ( m_memory_options . m_infile_offset , length ) ) ;
2010-10-10 20:52:20 +00:00
if ( data_sp )
{
length = data_sp - > GetByteSize ( ) ;
if ( length > 0 )
{
Error error ;
size_t bytes_written = process - > WriteMemory ( addr , data_sp - > GetBytes ( ) , length , error ) ;
if ( bytes_written = = length )
{
// All bytes written
result . GetOutputStream ( ) . Printf ( " %zu bytes were written to 0x%llx \n " , bytes_written , addr ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else if ( bytes_written > 0 )
{
// Some byte written
result . GetOutputStream ( ) . Printf ( " %zu bytes of %zu requested were written to 0x%llx \n " , bytes_written , length , addr ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
result . AppendErrorWithFormat ( " Memory write to 0x%llx failed: %s. \n " , addr , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
}
else
{
result . AppendErrorWithFormat ( " Unable to read contents of file. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
2011-10-25 06:44:01 +00:00
else if ( item_byte_size = = 0 )
2010-10-10 20:52:20 +00:00
{
2011-10-25 06:44:01 +00:00
if ( m_format_options . GetFormat ( ) = = eFormatPointer )
2010-10-10 20:52:20 +00:00
item_byte_size = buffer . GetAddressByteSize ( ) ;
else
item_byte_size = 1 ;
}
2010-06-08 16:52:24 +00:00
command . Shift ( ) ; // shift off the address argument
uint64_t uval64 ;
int64_t sval64 ;
bool success = false ;
const uint32_t num_value_args = command . GetArgumentCount ( ) ;
uint32_t i ;
for ( i = 0 ; i < num_value_args ; + + i )
{
const char * value_str = command . GetArgumentAtIndex ( i ) ;
2011-10-25 06:44:01 +00:00
switch ( m_format_options . GetFormat ( ) )
2010-06-08 16:52:24 +00:00
{
2011-06-23 21:22:24 +00:00
case kNumFormats :
2010-06-08 16:52:24 +00:00
case eFormatFloat : // TODO: add support for floats soon
case eFormatCharPrintable :
case eFormatBytesWithASCII :
case eFormatComplex :
case eFormatEnum :
case eFormatUnicode16 :
case eFormatUnicode32 :
case eFormatVectorOfChar :
case eFormatVectorOfSInt8 :
case eFormatVectorOfUInt8 :
case eFormatVectorOfSInt16 :
case eFormatVectorOfUInt16 :
case eFormatVectorOfSInt32 :
case eFormatVectorOfUInt32 :
case eFormatVectorOfSInt64 :
case eFormatVectorOfUInt64 :
case eFormatVectorOfFloat32 :
case eFormatVectorOfFloat64 :
case eFormatVectorOfUInt128 :
2011-03-20 04:57:14 +00:00
case eFormatOSType :
case eFormatComplexInteger :
2010-06-08 16:52:24 +00:00
result . AppendError ( " unsupported format for writing memory " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
case eFormatDefault :
case eFormatBytes :
case eFormatHex :
2010-07-09 20:39:50 +00:00
case eFormatPointer :
2010-06-08 16:52:24 +00:00
// Decode hex bytes
uval64 = Args : : StringToUInt64 ( value_str , UINT64_MAX , 16 , & success ) ;
if ( ! success )
{
result . AppendErrorWithFormat ( " '%s' is not a valid hex string value. \n " , value_str ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else if ( ! UIntValueIsValidForSize ( uval64 , item_byte_size ) )
{
2011-09-20 21:44:10 +00:00
result . AppendErrorWithFormat ( " Value 0x%llx is too large to fit in a %lu byte unsigned integer value. \n " , uval64 , item_byte_size ) ;
2010-06-08 16:52:24 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
buffer . PutMaxHex64 ( uval64 , item_byte_size ) ;
break ;
case eFormatBoolean :
uval64 = Args : : StringToBoolean ( value_str , false , & success ) ;
if ( ! success )
{
result . AppendErrorWithFormat ( " '%s' is not a valid boolean string value. \n " , value_str ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
buffer . PutMaxHex64 ( uval64 , item_byte_size ) ;
break ;
case eFormatBinary :
uval64 = Args : : StringToUInt64 ( value_str , UINT64_MAX , 2 , & success ) ;
if ( ! success )
{
result . AppendErrorWithFormat ( " '%s' is not a valid binary string value. \n " , value_str ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else if ( ! UIntValueIsValidForSize ( uval64 , item_byte_size ) )
{
2011-09-20 21:44:10 +00:00
result . AppendErrorWithFormat ( " Value 0x%llx is too large to fit in a %lu byte unsigned integer value. \n " , uval64 , item_byte_size ) ;
2010-06-08 16:52:24 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
buffer . PutMaxHex64 ( uval64 , item_byte_size ) ;
break ;
2011-06-17 23:50:44 +00:00
case eFormatCharArray :
2010-06-08 16:52:24 +00:00
case eFormatChar :
case eFormatCString :
if ( value_str [ 0 ] )
{
size_t len = strlen ( value_str ) ;
// Include the NULL for C strings...
2011-10-25 06:44:01 +00:00
if ( m_format_options . GetFormat ( ) = = eFormatCString )
2010-06-08 16:52:24 +00:00
+ + len ;
Error error ;
if ( process - > WriteMemory ( addr , value_str , len , error ) = = len )
{
addr + = len ;
}
else
{
result . AppendErrorWithFormat ( " Memory write to 0x%llx failed: %s. \n " , addr , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
break ;
case eFormatDecimal :
sval64 = Args : : StringToSInt64 ( value_str , INT64_MAX , 0 , & success ) ;
if ( ! success )
{
result . AppendErrorWithFormat ( " '%s' is not a valid signed decimal value. \n " , value_str ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else if ( ! SIntValueIsValidForSize ( sval64 , item_byte_size ) )
{
2011-09-20 21:44:10 +00:00
result . AppendErrorWithFormat ( " Value %lli is too large or small to fit in a %lu byte signed integer value. \n " , sval64 , item_byte_size ) ;
2010-06-08 16:52:24 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
buffer . PutMaxHex64 ( sval64 , item_byte_size ) ;
break ;
case eFormatUnsigned :
uval64 = Args : : StringToUInt64 ( value_str , UINT64_MAX , 0 , & success ) ;
if ( ! success )
{
result . AppendErrorWithFormat ( " '%s' is not a valid unsigned decimal string value. \n " , value_str ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else if ( ! UIntValueIsValidForSize ( uval64 , item_byte_size ) )
{
2011-09-20 21:44:10 +00:00
result . AppendErrorWithFormat ( " Value %llu is too large to fit in a %lu byte unsigned integer value. \n " , uval64 , item_byte_size ) ;
2010-06-08 16:52:24 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
buffer . PutMaxHex64 ( uval64 , item_byte_size ) ;
break ;
case eFormatOctal :
uval64 = Args : : StringToUInt64 ( value_str , UINT64_MAX , 8 , & success ) ;
if ( ! success )
{
result . AppendErrorWithFormat ( " '%s' is not a valid octal string value. \n " , value_str ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else if ( ! UIntValueIsValidForSize ( uval64 , item_byte_size ) )
{
2011-09-20 21:44:10 +00:00
result . AppendErrorWithFormat ( " Value %llo is too large to fit in a %lu byte unsigned integer value. \n " , uval64 , item_byte_size ) ;
2010-06-08 16:52:24 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
buffer . PutMaxHex64 ( uval64 , item_byte_size ) ;
break ;
}
}
if ( ! buffer . GetString ( ) . empty ( ) )
{
Error error ;
2010-07-20 22:52:08 +00:00
if ( process - > WriteMemory ( addr , buffer . GetString ( ) . c_str ( ) , buffer . GetString ( ) . size ( ) , error ) = = buffer . GetString ( ) . size ( ) )
2010-06-08 16:52:24 +00:00
return true ;
else
{
result . AppendErrorWithFormat ( " Memory write to 0x%llx failed: %s. \n " , addr , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
return true ;
}
protected :
2011-10-25 06:44:01 +00:00
OptionGroupOptions m_option_group ;
OptionGroupFormat m_format_options ;
OptionGroupWriteMemory m_memory_options ;
2010-06-08 16:52:24 +00:00
} ;
//-------------------------------------------------------------------------
// CommandObjectMemory
//-------------------------------------------------------------------------
2010-06-23 01:19:29 +00:00
CommandObjectMemory : : CommandObjectMemory ( CommandInterpreter & interpreter ) :
2010-09-18 01:14:36 +00:00
CommandObjectMultiword ( interpreter ,
" memory " ,
2010-09-07 22:38:08 +00:00
" A set of commands for operating on memory. " ,
2010-06-08 16:52:24 +00:00
" memory <subcommand> [<subcommand-options>] " )
{
2010-09-18 01:14:36 +00:00
LoadSubCommand ( " read " , CommandObjectSP ( new CommandObjectMemoryRead ( interpreter ) ) ) ;
LoadSubCommand ( " write " , CommandObjectSP ( new CommandObjectMemoryWrite ( interpreter ) ) ) ;
2010-06-08 16:52:24 +00:00
}
CommandObjectMemory : : ~ CommandObjectMemory ( )
{
}