无法在调试器中调用标准数学函数?

时间:2016-10-21 03:11:18

标签: ubuntu math gcc gdb symbols

我试图在调试器中调用我自己的函数和标准函数:

#include<stdlib.h>
#include<math.h>
#include<stdio.h>
int i=3;
void f(){
  ++i;
  printf("%d\n",i);
}
int main(){
  ++i;
  int j=i+2;
  double d=cos(0.0);
  printf("%f\n",d);
  return 0;
}

编译该程序并运行,它将打印&#34; 1.000000&#34;正如我所料。 在gdb中,我尝试过:

(gdb) b main
Breakpoint 1 at 0x40055b: file x.c, line 10.
(gdb) r
Starting program: /home/x/a.out 

Breakpoint 1, main () at x.c:10
10    ++i;
(gdb) call f()
4
(gdb) call f()
5
(gdb) call cos(0.0)
No symbol "cos" in current context.  # WHY?????
(gdb) call printf("%d\n",i)
5
$1 = 2
(gdb) call putchar('a')
$2 = 97

为什么gdb甚至找不到符号?我想&#34; -g&#34;选项将为我的程序和标准库带来调试信息,对吧?或者我是否必须为标准库的调试/源代码安装额外的包?我在ubuntu16.04上

非常感谢。

2 个答案:

答案 0 :(得分:3)

尽管很快出现,但这部分gdb运行良好。所以我的第一直觉是我们处于某种GIGO状态 - gdb异常容易受到编译器和内核的敌人攻击 - 并且需要进行一些调查。

您没有说您使用的是C还是C ++。

在C ++中,我可以看到没有为cos发出调试信息,并且调用完全被优化掉了。您可以通过运行nm进行检查,并注意cos未显示为未定义的符号;或者只是注意到该程序在没有-lm的情况下链接得很好。

我对C ++的理解是,这是因为范围内有constexpr coscos(我在预处理输出中看到它,但我没有尝试真正验证),所以g ++优化了整个调用。

对于C,我默认看到同样的事情。但是,我可以通过将-fno-builtin-cos传递给gcc来致电(gdb) p cos $1 = {<text gnu-indirect-function variable, no debug info>} 0x7ffff7aebc50 <cos> 。但是,哈哈,它仍然不在debuginfo中!

这对我来说似乎是一个gcc bug。通常,只需要访问程序使用的库中的类型或函数,就不需要为库提供debuginfo。

您还可以通过尝试打印函数本身来注意到一些奇怪的事情:

cos

这是个坏消息,因为“GNU间接”功能是gdb不能完全理解的神奇生物。特别是我认为即使安装了debuginfo,也无法从调试器中调用它们。

事实上,我唯一能做的工作就是在程序中取mumble *my_cos = &cos; ... (gdb) print my_cos(0.0) 的地址,然后通过指针调用,如:

(gdb) info func cos@plt
All functions matching regular expression "cos@plt":

Non-debugging symbols:
0x0000000000400500  cos@plt
(gdb) p ((double(*)(double))0x0000000000400500)(0.0)
$6 = 1

嗯,这不完全正确。我也可以做这个工作:

1. FROM
2. ON
3. OUTER
4. WHERE
5. GROUP BY
6. CUBE | ROLLUP
7. HAVING
8. SELECT
9. DISTINCT
10 ORDER BY
11. TOP

这避免了GNU间接的东西。然而,这是非常不愉快的。

答案 1 :(得分:0)

  • cos函数在libm中实现,而不是在libc中实现。你有甚至连接-lm?
  • 编译器优化了常量表达式。没有理由在运行时计算cos(0)。因此不需要包含cos函数,也没有理由将数学库链接起来。从您的可执行文件(您可以使用readelf或类似工具验证)中删除对libm的引用,因此gdb对cos(或数学库中的任何其他函数)一无所知。
  • 正如Tom Tromey解释的那样,一种可能的解决方法是禁用gcc的内置函数。在此之后,我可以从gdb调用cos(如:print cos(1.0))。