diff options
| author | Mingming Liu <mingmingl@google.com> | 2025-09-10 15:25:31 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-10 15:25:31 -0700 |
| commit | 1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch) | |
| tree | 57f4b1f313c8cf74eed8819870f39c36ea263c68 /cross-project-tests | |
| parent | 898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff) | |
| parent | b8cefcb601ddaa18482555c4ff363c01a270c2fe (diff) | |
Merge branch 'main' into users/mingmingl-llvm/samplefdo-profile-formatusers/mingmingl-llvm/samplefdo-profile-format
Diffstat (limited to 'cross-project-tests')
51 files changed, 686 insertions, 175 deletions
diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/aggregate-indirect-arg.cpp b/cross-project-tests/debuginfo-tests/dexter-tests/aggregate-indirect-arg.cpp index f20b7ce1d3e4..4e06ba5d375c 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/aggregate-indirect-arg.cpp +++ b/cross-project-tests/debuginfo-tests/dexter-tests/aggregate-indirect-arg.cpp @@ -3,7 +3,7 @@ // // RUN: %clang++ -std=gnu++11 -O0 -g %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -- %s +// RUN: --binary %t %dexter_lldb_args -- %s // Radar 8945514 class SVal { diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/asan-deque.cpp b/cross-project-tests/debuginfo-tests/dexter-tests/asan-deque.cpp index 08540145dc4e..d807fa190608 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/asan-deque.cpp +++ b/cross-project-tests/debuginfo-tests/dexter-tests/asan-deque.cpp @@ -10,7 +10,7 @@ // RUN: %clang++ -std=gnu++11 -O1 -glldb -fsanitize=address -arch x86_64 %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -- %s +// RUN: --binary %t %dexter_lldb_args -- %s #include <deque> struct A { diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/asan.c b/cross-project-tests/debuginfo-tests/dexter-tests/asan.c index e52494c585d8..9105e1d8801b 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/asan.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/asan.c @@ -6,7 +6,7 @@ // RUN: %clang -std=gnu11 --driver-mode=gcc -O0 -glldb -fblocks -arch x86_64 \ // RUN: -fsanitize=address %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -- %s +// RUN: --binary %t %dexter_lldb_args -- %s struct S { int a[8]; diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/ctor.cpp b/cross-project-tests/debuginfo-tests/dexter-tests/ctor.cpp index 48482ceb31b9..6b6dc3ef309b 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/ctor.cpp +++ b/cross-project-tests/debuginfo-tests/dexter-tests/ctor.cpp @@ -3,7 +3,7 @@ // // RUN: %clang++ -std=gnu++11 -O0 -glldb %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -- %s +// RUN: --binary %t %dexter_lldb_args -- %s class A { public: diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/dbg-arg.c b/cross-project-tests/debuginfo-tests/dexter-tests/dbg-arg.c index ff000f584db0..f1f145c7ff38 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/dbg-arg.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/dbg-arg.c @@ -4,7 +4,7 @@ // This test case checks debug info during register moves for an argument. // RUN: %clang -std=gnu11 -m64 -mllvm -fast-isel=false -g %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -- %s +// RUN: --binary %t %dexter_lldb_args -- %s // // Radar 8412415 diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/deferred_globals.cpp b/cross-project-tests/debuginfo-tests/dexter-tests/deferred_globals.cpp index 5954f5297be0..570708d4fa91 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/deferred_globals.cpp +++ b/cross-project-tests/debuginfo-tests/dexter-tests/deferred_globals.cpp @@ -6,7 +6,7 @@ // UNSUPPORTED: system-windows // RUN: %clang++ -std=gnu++11 -O0 -g %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -v -- %s +// RUN: --binary %t %dexter_lldb_args -v -- %s const int d = 100; diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/bitcast.c b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/bitcast.c index 314fd3b31c42..69e3b8035511 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/bitcast.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/bitcast.c @@ -4,7 +4,7 @@ // REQUIRES: lldb // UNSUPPORTED: system-windows // RUN: %clang -std=gnu11 -O3 -glldb %s -o %t -// RUN: %dexter --fail-lt 1.0 -w --debugger lldb --binary %t -- %s +// RUN: %dexter --fail-lt 1.0 -w %dexter_lldb_args --binary %t -- %s //// Adapted from https://bugs.llvm.org/show_bug.cgi?id=34136#c1 //// LowerDbgDeclare has since been updated to look through bitcasts. We still diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/const-branch.c b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/const-branch.c index 42629c556ffa..c67dd0a3747b 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/const-branch.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/const-branch.c @@ -4,7 +4,7 @@ // REQUIRES: lldb // UNSUPPORTED: system-windows // RUN: %clang -std=gnu11 -O3 -glldb %s -o %t -// RUN: %dexter --fail-lt 1.0 -w --debugger lldb --binary %t -- %s +// RUN: %dexter --fail-lt 1.0 -w %dexter_lldb_args --binary %t -- %s //// Adapted from https://bugs.llvm.org/show_bug.cgi?id=34136#c4 diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/ctrl-flow.c b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/ctrl-flow.c index 16ad91ec8ca0..4fa4e6e0120d 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/ctrl-flow.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/ctrl-flow.c @@ -1,7 +1,7 @@ // REQUIRES: lldb // UNSUPPORTED: system-windows // RUN: %clang -std=gnu11 -O2 -glldb %s -o %t -// RUN: %dexter --fail-lt 1.0 -w --debugger lldb --binary %t -- %s +// RUN: %dexter --fail-lt 1.0 -w %dexter_lldb_args --binary %t -- %s //// Check that we give good locations to a variable ('local') which is escaped //// down some control paths and not others. This example is handled well currently. diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/implicit-ptr.c b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/implicit-ptr.c index c43b99241445..5c11fe426d91 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/implicit-ptr.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/implicit-ptr.c @@ -4,7 +4,7 @@ // REQUIRES: lldb // UNSUPPORTED: system-windows // RUN: %clang -std=gnu11 -O3 -glldb %s -o %t -// RUN: %dexter --fail-lt 1.0 -w --debugger lldb --binary %t -- %s +// RUN: %dexter --fail-lt 1.0 -w %dexter_lldb_args --binary %t -- %s //// Check that 'param' in 'fun' can be read throughout, and that 'pa' and 'pb' //// can be dereferenced in the debugger even if we can't provide the pointer diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/inline-escaping-function.c b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/inline-escaping-function.c index 3c03603736f7..541f003c2615 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/inline-escaping-function.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/inline-escaping-function.c @@ -4,7 +4,7 @@ // REQUIRES: lldb // UNSUPPORTED: system-windows // RUN: %clang -std=gnu11 -O3 -glldb %s -o %t -// RUN: %dexter --fail-lt 1.0 -w --debugger lldb --binary %t -- %s +// RUN: %dexter --fail-lt 1.0 -w %dexter_lldb_args --binary %t -- %s // 1. param is escaped by inlineme(¶m) so it is not promoted by // SROA/mem2reg. diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/inlining-dse.c b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/inlining-dse.c index d5bdc3e01fa1..cded557f4e16 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/inlining-dse.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/inlining-dse.c @@ -4,7 +4,7 @@ // REQUIRES: lldb // UNSUPPORTED: system-windows // RUN: %clang -std=gnu11 -O2 -glldb %s -o %t -// RUN: %dexter --fail-lt 1.0 -w --debugger lldb --binary %t -- %s +// RUN: %dexter --fail-lt 1.0 -w %dexter_lldb_args --binary %t -- %s // //// Check that once-escaped variable 'param' can still be read after we //// perform inlining + mem2reg, and that we see the DSE'd value 255. diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/inlining.c b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/inlining.c index dd7b3452f2b0..7d02b2d4bc8c 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/inlining.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/inlining.c @@ -1,7 +1,7 @@ // REQUIRES: lldb // UNSUPPORTED: system-windows // RUN: %clang -std=gnu11 -O2 -glldb %s -o %t -// RUN: %dexter --fail-lt 1.0 -w --debugger lldb --binary %t -- %s +// RUN: %dexter --fail-lt 1.0 -w %dexter_lldb_args --binary %t -- %s // //// Check that the once-escaped variable 'param' can still be read after //// we perform inlining + mem2reg. See D89810 and D85555. diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/loop.c b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/loop.c index 8ce358b4aada..d74432579c3b 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/loop.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/loop.c @@ -4,7 +4,7 @@ // REQUIRES: lldb // UNSUPPORTED: system-windows // RUN: %clang -std=gnu11 -O3 -glldb %s -o %t -// RUN: %dexter --fail-lt 1.0 -w --debugger lldb --binary %t -- %s +// RUN: %dexter --fail-lt 1.0 -w %dexter_lldb_args --binary %t -- %s //// Check that escaped local 'param' in function 'fun' has sensible debug info //// after the escaping function 'use' gets arg promotion (int* -> int). Currently diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/merged-store.c b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/merged-store.c index bbd806a08819..492e42dfce0b 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/merged-store.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/merged-store.c @@ -4,7 +4,7 @@ // REQUIRES: lldb // UNSUPPORTED: system-windows // RUN: %clang -std=gnu11 -O3 -glldb %s -o %t -// RUN: %dexter --fail-lt 1.0 -w --debugger lldb --binary %t -- %s +// RUN: %dexter --fail-lt 1.0 -w %dexter_lldb_args --binary %t -- %s // 1. parama is escaped by esc(¶ma) so it is not promoted by // SROA/mem2reg. diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/ptr-to.c b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/ptr-to.c index 26adc2e4d978..632b499eebd1 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/ptr-to.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/ptr-to.c @@ -5,7 +5,7 @@ // REQUIRES: lldb // UNSUPPORTED: system-windows // RUN: %clang -std=gnu11 -O2 -glldb %s -o %t -// RUN: %dexter --fail-lt 1.0 -w --debugger lldb --binary %t -- %s +// RUN: %dexter --fail-lt 1.0 -w %dexter_lldb_args --binary %t -- %s // //// Check that a pointer to a variable living on the stack dereferences to the //// variable value. diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/struct-dse.c b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/struct-dse.c index 2975b88e8bc6..5a36bbe59873 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/struct-dse.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/struct-dse.c @@ -5,7 +5,7 @@ // REQUIRES: lldb // UNSUPPORTED: system-windows // RUN: %clang -std=gnu11 -O2 -glldb %s -o %t -// RUN: %dexter --fail-lt 1.0 -w --debugger lldb --binary %t -- %s +// RUN: %dexter --fail-lt 1.0 -w %dexter_lldb_args --binary %t -- %s // //// Check debug-info for the escaped struct variable num is reasonable. diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/unused-merged-value.c b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/unused-merged-value.c index 38a9b644be50..2cf3e968ca75 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/memvars/unused-merged-value.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/memvars/unused-merged-value.c @@ -6,7 +6,7 @@ // REQUIRES: lldb // UNSUPPORTED: system-windows // RUN: %clang -std=gnu11 -O3 -glldb %s -o %t -// RUN: %dexter --fail-lt 0.1 -w --debugger lldb --binary %t -- %s +// RUN: %dexter --fail-lt 0.1 -w %dexter_lldb_args --binary %t -- %s // See NOTE at end for more info about the RUN command. // 1. SROA/mem2reg fully promotes parama. diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/namespace.cpp b/cross-project-tests/debuginfo-tests/dexter-tests/namespace.cpp index e6709cc807db..ba910644de4e 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/namespace.cpp +++ b/cross-project-tests/debuginfo-tests/dexter-tests/namespace.cpp @@ -7,7 +7,7 @@ // RUN: %clang++ -g -O0 %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -v -- %s +// RUN: --binary %t %dexter_lldb_args -v -- %s #include <stdio.h> diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/nrvo-string.cpp b/cross-project-tests/debuginfo-tests/dexter-tests/nrvo-string.cpp index 5df190a07a4e..42a7110151b2 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/nrvo-string.cpp +++ b/cross-project-tests/debuginfo-tests/dexter-tests/nrvo-string.cpp @@ -9,11 +9,11 @@ // // RUN: %clang++ -std=gnu++11 -O0 -glldb -fno-exceptions %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -- %s +// RUN: --binary %t %dexter_lldb_args -- %s // // RUN: %clang++ -std=gnu++11 -O1 -glldb -fno-exceptions %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -- %s +// RUN: --binary %t %dexter_lldb_args -- %s // // PR34513 volatile int sideeffect = 0; diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/optnone-fastmath.cpp b/cross-project-tests/debuginfo-tests/dexter-tests/optnone-fastmath.cpp index 6053488dc680..3f21a8711b3d 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/optnone-fastmath.cpp +++ b/cross-project-tests/debuginfo-tests/dexter-tests/optnone-fastmath.cpp @@ -1,9 +1,9 @@ // RUN: %clang++ -std=gnu++11 -O2 -ffast-math -g %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -- %s +// RUN: --binary %t %dexter_lldb_args -- %s // RUN: %clang++ -std=gnu++11 -O0 -ffast-math -g %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -- %s +// RUN: --binary %t %dexter_lldb_args -- %s // REQUIRES: lldb // Currently getting intermittent failures on darwin. diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/optnone-loops.cpp b/cross-project-tests/debuginfo-tests/dexter-tests/optnone-loops.cpp index 230998c6d4e0..f760b7afe6cb 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/optnone-loops.cpp +++ b/cross-project-tests/debuginfo-tests/dexter-tests/optnone-loops.cpp @@ -7,7 +7,7 @@ // RUN: %clang++ -std=gnu++11 -O2 -g %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -- %s +// RUN: --binary %t %dexter_lldb_args -- %s // A simple loop of assignments. // With optimization level > 0 the compiler reorders basic blocks diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/optnone-simple-functions.cpp b/cross-project-tests/debuginfo-tests/dexter-tests/optnone-simple-functions.cpp index e585c20f4a01..cc693cc7c967 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/optnone-simple-functions.cpp +++ b/cross-project-tests/debuginfo-tests/dexter-tests/optnone-simple-functions.cpp @@ -1,9 +1,9 @@ // RUN: %clang++ -std=gnu++11 -O2 -g %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -- %s +// RUN: --binary %t %dexter_lldb_args -- %s // RUN: %clang++ -std=gnu++11 -O0 -g %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -- %s +// RUN: --binary %t %dexter_lldb_args -- %s // REQUIRES: lldb, D136396 // Currently getting intermittent failures on darwin. diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/optnone-struct-and-methods.cpp b/cross-project-tests/debuginfo-tests/dexter-tests/optnone-struct-and-methods.cpp index 6aebd502614f..94934356ac7e 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/optnone-struct-and-methods.cpp +++ b/cross-project-tests/debuginfo-tests/dexter-tests/optnone-struct-and-methods.cpp @@ -1,9 +1,9 @@ // RUN: %clang++ -std=gnu++11 -O2 -g %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -v -- %s +// RUN: --binary %t %dexter_lldb_args -v -- %s // RUN: %clang++ -std=gnu++11 -O0 -g %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -- %s +// RUN: --binary %t %dexter_lldb_args -- %s // REQUIRES: lldb // Currently getting intermittent failures on darwin. diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/optnone-vectors-and-functions.cpp b/cross-project-tests/debuginfo-tests/dexter-tests/optnone-vectors-and-functions.cpp index 5c4cfc0b9c43..fd244fbafdb7 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/optnone-vectors-and-functions.cpp +++ b/cross-project-tests/debuginfo-tests/dexter-tests/optnone-vectors-and-functions.cpp @@ -1,9 +1,9 @@ // RUN: %clang++ -std=gnu++11 -O2 -g %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -v -- %s +// RUN: --binary %t %dexter_lldb_args -v -- %s // RUN: %clang++ -std=gnu++11 -O0 -g %s -o %t // RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t --debugger 'lldb' -- %s +// RUN: --binary %t %dexter_lldb_args -- %s // REQUIRES: lldb // Currently getting intermittent failures on darwin. diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/stack-var.c b/cross-project-tests/debuginfo-tests/dexter-tests/stack-var.c index 7e3c4b5d0ce1..8447dd1cad29 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/stack-var.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/stack-var.c @@ -2,7 +2,7 @@ // UNSUPPORTED: system-windows // // RUN: %clang -std=gnu11 -O -glldb %s -o %t -// RUN: %dexter --fail-lt 1.0 -w --binary %t --debugger 'lldb' -- %s +// RUN: %dexter --fail-lt 1.0 -w --binary %t %dexter_lldb_args -- %s void __attribute__((noinline, optnone)) bar(int *test) {} int main() { diff --git a/cross-project-tests/debuginfo-tests/dexter-tests/vla.c b/cross-project-tests/debuginfo-tests/dexter-tests/vla.c index ff5297f890e7..6978b5b91fa3 100644 --- a/cross-project-tests/debuginfo-tests/dexter-tests/vla.c +++ b/cross-project-tests/debuginfo-tests/dexter-tests/vla.c @@ -3,7 +3,7 @@ // UNSUPPORTED: system-windows // // RUN: %clang -std=gnu11 -O0 -glldb %s -o %t -// RUN: %dexter --fail-lt 1.0 -w --binary %t --debugger 'lldb' -- %s +// RUN: %dexter --fail-lt 1.0 -w --binary %t %dexter_lldb_args -- %s void init_vla(int size) { int i; diff --git a/cross-project-tests/debuginfo-tests/dexter/Commands.md b/cross-project-tests/debuginfo-tests/dexter/Commands.md index a98261a50009..afec3e6bbd00 100644 --- a/cross-project-tests/debuginfo-tests/dexter/Commands.md +++ b/cross-project-tests/debuginfo-tests/dexter/Commands.md @@ -13,7 +13,8 @@ * [DexDeclareFile](Commands.md#DexDeclareFile) * [DexFinishTest](Commands.md#DexFinishTest) * [DexCommandLine](Commands.md#DexCommandLine) - +* [DexStepFunction](Commands.md#DexStepFunction) +* [DexContinue](Commands.md#DexContinue) --- ## DexExpectProgramState DexExpectProgramState(state [,**times]) @@ -377,3 +378,44 @@ line this command is found on. ### Heuristic [Deprecated] + + +--- +## DexStepFunction + DexStepFunction(function_name[, **hit_count=0]) + + Arg list: + function_name (str): function to step through. + hit_count (int): If provided, limit the number of times the command + triggers. + +### Description +NOTE: Only supported for DAP-based debuggers. + +This command controls stepping behaviour: Tell dexter to set a function +breakpoint and step through the function after hitting it. Composes well with +itself (you can may a callstack with multiple targets to step through) and +`DexContinue`. + +--- +## DexContinue + DexContinue(*[expr, *values], **from_line[, **to_line, **hit_count]) + + Arg list: + function_name (str): function to step through. + hit_count (int): If provided, limit the number of times the command + triggers. + +### Description +NOTE: Only supported for DAP-based debuggers. + +This command controls stepping behaviour: Tell dexter to set a breakpoint on +`from_line`. When it is hit and optionally '(expr) == (values[n])' is true, +optionally set a breakpoint on `to_line`. Then 'continue' (tell the debugger to +run freely until a breakpoint is hit). Composed with `DexStepFunction` this +lets you avoid stepping over certain regions (many loop iterations, for +example). Continue-ing off the end of a `DexStepFunction` is well defined; +stepping will resume in `DexStepFunction` targets deeper in the callstack. + +FIXME: hit_count should probably be inverted, like `DexLimitSteps`, to trigger +AFTER that many hits? diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py index 4496fdf3cb0e..1a30e0e8f375 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py @@ -35,6 +35,8 @@ from dex.command.commands.DexLimitSteps import DexLimitSteps from dex.command.commands.DexFinishTest import DexFinishTest from dex.command.commands.DexUnreachable import DexUnreachable from dex.command.commands.DexWatch import DexWatch +from dex.command.commands.DexStepFunction import DexStepFunction +from dex.command.commands.DexContinue import DexContinue from dex.utils import Timer from dex.utils.Exceptions import CommandParseError, DebuggerException @@ -59,6 +61,8 @@ def _get_valid_commands(): DexFinishTest.get_name(): DexFinishTest, DexUnreachable.get_name(): DexUnreachable, DexWatch.get_name(): DexWatch, + DexStepFunction.get_name(): DexStepFunction, + DexContinue.get_name(): DexContinue, } diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py new file mode 100644 index 000000000000..113f34bedd13 --- /dev/null +++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexContinue.py @@ -0,0 +1,55 @@ +# DExTer : Debugging Experience Tester +# ~~~~~~ ~ ~~ ~ ~~ +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +"""A Command that tells dexter to set a breakpoint which, after hitting, +signals that the debugger should 'continue' until another is hit. Continuing +out of a function being stepped through with DexStepFunction is well defined: +stepping will resume in other functions tracked further down the stacktrace. + +NOTE: Only supported for DAP-based debuggers. +""" + +from dex.command.CommandBase import CommandBase + + +class DexContinue(CommandBase): + def __init__(self, *args, **kwargs): + # DexContinue(*[expr, *values], **from_line[, **to_line, **hit_count]) + + # Optional positional args: expr, values. + if len(args) == 0: + self.expression = None + self.values = [] + elif len(args) == 1: + raise TypeError("expected 0 or at least 2 positional arguments") + else: + self.expression = args[0] + self.values = [str(arg) for arg in args[1:]] + + # Required keyword arg: from_line. + try: + self.from_line = kwargs.pop("from_line") + except: + raise TypeError("Missing from_line argument") + + # Optional conditional args: to_line, hit_count. + self.to_line = kwargs.pop("to_line", None) + self.hit_count = kwargs.pop("hit_count", None) + + if kwargs: + raise TypeError("unexpected named args: {}".format(", ".join(kwargs))) + super(DexContinue, self).__init__() + + def eval(self): + raise NotImplementedError("DexContinue commands cannot be evaled.") + + @staticmethod + def get_name(): + return __class__.__name__ + + @staticmethod + def get_subcommands() -> dict: + return None diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py new file mode 100644 index 000000000000..4b80de87a1bb --- /dev/null +++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexStepFunction.py @@ -0,0 +1,38 @@ +# DExTer : Debugging Experience Tester +# ~~~~~~ ~ ~~ ~ ~~ +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +"""A Command that tells dexter to set a function breakpoint and step through +the function after hitting it. + +NOTE: Only supported for DAP-based debuggers. +""" + +from dex.command.CommandBase import CommandBase + + +class DexStepFunction(CommandBase): + def __init__(self, *args, **kwargs): + if len(args) < 1: + raise TypeError("expected 1 positional argument") + self.function = str(args[0]) + self.hit_count = kwargs.pop("hit_count", None) + if kwargs: + raise TypeError(f"unexpected named args: {', '.join(kwargs)}") + super(DexStepFunction, self).__init__() + + def eval(self): + raise NotImplementedError("DexStepFunction commands cannot be evaled.") + + def get_function(self): + return self.function + + @staticmethod + def get_name(): + return __class__.__name__ + + @staticmethod + def get_subcommands() -> dict: + return None diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DAP.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DAP.py index 06515dd8e0b1..4e64f880487f 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DAP.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DAP.py @@ -218,6 +218,10 @@ class DAP(DebuggerBase, metaclass=abc.ABCMeta): self.file_to_bp = defaultdict(list) # { dex_breakpoint_id -> (file, line, condition) } self.bp_info = {} + # { dex_breakpoint_id -> function_name } + self.function_bp_info = {} + # { dex_breakpoint_id -> instruction_reference } + self.instruction_bp_info = {} # We don't rely on IDs returned directly from the debug adapter. Instead, we use dexter breakpoint IDs, and # maintain a two-way-mapping of dex_bp_id<->dap_bp_id. This also allows us to defer the setting of breakpoints # in the debug adapter itself until necessary. @@ -226,6 +230,8 @@ class DAP(DebuggerBase, metaclass=abc.ABCMeta): self.dex_id_to_dap_id = {} self.dap_id_to_dex_ids = {} self.pending_breakpoints: bool = False + self.pending_function_breakpoints: bool = False + self.pending_instruction_breakpoints: bool = False # List of breakpoints, indexed by BP ID # Each entry has the source file (for use in referencing desired_bps), and the DA-assigned # ID for that breakpoint if it has one (if it has been removed or not yet created then it will be None). @@ -288,6 +294,26 @@ class DAP(DebuggerBase, metaclass=abc.ABCMeta): {"source": {"path": source}, "breakpoints": [bp.toDict() for bp in bps]}, ) + @staticmethod + def make_set_function_breakpoint_request(function_names: list) -> dict: + # Function breakpoints may specify conditions and hit counts, though we + # don't use those here (though perhaps we should use native hit count, + # rather than emulating it ConditionalController, now that we have a + # shared interface (DAP)). + return DAP.make_request( + "setFunctionBreakpoints", + {"breakpoints": [{"name": f} for f in function_names]}, + ) + + @staticmethod + def make_set_instruction_breakpoint_request(addrs: list) -> dict: + # Instruction breakpoints have additional fields we're ignoring for the + # moment. + return DAP.make_request( + "setInstructionBreakpoints", + {"breakpoints": [{"instructionReference": a} for a in addrs]}, + ) + ############################################################################ ## DAP communication & state-handling functions @@ -355,8 +381,6 @@ class DAP(DebuggerBase, metaclass=abc.ABCMeta): else: pass elif message["type"] == "response": - request_seq = message["request_seq"] - debugger_state.set_response(request_seq, message) # TODO: We also receive a "continued" event, but it seems reasonable to set state based on either the # response or the event, since the DAP does not specify an order in which they are sent. May need revisiting # if there turns out to be some odd ordering issues, e.g. if we can receive messages in the order @@ -383,6 +407,10 @@ class DAP(DebuggerBase, metaclass=abc.ABCMeta): body = message.get("body") if body: debugger_state.capabilities.update(logger, body) + # Now we've done whatever we need to do with the response, tell the + # receiver thread we've got it. + request_seq = message["request_seq"] + debugger_state.set_response(request_seq, message) def _colorize_dap_message(message: dict) -> dict: colorized_message = copy.deepcopy(message) @@ -569,6 +597,22 @@ class DAP(DebuggerBase, metaclass=abc.ABCMeta): def _add_breakpoint(self, file, line): return self._add_conditional_breakpoint(file, line, None) + def add_function_breakpoint(self, name: str): + if not self._debugger_state.capabilities.supportsFunctionBreakpoints: + raise DebuggerException("Debugger does not support function breakpoints") + new_id = self.get_next_bp_id() + self.function_bp_info[new_id] = name + self.pending_function_breakpoints = True + return new_id + + def add_instruction_breakpoint(self, addr: str): + if not self._debugger_state.capabilities.supportsInstructionBreakpoints: + raise DebuggerException("Debugger does not support instruction breakpoints") + new_id = self.get_next_bp_id() + self.instruction_bp_info[new_id] = addr + self.pending_instruction_breakpoints = True + return new_id + def _add_conditional_breakpoint(self, file, line, condition): new_id = self.get_next_bp_id() self.file_to_bp[file].append(new_id) @@ -576,38 +620,73 @@ class DAP(DebuggerBase, metaclass=abc.ABCMeta): self.pending_breakpoints = True return new_id + def _update_breakpoint_ids_after_request(self, dex_bp_ids: list, response: dict): + dap_bp_ids = [bp["id"] for bp in response["body"]["breakpoints"]] + if len(dex_bp_ids) != len(dap_bp_ids): + self.context.logger.error( + f"Sent request to set {len(dex_bp_ids)} breakpoints, but received {len(dap_bp_ids)} in response." + ) + visited_dap_ids = set() + for i, dex_bp_id in enumerate(dex_bp_ids): + dap_bp_id = dap_bp_ids[i] + self.dex_id_to_dap_id[dex_bp_id] = dap_bp_id + # We take the mappings in the response as the canonical mapping, meaning that if the debug server has + # simply *changed* the DAP ID for a breakpoint we overwrite the existing mapping rather than adding to + # it, but if we receive the same DAP ID for multiple Dex IDs *then* we store a one-to-many mapping. + if dap_bp_id in visited_dap_ids: + self.dap_id_to_dex_ids[dap_bp_id].append(dex_bp_id) + else: + self.dap_id_to_dex_ids[dap_bp_id] = [dex_bp_id] + visited_dap_ids.add(dap_bp_id) + def _flush_breakpoints(self): - if not self.pending_breakpoints: - return - for file in self.file_to_bp.keys(): - desired_bps = self._get_desired_bps(file) + # Normal and conditional breakpoints. + if self.pending_breakpoints: + self.pending_breakpoints = False + for file in self.file_to_bp.keys(): + desired_bps = self._get_desired_bps(file) + request_id = self.send_message( + self.make_set_breakpoint_request(file, desired_bps) + ) + result = self._await_response(request_id, 10) + if not result["success"]: + raise DebuggerException(f"could not set breakpoints for '{file}'") + # The debug adapter may have chosen to merge our breakpoints. From here we need to identify such cases and + # handle them so that our internal bookkeeping is correct. + dex_bp_ids = self.get_current_bps(file) + self._update_breakpoint_ids_after_request(dex_bp_ids, result) + + # Function breakpoints. + if self.pending_function_breakpoints: + self.pending_function_breakpoints = False + desired_bps = list(self.function_bp_info.values()) request_id = self.send_message( - self.make_set_breakpoint_request(file, desired_bps) + self.make_set_function_breakpoint_request(desired_bps) ) result = self._await_response(request_id, 10) if not result["success"]: - raise DebuggerException(f"could not set breakpoints for '{file}'") - # The debug adapter may have chosen to merge our breakpoints. From here we need to identify such cases and - # handle them so that our internal bookkeeping is correct. - dex_bp_ids = self.get_current_bps(file) - dap_bp_ids = [bp["id"] for bp in result["body"]["breakpoints"]] - if len(dex_bp_ids) != len(dap_bp_ids): - self.context.logger.error( - f"Sent request to set {len(dex_bp_ids)} breakpoints, but received {len(dap_bp_ids)} in response." + raise DebuggerException( + f"could not set function breakpoints: '{desired_bps}'" ) - visited_dap_ids = set() - for i, dex_bp_id in enumerate(dex_bp_ids): - dap_bp_id = dap_bp_ids[i] - self.dex_id_to_dap_id[dex_bp_id] = dap_bp_id - # We take the mappings in the response as the canonical mapping, meaning that if the debug server has - # simply *changed* the DAP ID for a breakpoint we overwrite the existing mapping rather than adding to - # it, but if we receive the same DAP ID for multiple Dex IDs *then* we store a one-to-many mapping. - if dap_bp_id in visited_dap_ids: - self.dap_id_to_dex_ids[dap_bp_id].append(dex_bp_id) - else: - self.dap_id_to_dex_ids[dap_bp_id] = [dex_bp_id] - visited_dap_ids.add(dap_bp_id) - self.pending_breakpoints = False + # We expect the breakpoint order to match in request and response. + dex_bp_ids = list(self.function_bp_info.keys()) + self._update_breakpoint_ids_after_request(dex_bp_ids, result) + + # Address / instruction breakpoints. + if self.pending_instruction_breakpoints: + self.pending_instruction_breakpoints = False + desired_bps = list(self.instruction_bp_info.values()) + request_id = self.send_message( + self.make_set_instruction_breakpoint_request(desired_bps) + ) + result = self._await_response(request_id, 10) + if not result["success"]: + raise DebuggerException( + f"could not set instruction breakpoints: '{desired_bps}'" + ) + # We expect the breakpoint order to match in request and response. + dex_bp_ids = list(self.instruction_bp_info.keys()) + self._update_breakpoint_ids_after_request(dex_bp_ids, result) def _confirm_triggered_breakpoint_ids(self, dex_bp_ids): """Can be overridden for any specific implementations that need further processing from the debug server's @@ -619,11 +698,12 @@ class DAP(DebuggerBase, metaclass=abc.ABCMeta): # Breakpoints can only have been triggered if we've hit one. stop_reason = self._translate_stop_reason(self._debugger_state.stopped_reason) if stop_reason != StopReason.BREAKPOINT: - return [] + return set() breakpoint_ids = set( [ dex_id for dap_id in self._debugger_state.stopped_bps + if dap_id in self.dap_id_to_dex_ids for dex_id in self.dap_id_to_dex_ids[dap_id] ] ) @@ -632,8 +712,16 @@ class DAP(DebuggerBase, metaclass=abc.ABCMeta): def delete_breakpoints(self, ids): per_file_deletions = defaultdict(list) for dex_bp_id in ids: - source, _, _ = self.bp_info[dex_bp_id] - per_file_deletions[source].append(dex_bp_id) + if dex_bp_id in self.bp_info: + source, _, _ = self.bp_info[dex_bp_id] + per_file_deletions[source].append(dex_bp_id) + elif dex_bp_id in self.function_bp_info: + del self.function_bp_info[dex_bp_id] + self.pending_function_breakpoints = True + elif dex_bp_id in self.instruction_bp_info: + del self.instruction_bp_info[dex_bp_id] + self.pending_instruction_breakpoints = True + for file, deleted_ids in per_file_deletions.items(): old_len = len(self.file_to_bp[file]) self.file_to_bp[file] = [ @@ -651,7 +739,13 @@ class DAP(DebuggerBase, metaclass=abc.ABCMeta): """ "Set the debugger-specific params used in a launch request.""" def launch(self, cmdline): - assert len(self.file_to_bp.keys()) > 0 + # FIXME: Should this be a warning or exception, rather than assert? + assert ( + len(self.file_to_bp) + + len(self.function_bp_info) + + len(self.instruction_bp_info) + > 0 + ), "Expected at least one breakpoint before launching" if self.context.options.target_run_args: cmdline += shlex.split(self.context.options.target_run_args) diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py index bf7552bd5fe3..f8bee4ecb423 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py @@ -166,6 +166,22 @@ class DebuggerBase(object, metaclass=abc.ABCMeta): """Returns a unique opaque breakpoint id.""" pass + def add_function_breakpoint(self, name): + """Returns a unique opaque breakpoint id. + + The ID type depends on the debugger being used, but will probably be + an int. + """ + raise NotImplementedError() + + def add_instruction_breakpoint(self, addr): + """Returns a unique opaque breakpoint id. + + The ID type depends on the debugger being used, but will probably be + an int. + """ + raise NotImplementedError() + @abc.abstractmethod def delete_breakpoints(self, ids): """Delete a set of breakpoints by ids. @@ -217,6 +233,17 @@ class DebuggerBase(object, metaclass=abc.ABCMeta): def evaluate_expression(self, expression, frame_idx=0) -> ValueIR: pass + def get_pc(self, frame_idx: int = 0) -> str: + """Get the current PC in frame at frame_idx depth. + frame_idx 0 is the current function. + """ + r = self.evaluate_expression("$pc", frame_idx) + if not r.could_evaluate or r.is_optimized_away or r.is_irretrievable: + raise DebuggerException( + "evaluating '$pc' failed - possibly unsupported by the debugger" + ) + return r.value + def _external_to_debug_path(self, path): if not self.options.debugger_use_relative_paths: return path diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py index c53f1419ee13..f84c4fd153c7 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py @@ -22,7 +22,7 @@ from dex.debugger.DebuggerControllers.DebuggerControllerBase import ( from dex.debugger.DebuggerBase import DebuggerBase from dex.utils.Exceptions import DebuggerException from dex.utils.Timeout import Timeout - +from dex.dextIR import LocIR class BreakpointRange: """A range of breakpoints and a set of conditions. @@ -51,6 +51,9 @@ class BreakpointRange: values: list, hit_count: int, finish_on_remove: bool, + is_continue: bool = False, + function: str = None, + addr: str = None, ): self.expression = expression self.path = path @@ -60,6 +63,72 @@ class BreakpointRange: self.max_hit_count = hit_count self.current_hit_count = 0 self.finish_on_remove = finish_on_remove + self.is_continue = is_continue + self.function = function + self.addr = addr + + def limit_steps( + expression: str, + path: str, + range_from: int, + range_to: int, + values: list, + hit_count: int, + ): + return BreakpointRange( + expression, + path, + range_from, + range_to, + values, + hit_count, + False, + ) + + def finish_test( + expression: str, path: str, on_line: int, values: list, hit_count: int + ): + return BreakpointRange( + expression, + path, + on_line, + on_line, + values, + hit_count, + True, + ) + + def continue_from_to( + expression: str, + path: str, + from_line: int, + to_line: int, + values: list, + hit_count: int, + ): + return BreakpointRange( + expression, + path, + from_line, + to_line, + values, + hit_count, + finish_on_remove=False, + is_continue=True, + ) + + def step_function(function: str, path: str, hit_count: int): + return BreakpointRange( + None, + path, + None, + None, + None, + hit_count, + finish_on_remove=False, + is_continue=False, + function=function, + ) def has_conditions(self): return self.expression is not None @@ -96,34 +165,40 @@ class ConditionalController(DebuggerControllerBase): def _build_bp_ranges(self): commands = self.step_collection.commands self._bp_ranges = [] - try: - limit_commands = commands["DexLimitSteps"] - for lc in limit_commands: - bpr = BreakpointRange( - lc.expression, - lc.path, - lc.from_line, - lc.to_line, - lc.values, - lc.hit_count, - False, - ) - self._bp_ranges.append(bpr) - except KeyError: + + cond_controller_cmds = ["DexLimitSteps", "DexStepFunction", "DexContinue"] + if not any(c in commands for c in cond_controller_cmds): raise DebuggerException( - "Missing DexLimitSteps commands, cannot conditionally step." + f"No conditional commands {cond_controller_cmds}, cannot conditionally step." ) + + if "DexLimitSteps" in commands: + for c in commands["DexLimitSteps"]: + bpr = BreakpointRange.limit_steps( + c.expression, + c.path, + c.from_line, + c.to_line, + c.values, + c.hit_count, + ) + self._bp_ranges.append(bpr) if "DexFinishTest" in commands: - finish_commands = commands["DexFinishTest"] - for ic in finish_commands: - bpr = BreakpointRange( - ic.expression, - ic.path, - ic.on_line, - ic.on_line, - ic.values, - ic.hit_count + 1, - True, + for c in commands["DexFinishTest"]: + bpr = BreakpointRange.finish_test( + c.expression, c.path, c.on_line, c.values, c.hit_count + 1 + ) + self._bp_ranges.append(bpr) + if "DexContinue" in commands: + for c in commands["DexContinue"]: + bpr = BreakpointRange.continue_from_to( + c.expression, c.path, c.from_line, c.to_line, c.values, c.hit_count + ) + self._bp_ranges.append(bpr) + if "DexStepFunction" in commands: + for c in commands["DexStepFunction"]: + bpr = BreakpointRange.step_function( + c.get_function(), c.path, c.hit_count ) self._bp_ranges.append(bpr) @@ -138,6 +213,9 @@ class ConditionalController(DebuggerControllerBase): bpr.path, bpr.range_from, cond_expr ) self._leading_bp_handles[id] = bpr + elif bpr.function is not None: + id = self.debugger.add_function_breakpoint(bpr.function) + self._leading_bp_handles[id] = bpr else: # Add an unconditional breakpoint. id = self.debugger.add_breakpoint(bpr.path, bpr.range_from) @@ -163,6 +241,9 @@ class ConditionalController(DebuggerControllerBase): timed_out = False total_timeout = Timeout(self.context.options.timeout_total) + step_function_backtraces: list[list[str]] = [] + self.instr_bp_ids = set() + while not self.debugger.is_finished: breakpoint_timeout = Timeout(self.context.options.timeout_breakpoint) while self.debugger.is_running and not timed_out: @@ -185,21 +266,25 @@ class ConditionalController(DebuggerControllerBase): break step_info = self.debugger.get_step_info(self._watches, self._step_index) + backtrace = None if step_info.current_frame: - self._step_index += 1 - update_step_watches( - step_info, self._watches, self.step_collection.commands - ) - self.step_collection.new_step(self.context, step_info) + backtrace = [f.function for f in step_info.frames] + record_step = False + debugger_continue = False bp_to_delete = [] for bp_id in self.debugger.get_triggered_breakpoint_ids(): try: # See if this is one of our leading breakpoints. bpr = self._leading_bp_handles[bp_id] + record_step = True except KeyError: # This is a trailing bp. Mark it for removal. bp_to_delete.append(bp_id) + if bp_id in self.instr_bp_ids: + self.instr_bp_ids.remove(bp_id) + else: + record_step = True continue bpr.add_hit() @@ -208,17 +293,94 @@ class ConditionalController(DebuggerControllerBase): exit_desired = True bp_to_delete.append(bp_id) del self._leading_bp_handles[bp_id] - # Add a range of trailing breakpoints covering the lines - # requested in the DexLimitSteps command. Ignore first line as - # that's covered by the leading bp we just hit and include the - # final line. - for line in range(bpr.range_from + 1, bpr.range_to + 1): - self.debugger.add_breakpoint(bpr.path, line) + + if bpr.function is not None: + if step_info.frames: + # 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 backtrace we'll step-out. + if ( + len(step_function_backtraces) == 0 + or backtrace != step_function_backtraces[-1] + ): + step_function_backtraces.append(backtrace) + + # Add an address breakpoint so we don't fall out + # the end of nested DexStepFunctions with a DexContinue. + addr = self.debugger.get_pc(frame_idx=1) + instr_id = self.debugger.add_instruction_breakpoint(addr) + # Note the breakpoint so we don't log the source location + # it in the trace later. + self.instr_bp_ids.add(instr_id) + + elif bpr.is_continue: + debugger_continue = True + if bpr.range_to is not None: + self.debugger.add_breakpoint(bpr.path, bpr.range_to) + + else: + # Add a range of trailing breakpoints covering the lines + # requested in the DexLimitSteps command. Ignore first line as + # that's covered by the leading bp we just hit and include the + # final line. + for line in range(bpr.range_from + 1, bpr.range_to + 1): + id = self.debugger.add_breakpoint(bpr.path, line) # Remove any trailing or expired leading breakpoints we just hit. self.debugger.delete_breakpoints(bp_to_delete) + debugger_next = False + debugger_out = False + if not debugger_continue and step_info.current_frame and step_info.frames: + while len(step_function_backtraces) > 0: + match_subtrace = False # Backtrace contains a target trace. + match_trace = False # Backtrace matches top of target stack. + + # The top of the step_function_backtraces stack contains a + # backtrace that we want to step through. Check if the + # current backtrace ("backtrace") either matches that trace + # or otherwise contains it. + target_backtrace = step_function_backtraces[-1] + if len(backtrace) >= len(target_backtrace): + match_trace = len(backtrace) == len(target_backtrace) + # Check if backtrace contains target_backtrace, matching + # from the end (bottom of call stack) backwards. + match_subtrace = ( + backtrace[-len(target_backtrace) :] == target_backtrace + ) + + if match_trace: + # We want to step through this function; do so and + # log the steps in the step trace. + debugger_next = True + record_step = True + break + elif match_subtrace: + # There's a function we care about buried in the + # current backtrace. Step-out until we get to it. + debugger_out = True + break + else: + # Drop backtraces that are not match_subtraces of the current + # backtrace; the functions we wanted to step through + # there are no longer reachable. + step_function_backtraces.pop() + + if record_step and step_info.current_frame: + self._step_index += 1 + # Record the step. + update_step_watches( + step_info, self._watches, self.step_collection.commands + ) + self.step_collection.new_step(self.context, step_info) + if exit_desired: break - self.debugger.go() + elif debugger_next: + self.debugger.step_next() + elif debugger_out: + self.debugger.step_out() + else: + self.debugger.go() time.sleep(self._pause_between_steps) diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py index 4263fdb5aa01..73b2a4dd36d0 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py @@ -232,7 +232,7 @@ class LLDB(DebuggerBase): ): stepped_to_breakpoint = True if stepped_to_breakpoint: - self._thread.StepInto() + self._process.Continue() def go(self) -> ReturnCode: self._process.Continue() @@ -431,8 +431,15 @@ class LLDBDAP(DAP): if not trace_response["success"]: raise DebuggerException("failed to get stack frames") stackframes = trace_response["body"]["stackFrames"] - path = stackframes[0]["source"]["path"] addr = stackframes[0]["instructionPointerReference"] + try: + path = stackframes[0]["source"]["path"] + except KeyError: + # We may have no path, e.g., if the module hasn't loaded or + # there's no debug info. If that's the case we won't have + # bound a source-location breakpoint here, so we can bail now. + return + if any( self._debugger_state.bp_addr_map.get(self.dex_id_to_dap_id[dex_bp_id]) == addr @@ -441,7 +448,7 @@ class LLDBDAP(DAP): # Step again now to get to the breakpoint. step_req_id = self.send_message( self.make_request( - "stepIn", {"threadId": self._debugger_state.thread} + "continue", {"threadId": self._debugger_state.thread} ) ) response = self._await_response(step_req_id) @@ -528,6 +535,16 @@ class LLDBDAP(DAP): manually check conditions here.""" confirmed_breakpoint_ids = set() for dex_bp_id in dex_bp_ids: + # Function and instruction breakpoints don't use conditions. + # FIXME: That's not a DAP restriction, so they could in future. + if dex_bp_id not in self.bp_info: + assert ( + dex_bp_id in self.function_bp_info + or dex_bp_id in self.instruction_bp_info + ) + confirmed_breakpoint_ids.add(dex_bp_id) + continue + _, _, cond = self.bp_info[dex_bp_id] if cond is None: confirmed_breakpoint_ids.add(dex_bp_id) diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/tools/test/Tool.py b/cross-project-tests/debuginfo-tests/dexter/dex/tools/test/Tool.py index c366062cec7a..693c05b97af7 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/tools/test/Tool.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/tools/test/Tool.py @@ -121,7 +121,8 @@ class Tool(TestToolBase): self.context.options.source_files.extend(list(new_source_files)) - if "DexLimitSteps" in step_collection.commands: + cond_controller_cmds = ["DexLimitSteps", "DexStepFunction", "DexContinue"] + if any(c in step_collection.commands for c in cond_controller_cmds): debugger_controller = ConditionalController(self.context, step_collection) else: debugger_controller = DefaultController(self.context, step_collection) 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 new file mode 100644 index 000000000000..2d5cbe04569d --- /dev/null +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/control/dex-continue.cpp @@ -0,0 +1,64 @@ +// Purpose: +// Test \DexStepFunction usage with \DexContinue. Continuing out of `c` +// should result in stepping resuming in `a` (check there's no issue when +// `b` is inlined). Then continuing out of `a` should run on to `f` where +// stepping resumes again. Stepping out of `f` into `main`, run free +// again until the program exits. +// +// This command is only implemented for debuggers with DAP support. +// UNSUPPORTED: system-windows +// +// RUN: %dexter_regression_test_cxx_build %s -o %t +// RUN: %dexter_regression_test_run -v --binary %t -- %s 2>&1 | FileCheck %s + +int g = 0; +int c(int) { + ++g; + ++g; + ++g; + ++g; + ++g; + return 0; +} + +__attribute__((always_inline)) +int b(int) { + ++g; + return c(g); +} + +int a(int) { + ++g; + b(g); + ++g; + return g; +} + +void f() { + ++g; +} + +int main() { + int x = a(g); + f(); + return x; +} + +// DexStepFunction('c') +// DexContinue(from_line=17, to_line=19) +// DexContinue(from_line=20) +// DexStepFunction('a') +// DexContinue(from_line=33) +// 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: . [7, "f()", "{{.*}}dex-continue.cpp", 38, 3, "StopReason.BREAKPOINT", "StepKind.VERTICAL_FORWARD", []] +// CHECK-NEXT: . [8, "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 new file mode 100644 index 000000000000..900e10b64a96 --- /dev/null +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/control/dex_step_function.cpp @@ -0,0 +1,39 @@ +// Purpose: +// \DexStepFunction smoke test. Only steps in a and c should be logged. +// +// This command is only implemented for debuggers with DAP support. +// UNSUPPORTED: system-windows +// +// RUN: %dexter_regression_test_cxx_build %s -o %t +// RUN: %dexter_regression_test_run -v --binary %t -- %s 2>&1 | FileCheck %s + +int g = 0; +int c(int) { + ++g; + return 0; +} + +int b(int) { + ++g; + return c(g); +} + +int a(int) { + ++g; + return b(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:. [4, "a(int)", "{{.*}}dex_step_function.cpp", 23, 3, "StopReason.STEP", "StepKind.HORIZONTAL_BACKWARD", []] +// CHECK-NEXT: ## END (5 steps) ## diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/dex_declare_address/expression_address.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/dex_declare_address/expression_address.cpp index 2bb83850e2a1..0f4463338bba 100644 --- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/dex_declare_address/expression_address.cpp +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/dex_declare_address/expression_address.cpp @@ -14,4 +14,4 @@ int main() { // DexDeclareAddress('x_addr', '&x', on_line=ref('test_line')) // DexExpectWatchValue('&x', address('x_addr'), on_line=ref('test_line')) -// DexExpectWatchValue('&y', address('x_addr'), on_line=ref('test_line')) +// DexExpectWatchValue('y', address('x_addr'), on_line=ref('test_line')) diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/dex_finish_test/limit_steps_simple.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/dex_finish_test/limit_steps_simple.cpp index 27505d5a3f5a..923f596ab84e 100644 --- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/dex_finish_test/limit_steps_simple.cpp +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/dex_finish_test/limit_steps_simple.cpp @@ -12,10 +12,11 @@ // CHECK: limit_steps_simple.cpp int main() { - int x = 0; // DexLabel('start') - x = 1; + int x = 0; + x = 1; // DexLabel('start') x = 2; // DexLabel('finish_line') -} // DexLabel('finish') + return 0; // DexLabel('finish') +} // DexLimitSteps(from_line=ref('start'), to_line=ref('finish')) // DexFinishTest(on_line=ref('finish_line')) diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_label_kwarg.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_label_kwarg.cpp index b0bd50a248d1..da1573525253 100644 --- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_label_kwarg.cpp +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_label_kwarg.cpp @@ -2,7 +2,7 @@ // Check that bad keyword args in \DexLabel are reported. // Use --binary switch to trick dexter into skipping the build step. // -// RUN: not %dexter_base test --binary %s --debugger 'lldb' -- %s | FileCheck %s +// RUN: not %dexter_base test --binary %s %dexter_regression_test_debugger_args -- %s | FileCheck %s // CHECK: parser error:{{.*}}err_label_kwarg.cpp(8): unexpected named args: bad_arg // DexLabel('test', bad_arg=0) diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_limit_steps_no_values.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_limit_steps_no_values.cpp index 64e41495ece1..978450eeb8cd 100644 --- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_limit_steps_no_values.cpp +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_limit_steps_no_values.cpp @@ -3,7 +3,7 @@ // in a \DexLimitSteps command results in a useful error message. // Use --binary switch to trick dexter into skipping the build step. // -// RUN: not %dexter_base test --binary %s --debugger 'lldb' -- %s | FileCheck %s +// RUN: not %dexter_base test --binary %s %dexter_regression_test_debugger_args -- %s | FileCheck %s // CHECK: parser error:{{.*}}err_limit_steps_no_values.cpp(9): expected 0 or at least 2 positional arguments // DexLimitSteps('test') diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_paren.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_paren.cpp index 5a35b3a512be..e80b34da24ac 100644 --- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_paren.cpp +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_paren.cpp @@ -4,14 +4,11 @@ // Check directives are in check.txt to prevent dexter reading any embedded // commands. // -// Note: Despite using 'lldb' as the debugger, lldb is not actually required -// as the test should finish before lldb would be invoked. -// // RUN: %dexter_regression_test_cxx_build %s -o %t -// RUN: not %dexter_base test --binary %t --debugger 'lldb' \ +// RUN: not %dexter_base test --binary %t %dexter_regression_test_debugger_args \ // RUN: -v -- %s | FileCheck %s --match-full-lines --strict-whitespace // -// CHECK:parser error:{{.*}}err_paren.cpp(22): Unbalanced parenthesis starting here +// CHECK:parser error:{{.*}}err_paren.cpp(19): Unbalanced parenthesis starting here // CHECK:// {{Dex}}ExpectWatchValue( // CHECK: ^ diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_paren_mline.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_paren_mline.cpp index 0044b3b6eff0..8d5a9b057599 100644 --- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_paren_mline.cpp +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_paren_mline.cpp @@ -4,14 +4,11 @@ // Check directives are in check.txt to prevent dexter reading any embedded // commands. // -// Note: Despite using 'lldb' as the debugger, lldb is not actually required -// as the test should finish before lldb would be invoked. -// // RUN: %dexter_regression_test_cxx_build %s -o %t -// RUN: not %dexter_base test --binary %t --debugger "lldb" \ +// RUN: not %dexter_base test --binary %t %dexter_regression_test_debugger_args \ // RUN: -v -- %s | FileCheck %s --match-full-lines --strict-whitespace // -// CHECK:parser error:{{.*}}err_paren_mline.cpp(23): Unbalanced parenthesis starting here +// CHECK:parser error:{{.*}}err_paren_mline.cpp(20): Unbalanced parenthesis starting here // CHECK:{{Dex}}ExpectWatchValue( // CHECK: ^ diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_syntax.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_syntax.cpp index 599202544213..7e019df26e9b 100644 --- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_syntax.cpp +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_syntax.cpp @@ -4,14 +4,11 @@ // Check directives are in check.txt to prevent dexter reading any embedded // commands. // -// Note: Despite using 'lldb' as the debugger, lldb is not actually required -// as the test should finish before lldb would be invoked. -// // RUN: %dexter_regression_test_cxx_build %s -o %t -// RUN: not %dexter_base test --binary %t --debugger "lldb" \ +// RUN: not %dexter_base test --binary %t %dexter_regression_test_debugger_args \ // RUN: -v -- %s | FileCheck %s --match-full-lines --strict-whitespace // -// CHECK:parser error:{{.*}}err_syntax.cpp(21): invalid syntax +// CHECK:parser error:{{.*}}err_syntax.cpp(18): invalid syntax // CHECK:// {{Dex}}ExpectWatchValue(,'a', 3, 3, 3, 3, on_line=0) // CHECK: ^ diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_syntax_dexdeclarefile.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_syntax_dexdeclarefile.cpp index 40cc1581f85f..0fdf255eded8 100644 --- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_syntax_dexdeclarefile.cpp +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_syntax_dexdeclarefile.cpp @@ -3,7 +3,7 @@ // they appeared in rather than the current declared file. // // RUN: %dexter_regression_test_cxx_build %s -o %t -// RUN: not %dexter_base test --binary %t --debugger 'lldb' -v -- %s \ +// RUN: not %dexter_base test --binary %t %dexter_regression_test_debugger_args -v -- %s \ // RUN: | FileCheck %s --implicit-check-not=FAIL-FILENAME-MATCH // CHECK: err_syntax_dexdeclarefile.cpp(14): Undeclared address: 'not_been_declared' diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_syntax_mline.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_syntax_mline.cpp index 71b23a2a3a8b..342f2a53010e 100644 --- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_syntax_mline.cpp +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_syntax_mline.cpp @@ -4,14 +4,11 @@ // Check directives are in check.txt to prevent dexter reading any embedded // commands. // -// Note: Despite using 'lldb' as the debugger, lldb is not actually required -// as the test should finish before lldb would be invoked. -// // RUN: %dexter_regression_test_cxx_build %s -o %t -// RUN: not %dexter_base test --binary %t --debugger "lldb" \ +// RUN: not %dexter_base test --binary %t %dexter_regression_test_debugger_args \ // RUN: -v -- %s | FileCheck %s --match-full-lines --strict-whitespace // -// CHECK:parser error:{{.*}}err_syntax_mline.cpp(24): invalid syntax +// CHECK:parser error:{{.*}}err_syntax_mline.cpp(21): invalid syntax // CHECK: ,'a', 3, 3, 3, 3, on_line=0) // CHECK: ^ diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_type.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_type.cpp index 264515496f1c..286530410193 100644 --- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_type.cpp +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_type.cpp @@ -4,14 +4,11 @@ // Check directives are in check.txt to prevent dexter reading any embedded // commands. // -// Note: Despite using 'lldb' as the debugger, lldb is not actually required -// as the test should finish before lldb would be invoked. -// // RUN: %dexter_regression_test_cxx_build %s -o %t -// RUN: not %dexter_base test --binary %t --debugger "lldb" \ +// RUN: not %dexter_base test --binary %t %dexter_regression_test_debugger_args \ // RUN: -v -- %s | FileCheck %s --match-full-lines --strict-whitespace // -// CHECK:parser error:{{.*}}err_type.cpp(21): expected at least two args +// CHECK:parser error:{{.*}}err_type.cpp(18): expected at least two args // CHECK:// {{Dex}}ExpectWatchValue() // CHECK: ^ diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_type_mline.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_type_mline.cpp index 5cbcd2d88808..1062d2816b39 100644 --- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_type_mline.cpp +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/err_type_mline.cpp @@ -4,14 +4,11 @@ // Check directives are in check.txt to prevent dexter reading any embedded // commands. // -// Note: Despite using 'lldb' as the debugger, lldb is not actually required -// as the test should finish before lldb would be invoked. -// // RUN: %dexter_regression_test_cxx_build %s -o %t -// RUN: not %dexter_base test --binary %t --debugger "lldb" \ +// RUN: not %dexter_base test --binary %t %dexter_regression_test_debugger_args \ // RUN: -v -- %s | FileCheck %s --match-full-lines --strict-whitespace // -// CHECK:parser error:{{.*}}err_type_mline.cpp(22): expected at least two args +// CHECK:parser error:{{.*}}err_type_mline.cpp(19): expected at least two args // CHECK:{{Dex}}ExpectWatchValue( // CHECK: ^ diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/source-root-dir.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/source-root-dir.cpp index af24c5d8e572..edbafdc6bfc1 100644 --- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/source-root-dir.cpp +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/test/source-root-dir.cpp @@ -2,10 +2,8 @@ // XFAIL:* // RUN: %dexter_regression_test_cxx_build \ // RUN: -fdebug-prefix-map=%S=/changed %s -o %t -// RUN: %dexter --fail-lt 1.0 -w \ -// RUN: --binary %t \ -// RUN: --debugger %dexter_regression_test_debugger \ -// RUN: --source-root-dir=%S --debugger-use-relative-paths -- %s +// RUN: %dexter_regression_test_run \ +// RUN: --binary %t --source-root-dir=%S --debugger-use-relative-paths -- %s #include <stdio.h> int main() { diff --git a/cross-project-tests/lit.cfg.py b/cross-project-tests/lit.cfg.py index a3af729f8fff..b783f6639c93 100644 --- a/cross-project-tests/lit.cfg.py +++ b/cross-project-tests/lit.cfg.py @@ -102,9 +102,8 @@ if "compiler-rt" in config.llvm_enabled_projects: config.available_features.add("compiler-rt") # Check which debuggers are available: -lldb_path = llvm_config.use_llvm_tool("lldb", search_env="LLDB") - -if lldb_path is not None: +lldb_dap_path = llvm_config.use_llvm_tool("lldb-dap") +if lldb_dap_path is not None: config.available_features.add("lldb") if llvm_config.use_llvm_tool("llvm-ar"): @@ -117,10 +116,14 @@ def configure_dexter_substitutions(): dexter_path = os.path.join( config.cross_project_tests_src_root, "debuginfo-tests", "dexter", "dexter.py" ) - dexter_test_cmd = '"{}" "{}" test'.format(sys.executable, dexter_path) - if lldb_path is not None: - dexter_test_cmd += ' --lldb-executable "{}"'.format(lldb_path) - tools.append(ToolSubst("%dexter", dexter_test_cmd)) + tools.append(ToolSubst("%dexter", f'"{sys.executable}" "{dexter_path}" test')) + if lldb_dap_path is not None: + tools.append( + ToolSubst( + "%dexter_lldb_args", + f'--lldb-executable "{lldb_dap_path}" --debugger lldb-dap', + ) + ) # For testing other bits of dexter that aren't under the "test" subcommand, # have a %dexter_base substitution. @@ -144,33 +147,17 @@ def configure_dexter_substitutions(): dependencies = ["clang", "lldb"] dexter_regression_test_c_builder = "clang" dexter_regression_test_cxx_builder = "clang++" - dexter_regression_test_debugger = "lldb" + dexter_regression_test_debugger = "lldb-dap" + dexter_regression_test_additional_flags = f'--lldb-executable "{lldb_dap_path}"' dexter_regression_test_c_flags = "-O0 -glldb -std=gnu11" dexter_regression_test_cxx_flags = "-O0 -glldb -std=gnu++11" - dexter_regression_test_additional_flags = '--lldb-executable "{}"'.format( - lldb_path - ) tools.append( - ToolSubst("%dexter_regression_test_c_builder", dexter_regression_test_c_builder) - ) - tools.append( ToolSubst( - "%dexter_regression_test_cxx_builder", dexter_regression_test_cxx_builder + "%dexter_regression_test_debugger_args", + f"--debugger {dexter_regression_test_debugger} {dexter_regression_test_additional_flags}", ) ) - tools.append( - ToolSubst("%dexter_regression_test_debugger", dexter_regression_test_debugger) - ) - # We don't need to distinguish cflags and ldflags because for Dexter - # regression tests we use clang to drive the linker, and so all flags will be - # passed in a single command. - tools.append( - ToolSubst("%dexter_regression_test_c_flags", dexter_regression_test_c_flags) - ) - tools.append( - ToolSubst("%dexter_regression_test_cxx_flags", dexter_regression_test_cxx_flags) - ) # Typical command would take the form: # ./path_to_py/python.exe ./path_to_dex/dexter.py test --fail-lt 1.0 -w --binary %t --debugger lldb --cflags '-O0 -g' |
