Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions lldb/include/lldb/Breakpoint/BreakpointIDList.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,9 @@ class BreakpointIDList {
static std::pair<llvm::StringRef, llvm::StringRef>
SplitIDRangeExpression(llvm::StringRef in_string);

static llvm::Error
FindAndReplaceIDRanges(Args &old_args, Target *target, bool allow_locations,
BreakpointName::Permissions ::PermissionKinds purpose,
Args &new_args);
static llvm::Error FindAndReplaceIDRanges(
Args &old_args, ExecutionContext &exe_ctx, bool allow_locations,
BreakpointName::Permissions ::PermissionKinds purpose, Args &new_args);

private:
BreakpointIDArray m_breakpoint_ids;
Expand Down
41 changes: 40 additions & 1 deletion lldb/source/Breakpoint/BreakpointIDList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@

#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/lldb-forward.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
Expand Down Expand Up @@ -55,6 +59,16 @@ bool BreakpointIDList::Contains(BreakpointID bp_id) const {
return llvm::is_contained(m_breakpoint_ids, bp_id);
}

static std::string LocationIDForStop(StopInfoSP stop_info_sp, uint32_t idx) {
assert(stop_info_sp->GetStopReason() == lldb::eStopReasonBreakpoint &&
"expected breakpoint stop");
break_id_t bp_id = stop_info_sp->GetStopReasonDataAtIndex(idx);
break_id_t loc_id = stop_info_sp->GetStopReasonDataAtIndex(idx + 1);
StreamString stream;
BreakpointID::GetCanonicalReference(&stream, bp_id, loc_id);
return stream.GetString().str();
}

// This function takes OLD_ARGS, which is usually the result of breaking the
// command string arguments into
// an array of space-separated strings, and searches through the arguments for
Expand All @@ -69,8 +83,9 @@ bool BreakpointIDList::Contains(BreakpointID bp_id) const {
// by the members of the range.

llvm::Error BreakpointIDList::FindAndReplaceIDRanges(
Args &old_args, Target *target, bool allow_locations,
Args &old_args, ExecutionContext &exe_ctx, bool allow_locations,
BreakpointName::Permissions ::PermissionKinds purpose, Args &new_args) {
Target *target = exe_ctx.GetTargetPtr();
llvm::StringRef range_from;
llvm::StringRef range_to;
llvm::StringRef current_arg;
Expand All @@ -80,6 +95,30 @@ llvm::Error BreakpointIDList::FindAndReplaceIDRanges(
bool is_range = false;

current_arg = old_args[i].ref();

if (allow_locations && current_arg == ".") {
Thread *thread = exe_ctx.GetThreadPtr();
if (!thread) {
new_args.Clear();
return llvm::createStringError("no current thread");
}
StopInfoSP stop_info_sp = thread->GetStopInfo();
if (!stop_info_sp ||
stop_info_sp->GetStopReason() != eStopReasonBreakpoint) {
new_args.Clear();
return llvm::createStringError(
"current thread is not stopped at a breakpoint");
}

uint32_t data_count = stop_info_sp->GetStopReasonDataCount();
for (uint32_t j = 0; j < data_count; j += 2) {
std::string location_id = LocationIDForStop(stop_info_sp, j);
new_args.AppendArgument(location_id);
}

continue;
}

if (!allow_locations && current_arg.contains('.')) {
new_args.Clear();
return llvm::createStringError(
Expand Down
23 changes: 12 additions & 11 deletions lldb/source/Commands/CommandObjectBreakpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2075,7 +2075,7 @@ class CommandObjectBreakpointModify : public CommandObjectParsed {
BreakpointIDList valid_bp_ids;

CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
command, target, result, &valid_bp_ids,
command, m_exe_ctx, result, &valid_bp_ids,
BreakpointName::Permissions::PermissionKinds::disablePerm);

if (result.Succeeded()) {
Expand Down Expand Up @@ -2156,7 +2156,7 @@ class CommandObjectBreakpointEnable : public CommandObjectParsed {
// Particular breakpoint selected; enable that breakpoint.
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
command, target, result, &valid_bp_ids,
command, m_exe_ctx, result, &valid_bp_ids,
BreakpointName::Permissions::PermissionKinds::disablePerm);

if (result.Succeeded()) {
Expand Down Expand Up @@ -2265,7 +2265,7 @@ the second re-enables the first location.");
BreakpointIDList valid_bp_ids;

CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
command, target, result, &valid_bp_ids,
command, m_exe_ctx, result, &valid_bp_ids,
BreakpointName::Permissions::PermissionKinds::disablePerm);

if (result.Succeeded()) {
Expand Down Expand Up @@ -2412,7 +2412,7 @@ class CommandObjectBreakpointList : public CommandObjectParsed {
// Particular breakpoints selected; show info about that breakpoint.
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
command, target, result, &valid_bp_ids,
command, m_exe_ctx, result, &valid_bp_ids,
BreakpointName::Permissions::PermissionKinds::listPerm);

if (result.Succeeded()) {
Expand Down Expand Up @@ -2691,7 +2691,7 @@ class CommandObjectBreakpointDelete : public CommandObjectParsed {

if (!command.empty()) {
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
command, target, result, &excluded_bp_ids,
command, m_exe_ctx, result, &excluded_bp_ids,
BreakpointName::Permissions::PermissionKinds::deletePerm);
if (!result.Succeeded())
return;
Expand All @@ -2710,7 +2710,7 @@ class CommandObjectBreakpointDelete : public CommandObjectParsed {
}
} else {
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
command, target, result, &valid_bp_ids,
command, m_exe_ctx, result, &valid_bp_ids,
BreakpointName::Permissions::PermissionKinds::deletePerm);
if (!result.Succeeded())
return;
Expand Down Expand Up @@ -3021,7 +3021,7 @@ class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
// Particular breakpoint selected; disable that breakpoint.
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
command, target, result, &valid_bp_ids,
command, m_exe_ctx, result, &valid_bp_ids,
BreakpointName::Permissions::PermissionKinds::listPerm);

if (result.Succeeded()) {
Expand Down Expand Up @@ -3095,7 +3095,7 @@ class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
// Particular breakpoint selected; disable that breakpoint.
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
command, target, result, &valid_bp_ids,
command, m_exe_ctx, result, &valid_bp_ids,
BreakpointName::Permissions::PermissionKinds::deletePerm);

if (result.Succeeded()) {
Expand Down Expand Up @@ -3568,7 +3568,7 @@ class CommandObjectBreakpointWrite : public CommandObjectParsed {
BreakpointIDList valid_bp_ids;
if (!command.empty()) {
CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
command, target, result, &valid_bp_ids,
command, m_exe_ctx, result, &valid_bp_ids,
BreakpointName::Permissions::PermissionKinds::listPerm);

if (!result.Succeeded()) {
Expand Down Expand Up @@ -3654,7 +3654,7 @@ CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;

void CommandObjectMultiwordBreakpoint::VerifyIDs(
Args &args, Target &target, bool allow_locations,
Args &args, ExecutionContext &exe_ctx, bool allow_locations,
CommandReturnObject &result, BreakpointIDList *valid_ids,
BreakpointName::Permissions ::PermissionKinds purpose) {
// args can be strings representing 1). integers (for breakpoint ids)
Expand All @@ -3668,6 +3668,7 @@ void CommandObjectMultiwordBreakpoint::VerifyIDs(
// If args is empty, we will use the last created breakpoint (if there is
// one.)

Target &target = exe_ctx.GetTargetRef();
Args temp_args;

if (args.empty()) {
Expand All @@ -3689,7 +3690,7 @@ void CommandObjectMultiwordBreakpoint::VerifyIDs(
// into TEMP_ARGS.

if (llvm::Error err = BreakpointIDList::FindAndReplaceIDRanges(
args, &target, allow_locations, purpose, temp_args)) {
args, exe_ctx, allow_locations, purpose, temp_args)) {
result.SetError(std::move(err));
return;
}
Expand Down
14 changes: 7 additions & 7 deletions lldb/source/Commands/CommandObjectBreakpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,22 @@ class CommandObjectMultiwordBreakpoint : public CommandObjectMultiword {
~CommandObjectMultiwordBreakpoint() override;

static void VerifyBreakpointOrLocationIDs(
Args &args, Target &target, CommandReturnObject &result,
Args &args, ExecutionContext &exe_ctx, CommandReturnObject &result,
BreakpointIDList *valid_ids,
BreakpointName::Permissions ::PermissionKinds purpose) {
VerifyIDs(args, target, true, result, valid_ids, purpose);
VerifyIDs(args, exe_ctx, true, result, valid_ids, purpose);
}

static void
VerifyBreakpointIDs(Args &args, Target &target, CommandReturnObject &result,
BreakpointIDList *valid_ids,
VerifyBreakpointIDs(Args &args, ExecutionContext &exe_ctx,
CommandReturnObject &result, BreakpointIDList *valid_ids,
BreakpointName::Permissions::PermissionKinds purpose) {
VerifyIDs(args, target, false, result, valid_ids, purpose);
VerifyIDs(args, exe_ctx, false, result, valid_ids, purpose);
}

private:
static void VerifyIDs(Args &args, Target &target, bool allow_locations,
CommandReturnObject &result,
static void VerifyIDs(Args &args, ExecutionContext &exe_ctx,
bool allow_locations, CommandReturnObject &result,
BreakpointIDList *valid_ids,
BreakpointName::Permissions::PermissionKinds purpose);
};
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 @@ -344,7 +344,7 @@ are no syntax errors may indicate that a function was declared but never called.

BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
command, target, result, &valid_bp_ids,
command, m_exe_ctx, result, &valid_bp_ids,
BreakpointName::Permissions::PermissionKinds::listPerm);

m_bp_options_vec.clear();
Expand Down Expand Up @@ -500,7 +500,7 @@ class CommandObjectBreakpointCommandDelete : public CommandObjectParsed {

BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
command, target, result, &valid_bp_ids,
command, m_exe_ctx, result, &valid_bp_ids,
BreakpointName::Permissions::PermissionKinds::listPerm);

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

BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
command, target, result, &valid_bp_ids,
command, m_exe_ctx, result, &valid_bp_ids,
BreakpointName::Permissions::PermissionKinds::listPerm);

if (result.Succeeded()) {
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Commands/CommandObjectProcess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ class CommandObjectProcessContinue : public CommandObjectParsed {
// default breakpoint.
if (m_options.m_run_to_bkpt_args.GetArgumentCount() > 0)
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
m_options.m_run_to_bkpt_args, target, result, &run_to_bkpt_ids,
m_options.m_run_to_bkpt_args, m_exe_ctx, result, &run_to_bkpt_ids,
BreakpointName::Permissions::disablePerm);
if (!result.Succeeded()) {
return;
Expand Down
5 changes: 4 additions & 1 deletion lldb/source/Commands/CommandOptionArgumentTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ llvm::StringRef BreakpointIDHelpTextCallback() {
"major "
"number, or the major number followed by a dot and the location "
"number (e.g. "
"3 or 3.2 could both be valid breakpoint IDs.)";
"3 or 3.2 could both be valid breakpoint IDs.)\n"
"\n"
"You can use . to refer to the breakpoint location(s) at which the "
"current thread is stopped.";
}

llvm::StringRef BreakpointIDRangeHelpTextCallback() {
Expand Down
3 changes: 3 additions & 0 deletions lldb/test/API/commands/breakpoint/location-dot/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
C_SOURCES := main.c

include Makefile.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import lldb
from lldbsuite.test.lldbtest import TestBase
from lldbsuite.test import lldbutil


class TestCase(TestBase):
def test_disable_enable(self):
self.build()
_, _, _, bp = lldbutil.run_to_source_breakpoint(
self, "break here", lldb.SBFileSpec("main.c")
)

self.assertTrue(bp.FindLocationByID(1).IsEnabled())
self.expect("breakpoint disable .", startstr="1 breakpoints disabled.")
self.assertFalse(bp.FindLocationByID(1).IsEnabled())
self.expect("breakpoint enable .", startstr="1 breakpoints enabled.")
self.assertTrue(bp.FindLocationByID(1).IsEnabled())

def test_delete(self):
self.build()
_, _, _, bp = lldbutil.run_to_source_breakpoint(
self, "break here", lldb.SBFileSpec("main.c")
)

self.expect(
"breakpoint delete .",
startstr="0 breakpoints deleted; 1 breakpoint locations disabled",
)
self.assertFalse(bp.FindLocationByID(1).IsEnabled())

def test_error_not_breakpoint_stop(self):
self.build()
_, _, thread, bp = lldbutil.run_to_source_breakpoint(
self, "break here", lldb.SBFileSpec("main.c")
)

self.assertTrue(bp.FindLocationByID(1).IsEnabled())
thread.StepOver()
self.assertNotEqual(thread.stop_reason, lldb.eStopReasonBreakpoint)
self.expect(
"breakpoint disable .",
error=True,
startstr="error: current thread is not stopped at a breakpoint",
)
self.assertTrue(bp.FindLocationByID(1).IsEnabled())

def test_error_no_process(self):
self.build()
target = self.createTestTarget()
target.BreakpointCreateByLocation("main.c", 2)
self.expect("breakpoint disable .", error=True, substrs=["no current thread"])
5 changes: 5 additions & 0 deletions lldb/test/API/commands/breakpoint/location-dot/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
int main() {
int x = 1; // break here
int y = 2;
return x + y;
}