Did some work on the "register read" command to only show the first register

set by default when dumping registers. If you want to see all of the register
sets you can use the "--all" option:

(lldb) register read --all

If you want to just see some register sets, you can currently specify them
by index:

(lldb) register read --set 0 --set 2

We need to get shorter register set names soon so we can specify the register
sets by name without having to type too much. I will make this change soon.

You can also have any integer encoded registers resolve the address values
back to any code or data from the object files using the "--lookup" option.
Below is sample output when stopped in the libc function "puts" with some
const strings in registers:

Process 8973 stopped
* thread #1: tid = 0x2c03, 0x00007fff828fa30f libSystem.B.dylib`puts + 1, stop reason = instruction step into
  frame #0: 0x00007fff828fa30f libSystem.B.dylib`puts + 1
(lldb) register read --lookup 
General Purpose Registers:
  rax          = 0x0000000100000e98  "----------------------------------------------------------------------"
  rbx          = 0x0000000000000000
  rcx          = 0x0000000000000001  
  rdx          = 0x0000000000000000
  rdi          = 0x0000000100000e98  "----------------------------------------------------------------------"
  rsi          = 0x0000000100800000
  rbp          = 0x00007fff5fbff710
  rsp          = 0x00007fff5fbff280
  r8           = 0x0000000000000040  
  r9           = 0x0000000000000000
  r10          = 0x0000000000000000
  r11          = 0x0000000000000246  
  r12          = 0x0000000000000000
  r13          = 0x0000000000000000
  r14          = 0x0000000000000000
  r15          = 0x0000000000000000
  rip          = 0x00007fff828fa30f  libSystem.B.dylib`puts + 1
  rflags       = 0x0000000000000246  
  cs           = 0x0000000000000027  
  fs           = 0x0000000000000000
  gs           = 0x0000000000000000

As we can see, we see two constant strings and the PC (register "rip") is 
showing the code it resolves to.

I fixed the register "--format" option to work as expected.

Added a setting to disable skipping the function prologue when setting 
breakpoints as a target settings variable:

(lldb) settings set target.skip-prologue false

Updated the user settings controller boolean value handler funciton to be able
to take the default value so it can correctly respond to the eVarSetOperationClear
operation.

Did some usability work on the OptionValue classes.

Fixed the "image lookup" command to correctly respond to the "--verbose" 
option and display the detailed symbol context information when looking up
line table entries and functions by name. This previously was only working
for address lookups.

llvm-svn: 129977
This commit is contained in:
Greg Clayton 2011-04-22 03:55:06 +00:00
parent bafb9347dd
commit 385aa28cf6
13 changed files with 487 additions and 181 deletions

View File

@ -208,6 +208,7 @@ public:
UpdateBooleanVariable (VarSetOperationType op,
bool &bool_var,
const char *new_value,
bool clear_value, // Used for op == eVarSetOperationClear
Error &err);
static void

View File

@ -60,11 +60,11 @@ namespace lldb_private {
virtual void
DumpValue (Stream &strm) = 0;
virtual bool
virtual Error
SetValueFromCString (const char *value) = 0;
virtual bool
ResetValueToDefault () = 0;
Clear () = 0;
//-----------------------------------------------------------------
// Subclasses should NOT override these functions as they use the
@ -76,6 +76,18 @@ namespace lldb_private {
return 1u << GetType();
}
static uint32_t
ConvertTypeToMask (OptionValue::Type type)
{
return 1u << type;
}
// Get this value as a uint64_t value if it is encoded as a boolean,
// uint64_t or int64_t. Other types will cause "fail_value" to be
// returned
uint64_t
GetUInt64Value (uint64_t fail_value, bool *success_ptr);
OptionValueBoolean *
GetAsBooleanValue ();
@ -89,13 +101,21 @@ namespace lldb_private {
GetAsStringValue ();
OptionValueFileSpec *
GetAsFileSpecValue() ;
GetAsFileSpecValue();
OptionValueArray *
GetAsArrayValue() ;
GetAsArrayValue();
OptionValueDictionary *
GetAsDictionaryValue() ;
GetAsDictionaryValue();
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
// handy to know if an option value was set from
// the command line or as a setting, versus if we
// just have the default value that was already
// populated in the option value.
};
@ -131,13 +151,14 @@ namespace lldb_private {
virtual void
DumpValue (Stream &strm);
virtual bool
virtual Error
SetValueFromCString (const char *value);
virtual bool
ResetValueToDefault ()
Clear ()
{
m_current_value = m_default_value;
m_value_was_set = false;
return true;
}
@ -145,6 +166,26 @@ namespace lldb_private {
// Subclass specific functions
//---------------------------------------------------------------------
//------------------------------------------------------------------
/// Convert to bool operator.
///
/// This allows code to check a OptionValueBoolean in conditions.
///
/// @code
/// OptionValueBoolean bool_value(...);
/// if (bool_value)
/// { ...
/// @endcode
///
/// @return
/// /b True this object contains a valid namespace decl, \b
/// false otherwise.
//------------------------------------------------------------------
operator bool() const
{
return m_current_value;
}
bool
GetCurrentValue() const
{
@ -180,10 +221,16 @@ namespace lldb_private {
class OptionValueSInt64 : public OptionValue
{
public:
OptionValueSInt64 () :
m_current_value (0),
m_default_value (0)
{
}
OptionValueSInt64 (int64_t current_value,
int64_t default_value) :
m_current_value (current_value),
m_default_value (default_value)
m_current_value (current_value),
m_default_value (default_value)
{
}
@ -205,13 +252,14 @@ namespace lldb_private {
virtual void
DumpValue (Stream &strm);
virtual bool
virtual Error
SetValueFromCString (const char *value);
virtual bool
ResetValueToDefault ()
Clear ()
{
m_current_value = m_default_value;
m_value_was_set = false;
return true;
}
@ -254,10 +302,16 @@ namespace lldb_private {
class OptionValueUInt64 : public OptionValue
{
public:
OptionValueUInt64 () :
m_current_value (0),
m_default_value (0)
{
}
OptionValueUInt64 (uint64_t current_value,
uint64_t default_value) :
m_current_value (current_value),
m_default_value (default_value)
m_current_value (current_value),
m_default_value (default_value)
{
}
@ -266,6 +320,14 @@ namespace lldb_private {
{
}
//---------------------------------------------------------------------
// Decode a uint64_t from "value_cstr" return a OptionValueUInt64 object
// inside of a lldb::OptionValueSP object if all goes well. If the
// string isn't a uint64_t value or any other error occurs, return an
// empty lldb::OptionValueSP and fill error in with the correct stuff.
//---------------------------------------------------------------------
static lldb::OptionValueSP
Create (const char *value_cstr, Error &error);
//---------------------------------------------------------------------
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
@ -279,13 +341,14 @@ namespace lldb_private {
virtual void
DumpValue (Stream &strm);
virtual bool
virtual Error
SetValueFromCString (const char *value);
virtual bool
ResetValueToDefault ()
Clear ()
{
m_current_value = m_default_value;
m_value_was_set = false;
return true;
}
@ -363,13 +426,14 @@ namespace lldb_private {
virtual void
DumpValue (Stream &strm);
virtual bool
virtual Error
SetValueFromCString (const char *value);
virtual bool
ResetValueToDefault ()
Clear ()
{
m_current_value = m_default_value;
m_value_was_set = false;
return true;
}
@ -455,13 +519,14 @@ namespace lldb_private {
virtual void
DumpValue (Stream &strm);
virtual bool
virtual Error
SetValueFromCString (const char *value);
virtual bool
ResetValueToDefault ()
Clear ()
{
m_current_value = m_default_value;
m_value_was_set = false;
return true;
}
@ -528,13 +593,14 @@ namespace lldb_private {
virtual void
DumpValue (Stream &strm);
virtual bool
virtual Error
SetValueFromCString (const char *value);
virtual bool
ResetValueToDefault ()
Clear ()
{
m_values.clear();
m_value_was_set = false;
return true;
}
@ -543,7 +609,7 @@ namespace lldb_private {
//---------------------------------------------------------------------
uint32_t
GetNumValues() const
GetSize () const
{
return m_values.size();
}
@ -557,6 +623,11 @@ namespace lldb_private {
return value_sp;
}
uint64_t
GetUInt64ValueAtIndex (uint32_t idx,
uint64_t fail_value,
bool *success_ptr) const;
bool
AppendValue (const lldb::OptionValueSP &value_sp)
{
@ -652,13 +723,14 @@ namespace lldb_private {
virtual void
DumpValue (Stream &strm);
virtual bool
virtual Error
SetValueFromCString (const char *value);
virtual bool
ResetValueToDefault ()
Clear ()
{
m_values.clear();
m_value_was_set = false;
return true;
}

View File

@ -71,7 +71,13 @@ public:
{
return m_prefer_dynamic_value;
}
bool
GetSkipPrologue()
{
return m_skip_prologue;
}
protected:
void
@ -84,6 +90,7 @@ protected:
std::string m_expr_prefix_path;
std::string m_expr_prefix_contents;
bool m_prefer_dynamic_value;
bool m_skip_prologue;
};

View File

@ -83,7 +83,7 @@ our @archive_files = (
"$llvm_configuration/lib/libLLVMX86Utils.a",
);
if (-e "$llvm_srcroot/lib")
if ($ENV{CONFIGURATION} ne "BuildAndIntegration" and -e "$llvm_srcroot/lib")
{
print "Using standard LLVM build directory...\n";
# LLVM in the "lldb" root is a symlink which indicates we are using a

View File

@ -16,7 +16,7 @@
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
#include "lldb/lldb-private-log.h"
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
@ -146,6 +146,11 @@ BreakpointResolverName::SearchCallback
Address break_addr;
assert (m_breakpoint != NULL);
if (context.target_sp)
{
skip_prologue = context.target_sp->GetSkipPrologue();
}
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
if (m_class_name)

View File

@ -324,7 +324,7 @@ LookupSymbolInModule (CommandInterpreter &interpreter, Stream &strm, Module *mod
static void
DumpSymbolContextList (CommandInterpreter &interpreter, Stream &strm, SymbolContextList &sc_list, bool prepend_addr)
DumpSymbolContextList (CommandInterpreter &interpreter, Stream &strm, SymbolContextList &sc_list, bool prepend_addr, bool verbose)
{
strm.IndentMore ();
uint32_t i;
@ -336,31 +336,50 @@ DumpSymbolContextList (CommandInterpreter &interpreter, Stream &strm, SymbolCont
if (sc_list.GetContextAtIndex(i, sc))
{
strm.Indent();
ExecutionContextScope *exe_scope = interpreter.GetExecutionContext().GetBestExecutionContextScope ();
if (prepend_addr)
{
if (sc.line_entry.range.GetBaseAddress().IsValid())
{
lldb::addr_t vm_addr = sc.line_entry.range.GetBaseAddress().GetLoadAddress(interpreter.GetExecutionContext().target);
int addr_size = sizeof (addr_t);
Process *process = interpreter.GetExecutionContext().process;
if (process)
addr_size = process->GetTarget().GetArchitecture().GetAddressByteSize();
if (vm_addr != LLDB_INVALID_ADDRESS)
strm.Address (vm_addr, addr_size);
else
sc.line_entry.range.GetBaseAddress().Dump (&strm, NULL, Address::DumpStyleSectionNameOffset);
sc.line_entry.range.GetBaseAddress().Dump (&strm,
exe_scope,
Address::DumpStyleLoadAddress,
Address::DumpStyleModuleWithFileAddress);
strm.PutCString(" in ");
}
}
sc.DumpStopContext(&strm, interpreter.GetExecutionContext().process, sc.line_entry.range.GetBaseAddress(), true, true, false);
sc.DumpStopContext(&strm,
exe_scope,
sc.line_entry.range.GetBaseAddress(),
true,
true,
false);
strm.EOL();
if (verbose)
{
if (sc.line_entry.range.GetBaseAddress().IsValid())
{
if (sc.line_entry.range.GetBaseAddress().Dump (&strm,
exe_scope,
Address::DumpStyleDetailedSymbolContext))
strm.PutCString("\n\n");
}
else if (sc.function->GetAddressRange().GetBaseAddress().IsValid())
{
if (sc.function->GetAddressRange().GetBaseAddress().Dump (&strm,
exe_scope,
Address::DumpStyleDetailedSymbolContext))
strm.PutCString("\n\n");
}
}
}
}
strm.IndentLess ();
}
static uint32_t
LookupFunctionInModule (CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name, bool name_is_regex)
LookupFunctionInModule (CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name, bool name_is_regex, bool verbose)
{
if (module && name && name[0])
{
@ -392,7 +411,7 @@ LookupFunctionInModule (CommandInterpreter &interpreter, Stream &strm, Module *m
strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : "");
DumpFullpath (strm, &module->GetFileSpec(), 0);
strm.PutCString(":\n");
DumpSymbolContextList (interpreter, strm, sc_list, true);
DumpSymbolContextList (interpreter, strm, sc_list, true, verbose);
}
return num_matches;
}
@ -457,7 +476,13 @@ LookupTypeInModule
}
static uint32_t
LookupFileAndLineInModule (CommandInterpreter &interpreter, Stream &strm, Module *module, const FileSpec &file_spec, uint32_t line, bool check_inlines)
LookupFileAndLineInModule (CommandInterpreter &interpreter,
Stream &strm,
Module *module,
const FileSpec &file_spec,
uint32_t line,
bool check_inlines,
bool verbose)
{
if (module && file_spec)
{
@ -474,7 +499,7 @@ LookupFileAndLineInModule (CommandInterpreter &interpreter, Stream &strm, Module
strm << " in ";
DumpFullpath (strm, &module->GetFileSpec(), 0);
strm.PutCString(":\n");
DumpSymbolContextList (interpreter, strm, sc_list, true);
DumpSymbolContextList (interpreter, strm, sc_list, true, verbose);
return num_matches;
}
}
@ -1550,7 +1575,8 @@ public:
module,
m_options.m_file,
m_options.m_line_number,
m_options.m_check_inlines))
m_options.m_check_inlines,
m_options.m_verbose))
{
result.SetStatus(eReturnStatusSuccessFinishResult);
return true;
@ -1565,7 +1591,8 @@ public:
result.GetOutputStream(),
module,
m_options.m_str.c_str(),
m_options.m_use_regex))
m_options.m_use_regex,
m_options.m_verbose))
{
result.SetStatus(eReturnStatusSuccessFinishResult);
return true;

View File

@ -19,6 +19,7 @@
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/NamedOptionValue.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/RegisterContext.h"
@ -66,6 +67,85 @@ public:
return &m_options;
}
bool
DumpRegister (const ExecutionContext &exe_ctx,
Stream &strm,
RegisterContext *reg_ctx,
const RegisterInfo *reg_info)
{
if (reg_info)
{
uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
DataExtractor reg_data;
if (reg_ctx->ReadRegisterBytes(reg, reg_data))
{
strm.Indent ();
strm.Printf ("%-12s = ", reg_info ? reg_info->name : "<INVALID REGINFO>");
Format format;
if (m_options.format == eFormatDefault)
format = reg_info->format;
else
format = m_options.format;
reg_data.Dump(&strm, 0, format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
if (m_options.lookup_addresses && ((reg_info->encoding == eEncodingUint) || (reg_info->encoding == eEncodingSint)))
{
addr_t reg_addr = reg_ctx->ReadRegisterAsUnsigned (reg, 0);
if (reg_addr)
{
Address so_reg_addr;
if (exe_ctx.target->GetSectionLoadList().ResolveLoadAddress(reg_addr, so_reg_addr))
{
strm.PutCString (" ");
so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription);
}
else
{
}
}
}
strm.EOL();
return true;
}
}
return false;
}
bool
DumpRegisterSet (const ExecutionContext &exe_ctx,
Stream &strm,
RegisterContext *reg_ctx,
uint32_t set_idx)
{
uint32_t unavailable_count = 0;
uint32_t available_count = 0;
const RegisterSet * const reg_set = reg_ctx->GetRegisterSet(set_idx);
if (reg_set)
{
strm.Printf ("%s:\n", reg_set->name);
strm.IndentMore ();
const uint32_t num_registers = reg_set->num_registers;
for (uint32_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
{
const uint32_t reg = reg_set->registers[reg_idx];
if (DumpRegister (exe_ctx, strm, reg_ctx, reg_ctx->GetRegisterInfoAtIndex(reg)))
++available_count;
else
++unavailable_count;
}
strm.IndentLess ();
if (unavailable_count)
{
strm.Indent ();
strm.Printf("%u registers were unavailable.\n", unavailable_count);
}
strm.EOL();
}
return available_count > 0;
}
virtual bool
Execute
(
@ -73,73 +153,80 @@ public:
CommandReturnObject &result
)
{
Stream &output_stream = result.GetOutputStream();
DataExtractor reg_data;
Stream &strm = result.GetOutputStream();
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
RegisterContext *reg_context = exe_ctx.GetRegisterContext ();
RegisterContext *reg_ctx = exe_ctx.GetRegisterContext ();
if (reg_context)
if (reg_ctx)
{
const RegisterInfo *reg_info = NULL;
if (command.GetArgumentCount() == 0)
{
uint32_t set_idx;
const uint32_t num_register_sets = reg_context->GetRegisterSetCount();
for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
uint32_t num_register_sets = 1;
const uint32_t set_array_size = m_options.set_indexes.GetSize();
if (set_array_size > 0)
{
uint32_t unavailable_count = 0;
const RegisterSet * const reg_set = reg_context->GetRegisterSet(set_idx);
output_stream.Printf ("%s:\n", reg_set->name);
output_stream.IndentMore ();
const uint32_t num_registers = reg_set->num_registers;
for (uint32_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
for (uint32_t i=0; i<set_array_size; ++i)
{
uint32_t reg = reg_set->registers[reg_idx];
reg_info = reg_context->GetRegisterInfoAtIndex(reg);
if (reg_context->ReadRegisterBytes(reg, reg_data))
set_idx = m_options.set_indexes.GetUInt64ValueAtIndex (i, UINT32_MAX, NULL);
if (set_idx != UINT32_MAX)
{
output_stream.Indent ();
output_stream.Printf ("%-12s = ", reg_info ? reg_info->name : "<INVALID REGINFO>");
reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
output_stream.EOL();
if (!DumpRegisterSet (exe_ctx, strm, reg_ctx, set_idx))
{
result.AppendErrorWithFormat ("invalid register set index: %u\n", set_idx);
result.SetStatus (eReturnStatusFailed);
break;
}
}
else
{
++unavailable_count;
result.AppendError ("invalid register set index\n");
result.SetStatus (eReturnStatusFailed);
break;
}
}
if (unavailable_count)
}
else
{
if (m_options.dump_all_sets)
num_register_sets = reg_ctx->GetRegisterSetCount();
for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
{
output_stream.Indent ();
output_stream.Printf("%u registers were unavailable.\n", unavailable_count);
DumpRegisterSet (exe_ctx, strm, reg_ctx, set_idx);
}
output_stream.IndentLess ();
output_stream.EOL();
}
}
else
{
const char *arg_cstr;
for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
if (m_options.dump_all_sets)
{
reg_info = reg_context->GetRegisterInfoByName(arg_cstr);
if (reg_info)
result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n");
result.SetStatus (eReturnStatusFailed);
}
else if (m_options.set_indexes.GetSize() > 0)
{
result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n");
result.SetStatus (eReturnStatusFailed);
}
else
{
const char *arg_cstr;
for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
{
output_stream.Printf("%-12s = ", reg_info->name);
if (reg_context->ReadRegisterBytes(reg_info->kinds[eRegisterKindLLDB], reg_data))
reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr);
if (reg_info)
{
reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
if (!DumpRegister (exe_ctx, strm, reg_ctx, reg_info))
strm.Printf("%-12s = error: unavailable\n", reg_info->name);
}
else
{
output_stream.PutCString ("error: unavailable");
result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
}
output_stream.EOL();
}
else
{
result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
}
}
}
@ -157,7 +244,10 @@ protected:
{
public:
CommandOptions (CommandInterpreter &interpreter) :
Options(interpreter)
Options(interpreter),
set_indexes (OptionValue::ConvertTypeToMask (OptionValue::eTypeUInt64)),
dump_all_sets (false, false), // Initial and default values are false
lookup_addresses (false, false) // Initial and default values are false
{
OptionParsingStarting();
}
@ -175,9 +265,25 @@ protected:
switch (short_option)
{
case 'f':
error = Args::StringToFormat (option_arg, m_format);
error = Args::StringToFormat (option_arg, format);
break;
case 's':
{
OptionValueSP value_sp (OptionValueUInt64::Create (option_arg, error));
if (value_sp)
set_indexes.AppendValue (value_sp);
}
break;
case 'a':
dump_all_sets.SetCurrentValue(true);
break;
case 'l':
lookup_addresses.SetCurrentValue(true);
break;
default:
error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option);
break;
@ -188,7 +294,10 @@ protected:
void
OptionParsingStarting ()
{
m_format = eFormatBytes;
format = eFormatDefault;
set_indexes.Clear();
dump_all_sets.Clear();
lookup_addresses.Clear();
}
const OptionDefinition*
@ -202,7 +311,10 @@ protected:
static OptionDefinition g_option_table[];
// Instance variables to hold the values for command options.
lldb::Format m_format;
lldb::Format format;
OptionValueArray set_indexes;
OptionValueBoolean dump_all_sets;
OptionValueBoolean lookup_addresses;
};
CommandOptions m_options;
@ -211,13 +323,10 @@ protected:
OptionDefinition
CommandObjectRegisterRead::CommandOptions::g_option_table[] =
{
//{ LLDB_OPT_SET_ALL, false, "language", 'l', required_argument, NULL, 0, "[c|c++|objc|objc++]", "Sets the language to use when parsing the expression."},
//{ LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]", "Specify the format that the expression output should use."},
{ LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, eArgTypeExprFormat, "Specify the format that the expression output should use."},
{ LLDB_OPT_SET_2, false, "object-description", 'o', no_argument, NULL, 0, eArgTypeNone, "Print the object description of the value resulting from the expression."},
{ LLDB_OPT_SET_ALL, false, "unwind-on-error", 'u', required_argument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, breakpoint hit or signal."},
{ LLDB_OPT_SET_ALL, false, "debug", 'g', no_argument, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."},
{ LLDB_OPT_SET_ALL, false, "use-ir", 'i', no_argument, NULL, 0, eArgTypeNone, "[Temporary] Instructs the expression evaluator to use IR instead of ASTs."},
{ LLDB_OPT_SET_ALL, false, "format", 'f', required_argument, NULL, 0, eArgTypeExprFormat, "Specify the format to use when dumping register values."},
{ LLDB_OPT_SET_ALL, false, "lookup", 'l', no_argument , NULL, 0, eArgTypeNone , "Lookup the register values as addresses and show that each value maps to in the address space."},
{ LLDB_OPT_SET_1 , false, "set" , 's', required_argument, NULL, 0, eArgTypeIndex , "Specify which register sets to dump by index."},
{ LLDB_OPT_SET_2 , false, "all" , 'a', no_argument , NULL, 0, eArgTypeNone , "Show all register sets."},
{ 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
};
@ -275,9 +384,9 @@ public:
{
DataExtractor reg_data;
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
RegisterContext *reg_context = exe_ctx.GetRegisterContext ();
RegisterContext *reg_ctx = exe_ctx.GetRegisterContext ();
if (reg_context)
if (reg_ctx)
{
if (command.GetArgumentCount() != 2)
{
@ -288,7 +397,7 @@ public:
{
const char *reg_name = command.GetArgumentAtIndex(0);
const char *value_str = command.GetArgumentAtIndex(1);
const RegisterInfo *reg_info = reg_context->GetRegisterInfoByName(reg_name);
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
if (reg_info)
{
@ -296,7 +405,7 @@ public:
Error error(scalar.SetValueFromCString (value_str, reg_info->encoding, reg_info->byte_size));
if (error.Success())
{
if (reg_context->WriteRegisterValue(reg_info->kinds[eRegisterKindLLDB], scalar))
if (reg_ctx->WriteRegisterValue(reg_info->kinds[eRegisterKindLLDB], scalar))
{
result.SetStatus (eReturnStatusSuccessFinishNoResult);
return true;

View File

@ -1439,11 +1439,11 @@ DebuggerInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var
}
else if (var_name == UseExternalEditorVarName ())
{
UserSettingsController::UpdateBooleanVariable (op, m_use_external_editor, value, err);
UserSettingsController::UpdateBooleanVariable (op, m_use_external_editor, value, false, err);
}
else if (var_name == AutoConfirmName ())
{
UserSettingsController::UpdateBooleanVariable (op, m_auto_confirm_on, value, err);
UserSettingsController::UpdateBooleanVariable (op, m_auto_confirm_on, value, false, err);
}
}

View File

@ -109,15 +109,23 @@ Mangled::Compare (const Mangled& a, const Mangled& b)
void
Mangled::SetValue (const char *s, bool mangled)
{
m_mangled.Clear();
m_demangled.Clear();
if (s)
{
if (mangled)
{
m_demangled.Clear();
m_mangled.SetCString (s);
}
else
{
m_demangled.SetCString(s);
m_mangled.Clear();
}
}
else
{
m_demangled.Clear();
m_mangled.Clear();
}
}

View File

@ -2028,32 +2028,51 @@ UserSettingsController::UpdateStringVariable (VarSetOperationType op,
void
UserSettingsController::UpdateBooleanVariable (VarSetOperationType op,
bool &bool_var,
const char *new_value,
bool &bool_value,
const char *value_cstr,
bool clear_value,
Error &err)
{
if (op != eVarSetOperationAssign)
err.SetErrorString ("Invalid operation for Boolean variable. Cannot update value.\n");
if (new_value && new_value[0])
switch (op)
{
if ((::strcasecmp(new_value, "true") == 0) ||
(::strcasecmp(new_value, "yes") == 0) ||
(::strcasecmp(new_value, "on") == 0) ||
(::strcasecmp(new_value, "1") == 0))
bool_var = true;
else
if ((::strcasecmp(new_value, "false") == 0) ||
(::strcasecmp(new_value, "no") == 0) ||
(::strcasecmp(new_value, "off") == 0) ||
(::strcasecmp(new_value, "0") == 0))
bool_var = false;
else
err.SetErrorStringWithFormat ("Invalid boolean value '%s'\n", new_value);
}
else
err.SetErrorString ("Invalid value. Cannot perform update.\n");
case eVarSetOperationReplace:
case eVarSetOperationInsertBefore:
case eVarSetOperationInsertAfter:
case eVarSetOperationRemove:
case eVarSetOperationAppend:
case eVarSetOperationInvalid:
default:
err.SetErrorString ("Invalid operation for Boolean variable. Cannot update value.\n");
break;
case eVarSetOperationClear:
err.Clear();
bool_value = clear_value;
break;
case eVarSetOperationAssign:
{
bool success = false;
if (value_cstr == NULL)
err.SetErrorStringWithFormat ("invalid boolean string value (NULL)\n", value_cstr);
else if (value_cstr[0] == '\0')
err.SetErrorStringWithFormat ("invalid boolean string value (empty)\n", value_cstr);
else
{
bool new_value = Args::StringToBoolean (value_cstr, false, &success);
if (success)
{
err.Clear();
bool_value = new_value;
}
else
err.SetErrorStringWithFormat ("invalid boolean string value: '%s'\n", value_cstr);
}
}
break;
}
}
void

View File

@ -23,6 +23,29 @@ using namespace lldb_private;
//-------------------------------------------------------------------------
// OptionValue
//-------------------------------------------------------------------------
// Get this value as a uint64_t value if it is encoded as a boolean,
// uint64_t or int64_t. Other types will cause "fail_value" to be
// returned
uint64_t
OptionValue::GetUInt64Value (uint64_t fail_value, bool *success_ptr)
{
if (success_ptr)
*success_ptr = true;
switch (GetType())
{
case OptionValue::eTypeBoolean: return static_cast<OptionValueBoolean *>(this)->GetCurrentValue();
case OptionValue::eTypeSInt64: return static_cast<OptionValueSInt64 *>(this)->GetCurrentValue();
case OptionValue::eTypeUInt64: return static_cast<OptionValueUInt64 *>(this)->GetCurrentValue();
default:
break;
}
if (success_ptr)
*success_ptr = false;
return fail_value;
}
OptionValueBoolean *
OptionValue::GetAsBooleanValue ()
{
@ -105,17 +128,22 @@ OptionValueBoolean::DumpValue (Stream &strm)
strm.PutCString (m_current_value ? "true" : "false");
}
bool
Error
OptionValueBoolean::SetValueFromCString (const char *value_cstr)
{
Error error;
bool success = false;
bool value = Args::StringToBoolean(value_cstr, false, &success);
if (success)
{
m_value_was_set = true;
m_current_value = value;
return true;
}
return false;
else
{
error.SetErrorStringWithFormat ("invalid boolean string value: '%s'\n", value_cstr);
}
return error;
}
//-------------------------------------------------------------------------
@ -127,39 +155,62 @@ OptionValueSInt64::DumpValue (Stream &strm)
strm.Printf ("%lli", m_current_value);
}
bool
Error
OptionValueSInt64::SetValueFromCString (const char *value_cstr)
{
Error error;
bool success = false;
int64_t value = Args::StringToSInt64 (value_cstr, 0, 0, &success);
if (success)
{
m_value_was_set = true;
m_current_value = value;
return true;
}
return false;
else
{
error.SetErrorStringWithFormat ("invalid int64_t string value: '%s'\n", value_cstr);
}
return error;
}
//-------------------------------------------------------------------------
// OptionValueUInt64
//-------------------------------------------------------------------------
lldb::OptionValueSP
OptionValueUInt64::Create (const char *value_cstr, Error &error)
{
lldb::OptionValueSP value_sp (new OptionValueUInt64());
error = value_sp->SetValueFromCString (value_cstr);
if (error.Fail())
value_sp.reset();
return value_sp;
}
void
OptionValueUInt64::DumpValue (Stream &strm)
{
strm.Printf ("0x%llx", m_current_value);
}
bool
Error
OptionValueUInt64::SetValueFromCString (const char *value_cstr)
{
Error error;
bool success = false;
uint64_t value = Args::StringToUInt64 (value_cstr, 0, 0, &success);
if (success)
{
m_value_was_set = true;
m_current_value = value;
return true;
}
return false;
else
{
error.SetErrorStringWithFormat ("invalid uint64_t string value: '%s'\n", value_cstr);
}
return error;
}
//-------------------------------------------------------------------------
@ -171,11 +222,12 @@ OptionValueString::DumpValue (Stream &strm)
strm.Printf ("\"%s\"", m_current_value.c_str());
}
bool
Error
OptionValueString::SetValueFromCString (const char *value_cstr)
{
m_value_was_set = true;
SetCurrentValue (value_cstr);
return true;
return Error ();
}
@ -202,14 +254,15 @@ OptionValueFileSpec::DumpValue (Stream &strm)
}
}
bool
Error
OptionValueFileSpec::SetValueFromCString (const char *value_cstr)
{
if (value_cstr && value_cstr[0])
m_current_value.SetFile(value_cstr, false);
else
m_current_value.Clear();
return true;
m_value_was_set = true;
return Error();
}
@ -227,13 +280,25 @@ OptionValueArray::DumpValue (Stream &strm)
}
}
bool
Error
OptionValueArray::SetValueFromCString (const char *value_cstr)
{
// We must be able to set this using the array specific functions
return false;
Error error;
error.SetErrorStringWithFormat ("array option values don't yet support being set by string: '%s'\n", value_cstr);
return error;
}
uint64_t
OptionValueArray::GetUInt64ValueAtIndex (uint32_t idx, uint64_t fail_value, bool *success_ptr) const
{
if (idx < m_values.size())
return m_values[idx]->GetUInt64Value (fail_value, success_ptr);
return fail_value;
}
//-------------------------------------------------------------------------
// OptionValueDictionary
//-------------------------------------------------------------------------
@ -249,11 +314,12 @@ OptionValueDictionary::DumpValue (Stream &strm)
}
}
bool
Error
OptionValueDictionary::SetValueFromCString (const char *value_cstr)
{
// We must be able to set this using the array specific functions
return false;
Error error;
error.SetErrorStringWithFormat ("dictionary option values don't yet support being set by string: '%s'\n", value_cstr);
return error;
}
lldb::OptionValueSP

View File

@ -4062,9 +4062,9 @@ ProcessInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_
else if (var_name == ErrorPathVarName())
UserSettingsController::UpdateStringVariable (op, m_error_path, value, err);
else if (var_name == DisableASLRVarName())
UserSettingsController::UpdateBooleanVariable (op, m_disable_aslr, value, err);
UserSettingsController::UpdateBooleanVariable (op, m_disable_aslr, value, true, err);
else if (var_name == DisableSTDIOVarName ())
UserSettingsController::UpdateBooleanVariable (op, m_disable_stdio, value, err);
UserSettingsController::UpdateBooleanVariable (op, m_disable_stdio, value, false, err);
}
void

View File

@ -1290,6 +1290,7 @@ Target::SettingsController::CreateInstanceSettings (const char *instance_name)
#define TSC_DEFAULT_ARCH "default-arch"
#define TSC_EXPR_PREFIX "expr-prefix"
#define TSC_PREFER_DYNAMIC "prefer-dynamic-value"
#define TSC_SKIP_PROLOGUE "skip-prologue"
static const ConstString &
@ -1315,6 +1316,15 @@ GetSettingNameForPreferDynamicValue ()
}
static const ConstString &
GetSettingNameForSkipPrologue ()
{
static ConstString g_const_string (TSC_SKIP_PROLOGUE);
return g_const_string;
}
bool
Target::SettingsController::SetGlobalVariable (const ConstString &var_name,
const char *index_value,
@ -1364,7 +1374,8 @@ TargetInstanceSettings::TargetInstanceSettings
InstanceSettings (owner, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance),
m_expr_prefix_path (),
m_expr_prefix_contents (),
m_prefer_dynamic_value (true)
m_prefer_dynamic_value (true),
m_skip_prologue (true)
{
// CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
// until the vtables for TargetInstanceSettings are properly set up, i.e. AFTER all the initializers.
@ -1381,7 +1392,6 @@ TargetInstanceSettings::TargetInstanceSettings
{
const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
CopyInstanceSettings (pending_settings,false);
//m_owner.RemovePendingSettings (m_instance_name);
}
}
@ -1392,7 +1402,6 @@ TargetInstanceSettings::TargetInstanceSettings (const TargetInstanceSettings &rh
{
const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
CopyInstanceSettings (pending_settings,false);
//m_owner.RemovePendingSettings (m_instance_name);
}
}
@ -1464,36 +1473,11 @@ TargetInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_n
}
else if (var_name == GetSettingNameForPreferDynamicValue())
{
switch (op)
{
default:
err.SetErrorToGenericError ();
err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
return;
case eVarSetOperationAssign:
{
bool success;
bool result = Args::StringToBoolean(value, false, &success);
if (success)
{
m_prefer_dynamic_value = result;
}
else
{
err.SetErrorStringWithFormat ("Bad value \"%s\" for %s, should be Boolean.",
value,
GetSettingNameForPreferDynamicValue().AsCString());
}
return;
}
case eVarSetOperationClear:
m_prefer_dynamic_value = true;
case eVarSetOperationAppend:
err.SetErrorToGenericError ();
err.SetErrorString ("Cannot append to a bool.\n");
return;
}
UserSettingsController::UpdateBooleanVariable (op, m_prefer_dynamic_value, value, true, err);
}
else if (var_name == GetSettingNameForSkipPrologue())
{
UserSettingsController::UpdateBooleanVariable (op, m_skip_prologue, value, true, err);
}
}
@ -1527,6 +1511,13 @@ TargetInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
else
value.AppendString ("false");
}
else if (var_name == GetSettingNameForSkipPrologue())
{
if (m_skip_prologue)
value.AppendString ("true");
else
value.AppendString ("false");
}
else
{
if (err)
@ -1570,5 +1561,6 @@ Target::SettingsController::instance_settings_table[] =
// ================= ================== =========== ==== ====== ====== =========================================================================
{ TSC_EXPR_PREFIX , eSetVarTypeString , NULL , NULL, false, false, "Path to a file containing expressions to be prepended to all expressions." },
{ TSC_PREFER_DYNAMIC, eSetVarTypeBoolean ,"true" , NULL, false, false, "Should printed values be shown as their dynamic value." },
{ TSC_SKIP_PROLOGUE , eSetVarTypeBoolean ,"true" , NULL, false, false, "Skip function prologues when setting breakpoints by name." },
{ NULL , eSetVarTypeNone , NULL , NULL, false, false, NULL }
};