Skip to content

Conversation

OCHyams
Copy link
Contributor

@OCHyams OCHyams commented Aug 8, 2025

Adding together in a single commit as their implementations are linked.

Only supported for DAP debuggers. These two commands make it a bit easier to
drive dexter: DexStepFunction tells dexter to step-next though a function and
DexContinue tells dexter to continue (run free) from one breakpoint to another
within the current DexStepFunction function.

When the DexStepFunction function breakpoint is triggered, dexter sets an
instruction breakpoint at the return-address. This is so that stepping can
resume in any other DexStepFunctions deeps in the call stack.

Copy link

github-actions bot commented Aug 8, 2025

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff origin/main HEAD --extensions cpp -- cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/control/dex-continue.cpp cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/control/dex_step_function.cpp

⚠️
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing origin/main to the base branch/commit you want to compare against.
⚠️

View the diff from clang-format here.
diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/control/dex-continue.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/control/dex-continue.cpp
index bb51b85cb..0e9c36c22 100644
--- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/control/dex-continue.cpp
+++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/control/dex-continue.cpp
@@ -21,8 +21,7 @@ int c(int) {
   return 0;
 }
 
-__attribute__((always_inline))
-int b(int) {
+__attribute__((always_inline)) int b(int) {
   ++g;
   return c(g);
 }
@@ -34,9 +33,7 @@ int a(int) {
   return g;
 }
 
-void f() {
-  ++g;
-}
+void f() { ++g; }
 
 int main() {
   int x = a(g);
@@ -52,13 +49,20 @@ int main() {
 // DexStepFunction('f')
 
 // CHECK:      ## BEGIN ##
-// CHECK-NEXT: .   [0, "a(int)", "{{.*}}dex-continue.cpp", 31, 3, "StopReason.BREAKPOINT", "StepKind.FUNC", []]
-// CHECK-NEXT: .   [1, "a(int)", "{{.*}}dex-continue.cpp", 32, 5, "StopReason.STEP", "StepKind.VERTICAL_FORWARD", []]
-// CHECK-NEXT: .   .   .   [2, "c(int)", "{{.*}}dex-continue.cpp", 16, 3, "StopReason.BREAKPOINT", "StepKind.FUNC", []]
-// CHECK-NEXT: .   .   .   [3, "c(int)", "{{.*}}dex-continue.cpp", 17, 3, "StopReason.BREAKPOINT", "StepKind.VERTICAL_FORWARD", []]
-// CHECK-NEXT: .   .   .   [4, "c(int)", "{{.*}}dex-continue.cpp", 19, 3, "StopReason.BREAKPOINT", "StepKind.VERTICAL_FORWARD", []]
-// CHECK-NEXT: .   .   .   [5, "c(int)", "{{.*}}dex-continue.cpp", 20, 3, "StopReason.BREAKPOINT", "StepKind.VERTICAL_FORWARD", []]
-// CHECK-NEXT: .   [6, "a(int)", "{{.*}}dex-continue.cpp", 33, 3, "StopReason.BREAKPOINT", "StepKind.VERTICAL_FORWARD", []]
-// CHECK-NEXT: .   [8, "f()", "{{.*}}dex-continue.cpp", 38, 3, "StopReason.BREAKPOINT", "StepKind.VERTICAL_FORWARD", []]
-// CHECK-NEXT: .   [9, "f()", "{{.*}}dex-continue.cpp", 39, 1, "StopReason.STEP", "StepKind.VERTICAL_FORWARD", []]
-// CHECK-NEXT: ## END (9 steps) ##
+// CHECK-NEXT: .   [0, "a(int)", "{{.*}}dex-continue.cpp", 31, 3,
+// "StopReason.BREAKPOINT", "StepKind.FUNC", []] CHECK-NEXT: .   [1, "a(int)",
+// "{{.*}}dex-continue.cpp", 32, 5, "StopReason.STEP",
+// "StepKind.VERTICAL_FORWARD", []] CHECK-NEXT: .   .   .   [2, "c(int)",
+// "{{.*}}dex-continue.cpp", 16, 3, "StopReason.BREAKPOINT", "StepKind.FUNC",
+// []] CHECK-NEXT: .   .   .   [3, "c(int)", "{{.*}}dex-continue.cpp", 17, 3,
+// "StopReason.BREAKPOINT", "StepKind.VERTICAL_FORWARD", []] CHECK-NEXT: .   .
+// .   [4, "c(int)", "{{.*}}dex-continue.cpp", 19, 3, "StopReason.BREAKPOINT",
+// "StepKind.VERTICAL_FORWARD", []] CHECK-NEXT: .   .   .   [5, "c(int)",
+// "{{.*}}dex-continue.cpp", 20, 3, "StopReason.BREAKPOINT",
+// "StepKind.VERTICAL_FORWARD", []] CHECK-NEXT: .   [6, "a(int)",
+// "{{.*}}dex-continue.cpp", 33, 3, "StopReason.BREAKPOINT",
+// "StepKind.VERTICAL_FORWARD", []] CHECK-NEXT: .   [8, "f()",
+// "{{.*}}dex-continue.cpp", 38, 3, "StopReason.BREAKPOINT",
+// "StepKind.VERTICAL_FORWARD", []] CHECK-NEXT: .   [9, "f()",
+// "{{.*}}dex-continue.cpp", 39, 1, "StopReason.STEP",
+// "StepKind.VERTICAL_FORWARD", []] CHECK-NEXT: ## END (9 steps) ##
diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/control/dex_step_function.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/control/dex_step_function.cpp
index e7e666d0e..4aaabb47f 100644
--- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/control/dex_step_function.cpp
+++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/control/dex_step_function.cpp
@@ -23,17 +23,19 @@ int a(int) {
   return b(g);
 }
 
-int main() {
-  return a(g);
-}
+int main() { return a(g); }
 
 // DexStepFunction('a')
 // DexStepFunction('c')
 
 // CHECK:      ## BEGIN ##
-// CHECK-NEXT:.   [0, "a(int)", "{{.*}}dex_step_function.cpp", 22, 3, "StopReason.BREAKPOINT", "StepKind.FUNC", []]
-// CHECK-NEXT:.   [1, "a(int)", "{{.*}}dex_step_function.cpp", 23, 12, "StopReason.STEP", "StepKind.VERTICAL_FORWARD", []]
-// CHECK-NEXT:.   .   .   [2, "c(int)", "{{.*}}dex_step_function.cpp", 12, 3, "StopReason.BREAKPOINT", "StepKind.FUNC", []]
-// CHECK-NEXT:.   .   .   [3, "c(int)", "{{.*}}dex_step_function.cpp", 13, 3, "StopReason.STEP", "StepKind.VERTICAL_FORWARD", []]
-// CHECK-NEXT:.   [6, "a(int)", "{{.*}}dex_step_function.cpp", 23, 3, "StopReason.STEP", "StepKind.HORIZONTAL_BACKWARD", []]
-// CHECK-NEXT: ## END (5 steps) ##
+// CHECK-NEXT:.   [0, "a(int)", "{{.*}}dex_step_function.cpp", 22, 3,
+// "StopReason.BREAKPOINT", "StepKind.FUNC", []] CHECK-NEXT:.   [1, "a(int)",
+// "{{.*}}dex_step_function.cpp", 23, 12, "StopReason.STEP",
+// "StepKind.VERTICAL_FORWARD", []] CHECK-NEXT:.   .   .   [2, "c(int)",
+// "{{.*}}dex_step_function.cpp", 12, 3, "StopReason.BREAKPOINT",
+// "StepKind.FUNC", []] CHECK-NEXT:.   .   .   [3, "c(int)",
+// "{{.*}}dex_step_function.cpp", 13, 3, "StopReason.STEP",
+// "StepKind.VERTICAL_FORWARD", []] CHECK-NEXT:.   [6, "a(int)",
+// "{{.*}}dex_step_function.cpp", 23, 3, "StopReason.STEP",
+// "StepKind.HORIZONTAL_BACKWARD", []] CHECK-NEXT: ## END (5 steps) ##

Copy link

github-actions bot commented Aug 8, 2025

✅ With the latest revision this PR passed the Python code formatter.

@OCHyams OCHyams marked this pull request as ready for review August 8, 2025 13:38
@OCHyams OCHyams requested a review from SLTozer August 8, 2025 13:38
@OCHyams OCHyams force-pushed the users/OCHyams/dex-skeletons branch from f42e8d1 to 3c16976 Compare August 12, 2025 11:14
@OCHyams OCHyams force-pushed the users/OCHyams/dex-new-cmds-impl branch from 18b6dc8 to 07cee24 Compare August 12, 2025 11:16
Copy link
Contributor

@SLTozer SLTozer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with comments.

Comment on lines 218 to 220
self.context.logger.warning(
f"Set leading breakpoint {id} at {bpr.function}"
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably don't need this log anymore!


log_step = False
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly change this to record_step or similar, since this isn't what we'd usually refer to by "log"?

step_info, self._watches, self.step_collection.commands
)
self.step_collection.new_step(self.context, step_info)
backtrace = list([f.function for f in step_info.frames])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
backtrace = list([f.function for f in step_info.frames])
backtrace = [f.function for f in step_info.frames]

AFAICT the square-brackets already make this a list, no need for the explicit list.

# Add this backtrace to the stack. While the current
# backtrace matches the top of the stack we'll step,
# and while there's a backtrace in the stack that
# is a subset of the current backtrack we'll step-out.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# is a subset of the current backtrack we'll step-out.
# is a subset of the current backtrace we'll step-out.


elif bpr.is_continue:
debugger_continue = True
self.debugger.add_breakpoint(bpr.path, bpr.range_to)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

range_to is an optional argument right? I'd assume this should be conditional on bpr.range_to is not None

Comment on lines 350 to 354
for i, f in enumerate(reversed(step_function_backtraces[-1])):
if backtrace[-1 - i] != f:
match_subtrace = False
match_trace = False
break
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for i, f in enumerate(reversed(step_function_backtraces[-1])):
if backtrace[-1 - i] != f:
match_subtrace = False
match_trace = False
break
if backtrace[-len(step_function_backtraces[-1]):] != step_function_backtraces[-1]:
match_subtrace = False
match_trace = False

A possible alternative way of expressing this, YMMV on whether this is clearer!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 also added a comment to hopefully make it clearer

@OCHyams OCHyams force-pushed the users/OCHyams/dex-skeletons branch from 3c16976 to 83608ac Compare August 27, 2025 13:41
@OCHyams OCHyams force-pushed the users/OCHyams/dex-new-cmds-impl branch from 07cee24 to 0605b1e Compare August 27, 2025 13:44
Comment on lines 330 to 332
self.context.logger.warning(
f"Set trailing breakpoint {id} at {line}"
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also some unnecessary logging.

Base automatically changed from users/OCHyams/dex-skeletons to main August 27, 2025 17:03
Adding together in a single commit as their implementations are linked.

Only supported for DAP debuggers. These two commands make it a bit easier to
drive dexter: DexStepFunction tells dexter to step-next though a function and
DexContinue tells dexter to continue (run free) from one breakpoint to another
within the current DexStepFunction function.

When the DexStepFunction function breakpoint is triggered, dexter sets an
instruction breakpoint at the return-address. This is so that stepping can
resume in any other DexStepFunctions deeps in the call stack.
@OCHyams OCHyams force-pushed the users/OCHyams/dex-new-cmds-impl branch from 4947499 to d7c91f8 Compare August 27, 2025 17:29
@OCHyams
Copy link
Contributor Author

OCHyams commented Aug 27, 2025

Thanks

Rebased. I'll land this one once we move over to using lldb-dap (rather than lldb) in feature_tests.

…erControllers/ConditionalController.py

Co-authored-by: Stephen Tozer <stephen.tozer@sony.com>
We should only notify the receiver thread that we've got a response after
we've handled it, else we risk race conditions read/writing the debugger_state.
@OCHyams
Copy link
Contributor Author

OCHyams commented Sep 1, 2025

I've added two commits to fix test failures -

  • The 1st fixes a sync issue with the receiver thread (previously it signalled it had got a response before fully handling it itself, leading to other threads reading incomplete debugger state)
  • The 2nd filters out breakpoint IDs that we didn't set from dexter. LLDB-DAP is sometimes returning negative breakpoint IDs

@SLTozer does this still look good?

Copy link
Contributor

@SLTozer SLTozer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes LGTM!

@OCHyams OCHyams merged commit d7d8703 into main Sep 1, 2025
8 of 9 checks passed
@OCHyams OCHyams deleted the users/OCHyams/dex-new-cmds-impl branch September 1, 2025 08:56
@adrian-prantl
Copy link
Collaborator

@OCHyams This broke the x86 bot on green dragon: https://green.lab.llvm.org/job/llvm.org/view/LLDB/job/as-lldb-cmake/32349/

Can you take a look?
The x86 machine is on an older OS/SDK than the arm64 one. Maybe that information helps.

@OCHyams
Copy link
Contributor Author

OCHyams commented Sep 1, 2025

@OCHyams This broke the x86 bot on green dragon: https://green.lab.llvm.org/job/llvm.org/view/LLDB/job/as-lldb-cmake/32349/

Can you take a look? The x86 machine is on an older OS/SDK than the arm64 one. Maybe that information helps.

It looks like the link is to a broken arm64 bot, or am I confused? I'm testing on x86 locally and the test passes for me.

Looking at the output... it looks like maybe some of the breakpoints are either not triggering or dexter doesn't see them as having been triggered. It could be the code I added that skips unknown breakpoints returned by lldb-dap - @adrian-prantl I was seeing LLDB-DAP return hitBreakpointIds with negative IDs (which seems unusual by itself, but importantly the ID doesn't match any of those sent in Breakpoint events or BreakpointLocationsResponse responses). Do you know what could cause that (or know someone who might)? It may be related to this failure.

In the mean time, I'm out of office now but please feel free to revert this if it's blocking. Otherwise I'll be able to get to it tomorrow morning (UK).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants