44 changes: 43 additions & 1 deletion lldb/source/Breakpoint/BreakpointIDList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,27 +159,52 @@ BreakpointIDList::InsertStringArray (const char **string_array, size_t array_siz
// NEW_ARGS should be a copy of OLD_ARGS, with and ID range specifiers replaced by the members of the range.

void
BreakpointIDList::FindAndReplaceIDRanges (Args &old_args, Target *target, CommandReturnObject &result,
BreakpointIDList::FindAndReplaceIDRanges (Args &old_args,
Target *target,
bool allow_locations,
CommandReturnObject &result,
Args &new_args)
{
std::string range_start;
const char *range_end;
const char *current_arg;
const size_t num_old_args = old_args.GetArgumentCount();
std::set<std::string> names_found;

for (size_t i = 0; i < num_old_args; ++i)
{
bool is_range = false;

current_arg = old_args.GetArgumentAtIndex (i);
if (!allow_locations && strchr(current_arg, '.') != nullptr)
{
result.AppendErrorWithFormat ("Breakpoint locations not allowed, saw location: %s.", current_arg);
new_args.Clear();
return;
}

size_t range_start_len = 0;
size_t range_end_pos = 0;
Error error;

if (BreakpointIDList::StringContainsIDRangeExpression (current_arg, &range_start_len, &range_end_pos))
{
is_range = true;
range_start.assign (current_arg, range_start_len);
range_end = current_arg + range_end_pos;
}
else if (BreakpointID::StringIsBreakpointName(current_arg, error))
{
if (!error.Success())
{
new_args.Clear();
result.AppendError (error.AsCString());
result.SetStatus (eReturnStatusFailed);
return;
}
else
names_found.insert(current_arg);
}
else if ((i + 2 < num_old_args)
&& BreakpointID::IsRangeIdentifier (old_args.GetArgumentAtIndex (i+1))
&& BreakpointID::IsValidIDExpression (current_arg)
Expand Down Expand Up @@ -342,6 +367,23 @@ BreakpointIDList::FindAndReplaceIDRanges (Args &old_args, Target *target, Comman
}
}

// Okay, now see if we found any names, and if we did, add them:
if (target && names_found.size())
{
for (BreakpointSP bkpt_sp : target->GetBreakpointList().Breakpoints())
{
for (std::string name : names_found)
{
if (bkpt_sp->MatchesName(name.c_str()))
{
StreamString canonical_id_str;
BreakpointID::GetCanonicalReference (&canonical_id_str, bkpt_sp->GetID(), LLDB_INVALID_BREAK_ID);
new_args.AppendArgument (canonical_id_str.GetData());
}
}
}
}

result.SetStatus (eReturnStatusSuccessFinishNoResult);
return;
}
Expand Down
3 changes: 1 addition & 2 deletions lldb/source/Breakpoint/BreakpointOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,7 @@ BreakpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) cons

if (m_thread_spec_ap.get())
m_thread_spec_ap->GetDescription (s, level);
else if (level == eDescriptionLevelBrief)
s->PutCString ("thread spec: no ");

if (level == lldb::eDescriptionLevelFull)
{
s->IndentLess();
Expand Down
439 changes: 431 additions & 8 deletions lldb/source/Commands/CommandObjectBreakpoint.cpp

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion lldb/source/Commands/CommandObjectBreakpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,20 @@ class CommandObjectMultiwordBreakpoint : public CommandObjectMultiword
~CommandObjectMultiwordBreakpoint ();

static void
VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids);
VerifyBreakpointOrLocationIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids)
{
VerifyIDs (args, target, true, result, valid_ids);
}

static void
VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids)
{
VerifyIDs (args, target, false, result, valid_ids);
}

private:
static void
VerifyIDs (Args &args, Target *target, bool allow_locations, CommandReturnObject &result, BreakpointIDList *valid_ids);
};

} // namespace lldb_private
Expand Down
6 changes: 3 additions & 3 deletions lldb/source/Commands/CommandObjectBreakpointCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ one command per line.\n" );
}

BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);

m_bp_options_vec.clear();

Expand Down Expand Up @@ -714,7 +714,7 @@ class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
}

BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);

if (result.Succeeded())
{
Expand Down Expand Up @@ -824,7 +824,7 @@ class CommandObjectBreakpointCommandList : public CommandObjectParsed
}

BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);

if (result.Succeeded())
{
Expand Down
17 changes: 17 additions & 0 deletions lldb/source/Interpreter/CommandObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,22 @@ BreakpointIDRangeHelpTextCallback ()
" is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal.";
}

static const char *
BreakpointNameHelpTextCallback ()
{
return "A name that can be added to a breakpoint when it is created, or later "
"on with the \"breakpoint name add\" command. "
"Breakpoint names can be used to specify breakpoints in all the places breakpoint ID's "
"and breakpoint ID ranges can be used. As such they provide a convenient way to group breakpoints, "
"and to operate on breakpoints you create without having to track the breakpoint number. "
"Note, the attributes you set when using a breakpoint name in a breakpoint command don't "
"adhere to the name, but instead are set individually on all the breakpoints currently tagged with that name. Future breakpoints "
"tagged with that name will not pick up the attributes previously given using that name. "
"In order to distinguish breakpoint names from breakpoint ID's and ranges, "
"names must start with a letter from a-z or A-Z and cannot contain spaces, \".\" or \"-\". "
"Also, breakpoint names can only be applied to breakpoints, not to breakpoint locations.";
}

static const char *
GDBFormatHelpTextCallback ()
{
Expand Down Expand Up @@ -1112,6 +1128,7 @@ CommandObject::g_arguments_data[] =
{ eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { nullptr, false }, "A Boolean value: 'true' or 'false'" },
{ eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, nullptr },
{ eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, nullptr },
{ eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eNoCompletion, { BreakpointNameHelpTextCallback, false }, nullptr },
{ eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { nullptr, false }, "Number of bytes to use." },
{ eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { nullptr, false }, "Then name of a class from the debug information in the program." },
{ eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A debugger command (may be multiple words), without any options or arguments." },
Expand Down