是否只有当调用堆栈中存在某个方法时才可以在断点处中断?
Is it possible to break on a breakpoint only when a certain method is present in the call stack?
假设我有一个方法 foo
,在遍历对象的层次结构时被不同的方法调用。
是否可以在方法 foo
内部中断,只有当它被方法 bar
调用时(所以 bar
存在于调用堆栈中)?
LLDB 或 GDB 是否支持这样的用例?
在 GDB 中,您可以将调试器 command list 关联到一个断点,因此为了实现您的目的,您可以在 bar()
中放置一个断点,它使用命令列表调用 foo()
在 foo()
中设置断点并继续。在 bar()
中的另一个断点在 其对 foo()
的调用之后将需要清除 foo()
.
中的断点
所以:
int bar()
{
foo() ; // Add breakpoint with command list here to set breakpoint in foo()
return 0 ; // Add breakpoint command list here to clear breakpoint in foo()
}
当然,如果这种情况很少发生,您可以手动设置断点。
如果foo()
不是直接从bar()
调用,或者可能foo()
是从bar()
的多个地方调用,那么同样的解决方案适用;如果 bar()
在开始设置断点并在结束时清除它就足够了。
一个警告;如果应用程序是多线程的,并且可以从多个线程调用 bar()
或 foo()
,那么您将需要一个 thread specific breakpoint.
最新版本的 gdb 附带了一些用 Python 编写的便利函数,就是为了这种情况。看看$_caller_is
和朋友们。 (FWIW 这个确切的用例是促使我努力将 Python 添加到 gdb 的原因......)
一个简单的用法是:
(gdb) break foo if $_any_caller_matches("bar")
如果调用堆栈在 foo
和 bar
调用之间包含更多函数,导致堆栈如下所示,
foo()
...
...
...
bar()
...
...
...
main()
您可以向 _any_caller_matches
传递一个额外的参数,它指示要检查 bar
出现的帧数
(gdb) break foo if $_any_caller_matches("bar", 10)
参考:https://sourceware.org/gdb/current/onlinedocs/gdb/Convenience-Funs.html
$_any_caller_matches(regexp[, number_of_frames])
Returns one if any
calling function’s name matches the regular expression regexp.
Otherwise it returns zero.
If the optional argument number_of_frames is provided, it is the
number of frames up in the stack to look. The default is 1.
This function differs from $_caller_matches in that this function
checks all stack frames from the immediate caller to the frame
specified by number_of_frames, whereas $_caller_matches only checks
the frame specified by number_of_frames.
您在 lldb 中执行此操作的方法是编写一个基于 Python 的断点命令,该命令检查遇到断点的线程的堆栈,如果它不包含具有该函数的帧则继续.断点命令通过分别从函数返回 True 或 False 来告诉 lldb 是否停止。因此,一种非常简单的方法是制作一个 Python 文件 (break_here.py):
import lldb
desired_func = "some_func"
def break_here(frame, bp_loc, dict):
thread = frame.thread
for frame in thread.frames:
if frame.name == desired_func:
return True
return False
假设这个文件在/tmp。然后在 lldb 中你做:
(lldb) com scr imp /tmp/break_here.py
(lldb) br s -n whatever
(lldb) br com add --python-function break_here.break_here
假设我有一个方法 foo
,在遍历对象的层次结构时被不同的方法调用。
是否可以在方法 foo
内部中断,只有当它被方法 bar
调用时(所以 bar
存在于调用堆栈中)?
LLDB 或 GDB 是否支持这样的用例?
在 GDB 中,您可以将调试器 command list 关联到一个断点,因此为了实现您的目的,您可以在 bar()
中放置一个断点,它使用命令列表调用 foo()
在 foo()
中设置断点并继续。在 bar()
中的另一个断点在 其对 foo()
的调用之后将需要清除 foo()
.
所以:
int bar()
{
foo() ; // Add breakpoint with command list here to set breakpoint in foo()
return 0 ; // Add breakpoint command list here to clear breakpoint in foo()
}
当然,如果这种情况很少发生,您可以手动设置断点。
如果foo()
不是直接从bar()
调用,或者可能foo()
是从bar()
的多个地方调用,那么同样的解决方案适用;如果 bar()
在开始设置断点并在结束时清除它就足够了。
一个警告;如果应用程序是多线程的,并且可以从多个线程调用 bar()
或 foo()
,那么您将需要一个 thread specific breakpoint.
最新版本的 gdb 附带了一些用 Python 编写的便利函数,就是为了这种情况。看看$_caller_is
和朋友们。 (FWIW 这个确切的用例是促使我努力将 Python 添加到 gdb 的原因......)
一个简单的用法是:
(gdb) break foo if $_any_caller_matches("bar")
如果调用堆栈在 foo
和 bar
调用之间包含更多函数,导致堆栈如下所示,
foo()
...
...
...
bar()
...
...
...
main()
您可以向 _any_caller_matches
传递一个额外的参数,它指示要检查 bar
(gdb) break foo if $_any_caller_matches("bar", 10)
参考:https://sourceware.org/gdb/current/onlinedocs/gdb/Convenience-Funs.html
$_any_caller_matches(regexp[, number_of_frames])
Returns one if any calling function’s name matches the regular expression regexp. Otherwise it returns zero.
If the optional argument number_of_frames is provided, it is the number of frames up in the stack to look. The default is 1.
This function differs from $_caller_matches in that this function checks all stack frames from the immediate caller to the frame specified by number_of_frames, whereas $_caller_matches only checks the frame specified by number_of_frames.
您在 lldb 中执行此操作的方法是编写一个基于 Python 的断点命令,该命令检查遇到断点的线程的堆栈,如果它不包含具有该函数的帧则继续.断点命令通过分别从函数返回 True 或 False 来告诉 lldb 是否停止。因此,一种非常简单的方法是制作一个 Python 文件 (break_here.py):
import lldb
desired_func = "some_func"
def break_here(frame, bp_loc, dict):
thread = frame.thread
for frame in thread.frames:
if frame.name == desired_func:
return True
return False
假设这个文件在/tmp。然后在 lldb 中你做:
(lldb) com scr imp /tmp/break_here.py
(lldb) br s -n whatever
(lldb) br com add --python-function break_here.break_here