Added a new OptionValue subclass for lldb::Format: OptionValueFormat. Added

new OptionGroup subclasses for:
- output file for use with options: 
        long opts: --outfile <path> --append--output
        short opts: -o <path> -A
        
- format for use with options:
        long opts: --format <format>

- variable object display controls for depth, pointer depth, wether to show
  types, show summary, show location, flat output, use objc "po" style summary.
  
Modified ValueObjectMemory to be able to be created either with a TypeSP or
a ClangASTType.

Switched "memory read" over to use OptionGroup subclasses: one for the outfile
options, one for the command specific options, and one for the format.

llvm-svn: 130334
This commit is contained in:
Greg Clayton 2011-04-27 22:04:39 +00:00
parent 8513d4236c
commit 84c39663a9
21 changed files with 1455 additions and 275 deletions

View File

@ -38,6 +38,9 @@ StateIsRunningState (lldb::StateType state);
bool
StateIsStoppedState (lldb::StateType state);
const char *
GetFormatAsCString (lldb::Format format);
} // namespace lldb_private
#endif // liblldb_State_h_

View File

@ -15,6 +15,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Core/ValueObject.h"
#include "lldb/Symbol/ClangASTType.h"
namespace lldb_private {
@ -31,6 +32,12 @@ public:
const Address &address,
lldb::TypeSP &type_sp);
static lldb::ValueObjectSP
Create (ExecutionContextScope *exe_scope,
const char *name,
const Address &address,
const ClangASTType &ast_type);
virtual
~ValueObjectMemory();
@ -61,6 +68,7 @@ protected:
Address m_address; ///< The variable that this value object is based upon
lldb::TypeSP m_type_sp;
ClangASTType m_clang_type;
private:
ValueObjectMemory (ExecutionContextScope *exe_scope,
@ -68,6 +76,10 @@ private:
const Address &address,
lldb::TypeSP &type_sp);
ValueObjectMemory (ExecutionContextScope *exe_scope,
const char *name,
const Address &address,
const ClangASTType &ast_type);
//------------------------------------------------------------------
// For ValueObject only
//------------------------------------------------------------------

View File

@ -27,6 +27,7 @@ namespace lldb_private {
class OptionValueUInt64;
class OptionValueString;
class OptionValueFileSpec;
class OptionValueFormat;
class OptionValueArray;
class OptionValueDictionary;
@ -43,6 +44,7 @@ namespace lldb_private {
eTypeDictionary,
eTypeEnum,
eTypeFileSpec,
eTypeFormat,
eTypeSInt64,
eTypeUInt64,
eTypeString
@ -89,32 +91,38 @@ namespace lldb_private {
GetUInt64Value (uint64_t fail_value, bool *success_ptr);
OptionValueBoolean *
GetAsBooleanValue ();
GetAsBoolean ();
OptionValueSInt64 *
GetAsSInt64Value ();
GetAsSInt64 ();
OptionValueUInt64 *
GetAsUInt64Value ();
GetAsUInt64 ();
OptionValueString *
GetAsStringValue ();
GetAsString ();
OptionValueFileSpec *
GetAsFileSpecValue();
GetAsFileSpec ();
OptionValueFormat *
GetAsFormat ();
OptionValueArray *
GetAsArrayValue();
GetAsArray ();
OptionValueDictionary *
GetAsDictionaryValue();
GetAsDictionary ();
const char *
GetStringValue ();
GetStringValue (const char *fail_value = NULL);
uint64_t
GetUInt64Value ();
GetUInt64Value (uint64_t fail_value = 0);
lldb::Format
GetFormatValue (lldb::Format fail_value = lldb::eFormatDefault);
protected:
bool m_value_was_set; // This can be used to see if a value has been set
// by a call to SetValueFromCString(). It is often
@ -532,13 +540,13 @@ namespace lldb_private {
m_default_value ()
{
}
OptionValueFileSpec (const FileSpec &current_value) :
m_current_value (current_value),
m_default_value ()
{
}
OptionValueFileSpec (const FileSpec &current_value,
const FileSpec &default_value) :
m_current_value (current_value),
@ -584,7 +592,13 @@ namespace lldb_private {
{
return m_current_value;
}
const FileSpec &
GetCurrentValue() const
{
return m_current_value;
}
const FileSpec &
GetDefaultValue() const
{
@ -608,6 +622,93 @@ namespace lldb_private {
FileSpec m_default_value;
};
//---------------------------------------------------------------------
// OptionValueFormat
//---------------------------------------------------------------------
class OptionValueFormat : public OptionValue
{
public:
OptionValueFormat () :
m_current_value (lldb::eFormatInvalid),
m_default_value (lldb::eFormatDefault)
{
}
OptionValueFormat (lldb::Format current_value) :
m_current_value (current_value),
m_default_value (lldb::eFormatDefault)
{
}
OptionValueFormat (lldb::Format current_value,
lldb::Format default_value) :
m_current_value (current_value),
m_default_value (default_value)
{
}
virtual
~OptionValueFormat()
{
}
//---------------------------------------------------------------------
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
virtual OptionValue::Type
GetType ()
{
return eTypeFormat;
}
virtual void
DumpValue (Stream &strm);
virtual Error
SetValueFromCString (const char *value);
virtual bool
Clear ()
{
m_current_value = m_default_value;
m_value_was_set = false;
return true;
}
//---------------------------------------------------------------------
// Subclass specific functions
//---------------------------------------------------------------------
lldb::Format
GetCurrentValue()
{
return m_current_value;
}
lldb::Format
GetDefaultValue() const
{
return m_default_value;
}
void
SetCurrentValue (lldb::Format value)
{
m_current_value = value;
}
void
SetDefaultValue (lldb::Format value)
{
m_default_value = value;
}
protected:
lldb::Format m_current_value;
lldb::Format m_default_value;
};
//---------------------------------------------------------------------
// OptionValueArray
//---------------------------------------------------------------------

View File

@ -0,0 +1,64 @@
//===-- OptionGroupFormat.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_OptionGroupFormat_h_
#define liblldb_OptionGroupFormat_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/NamedOptionValue.h"
namespace lldb_private {
//-------------------------------------------------------------------------
// OptionGroupFormat
//-------------------------------------------------------------------------
class OptionGroupFormat : public OptionGroup
{
public:
OptionGroupFormat (lldb::Format default_format);
virtual
~OptionGroupFormat ();
virtual uint32_t
GetNumDefinitions ();
virtual const OptionDefinition*
GetDefinitions ();
virtual Error
SetOptionValue (CommandInterpreter &interpreter,
uint32_t option_idx,
const char *option_value);
virtual void
OptionParsingStarting (CommandInterpreter &interpreter);
lldb::Format
GetFormat ()
{
return m_format.GetCurrentValue();
}
protected:
OptionValueFormat m_format;
};
} // namespace lldb_private
#endif // liblldb_OptionGroupFormat_h_

View File

@ -0,0 +1,69 @@
//===-- OptionGroupOutputFile.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_OptionGroupOutputFile_h_
#define liblldb_OptionGroupOutputFile_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/NamedOptionValue.h"
namespace lldb_private {
//-------------------------------------------------------------------------
// OptionGroupOutputFile
//-------------------------------------------------------------------------
class OptionGroupOutputFile : public OptionGroup
{
public:
OptionGroupOutputFile ();
virtual
~OptionGroupOutputFile ();
virtual uint32_t
GetNumDefinitions ();
virtual const OptionDefinition*
GetDefinitions ();
virtual Error
SetOptionValue (CommandInterpreter &interpreter,
uint32_t option_idx,
const char *option_value);
virtual void
OptionParsingStarting (CommandInterpreter &interpreter);
const OptionValueFileSpec &
GetFile ()
{
return m_file;
}
const OptionValueBoolean &
GetAppend ()
{
return m_append;
}
protected:
OptionValueFileSpec m_file;
OptionValueBoolean m_append;
};
} // namespace lldb_private
#endif // liblldb_OptionGroupOutputFile_h_

View File

@ -0,0 +1,61 @@
//===-- OptionGroupValueObjectDisplay.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_OptionGroupValueObjectDisplay_h_
#define liblldb_OptionGroupValueObjectDisplay_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Interpreter/Options.h"
namespace lldb_private {
//-------------------------------------------------------------------------
// OptionGroupValueObjectDisplay
//-------------------------------------------------------------------------
class OptionGroupValueObjectDisplay : public OptionGroup
{
public:
OptionGroupValueObjectDisplay ();
virtual
~OptionGroupValueObjectDisplay ();
virtual uint32_t
GetNumDefinitions ();
virtual const OptionDefinition*
GetDefinitions ();
virtual Error
SetOptionValue (CommandInterpreter &interpreter,
uint32_t option_idx,
const char *option_value);
virtual void
OptionParsingStarting (CommandInterpreter &interpreter);
bool show_types;
bool show_summary;
bool show_location;
bool flat_output;
bool use_objc;
uint32_t max_depth;
uint32_t ptr_depth;
lldb::Format format;
};
} // namespace lldb_private
#endif // liblldb_OptionGroupValueObjectDisplay_h_

View File

@ -392,6 +392,20 @@ protected:
{
}
//----------------------------------------------------------------------
/// Append options from a OptionGroup class.
///
/// Append all options from \a group using the exact same option groups
/// that each option is defined with.
///
/// @param[in] group
/// A group of options to take option values from and copy their
/// definitions into this class.
//----------------------------------------------------------------------
void
Append (OptionGroup* group);
//----------------------------------------------------------------------
/// Append options from a OptionGroup class.
///

View File

@ -27,7 +27,7 @@ namespace lldb_private {
//----------------------------------------------------------------------
class ClangASTType
{
protected:
public:
ClangASTType (lldb::clang_type_t type, clang::ASTContext *ast_context) :
m_type (type),
m_ast (ast_context)
@ -56,7 +56,6 @@ protected:
return *this;
}
public:
lldb::clang_type_t
GetOpaqueQualType() const
{
@ -218,6 +217,13 @@ public:
const Scalar &value,
Stream &strm);
void
SetClangType (clang::ASTContext *ast, lldb::clang_type_t type)
{
m_type = type;
m_ast = ast;
}
bool
ReadFromMemory (ExecutionContext *exe_ctx,
lldb::addr_t addr,
@ -256,8 +262,8 @@ public:
RemoveFastQualifiers (lldb::clang_type_t);
private:
void *m_type;
clang::ASTContext *m_ast;
lldb::clang_type_t m_type;
clang::ASTContext *m_ast;
};

View File

@ -73,6 +73,8 @@
26744EF21338317700EF765A /* GDBRemoteCommunicationClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 26744EEE1338317700EF765A /* GDBRemoteCommunicationClient.h */; };
26744EF31338317700EF765A /* GDBRemoteCommunicationServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EEF1338317700EF765A /* GDBRemoteCommunicationServer.cpp */; };
26744EF41338317700EF765A /* GDBRemoteCommunicationServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 26744EF01338317700EF765A /* GDBRemoteCommunicationServer.h */; };
267C012B136880DF006E963E /* OptionGroupValueObjectDisplay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267C012A136880DF006E963E /* OptionGroupValueObjectDisplay.cpp */; };
267C01371368C49C006E963E /* OptionGroupOutputFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BCFC531368B3E4006DC050 /* OptionGroupOutputFile.cpp */; };
2689000013353DB600698AC0 /* BreakpointResolverAddress.h in Headers */ = {isa = PBXBuildFile; fileRef = 26D0DD5010FE554D00271C65 /* BreakpointResolverAddress.h */; };
2689000113353DB600698AC0 /* BreakpointResolverAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D0DD5310FE555900271C65 /* BreakpointResolverAddress.cpp */; };
2689000213353DB600698AC0 /* BreakpointResolverFileLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 26D0DD5110FE554D00271C65 /* BreakpointResolverFileLine.h */; };
@ -379,6 +381,7 @@
26B1FCBD13381071002886E2 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C74CB6212288704006A8171 /* Carbon.framework */; };
26B1FCC21338115F002886E2 /* Host.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7EE810F1B88F00F91463 /* Host.mm */; };
26B42C4D1187ABA50079C8C8 /* LLDB.h in Headers */ = {isa = PBXBuildFile; fileRef = 26B42C4C1187ABA50079C8C8 /* LLDB.h */; settings = {ATTRIBUTES = (Public, ); }; };
26BCFC521368AE38006DC050 /* OptionGroupFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BCFC511368AE38006DC050 /* OptionGroupFormat.cpp */; };
26BD407F135D2AE000237D80 /* FileLineResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BD407E135D2ADF00237D80 /* FileLineResolver.cpp */; };
26C72C94124322890068DC16 /* SBStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 26C72C93124322890068DC16 /* SBStream.h */; settings = {ATTRIBUTES = (Public, ); }; };
26C72C961243229A0068DC16 /* SBStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C72C951243229A0068DC16 /* SBStream.cpp */; };
@ -695,6 +698,8 @@
2675F6FF1332BE690067997B /* PlatformRemoteiOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformRemoteiOS.h; sourceTree = "<group>"; };
2676A093119C93C8008A98EF /* StringExtractorGDBRemote.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractorGDBRemote.cpp; path = source/Utility/StringExtractorGDBRemote.cpp; sourceTree = "<group>"; };
2676A094119C93C8008A98EF /* StringExtractorGDBRemote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringExtractorGDBRemote.h; path = source/Utility/StringExtractorGDBRemote.h; sourceTree = "<group>"; };
267C0128136880C7006E963E /* OptionGroupValueObjectDisplay.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupValueObjectDisplay.h; path = include/lldb/Interpreter/OptionGroupValueObjectDisplay.h; sourceTree = "<group>"; };
267C012A136880DF006E963E /* OptionGroupValueObjectDisplay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupValueObjectDisplay.cpp; path = source/Interpreter/OptionGroupValueObjectDisplay.cpp; sourceTree = "<group>"; };
2682F16A115EDA0D00CCFF99 /* PseudoTerminal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PseudoTerminal.cpp; path = source/Utility/PseudoTerminal.cpp; sourceTree = "<group>"; };
2682F16B115EDA0D00CCFF99 /* PseudoTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PseudoTerminal.h; path = include/lldb/Utility/PseudoTerminal.h; sourceTree = "<group>"; };
2682F284115EF3A700CCFF99 /* SBError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBError.cpp; path = source/API/SBError.cpp; sourceTree = "<group>"; };
@ -988,6 +993,10 @@
26BC7F3E10F1B90C00F91463 /* ThreadList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadList.cpp; path = source/Target/ThreadList.cpp; sourceTree = "<group>"; };
26BC7F3F10F1B90C00F91463 /* ThreadPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlan.cpp; path = source/Target/ThreadPlan.cpp; sourceTree = "<group>"; };
26BC7F4C10F1BC1A00F91463 /* ObjectFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjectFile.cpp; path = source/Symbol/ObjectFile.cpp; sourceTree = "<group>"; };
26BCFC4F1368ADF7006DC050 /* OptionGroupFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupFormat.h; path = include/lldb/Interpreter/OptionGroupFormat.h; sourceTree = "<group>"; };
26BCFC511368AE38006DC050 /* OptionGroupFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupFormat.cpp; path = source/Interpreter/OptionGroupFormat.cpp; sourceTree = "<group>"; };
26BCFC531368B3E4006DC050 /* OptionGroupOutputFile.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupOutputFile.cpp; path = source/Interpreter/OptionGroupOutputFile.cpp; sourceTree = "<group>"; };
26BCFC541368B4B8006DC050 /* OptionGroupOutputFile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupOutputFile.h; path = include/lldb/Interpreter/OptionGroupOutputFile.h; sourceTree = "<group>"; };
26BD407D135D2AC400237D80 /* FileLineResolver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FileLineResolver.h; path = include/lldb/Core/FileLineResolver.h; sourceTree = "<group>"; };
26BD407E135D2ADF00237D80 /* FileLineResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileLineResolver.cpp; path = source/Core/FileLineResolver.cpp; sourceTree = "<group>"; };
26C5577B132575AD008FD8FE /* PlatformMacOSX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformMacOSX.cpp; sourceTree = "<group>"; };
@ -2248,8 +2257,14 @@
26BC7E8610F1B85900F91463 /* Options.cpp */,
26D5E160135BAEB0006EA0A7 /* OptionGroupArchitecture.h */,
26D5E15E135BAEA2006EA0A7 /* OptionGroupArchitecture.cpp */,
26BCFC4F1368ADF7006DC050 /* OptionGroupFormat.h */,
26BCFC511368AE38006DC050 /* OptionGroupFormat.cpp */,
26BCFC541368B4B8006DC050 /* OptionGroupOutputFile.h */,
26BCFC531368B3E4006DC050 /* OptionGroupOutputFile.cpp */,
26D5E161135BB040006EA0A7 /* OptionGroupPlatform.h */,
26D5E162135BB054006EA0A7 /* OptionGroupPlatform.cpp */,
267C0128136880C7006E963E /* OptionGroupValueObjectDisplay.h */,
267C012A136880DF006E963E /* OptionGroupValueObjectDisplay.cpp */,
26BC7DE510F1B7F900F91463 /* ScriptInterpreter.h */,
9A82010B10FFB49800182560 /* ScriptInterpreter.cpp */,
9A2771FB1135A35C00E6ADB6 /* ScriptInterpreterNone.h */,
@ -3235,6 +3250,9 @@
263E949F13661AEA00E7D1CE /* UnwindAssembly-x86.cpp in Sources */,
264D8D5013661BD7003A368F /* UnwindAssembly.cpp in Sources */,
26ECA04313665FED008D1F18 /* ARM_DWARF_Registers.cpp in Sources */,
267C012B136880DF006E963E /* OptionGroupValueObjectDisplay.cpp in Sources */,
26BCFC521368AE38006DC050 /* OptionGroupFormat.cpp in Sources */,
267C01371368C49C006E963E /* OptionGroupOutputFile.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -17,15 +17,195 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupOutputFile.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
using namespace lldb;
using namespace lldb_private;
OptionDefinition
g_option_table[] =
{
{ LLDB_OPT_SET_1|
LLDB_OPT_SET_2, false, "size" ,'s', required_argument, NULL, 0, eArgTypeByteSize ,"The size in bytes to use when displaying with the selected format."},
{ LLDB_OPT_SET_1|
LLDB_OPT_SET_3, false, "count" ,'c', required_argument, NULL, 0, eArgTypeCount ,"The number of total items to display."},
{ 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."},
};
class OptionGroupReadMemory : public OptionGroup
{
public:
OptionGroupReadMemory () :
m_byte_size (0,0),
m_count (0,0),
m_num_per_line (0,0),
m_output_as_binary (false),
m_view_as_type()
{
}
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)
{
case 'l':
error = m_num_per_line.SetValueFromCString (option_arg);
if (m_num_per_line.GetCurrentValue() == 0)
error.SetErrorStringWithFormat("Invalid value for --num-per-line option '%s'. Must be positive integer value.\n", option_arg);
break;
case 'c':
error = m_count.SetValueFromCString (option_arg);
if (m_count.GetCurrentValue() == 0)
error.SetErrorStringWithFormat("Invalid value for --count option '%s'. Must be positive integer value.\n", option_arg);
break;
case 's':
error = m_byte_size.SetValueFromCString (option_arg);
if (m_byte_size.GetCurrentValue() == 0)
error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
break;
case 'b':
m_output_as_binary = true;
break;
case 't':
error = m_view_as_type.SetValueFromCString (option_arg);
break;
default:
error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
break;
}
return error;
}
virtual void
OptionParsingStarting (CommandInterpreter &interpreter)
{
m_byte_size.Clear();
m_count.Clear();
m_num_per_line.Clear();
m_output_as_binary = false;
m_view_as_type.Clear();
}
void
FinalizeSettings (lldb::Format format)
{
if (m_num_per_line.GetCurrentValue() == 0)
m_num_per_line.SetCurrentValue(1);
switch (format)
{
default:
break;
case eFormatBoolean:
if (m_byte_size.GetCurrentValue() == 0)
m_byte_size = 1;
break;
case eFormatCString:
break;
case eFormatPointer:
break;
case eFormatBinary:
case eFormatFloat:
case eFormatOctal:
case eFormatDecimal:
case eFormatEnum:
case eFormatUnicode16:
case eFormatUnicode32:
case eFormatUnsigned:
if (m_byte_size.GetCurrentValue() == 0)
m_byte_size = 4;
break;
case eFormatBytes:
case eFormatBytesWithASCII:
if (m_byte_size.GetCurrentValue() == 0)
m_byte_size = 1;
break;
case eFormatChar:
case eFormatCharPrintable:
if (m_byte_size.GetCurrentValue() == 0)
m_byte_size = 1;
break;
case eFormatComplex:
if (m_byte_size.GetCurrentValue() == 0)
m_byte_size = 8;
break;
case eFormatHex:
if (m_byte_size.GetCurrentValue() == 0)
m_byte_size = 4;
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:
break;
}
}
OptionValueUInt64 m_byte_size;
OptionValueUInt64 m_count;
OptionValueUInt64 m_num_per_line;
bool m_output_as_binary;
OptionValueString m_view_as_type;
};
//----------------------------------------------------------------------
// Read memory from the inferior process
//----------------------------------------------------------------------
@ -33,165 +213,171 @@ class CommandObjectMemoryRead : public CommandObject
{
public:
class CommandOptions : public Options
{
public:
CommandOptions (CommandInterpreter &interpreter) :
Options(interpreter)
{
OptionParsingStarting();
}
virtual
~CommandOptions ()
{
}
virtual Error
SetOptionValue (uint32_t option_idx, const char *option_arg)
{
Error error;
char short_option = (char) m_getopt_table[option_idx].val;
switch (short_option)
{
case 'f':
error = Args::StringToFormat (option_arg, m_format);
switch (m_format)
{
default:
break;
case eFormatBoolean:
if (m_byte_size == 0)
m_byte_size = 1;
if (m_num_per_line == 0)
m_num_per_line = 1;
break;
case eFormatCString:
if (m_num_per_line == 0)
m_num_per_line = 1;
break;
case eFormatPointer:
break;
case eFormatBinary:
case eFormatFloat:
case eFormatOctal:
case eFormatDecimal:
case eFormatEnum:
case eFormatUnicode16:
case eFormatUnicode32:
case eFormatUnsigned:
if (m_byte_size == 0)
m_byte_size = 4;
if (m_num_per_line == 0)
m_num_per_line = 1;
break;
case eFormatBytes:
case eFormatBytesWithASCII:
case eFormatChar:
case eFormatCharPrintable:
if (m_byte_size == 0)
m_byte_size = 1;
break;
case eFormatComplex:
if (m_byte_size == 0)
m_byte_size = 8;
break;
case eFormatHex:
if (m_byte_size == 0)
m_byte_size = 4;
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:
break;
}
break;
case 'l':
m_num_per_line = Args::StringToUInt32 (option_arg, 0);
if (m_num_per_line == 0)
error.SetErrorStringWithFormat("Invalid value for --num-per-line option '%s'. Must be positive integer value.\n", option_arg);
break;
case 'c':
m_count = Args::StringToUInt32 (option_arg, 0);
if (m_count == 0)
error.SetErrorStringWithFormat("Invalid value for --count option '%s'. Must be positive integer value.\n", option_arg);
break;
case 's':
m_byte_size = Args::StringToUInt32 (option_arg, 0);
if (m_byte_size == 0)
error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
break;
case 'o':
m_outfile_filespec.SetFile (option_arg, true);
break;
case 'b':
m_output_as_binary = true;
break;
case 'a':
m_append_to_outfile = true;
break;
default:
error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
break;
}
return error;
}
void
OptionParsingStarting ()
{
m_format = eFormatBytesWithASCII;
m_byte_size = 0;
m_count = 0;
m_num_per_line = 0;
m_outfile_filespec.Clear();
m_append_to_outfile = false;
m_output_as_binary = false;
}
const OptionDefinition*
GetDefinitions ()
{
return g_option_table;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table[];
// Instance variables to hold the values for command options.
lldb::Format m_format;
uint32_t m_byte_size;
uint32_t m_count;
uint32_t m_num_per_line;
FileSpec m_outfile_filespec;
bool m_append_to_outfile;
bool m_output_as_binary;
};
// class CommandOptions : public Options
// {
// public:
// CommandOptions (CommandInterpreter &interpreter) :
// Options(interpreter)
// {
// OptionParsingStarting();
// }
//
// virtual
// ~CommandOptions ()
// {
// }
//
// virtual Error
// SetOptionValue (uint32_t option_idx, const char *option_arg)
// {
// Error error;
// char short_option = (char) m_getopt_table[option_idx].val;
//
// switch (short_option)
// {
// case 'f':
// error = Args::StringToFormat (option_arg, m_format);
//
// switch (m_format)
// {
// default:
// break;
//
// case eFormatBoolean:
// if (m_byte_size == 0)
// m_byte_size = 1;
// if (m_num_per_line == 0)
// m_num_per_line = 1;
// break;
//
// case eFormatCString:
// if (m_num_per_line == 0)
// m_num_per_line = 1;
// break;
//
// case eFormatPointer:
// break;
//
// case eFormatBinary:
// case eFormatFloat:
// case eFormatOctal:
// case eFormatDecimal:
// case eFormatEnum:
// case eFormatUnicode16:
// case eFormatUnicode32:
// case eFormatUnsigned:
// if (m_byte_size == 0)
// m_byte_size = 4;
// if (m_num_per_line == 0)
// m_num_per_line = 1;
// break;
//
// case eFormatBytes:
// case eFormatBytesWithASCII:
// case eFormatChar:
// case eFormatCharPrintable:
// if (m_byte_size == 0)
// m_byte_size = 1;
// break;
// case eFormatComplex:
// if (m_byte_size == 0)
// m_byte_size = 8;
// break;
// case eFormatHex:
// if (m_byte_size == 0)
// m_byte_size = 4;
// 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:
// break;
// }
// break;
//
// case 'l':
// m_num_per_line = Args::StringToUInt32 (option_arg, 0);
// if (m_num_per_line == 0)
// error.SetErrorStringWithFormat("Invalid value for --num-per-line option '%s'. Must be positive integer value.\n", option_arg);
// break;
//
// case 'c':
// m_count = Args::StringToUInt32 (option_arg, 0);
// if (m_count == 0)
// error.SetErrorStringWithFormat("Invalid value for --count option '%s'. Must be positive integer value.\n", option_arg);
// break;
//
// case 's':
// m_byte_size = Args::StringToUInt32 (option_arg, 0);
// if (m_byte_size == 0)
// error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
// break;
//
// case 'o':
// m_outfile_filespec.SetFile (option_arg, true);
// break;
//
// case 'b':
// m_output_as_binary = true;
// break;
//
// case 'a':
// m_append_to_outfile = true;
// break;
//
// case 't':
// m_view_as_type.assign (option_arg);
// break;
//
// default:
// error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
// break;
// }
// return error;
// }
//
// void
// OptionParsingStarting ()
// {
// m_format = eFormatBytesWithASCII;
// m_byte_size = 0;
// m_count = 0;
// m_num_per_line = 0;
// m_outfile_filespec.Clear();
// m_view_as_type.clear();
// m_append_to_outfile = false;
// m_output_as_binary = false;
// }
//
// const OptionDefinition*
// GetDefinitions ()
// {
// return g_option_table;
// }
//
// // Options table: Required for subclasses of Options.
//
// static OptionDefinition g_option_table[];
//
// // Instance variables to hold the values for command options.
// lldb::Format m_format;
// uint32_t m_byte_size;
// uint32_t m_count;
// uint32_t m_num_per_line;
// FileSpec m_outfile_filespec;
// std::string m_view_as_type;
// bool m_append_to_outfile;
// bool m_output_as_binary;
// };
CommandObjectMemoryRead (CommandInterpreter &interpreter) :
CommandObject (interpreter,
@ -199,7 +385,10 @@ public:
"Read from the memory of the process being debugged.",
NULL,
eFlagProcessMustBeLaunched),
m_options (interpreter)
m_option_group (interpreter),
m_format_options (eFormatBytesWithASCII),
m_memory_options (),
m_outfile_options ()
{
CommandArgumentEntry arg1;
CommandArgumentEntry arg2;
@ -223,6 +412,12 @@ public:
// Push the data for the first argument into the m_arguments vector.
m_arguments.push_back (arg1);
m_arguments.push_back (arg2);
m_option_group.Append (&m_format_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
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);
m_option_group.Finalize();
}
virtual
@ -233,15 +428,15 @@ public:
Options *
GetOptions ()
{
return &m_options;
return &m_option_group;
}
virtual bool
Execute (Args& command,
CommandReturnObject &result)
{
Process *process = m_interpreter.GetExecutionContext().process;
if (process == NULL)
ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
if (exe_ctx.process == NULL)
{
result.AppendError("need a process to read memory");
result.SetStatus(eReturnStatusFailed);
@ -249,6 +444,7 @@ public:
}
const size_t argc = command.GetArgumentCount();
if (argc == 0 || argc > 2)
{
result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
@ -256,26 +452,162 @@ public:
return false;
}
size_t item_byte_size = m_options.m_byte_size;
if (item_byte_size == 0)
size_t item_byte_size = m_memory_options.m_byte_size.GetCurrentValue();
ClangASTType clang_ast_type;
const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
if (view_as_type_cstr && view_as_type_cstr[0])
{
if (m_options.m_format == eFormatPointer)
item_byte_size = process->GetTarget().GetArchitecture().GetAddressByteSize();
else
item_byte_size = 1;
// 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());
if (exe_ctx.frame)
{
sc = exe_ctx.frame->GetSymbolContext (eSymbolContextModule);
if (sc.module_sp)
{
sc.module_sp->FindTypes (sc,
lookup_type_name,
append,
1,
type_list);
}
}
if (type_list.GetSize() == 0)
{
exe_ctx.target->GetImages().FindTypes (sc,
lookup_type_name,
append,
1,
type_list);
}
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;
}
item_byte_size = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
if (item_byte_size == 0)
{
result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
view_as_type_cstr);
result.SetStatus(eReturnStatusFailed);
return false;
}
}
else
{
if (item_byte_size == 0)
{
if (m_format_options.GetFormat() == eFormatPointer)
item_byte_size = exe_ctx.target->GetArchitecture().GetAddressByteSize();
else
item_byte_size = 1;
}
}
size_t item_count = m_options.m_count;
size_t item_count = m_memory_options.m_count.GetCurrentValue();
size_t num_per_line = m_options.m_num_per_line;
size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
if (num_per_line == 0)
{
num_per_line = (16/item_byte_size);
if (num_per_line == 0)
if (clang_ast_type.GetOpaqueQualType())
num_per_line = 1;
else
{
num_per_line = (16/item_byte_size);
if (num_per_line == 0)
num_per_line = 1;
}
}
size_t total_byte_size = m_options.m_count * item_byte_size;
size_t total_byte_size = item_count * item_byte_size;
if (total_byte_size == 0)
total_byte_size = 32;
@ -316,49 +648,56 @@ public:
else
{
if (item_count == 0)
item_count = 32;
{
if (clang_ast_type.GetOpaqueQualType())
item_count = 1;
else
item_count = 32;
}
}
DataBufferSP data_sp(new DataBufferHeap (total_byte_size, '\0'));
DataBufferSP data_sp;
Error error;
size_t bytes_read = process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error);
if (bytes_read == 0)
size_t bytes_read = 0;
if (!clang_ast_type.GetOpaqueQualType())
{
result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
result.AppendError(error.AsCString());
result.SetStatus(eReturnStatusFailed);
return false;
data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
bytes_read = exe_ctx.process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error);
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)
result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
}
if (bytes_read < total_byte_size)
result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
result.SetStatus(eReturnStatusSuccessFinishResult);
DataExtractor data (data_sp,
process->GetTarget().GetArchitecture().GetByteOrder(),
process->GetTarget().GetArchitecture().GetAddressByteSize());
StreamFile outfile_stream;
Stream *output_stream = NULL;
if (m_options.m_outfile_filespec)
const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
if (outfile_spec)
{
char path[PATH_MAX];
m_options.m_outfile_filespec.GetPath (path, sizeof(path));
char mode[16] = { 'w', '\0' };
if (m_options.m_append_to_outfile)
mode[0] = 'a';
if (outfile_stream.GetFile ().Open (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
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())
{
if (m_options.m_output_as_binary)
if (m_memory_options.m_output_as_binary)
{
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,
m_options.m_append_to_outfile ? "appended" : "written",
append ? "appended" : "written",
path);
return true;
}
@ -378,7 +717,7 @@ public:
}
else
{
result.AppendErrorWithFormat("Failed to open file '%s' with a mode of '%s'.\n", path, mode);
result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
result.SetStatus(eReturnStatusFailed);
return false;
}
@ -388,10 +727,66 @@ public:
output_stream = &result.GetOutputStream();
}
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)
{
uint32_t ptr_depth = 0;
uint32_t curr_depth = 0;
uint32_t max_depth = UINT32_MAX;
bool show_types = false;
bool show_location = false;
bool use_objc = false;
bool use_dynamic = false;
bool scope_already_checked = false;
bool flat_output = false;
ValueObject::DumpValueObject (*output_stream,
valobj_sp.get(),
NULL,
ptr_depth,
curr_depth,
max_depth,
show_types,
show_location,
use_objc,
use_dynamic,
scope_already_checked,
flat_output);
}
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,
exe_ctx.target->GetArchitecture().GetByteOrder(),
exe_ctx.target->GetArchitecture().GetAddressByteSize());
assert (output_stream);
data.Dump (output_stream,
0,
m_options.m_format,
m_format_options.GetFormat(),
item_byte_size,
item_count,
num_per_line,
@ -403,27 +798,33 @@ public:
}
protected:
CommandOptions m_options;
// CommandOptions m_options;
OptionGroupOptions m_option_group;
OptionGroupFormat m_format_options;
OptionGroupReadMemory m_memory_options;
OptionGroupOutputFile m_outfile_options;
};
#define SET1 LLDB_OPT_SET_1
#define SET2 LLDB_OPT_SET_2
OptionDefinition
CommandObjectMemoryRead::CommandOptions::g_option_table[] =
{
{ SET1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format that will be used to display the memory. Defaults to bytes with ASCII (--format=Y)."},
{ SET1 , false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes to use when displaying with the selected format."},
{ SET1 , false, "num-per-line", 'l', required_argument, NULL, 0, eArgTypeNumberPerLine,"The number of items per line to display."},
{ SET1 | SET2, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "The number of total items to display."},
{ SET1 | SET2, false, "outfile", 'o', required_argument, NULL, 0, eArgTypeFilename, "Dump memory read results into a file."},
{ SET1 | SET2, false, "append", 'a', no_argument, NULL, 0, eArgTypeNone, "Append memory read results to 'outfile'."},
{ SET2, 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."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
#undef SET1
#undef SET2
//OptionDefinition
//CommandObjectMemoryRead::CommandOptions::g_option_table[] =
//{
//{ LLDB_OPT_SET_1, false, "format" ,'f', required_argument, NULL, 0, eArgTypeFormat ,"The format that will be used to display the memory. Defaults to bytes with ASCII (--format=Y)."},
//{ LLDB_OPT_SET_1, false, "size" ,'s', required_argument, NULL, 0, eArgTypeByteSize ,"The size in bytes to use when displaying with the selected format."},
//{ 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_1|
// LLDB_OPT_SET_2|
// LLDB_OPT_SET_3, false, "count" ,'c', required_argument, NULL, 0, eArgTypeCount ,"The number of total items to display."},
//{ LLDB_OPT_SET_1|
// LLDB_OPT_SET_2|
// LLDB_OPT_SET_3, false, "outfile" ,'o', required_argument, NULL, 0, eArgTypeFilename ,"Dump memory read results into a file."},
//{ LLDB_OPT_SET_1|
// LLDB_OPT_SET_2|
// LLDB_OPT_SET_3, false, "append" ,'a', no_argument , NULL, 0, eArgTypeNone ,"Append memory read results to 'outfile'."},
//{ 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."},
//{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL }
//};
//----------------------------------------------------------------------
// Write memory to the inferior process

View File

@ -569,7 +569,7 @@ Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type dat
break;
}
option_value_sp->GetAsArrayValue()->InsertValue (idx, data_value_sp);
option_value_sp->GetAsArray()->InsertValue (idx, data_value_sp);
++idx;
}
}
@ -687,7 +687,7 @@ Instruction::ReadDictionary (FILE *in_file, Stream *out_stream)
data_type = OptionValue::eTypeUInt64;
}
else
option_value_sp->GetAsDictionaryValue()->SetValueForKey (const_key, value_sp, false);
option_value_sp->GetAsDictionary()->SetValueForKey (const_key, value_sp, false);
}
}
@ -740,7 +740,7 @@ Instruction::TestEmulation (Stream *out_stream, const char *file_name)
fclose (test_file);
OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionaryValue();
OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionary();
static ConstString description_key ("assembly_string");
static ConstString triple_key ("triple");

View File

@ -40,6 +40,50 @@ lldb_private::StateAsCString (StateType state)
return unknown_state_string;
}
const char *
lldb_private::GetFormatAsCString (lldb::Format format)
{
switch (format)
{
case eFormatDefault: return "default";
case eFormatBoolean: return "boolean";
case eFormatBinary: return "binary";
case eFormatBytes: return "bytes";
case eFormatBytesWithASCII: return "bytes with ASCII";
case eFormatChar: return "character";
case eFormatCharPrintable: return "printable character";
case eFormatComplexFloat: return "complet float";
case eFormatCString: return "c-string";
case eFormatDecimal: return "signed decimal";
case eFormatEnum: return "enumeration";
case eFormatHex: return "hex";
case eFormatFloat: return "float";
case eFormatOctal: return "octal";
case eFormatOSType: return "OSType";
case eFormatUnicode16: return "Unicode16";
case eFormatUnicode32: return "Unicode32";
case eFormatUnsigned: return "unsigned decimal";
case eFormatPointer: return "pointer";
case eFormatVectorOfChar: return "vector of characters";
case eFormatVectorOfSInt8: return "vector of int8_t";
case eFormatVectorOfUInt8: return "vector of uint8_t";
case eFormatVectorOfSInt16: return "vector of int16_t";
case eFormatVectorOfUInt16: return "vector of uint16_t";
case eFormatVectorOfSInt32: return "vector of int32_t";
case eFormatVectorOfUInt32: return "vector of uint32_t";
case eFormatVectorOfSInt64: return "vector of int64_t";
case eFormatVectorOfUInt64: return "vector of uint64_t";
case eFormatVectorOfFloat32:return "vector of float32";
case eFormatVectorOfFloat64:return "vector of float64";
case eFormatVectorOfUInt128:return "vector of uint128_t";
case eFormatComplexInteger: return "complex integer";
default: break;
}
static char unknown_format_string[64];
snprintf(unknown_format_string, sizeof (unknown_format_string), "Format = %u", format);
return unknown_format_string;
}
bool
lldb_private::StateIsRunningState (StateType state)
{

View File

@ -42,13 +42,23 @@ ValueObjectMemory::Create (ExecutionContextScope *exe_scope,
return (new ValueObjectMemory (exe_scope, name, address, type_sp))->GetSP();
}
ValueObjectSP
ValueObjectMemory::Create (ExecutionContextScope *exe_scope,
const char *name,
const Address &address,
const ClangASTType &ast_type)
{
return (new ValueObjectMemory (exe_scope, name, address, ast_type))->GetSP();
}
ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope,
const char *name,
const Address &address,
lldb::TypeSP &type_sp) :
ValueObject(exe_scope),
m_address (address),
m_type_sp(type_sp)
m_type_sp(type_sp),
m_clang_type()
{
// Do not attempt to construct one of these objects with no variable!
assert (m_type_sp.get() != NULL);
@ -76,6 +86,43 @@ ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope,
}
}
ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope,
const char *name,
const Address &address,
const ClangASTType &ast_type) :
ValueObject(exe_scope),
m_address (address),
m_type_sp(),
m_clang_type(ast_type)
{
// Do not attempt to construct one of these objects with no variable!
assert (m_clang_type.GetASTContext());
assert (m_clang_type.GetOpaqueQualType());
SetName (name);
m_value.SetContext(Value::eContextTypeClangType, m_clang_type.GetOpaqueQualType());
lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTarget());
if (load_address != LLDB_INVALID_ADDRESS)
{
m_value.SetValueType(Value::eValueTypeLoadAddress);
m_value.GetScalar() = load_address;
}
else
{
lldb::addr_t file_address = m_address.GetFileAddress();
if (file_address != LLDB_INVALID_ADDRESS)
{
m_value.SetValueType(Value::eValueTypeFileAddress);
m_value.GetScalar() = file_address;
}
else
{
m_value.GetScalar() = m_address.GetOffset();
m_value.SetValueType (Value::eValueTypeScalar);
}
}
}
ValueObjectMemory::~ValueObjectMemory()
{
}
@ -83,31 +130,48 @@ ValueObjectMemory::~ValueObjectMemory()
lldb::clang_type_t
ValueObjectMemory::GetClangType ()
{
return m_type_sp->GetClangForwardType();
if (m_type_sp)
return m_type_sp->GetClangForwardType();
return m_clang_type.GetOpaqueQualType();
}
ConstString
ValueObjectMemory::GetTypeName()
{
return m_type_sp->GetName();
if (m_type_sp)
return m_type_sp->GetName();
ConstString name;
std::string type_name (ClangASTContext::GetTypeName (m_clang_type.GetOpaqueQualType()));
if (!type_name.empty())
name.SetCString (type_name.c_str());
return name;
}
uint32_t
ValueObjectMemory::CalculateNumChildren()
{
return m_type_sp->GetNumChildren(true);
if (m_type_sp)
return m_type_sp->GetNumChildren(true);
const bool omit_empty_base_classes = true;
return ClangASTContext::GetNumChildren (m_clang_type.GetASTContext(),
m_clang_type.GetOpaqueQualType(),
omit_empty_base_classes);
}
clang::ASTContext *
ValueObjectMemory::GetClangAST ()
{
return m_type_sp->GetClangAST();
if (m_type_sp)
return m_type_sp->GetClangAST();
return m_clang_type.GetASTContext();
}
size_t
ValueObjectMemory::GetByteSize()
{
return m_type_sp->GetByteSize();
if (m_type_sp)
return m_type_sp->GetByteSize();
return (m_clang_type.GetClangTypeBitWidth () + 7) / 8;
}
lldb::ValueType
@ -182,7 +246,11 @@ ValueObjectMemory::UpdateValue ()
// Copy the Value and set the context to use our Variable
// so it can extract read its value into m_data appropriately
Value value(m_value);
value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
if (m_type_sp)
value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
else
value.SetContext(Value::eContextTypeClangType, m_clang_type.GetOpaqueQualType());
m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0);
}
break;

View File

@ -13,6 +13,7 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
#include "lldb/Interpreter/Args.h"
@ -47,7 +48,7 @@ OptionValue::GetUInt64Value (uint64_t fail_value, bool *success_ptr)
OptionValueBoolean *
OptionValue::GetAsBooleanValue ()
OptionValue::GetAsBoolean ()
{
if (GetType () == OptionValue::eTypeBoolean)
return static_cast<OptionValueBoolean *>(this);
@ -55,7 +56,7 @@ OptionValue::GetAsBooleanValue ()
}
OptionValueSInt64 *
OptionValue::GetAsSInt64Value ()
OptionValue::GetAsSInt64 ()
{
if (GetType () == OptionValue::eTypeSInt64)
return static_cast<OptionValueSInt64 *>(this);
@ -63,7 +64,7 @@ OptionValue::GetAsSInt64Value ()
}
OptionValueUInt64 *
OptionValue::GetAsUInt64Value ()
OptionValue::GetAsUInt64 ()
{
if (GetType () == OptionValue::eTypeUInt64)
return static_cast<OptionValueUInt64 *>(this);
@ -71,7 +72,7 @@ OptionValue::GetAsUInt64Value ()
}
OptionValueString *
OptionValue::GetAsStringValue ()
OptionValue::GetAsString ()
{
if (GetType () == OptionValue::eTypeString)
return static_cast<OptionValueString *>(this);
@ -79,15 +80,24 @@ OptionValue::GetAsStringValue ()
}
OptionValueFileSpec *
OptionValue::GetAsFileSpecValue ()
OptionValue::GetAsFileSpec ()
{
if (GetType () == OptionValue::eTypeFileSpec)
return static_cast<OptionValueFileSpec *>(this);
return NULL;
}
OptionValueFormat *
OptionValue::GetAsFormat ()
{
if (GetType () == OptionValue::eTypeFormat)
return static_cast<OptionValueFormat *>(this);
return NULL;
}
OptionValueArray *
OptionValue::GetAsArrayValue ()
OptionValue::GetAsArray ()
{
if (GetType () == OptionValue::eTypeArray)
return static_cast<OptionValueArray *>(this);
@ -95,7 +105,7 @@ OptionValue::GetAsArrayValue ()
}
OptionValueDictionary *
OptionValue::GetAsDictionaryValue ()
OptionValue::GetAsDictionary ()
{
if (GetType () == OptionValue::eTypeDictionary)
return static_cast<OptionValueDictionary *>(this);
@ -103,19 +113,30 @@ OptionValue::GetAsDictionaryValue ()
}
const char *
OptionValue::GetStringValue ()
OptionValue::GetStringValue (const char *fail_value)
{
if (GetType () == OptionValue::eTypeString)
return static_cast<OptionValueString *>(this)->GetCurrentValue();
return NULL;
OptionValueString *option_value = GetAsString ();
if (option_value)
return option_value->GetCurrentValue();
return fail_value;
}
uint64_t
OptionValue::GetUInt64Value ()
OptionValue::GetUInt64Value (uint64_t fail_value)
{
if (GetType () == OptionValue::eTypeUInt64)
return static_cast<OptionValueUInt64 *>(this)->GetCurrentValue();
return 0;
OptionValueUInt64 *option_value = GetAsUInt64 ();
if (option_value)
return option_value->GetCurrentValue();
return fail_value;
}
lldb::Format
OptionValue::GetFormatValue (lldb::Format fail_value)
{
OptionValueFormat *option_value = GetAsFormat ();
if (option_value)
return option_value->GetCurrentValue();
return fail_value;
}
//-------------------------------------------------------------------------
@ -250,8 +271,6 @@ OptionValueString::SetValueFromCString (const char *value_cstr)
return Error ();
}
//-------------------------------------------------------------------------
// OptionValueFileSpec
//-------------------------------------------------------------------------
@ -286,6 +305,29 @@ OptionValueFileSpec::SetValueFromCString (const char *value_cstr)
}
//-------------------------------------------------------------------------
// OptionValueFormat
//-------------------------------------------------------------------------
void
OptionValueFormat::DumpValue (Stream &strm)
{
strm.PutCString (GetFormatAsCString (m_current_value));
}
Error
OptionValueFormat::SetValueFromCString (const char *value_cstr)
{
Format new_format;
Error error (Args::StringToFormat(value_cstr, new_format));
if (error.Success())
{
m_value_was_set = true;
m_current_value = new_format;
}
return error;
}
//-------------------------------------------------------------------------
// OptionValueArray
//-------------------------------------------------------------------------

View File

@ -26,11 +26,13 @@ OptionGroupArchitecture::~OptionGroupArchitecture ()
{
}
OptionDefinition g_file_option_table[] =
static OptionDefinition
g_option_table[] =
{
{ LLDB_OPT_SET_1 , false, "arch" , 'a', required_argument, NULL, 0, eArgTypeArchitecture , "Specify the architecture for the target."},
{ LLDB_OPT_SET_1 , false, "arch" , 'a', required_argument, NULL, 0, eArgTypeArchitecture , "Specify the architecture for the target."},
};
const uint32_t k_num_file_options = sizeof(g_file_option_table)/sizeof(OptionDefinition);
const uint32_t k_num_file_options = sizeof(g_option_table)/sizeof(OptionDefinition);
uint32_t
OptionGroupArchitecture::GetNumDefinitions ()
@ -41,7 +43,7 @@ OptionGroupArchitecture::GetNumDefinitions ()
const OptionDefinition *
OptionGroupArchitecture::GetDefinitions ()
{
return g_file_option_table;
return g_option_table;
}
bool
@ -61,7 +63,7 @@ OptionGroupArchitecture::SetOptionValue (CommandInterpreter &interpreter,
const char *option_arg)
{
Error error;
char short_option = (char) g_file_option_table[option_idx].short_option;
char short_option = (char) g_option_table[option_idx].short_option;
switch (short_option)
{

View File

@ -0,0 +1,75 @@
//===-- OptionGroupFormat.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "OptionGroupFormat.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
using namespace lldb;
using namespace lldb_private;
OptionGroupFormat::OptionGroupFormat(lldb::Format default_format) :
m_format (default_format, default_format)
{
}
OptionGroupFormat::~OptionGroupFormat ()
{
}
static OptionDefinition
g_option_table[] =
{
{ LLDB_OPT_SET_1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat , "Specify a format to be used for display."},
};
const uint32_t k_num_file_options = sizeof(g_option_table)/sizeof(OptionDefinition);
uint32_t
OptionGroupFormat::GetNumDefinitions ()
{
return k_num_file_options;
}
const OptionDefinition *
OptionGroupFormat::GetDefinitions ()
{
return g_option_table;
}
Error
OptionGroupFormat::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)
{
case 'f':
error = m_format.SetValueFromCString (option_arg);
break;
default:
error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
break;
}
return error;
}
void
OptionGroupFormat::OptionParsingStarting (CommandInterpreter &interpreter)
{
m_format.Clear();
}

View File

@ -0,0 +1,82 @@
//===-- OptionGroupOutputFile.cpp -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "OptionGroupOutputFile.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
using namespace lldb;
using namespace lldb_private;
OptionGroupOutputFile::OptionGroupOutputFile() :
m_file (),
m_append (false, false)
{
}
OptionGroupOutputFile::~OptionGroupOutputFile ()
{
}
static OptionDefinition
g_option_table[] =
{
{ LLDB_OPT_SET_1 , false, "outfile", 'o', required_argument, NULL, 0, eArgTypePath , "Specify a path for capturing command output."},
{ LLDB_OPT_SET_1 , false, "append-outfile" , 'A', no_argument, NULL, 0, eArgTypeNone , "Append to the the file specified with '--outfile <path>'."},
};
const uint32_t k_num_file_options = sizeof(g_option_table)/sizeof(OptionDefinition);
uint32_t
OptionGroupOutputFile::GetNumDefinitions ()
{
return k_num_file_options;
}
const OptionDefinition *
OptionGroupOutputFile::GetDefinitions ()
{
return g_option_table;
}
Error
OptionGroupOutputFile::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)
{
case 'o':
error = m_file.SetValueFromCString (option_arg);
break;
case 'A':
m_append.SetCurrentValue(true);
break;
default:
error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
break;
}
return error;
}
void
OptionGroupOutputFile::OptionParsingStarting (CommandInterpreter &interpreter)
{
m_file.Clear();
m_append.Clear();
}

View File

@ -0,0 +1,106 @@
//===-- OptionGroupValueObjectDisplay.cpp -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "OptionGroupValueObjectDisplay.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
using namespace lldb;
using namespace lldb_private;
OptionGroupValueObjectDisplay::OptionGroupValueObjectDisplay()
{
}
OptionGroupValueObjectDisplay::~OptionGroupValueObjectDisplay ()
{
}
OptionDefinition
g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "depth", 'd', required_argument, NULL, 0, eArgTypeCount, "Set the max recurse depth when dumping aggregate types (default is infinity)."},
{ LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, eArgTypeExprFormat,"Specify the format that the variable output should use."},
{ LLDB_OPT_SET_1, false, "flat", 'F', no_argument, NULL, 0, eArgTypeNone, "Display results in a flat format that uses expression paths for each variable or member."},
{ LLDB_OPT_SET_1, false, "location", 'L', no_argument, NULL, 0, eArgTypeNone, "Show variable location information."},
{ LLDB_OPT_SET_1, false, "objc", 'o', no_argument, NULL, 0, eArgTypeNone, "Print as an Objective-C object."},
{ LLDB_OPT_SET_1, false, "ptr-depth", 'p', required_argument, NULL, 0, eArgTypeCount, "The number of pointers to be traversed when dumping values (default is zero)."},
{ LLDB_OPT_SET_1, false, "show-types", 't', no_argument, NULL, 0, eArgTypeNone, "Show variable types when dumping values."},
{ LLDB_OPT_SET_1, false, "no-summary", 'y', no_argument, NULL, 0, eArgTypeNone, "Omit summary information."},
{ 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
};
const uint32_t k_num_file_options = sizeof(g_option_table)/sizeof(OptionDefinition);
uint32_t
OptionGroupValueObjectDisplay::GetNumDefinitions ()
{
return k_num_file_options;
}
const OptionDefinition *
OptionGroupValueObjectDisplay::GetDefinitions ()
{
return g_option_table;
}
Error
OptionGroupValueObjectDisplay::SetOptionValue (CommandInterpreter &interpreter,
uint32_t option_idx,
const char *option_arg)
{
Error error;
char short_option = (char) g_option_table[option_idx].short_option;
bool success = false;
switch (short_option)
{
case 't': show_types = true; break;
case 'y': show_summary = false; break;
case 'L': show_location= true; break;
case 'F': flat_output = true; break;
case 'f': error = Args::StringToFormat(option_arg, format); break;
case 'o': use_objc = true; break;
case 'd':
max_depth = Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success);
if (!success)
error.SetErrorStringWithFormat("Invalid max depth '%s'.\n", option_arg);
break;
case 'p':
ptr_depth = Args::StringToUInt32 (option_arg, 0, 0, &success);
if (!success)
error.SetErrorStringWithFormat("Invalid pointer depth '%s'.\n", option_arg);
break;
default:
error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
break;
}
return error;
}
void
OptionGroupValueObjectDisplay::OptionParsingStarting (CommandInterpreter &interpreter)
{
show_types = false;
show_summary = true;
show_location = false;
flat_output = false;
use_objc = false;
max_depth = UINT32_MAX;
ptr_depth = 0;
format = eFormatDefault;
}

View File

@ -906,6 +906,18 @@ Options::HandleOptionArgumentCompletion
}
void
OptionGroupOptions::Append (OptionGroup* group)
{
const OptionDefinition* group_option_defs = group->GetDefinitions ();
const uint32_t group_option_count = group->GetNumDefinitions();
for (uint32_t i=0; i<group_option_count; ++i)
{
m_option_infos.push_back (OptionInfo (group, i));
m_option_defs.push_back (group_option_defs[i]);
}
}
void
OptionGroupOptions::Append (OptionGroup* group,
uint32_t src_mask,

View File

@ -13348,7 +13348,7 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, Option
return false;
}
OptionValueDictionary *state_dictionary = value_sp->GetAsDictionaryValue ();
OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary ();
if (!before_state.LoadStateFromDictionary (state_dictionary))
{
out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
@ -13362,7 +13362,7 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, Option
return false;
}
state_dictionary = value_sp->GetAsDictionaryValue ();
state_dictionary = value_sp->GetAsDictionary ();
if (!after_state.LoadStateFromDictionary (state_dictionary))
{
out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");

View File

@ -341,7 +341,7 @@ EmulationStateARM::LoadStateFromDictionary (OptionValueDictionary *test_data)
static ConstString data_key ("data");
uint64_t start_address = 0;
OptionValueDictionary *mem_dict = value_sp->GetAsDictionaryValue();
OptionValueDictionary *mem_dict = value_sp->GetAsDictionary();
value_sp = mem_dict->GetValueForKey (address_key);
if (value_sp.get() == NULL)
return false;
@ -349,7 +349,7 @@ EmulationStateARM::LoadStateFromDictionary (OptionValueDictionary *test_data)
start_address = value_sp->GetUInt64Value ();
value_sp = mem_dict->GetValueForKey (data_key);
OptionValueArray *mem_array = value_sp->GetAsArrayValue();
OptionValueArray *mem_array = value_sp->GetAsArray();
if (!mem_array)
return false;
@ -374,7 +374,7 @@ EmulationStateARM::LoadStateFromDictionary (OptionValueDictionary *test_data)
// Load General Registers
OptionValueDictionary *reg_dict = value_sp->GetAsDictionaryValue ();
OptionValueDictionary *reg_dict = value_sp->GetAsDictionary ();
StreamString sstr;
for (int i = 0; i < 16; ++i)