llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.03k stars 11.97k forks source link

Teach 'br set' a new option: stop if the stack matches a given stack-pattern #20482

Open llvmbot opened 10 years ago

llvmbot commented 10 years ago
Bugzilla Link 20108
Version unspecified
OS All
Reporter LLVM Bugzilla Contributor

Extended Description

Suppose a future lldb provides a built-in command, 'stackpat', which takes a name argument that can later be used to refer to a pattern---given as a multi-line sequence when the command is entered---that matches zero or more stacks.

As a convenience, stackpat would also take an option, -b, that causes the topmost frame of the pattern to be implicitly passed either to 'br set' or to _regexp-break.

Example session:

% cat -n foo.c 1 void h() {} 2 void g() { h(); } 3 void f() { h(); g(); } 4 int main(int argc, char *argv[]) 5 { 6 h(); 7 g(); 8 f(); 9 return 0; 10 } % cc -g foo.c -o a.out % lldb -x ./a.out Current executable set to './a.out' (x86_64). (lldb) stackpat x -b Enter frame patterns (just like args to 'breakpoint set' or 'b'). Type DONE to end.

h g f DONE Breakpoint 1: where = a.out`h + 4 at foo.c:1, address = 0x0000000100000f44, stackpat=x (lldb) process launch Process 55500 launched: './a.out' (x86_64) Process 55500 stopped

  • thread #​1: tid = 0x1c8077, 0x0000000100000f44 a.outh + 4 at foo.c:1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #​0: 0x0000000100000f44 a.outh + 4 at foo.c:1 -> 1 void h() {} 2 void g() { h(); } 3 void f() { h(); g(); } 4 int main(int argc, char *argv[]) 5 { 6 h(); 7 g(); (lldb) bt
  • thread #​1: tid = 0x1c8077, 0x0000000100000f44 a.out`h + 4 at foo.c:1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  • frame #​0: 0x0000000100000f44 a.outh + 4 at foo.c:1 frame #​1: 0x0000000100000f59 a.outg + 9 at foo.c:2 frame #​2: 0x0000000100000f6e a.outf + 14 at foo.c:3 frame #​3: 0x0000000100000f95 a.outmain(argc=1, argv=0x00007fff5fbfebc0) + 37 at foo.c:8 (lldb)

Here's an example with C++, where it isn't always clear which template arguments you want to use in the function name regex. Example:

% cat -n foo.cpp 1 2 namespace Some_lib_impl 3 { 4 struct apparently_unrelated_class {}; 5 } 6 7 namespace N 8 { 9 template 10 struct stuff { typedef Some_lib_impl::apparently_unrelated_class U; }; 11 } / N / 12 13 14 template void tn() {} 15 template void t2() { tn< typename N::stuff::U >(); } 16 template void t1() { t2(); } 17 template void t0() { t1(); } 18 int main(int argc, char *argv[]) 19 { 20 tn(); 21 t0(); 22 return 0; 23 } % cc -g foo.cpp % lldb -x ./a.out Current executable set to './a.out' (x86_64). (lldb) stackpat y -b Enter frame patterns (just like args to 'breakpoint set' or 'b'). Type DONE to end.

tn ... t0 main DONE Breakpoint 1: 1 location, stackpat = y (lldb) r Process 55605 launched: './a.out' (x86_64) Process 55605 stopped

  • thread #​1: tid = 0x1ca1b3, 0x0000000100000f64 a.outvoid tn<__Some_lib_impl::apparently_unrelated_class>() + 4 at foo.cpp:14, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #&#8203;0: 0x0000000100000f64 a.outvoid tn<__Some_lib_impl::apparently_unrelated_class>() + 4 at foo.cpp:14 11 } / N / 12 13 -> 14 template void tn() {} 15 template void t2() { tn< typename N::stuff::U >(); } 16 template void t1() { t2(); } 17 template void t0() { t1(); } (lldb) bt
  • thread #​1: tid = 0x1ca1b3, 0x0000000100000f64 a.out`void tn<__Some_lib_impl::apparently_unrelated_class>() + 4 at foo.cpp:14, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
  • frame #​0: 0x0000000100000f64 a.outvoid tn<__Some_lib_impl::apparently_unrelated_class>() + 4 at foo.cpp:14 frame #&#8203;1: 0x0000000100000f59 a.outvoid t2() + 9 at foo.cpp:15 frame #​2: 0x0000000100000f49 a.outvoid t1<double>() + 9 at foo.cpp:16 frame #&#8203;3: 0x0000000100000f39 a.outvoid t0() + 9 at foo.cpp:17 frame #​4: 0x0000000100000f10 a.out`main(argc=1, argv=0x00007fff5fbfebd0) + 32 at foo.cpp:21 (lldb)

The stackpat name ("x", "y" above) could then be re-used in other 'br set' commands or in other stackpat commands.

llvmbot commented 10 years ago

Also: the ellipsis in the template example should be read as literal text. So, to match an indirect call from f to g through zero or more frames, use:

(lldb) stackpat fg

g ... f DONE

Then break in direct callees of g() with:

(lldb) br set -n helper_bar --stackpat=fg (lldb) br set -n helper_baz --stackpat=fg