Skip to content

Commit

Permalink
MIEngine: Fix multi-breakpoint gdb/mi information parsing (#1435)
Browse files Browse the repository at this point in the history
This PR fixes gdb/mi breakpoint information parsing for breakpoints
that bind to multiple locations, which have a '<MULTIPLE>' in the addr field.
According to https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Breakpoint-Information.html#GDB_002fMI-Breakpoint-Information
the locations field contains the list of locations for this breakpoint type.
This list of locations is used then to create the bound breakpoints for the specific breakpoint.

Signed-off-by: Andria Pazarloglou <[email protected]>
  • Loading branch information
apazarlo authored Jul 3, 2024
1 parent 8ce5af7 commit b8bfa53
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 25 deletions.
15 changes: 4 additions & 11 deletions src/MIDebugEngine/Engine.Impl/BreakpointManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,13 @@ public async Task BreakpointModified(object sender, EventArgs args)
string bkptId = null;
//
// =breakpoint-modified,
// bkpt ={number="2",type="breakpoint",disp="keep",enabled="y",addr="<MULTIPLE>",times="0",original-location="main.cpp:220"},
// bkpt ={number="2",type="breakpoint",disp="keep",enabled="y",addr="<MULTIPLE>",times="0",original-location="main.cpp:220"},locations=[
// { number="2.1",enabled="y",addr="0x9c2149a9",func="Foo::bar<int>(int)",file="main.cpp",fullname="C:\\\\...\\\\main.cpp",line="220",thread-groups=["i1"]},
// { number="2.2",enabled="y",addr="0x9c2149f2",func="Foo::bar<float>(float)",file="main.cpp",fullname="C:\\\\...\\\\main.cpp",line="220",thread-groups=["i1"]}
// { number="2.2",enabled="y",addr="0x9c2149f2",func="Foo::bar<float>(float)",file="main.cpp",fullname="C:\\\\...\\\\main.cpp",line="220",thread-groups=["i1"]}]}
// note: the ".x" part of the breakpoint number never appears in stopping events, that is, when executing at one of these addresses
// the stopping event delivered contains bkptno="2"
if (bkpt is MICore.ValueListValue)
{
MICore.ValueListValue list = bkpt as MICore.ValueListValue;
bkptId = list.Content[0].FindString("number"); // 0 is the "<MULTIPLE>" entry
}
else
{
bkptId = bkpt.FindString("number");
}
bkptId = bkpt.FindString("number");

AD7PendingBreakpoint pending = CodeBreakpoints.FirstOrDefault((p) => { return p.BreakpointId == bkptId; });
if (pending == null)
{
Expand Down
24 changes: 12 additions & 12 deletions src/MIDebugEngine/Engine.Impl/Breakpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,11 @@ private static async Task<BindResult> EvalBindResult(Results bindResult, AD7Pend
if (b is TupleValue)
{
bkpt = b as TupleValue;
}
else if (b is ValueListValue)
{
// "<MULTIPLE>" sometimes includes a list of bound breakpoints
list = b as ValueListValue;
bkpt = list.Content[0] as TupleValue;
// The locations field is present if the breakpoint has multiple locations.
if (b.TryFind("locations", out var locations) && locations is ValueListValue)
{
list = (ValueListValue) locations;
}
}
}
else
Expand Down Expand Up @@ -189,9 +188,9 @@ private static async Task<BindResult> EvalBindResult(Results bindResult, AD7Pend
else // <MULTIPLE> with list of addresses
{
BindResult res = new BindResult(bp);
for (int i = 1; i < list.Content.Length; ++i)
foreach (var t in list.Content)
{
BoundBreakpoint bbp = await bp.GetBoundBreakpoint(list.Content[i] as TupleValue);
BoundBreakpoint bbp = await bp.GetBoundBreakpoint(t as TupleValue);
res.BoundBreakpoints.Add(bbp);
}
return res;
Expand Down Expand Up @@ -290,12 +289,13 @@ internal async Task<List<BoundBreakpoint>> BindAddresses(ResultValue bkpt)
return resultList;
}
BoundBreakpoint bbp = null;
if (bkpt is ValueListValue)

// The locations field is present if the breakpoint has multiple locations.
if (bkpt.TryFind("locations", out var locations) && locations is ValueListValue list)
{
var list = (ValueListValue)bkpt;
for (int i = 1; i < list.Content.Length; ++i)
foreach (var t in list.Content)
{
bbp = await GetBoundBreakpoint(list.Content[i] as TupleValue);
bbp = await GetBoundBreakpoint(t as TupleValue);
if (bbp != null)
resultList.Add(bbp);
}
Expand Down
4 changes: 2 additions & 2 deletions test/CppTests/Tests/BreakpointTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public void FunctionBreakpointsBasic(ITestSettings settings)
runner.Launch(settings.DebuggerSettings, debuggee, "-fCalling");

this.Comment("Set initial function breakpoints");
FunctionBreakpoints functionBreakpoints = new FunctionBreakpoints("Arguments::CoreRun", "Calling::CoreRun", "a()");
FunctionBreakpoints functionBreakpoints = new FunctionBreakpoints("Arguments::CoreRun", "Calling::CoreRun", "a");
runner.SetFunctionBreakpoints(functionBreakpoints);

this.Comment("Launch and run until first initial breakpoint");
Expand All @@ -137,7 +137,7 @@ public void FunctionBreakpointsBasic(ITestSettings settings)
.AfterContinue();

this.Comment("Remove and replace third initial function breakpoint while in break mode");
functionBreakpoints.Remove("a()");
functionBreakpoints.Remove("a");
functionBreakpoints.Add("b()");
runner.SetFunctionBreakpoints(functionBreakpoints);

Expand Down
6 changes: 6 additions & 0 deletions test/CppTests/debuggees/kitchensink/src/calling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,10 @@ void Calling::CoreRun()
this->Log("Calling variable arg function.");
double ave = average(10, 1.0, 3.0, 4.5, 11.0, -30.0, 17.4, 2.1, -4.0, 0.0, 12.1);
this->Log("Average ", ave);
}

int a(int count)
{
b();
return count - 1;
}

0 comments on commit b8bfa53

Please sign in to comment.