diff --git a/lldb/include/lldb/Interpreter/Args.h b/lldb/include/lldb/Interpreter/Args.h index 61f267bd9895..8296e2fd03b7 100644 --- a/lldb/include/lldb/Interpreter/Args.h +++ b/lldb/include/lldb/Interpreter/Args.h @@ -382,7 +382,10 @@ public: } static lldb::addr_t - StringToAddress (const char *s, lldb::addr_t fail_value = LLDB_INVALID_ADDRESS, bool *success_ptr = NULL); + StringToAddress (const ExecutionContext *exe_ctx, + const char *s, + lldb::addr_t fail_value, + Error *error); static bool StringToBoolean (const char *s, bool fail_value, bool *success_ptr); diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp index d8cfe0e22afd..2bd768901eb1 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -125,12 +125,10 @@ public: switch (short_option) { case 'a': - m_load_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 0); - if (m_load_addr == LLDB_INVALID_ADDRESS) - m_load_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 16); - - if (m_load_addr == LLDB_INVALID_ADDRESS) - error.SetErrorStringWithFormat ("invalid address string '%s'", option_arg); + { + ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); + m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); + } break; case 'b': diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp index 84172dc87ed9..291b527ae4a1 100644 --- a/lldb/source/Commands/CommandObjectDisassemble.cpp +++ b/lldb/source/Commands/CommandObjectDisassemble.cpp @@ -88,23 +88,21 @@ CommandObjectDisassemble::CommandOptions::SetOptionValue (uint32_t option_idx, c break; case 's': - start_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 0); - if (start_addr == LLDB_INVALID_ADDRESS) - start_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 16); - - if (start_addr == LLDB_INVALID_ADDRESS) - error.SetErrorStringWithFormat ("invalid start address string '%s'", option_arg); - some_location_specified = true; + { + ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); + start_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); + if (start_addr != LLDB_INVALID_ADDRESS) + some_location_specified = true; + } break; case 'e': - end_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 0); - if (end_addr == LLDB_INVALID_ADDRESS) - end_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 16); - - if (end_addr == LLDB_INVALID_ADDRESS) - error.SetErrorStringWithFormat ("invalid end address string '%s'", option_arg); + { + ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); + end_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); + if (end_addr != LLDB_INVALID_ADDRESS) + some_location_specified = true; + } break; - some_location_specified = true; case 'n': func_name.assign (option_arg); some_location_specified = true; diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp index 09c2e4859cbf..9de5af4bbf6d 100644 --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -369,8 +369,7 @@ public: protected: virtual bool - DoExecute (Args& command, - CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) { ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); Target *target = exe_ctx.GetTargetPtr(); @@ -385,7 +384,8 @@ protected: if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2) { - result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str()); + result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str()); + result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters."); result.SetStatus(eReturnStatusFailed); return false; } @@ -565,7 +565,7 @@ protected: // Look for invalid combinations of settings if (error.Fail()) { - result.AppendErrorWithFormat("%s", error.AsCString()); + result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; } @@ -602,21 +602,23 @@ protected: } if (argc > 0) - addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); + addr = Args::StringToAddress(&exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error); if (addr == LLDB_INVALID_ADDRESS) { - result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0)); + result.AppendError("invalid start address expression."); + result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; } if (argc == 2) { - lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); + lldb::addr_t end_addr = Args::StringToAddress(&exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); if (end_addr == LLDB_INVALID_ADDRESS) { - result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1)); + result.AppendError("invalid end address expression."); + result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; } @@ -667,7 +669,7 @@ protected: } if (bytes_read < total_byte_size) - result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr); + result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".", bytes_read, total_byte_size, addr); else { m_next_addr = addr + bytes_read; @@ -987,7 +989,8 @@ protected: virtual bool DoExecute (Args& command, CommandReturnObject &result) { - Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); + ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); + Process *process = exe_ctx.GetProcessPtr(); if (process == NULL) { result.AppendError("need a process to read memory"); @@ -1020,11 +1023,16 @@ protected: OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue(); size_t item_byte_size = byte_size_value.GetCurrentValue(); - lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); + Error error; + lldb::addr_t addr = Args::StringToAddress (&exe_ctx, + command.GetArgumentAtIndex(0), + LLDB_INVALID_ADDRESS, + &error); if (addr == LLDB_INVALID_ADDRESS) { - result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0)); + result.AppendError("invalid address expression\n"); + result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; } diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index d5eb34eaf1b0..e44c2d79b20b 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -3026,6 +3026,8 @@ public: virtual Error SetOptionValue (uint32_t option_idx, const char *option_arg) { + Error error; + const int short_option = m_getopt_table[option_idx].val; if (short_option == 'g') { @@ -3033,13 +3035,7 @@ public: } else if (short_option == 'a') { - bool success; - m_module_addr = Args::StringToAddress(option_arg, LLDB_INVALID_ADDRESS, &success); - if (!success) - { - Error error; - error.SetErrorStringWithFormat("invalid address: \"%s\"", option_arg); - } + m_module_addr = Args::StringToAddress(NULL, option_arg, LLDB_INVALID_ADDRESS, &error); } else { @@ -3048,7 +3044,6 @@ public: width = strtoul (option_arg, NULL, 0); m_format_array.push_back(std::make_pair(short_option, width)); } - Error error; return error; } diff --git a/lldb/source/Interpreter/Args.cpp b/lldb/source/Interpreter/Args.cpp index 65c31539501f..266bcd6fb9c5 100644 --- a/lldb/source/Interpreter/Args.cpp +++ b/lldb/source/Interpreter/Args.cpp @@ -22,6 +22,11 @@ #include "lldb/Core/StreamString.h" #include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Target/Process.h" +//#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +//#include "lldb/Target/Thread.h" using namespace lldb; using namespace lldb_private; @@ -782,26 +787,119 @@ Args::StringToUInt64 (const char *s, uint64_t fail_value, int base, bool *succes } lldb::addr_t -Args::StringToAddress (const char *s, lldb::addr_t fail_value, bool *success_ptr) +Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::addr_t fail_value, Error *error_ptr) { + bool error_set = false; if (s && s[0]) { char *end = NULL; lldb::addr_t addr = ::strtoull (s, &end, 0); if (*end == '\0') { - if (success_ptr) *success_ptr = true; + if (error_ptr) + error_ptr->Clear(); return addr; // All characters were used, return the result } // Try base 16 with no prefix... addr = ::strtoull (s, &end, 16); if (*end == '\0') { - if (success_ptr) *success_ptr = true; + if (error_ptr) + error_ptr->Clear(); return addr; // All characters were used, return the result } + + if (exe_ctx) + { + Target *target = exe_ctx->GetTargetPtr(); + if (target) + { + lldb::ValueObjectSP valobj_sp; + EvaluateExpressionOptions options; + options.SetCoerceToId(false); + options.SetUnwindOnError(true); + options.SetKeepInMemory(false); + options.SetRunOthers(true); + + ExecutionResults expr_result = target->EvaluateExpression(s, + exe_ctx->GetFramePtr(), + valobj_sp, + options); + + bool success = false; + if (expr_result == eExecutionCompleted) + { + // Get the address to watch. + addr = valobj_sp->GetValueAsUnsigned(fail_value, &success); + if (success) + { + if (error_ptr) + error_ptr->Clear(); + return addr; + } + else + { + if (error_ptr) + { + error_set = true; + error_ptr->SetErrorStringWithFormat("address expression \"%s\" resulted in a value whose type can't be converted to an address: %s", s, valobj_sp->GetTypeName().GetCString()); + } + } + + } + else + { + // Since the compiler can't handle things like "main + 12" we should + // try to do this for now. The compliler doesn't like adding offsets + // to function pointer types. + RegularExpression symbol_plus_offset_regex("^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$"); + if (symbol_plus_offset_regex.Execute(s, 3)) + { + uint64_t offset = 0; + bool add = true; + std::string name; + std::string str; + if (symbol_plus_offset_regex.GetMatchAtIndex(s, 1, name)) + { + if (symbol_plus_offset_regex.GetMatchAtIndex(s, 2, str)) + { + add = str[0] == '+'; + + if (symbol_plus_offset_regex.GetMatchAtIndex(s, 3, str)) + { + offset = Args::StringToUInt64(str.c_str(), 0, 0, &success); + + if (success) + { + Error error; + addr = StringToAddress (exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, &error); + if (addr != LLDB_INVALID_ADDRESS) + { + if (add) + return addr + offset; + else + return addr - offset; + } + } + } + } + } + } + + if (error_ptr) + { + error_set = true; + error_ptr->SetErrorStringWithFormat("address expression \"%s\" evaluation failed", s); + } + } + } + } + } + if (error_ptr) + { + if (!error_set) + error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", s); } - if (success_ptr) *success_ptr = false; return fail_value; } diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 900726c56bd7..9269c267d7ec 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -2050,7 +2050,7 @@ ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &erro return response.GetHexBytes(buf, size, '\xdd'); } else if (response.IsErrorResponse()) - error.SetErrorString("memory read failed"); + error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr); else if (response.IsUnsupportedResponse()) error.SetErrorStringWithFormat("GDB server does not support reading memory"); else @@ -2086,7 +2086,7 @@ ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Erro return size; } else if (response.IsErrorResponse()) - error.SetErrorString("memory write failed"); + error.SetErrorStringWithFormat("memory write failed for 0x%" PRIx64, addr); else if (response.IsUnsupportedResponse()) error.SetErrorStringWithFormat("GDB server does not support writing memory"); else