Add a "-a/--address" option to "thread until". You can specify one or more line numbers (as arguments)

and/or one or more addresses (with -a) and until will stop at the first one of  thesepoints it hits,
or on exit from the function if you leave the function before hitting any of these stop points.

<rdar://problem/12438270>

llvm-svn: 228370
This commit is contained in:
Jim Ingham
2015-02-06 02:10:56 +00:00
parent 8378ac3684
commit 9bdea541ca

View File

@@ -985,6 +985,14 @@ public:
switch (short_option)
{
case 'a':
{
ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
lldb::addr_t tmp_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
if (error.Success())
m_until_addrs.push_back(tmp_addr);
}
break;
case 't':
{
m_thread_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_INDEX32);
@@ -1031,6 +1039,7 @@ public:
m_thread_idx = LLDB_INVALID_THREAD_ID;
m_frame_idx = 0;
m_stop_others = false;
m_until_addrs.clear();
}
const OptionDefinition*
@@ -1041,6 +1050,7 @@ public:
uint32_t m_step_thread_idx;
bool m_stop_others;
std::vector<lldb::addr_t> m_until_addrs;
// Options table: Required for subclasses of Options.
@@ -1052,7 +1062,7 @@ public:
CommandObjectThreadUntil (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
"thread until",
"Run the current or specified thread until it reaches a given line number or leaves the current function.",
"Run the current or specified thread until it reaches a given line number or address or leaves the current function.",
NULL,
eFlagRequiresThread |
eFlagTryTargetAPILock |
@@ -1111,22 +1121,32 @@ protected:
else
{
Thread *thread = NULL;
uint32_t line_number;
std::vector<uint32_t> line_numbers;
if (command.GetArgumentCount() != 1)
if (command.GetArgumentCount() >= 1)
{
result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
size_t num_args = command.GetArgumentCount();
for (size_t i = 0; i < num_args; i++)
{
uint32_t line_number;
line_number = StringConvert::ToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
if (line_number == UINT32_MAX)
{
result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
result.SetStatus (eReturnStatusFailed);
return false;
}
else
line_numbers.push_back(line_number);
}
}
else if (m_options.m_until_addrs.empty())
{
result.AppendErrorWithFormat ("No line number or address provided:\n%s", GetSyntax());
result.SetStatus (eReturnStatusFailed);
return false;
}
line_number = StringConvert::ToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
if (line_number == UINT32_MAX)
{
result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
result.SetStatus (eReturnStatusFailed);
return false;
}
if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
{
@@ -1189,27 +1209,40 @@ protected:
Address fun_end_addr(fun_start_addr.GetSection(),
fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
bool all_in_function = true;
while (index_ptr <= end_ptr)
{
LineEntry line_entry;
const bool exact = false;
index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, exact, &line_entry);
if (index_ptr == UINT32_MAX)
break;
addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
if (address != LLDB_INVALID_ADDRESS)
line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
for (uint32_t line_number : line_numbers)
{
uint32_t start_idx_ptr = index_ptr;
while (start_idx_ptr <= end_ptr)
{
if (fun_addr_range.ContainsLoadAddress (address, target))
address_list.push_back (address);
else
all_in_function = false;
LineEntry line_entry;
const bool exact = false;
start_idx_ptr = sc.comp_unit->FindLineEntry(start_idx_ptr, line_number, sc.comp_unit, exact, &line_entry);
if (start_idx_ptr == UINT32_MAX)
break;
addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
if (address != LLDB_INVALID_ADDRESS)
{
if (fun_addr_range.ContainsLoadAddress (address, target))
address_list.push_back (address);
else
all_in_function = false;
}
start_idx_ptr++;
}
index_ptr++;
}
for (lldb::addr_t address : m_options.m_until_addrs)
{
if (fun_addr_range.ContainsLoadAddress (address, target))
address_list.push_back (address);
else
all_in_function = false;
}
if (address_list.size() == 0)
@@ -1291,7 +1324,8 @@ CommandObjectThreadUntil::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"},
{ LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"},
{ LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, NULL, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"},
{ LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, NULL, g_duo_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping this one"},
{ LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression, "Run until we reach the specified address, or leave the function - can be specified multiple times."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};