2014-11-05 94 views
3

我只想在堆栈经过特定函数时抛出异常时使用GDB中断。从特定函数调用时引发的异常GDB中断

我的使用情况是,我有一个Thread类,其doRun()函数被调用一个新的线程。该线程捕捉到任何异常,但我希望能够在抛出异常时捕获异常(未捕获)。我知道GDB可以做“反向调试”(真棒概念),所以这可能会被使用,但我想要更通用的东西 - 事实上,我希望这个解决方案能够找到我的方式.gdbinit文件。

+0

也许你可以在异常的构造函数上设置一个断点? – bialpio 2014-11-05 19:48:44

+0

我想捕捉任何类型的异常,但这可能会帮助我追踪这个特定的问题... – notlesh 2014-11-05 20:59:10

回答

6

最近GDB的版本有是这个有用的一些便利功能,例如“$ _any_caller_matches”。这些都是用Python编写的,所以即使你的gdb没有内置的代码,你也可以抓住代码并放到你的gdb中。

你会用它喜欢(未经测试,但你的想法):

catch throw if $_any_caller_matches("Thread::doRun") 
+0

谢谢,这看起来很有希望。你的确切声明不起作用(总是捕捉抛出),但我会玩它。 – notlesh 2014-11-05 22:14:48

+0

此外,我发现我真正想要的是只有在特定的地方捕捉到“扔”。但这也会有用。 – notlesh 2014-11-05 22:15:31

+0

根据文档,它应该只是'$ caller_matches'。 – Qix 2014-11-05 23:21:41

5

它不会出现$caller_matches(或它的姐妹功能$caller_is)包含在基本安装GDB的。


来吧,加入source code到您的GDB Python函数的文件夹。

此文件夹中/usr/share/gdb/python/gdb/function通常发现;文件名应该是caller_is.py

请注意,使用$caller_matches时,底层实现使用re.match,因此请确保您传递的字符串与该函数一起使用。

同样,两个功能有一个可选的第二个参数,默认为1,即指定有多少了堆栈遍历(样子)。这意味着如果省略它,它将仅检查直接当前函数的调用者。如果你想检查特定的堆栈位置(例如,如果你想检查祖父母打电话的人),使用2,3等。

我已经在下面的源代码中。

# Caller-is functions. 

# Copyright (C) 2008 Free Software Foundation, Inc. 

# This program is free software; you can redistribute it and/or modify 
# it under the terms of the GNU General Public License as published by 
# the Free Software Foundation; either version 3 of the License, or 
# (at your option) any later version. 
# 
# This program is distributed in the hope that it will be useful, 
# but WITHOUT ANY WARRANTY; without even the implied warranty of 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
# GNU General Public License for more details. 
# 
# You should have received a copy of the GNU General Public License 
# along with this program. If not, see <http://www.gnu.org/licenses/>. 

import gdb 
import re 

class CallerIs (gdb.Function): 
    """Return True if the calling function's name is equal to a string. 
This function takes one or two arguments. 
The first argument is the name of a function; if the calling function's 
name is equal to this argument, this function returns True. 
The optional second argument tells this function how many stack frames 
to traverse to find the calling function. The default is 1.""" 

    def __init__ (self): 
     super (CallerIs, self).__init__ ("caller_is") 

    def invoke (self, name, nframes = 1): 
     frame = gdb.selected_frame() 
     while nframes > 0: 
      frame = frame.older() 
      nframes = nframes - 1 
     return frame.name() == name.string() 

class CallerMatches (gdb.Function): 
    """Return True if the calling function's name matches a string. 
This function takes one or two arguments. 
The first argument is a regular expression; if the calling function's 
name is matched by this argument, this function returns True. 
The optional second argument tells this function how many stack frames 
to traverse to find the calling function. The default is 1.""" 

    def __init__ (self): 
     super (CallerMatches, self).__init__ ("caller_matches") 

    def invoke (self, name, nframes = 1): 
     frame = gdb.selected_frame() 
     while nframes > 0: 
      frame = frame.older() 
      nframes = nframes - 1 
     return re.match (name.string(), frame.name()) is not None 

CallerIs() 
CallerMatches() 
+0

太奇怪了!我从9月份开始在我的树上,但现在确实没有看到它在上游。我不知道发生了什么。 – 2014-11-06 15:00:07