中断 gdb (llvm) 中的命名空间函数

Posted

技术标签:

【中文标题】中断 gdb (llvm) 中的命名空间函数【英文标题】:Break on namespace function in gdb (llvm) 【发布时间】:2014-05-14 15:42:13 【问题描述】:

我正在尝试逐步完成 llvm 的 opt 程序(用于作业),讲师建议在 runOnFunction 处设置断点。我在其中一个文件中看到了这一点:

bool InstCombiner::runOnFunction(Function &F)  /* (Code removed for SO) */ 

但 gdb 似乎没有找到 runOnFunction 断点。我突然想到问题可能出在名称空间上?我试过了,但 gdb 永远不会中断,它只是创建 fooOpt.s 文件:

(gdb) b runOnFunction
Function "runOnFunction" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (runOnFunction) pending.
(gdb) r -S -instcombine -debug -o ~/Desktop/fooOpt.s ~/Desktop/foo.s

我在 Mac 上,所以我没有 objdump,但 otool 产生了 560 万行,因为 runOnFunction 不止一次出现在那里,因此作为起点涉水似乎并不合理。

【问题讨论】:

InstCombiner 不是命名空间,它是类。它是来自llvm 命名空间的类llvm::InstCombiner。因此,正确的命令可能听起来像 break 'llvm::InstCombiner::runOnFunction(llvm::Function &F)' 甚至只是 break sourceFile.cpp:line,其中 line 是 runOnFunction 中的第一条语句 【参考方案1】:

Gdb 有几个内置命令来查找这些函数的名称。首先是info functions,它可以与可选的regexp参数一起使用来grep所有可用的函数,https://sourceware.org/gdb/current/onlinedocs/gdb/Symbols.html

info functions regexp

打印名称包含正则表达式正则表达式匹配的所有已定义函数的名称和数据类型。因此,‘info fun step’会查找名称中包含 step 的所有函数; 'info fun ^step' 查找名称以 step 开头的人。如果函数名包含与正则表达式语言冲突的字符(例如“operator*()”),则可以用反斜杠将它们引用。

所以,您可以尝试info functions runOnFunction 来获取名称。有时在执行break 命令时在名称周围添加引号会很有用。

另一种方法是使用rbreak 命令代替break (b)。 rbreak 将在函数名称中进行正则表达式搜索,并可能定义多个断点:https://sourceware.org/gdb/current/onlinedocs/gdb/Set-Breaks.html#Set-Breaks

rbreak regex

在所有匹配正则表达式正则表达式的函数上设置断点。此命令在所有匹配项上设置一个无条件断点,打印它设置的所有断点的列表。 ...

正则表达式的语法是与 grep 等工具一起使用的标准语法。请注意,这与 shell 使用的语法不同,例如 foo* 匹配所有包含 fo 后跟零个或多个 os 的函数。您提供的正则表达式有一个隐含的 .* 前导和尾随,因此要仅匹配以 foo 开头的函数,请使用 ^foo。

(甚至rbreak file:regex 将搜索限制为单个源文件)

PS:如果需要,您可以使用 set print demangle onoff (https://sourceware.org/gdb/current/onlinedocs/gdb/Debugging-C-Plus-Plus.html#Debugging-C-Plus-Plus) 开启或关闭 C++ 函数名称解构。关闭拆解后,将函数名称复制到break 命令会更容易。

【讨论】:

谢谢,我没有意识到我可以使用正则表达式来查找函数 实际上,当我从***.com/a/1980793/196561 和***.com/a/1980770/196561 修补bash+gdb 脚本callgraph 时,我也犯了同样的错误。我需要从可执行文件中获取所有函数列表,使用正则表达式对其进行过滤,然后在所有过滤后的函数上定义断点。我使用info functions 和外部grep 进行了此操作,而使用info functions regex 对大型项目来说会更快。另外,我应该尝试修改callgraph.tar.gz以使用rbreak,但我不确定是否可以为rbreak生成的所有断点定义commands 是的,我确实注意到进行正则表达式搜索很慢(项目很大)但grep 有效。实际上,由于我知道您对使用该文件的建议有帮助,再次感谢 PS,对我来说,为 C++ 设置断点一直是 gdb 的难点。有解决方案的手册:cs.swarthmore.edu/~newhall/unixhelp/howto_gdb.html - ...“C++程序中的断点”你需要使用“classname::”前缀来指定方法和数据成员。此外,你经常需要使用前导' 在名称前供 gdb 查找符号", (gdb) break 'BufMgr::pinPage(int, Page *&, int)'

以上是关于中断 gdb (llvm) 中的命名空间函数的主要内容,如果未能解决你的问题,请参考以下文章

LLVM 中间代码归纳

是否可以使用 GDB 查看未命名的框架/函数参数?

为啥将 javascript 命名空间作为一个函数?

面向对象进阶

为啥我的命名空间引用在 Visual Studio 中不断中断?

使用在同一命名空间中定义的构造函数实例化命名空间中的对象。 C++