【问题标题】:How to make gdb allow me to call "floor" even when debug info files are installed?即使安装了调试信息文件,如何让 gdb 允许我调用“地板”?
【发布时间】:2020-03-31 01:10:08
【问题描述】:

在回复 Employed Russian's answer 时,我确认我确实有调试包,它们应该提供足以从 gdb 命令行调用函数(例如 floor)的调试信息,但在 gdb 中仍有一些奇怪的行为。

我正在通过以下方式运行此版本的 gdb:

gdb --version

是:

GNU gdb (Ubuntu 8.3-0ubuntu1) 8.3
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Linux机器操作系统信息来自:

lsb_release -r -i 

是:

Distributor ID: Ubuntu
Release:    19.10

我希望 gdb 使用的调试包,以便通过以下方式找到 floor 符号:

dpkg --listfiles libc6-dbg | grep libm

是:

/usr/lib/debug/lib/x86_64-linux-gnu/libm-2.30.so
/usr/lib/debug/lib/x86_64-linux-gnu/libmemusage.so
/usr/lib/debug/lib/x86_64-linux-gnu/libmvec-2.30.so

编译,运行,然后运行gdb via:

#!/bin/bash

exec 2>&1
set -x

rm -rf "/tmp/testdir"
mkdir -p "/tmp/testdir"
cd "/tmp/testdir"

cat > main.cpp <<'EOF'
#include <stdio.h>
#include <math.h>  // double floor(double x);

int main(int argc, char *argv[], char *const envp[])
{
  printf("From inside C++: floor(2.12) %g\n", floor(2.12));
  return 0;
} // end main
EOF

/usr/bin/c++  -MD -DDEBUG -g  -fPIC  -Wall -Werror -Wsynth -Wno-comment -Wreturn-type $cxx_args main.cpp -c -o main.o
/usr/bin/c++  -MD -DDEBUG -g  -fPIC  -Wall -Werror -Wsynth -Wno-comment -Wreturn-type $cxx_args main.o -L. -L/usr/lib64 -lstdc++  -o main.exe
(./main.exe; exit 0)
cat > /tmp/gdb.commands <<EOF
# https://stackoverflow.com/a/60909020/257924
set trace-commands on
b main
r
info shared
p floor(2.12)
EOF

gdb -batch -x /tmp/gdb.commands main.exe

exit 0

是:

+ rm -rf /tmp/testdir
+ mkdir -p /tmp/testdir
+ cd /tmp/testdir
+ cat
+ /usr/bin/c++ -MD -DDEBUG -g -fPIC -Wall -Werror -Wsynth -Wno-comment -Wreturn-type main.cpp -c -o main.o
+ /usr/bin/c++ -MD -DDEBUG -g -fPIC -Wall -Werror -Wsynth -Wno-comment -Wreturn-type main.o -L. -L/usr/lib64 -lstdc++ -o main.exe
+ ./main.exe
From inside C++: floor(2.12) 2
+ exit 0
+ cat
+ gdb -batch -x /tmp/gdb.commands main.exe
+b main
Breakpoint 1 at 0x1149: file main.cpp, line 5.
+r

Breakpoint 1, main (argc=0, argv=0x7fffffffdbc0, envp=0x555555555060 <_start>) at main.cpp:5
5   {
+info shared
From                To                  Syms Read   Shared Object Library
0x00007ffff7fd1100  0x00007ffff7ff23f4  Yes         /lib64/ld-linux-x86-64.so.2
0x00007ffff7dc9670  0x00007ffff7f3e74f  Yes         /lib/x86_64-linux-gnu/libc.so.6
+p floor(2.12)
/tmp/gdb.commands:6: Error in sourced command file:
No symbol "floor" in current context.
+ exit 0

即使我确实安装了如上所示的调试信息,为什么 gdb 无法让我调用程序本身能够调用的函数?

我该如何解决?

更新 1

根据来自 https://stackoverflow.com/a/60909020/257924 的 Employed Russian 的帮助,我在 gdb 命令中使用了 set trace-command on

更新 2

根据Employed Russian's comment,将info shared 插入到gdb 命令中。

更新 3

根据Employed Russian's answer,我使用-fno-builtin 重建,通过:

#!/bin/bash

exec 2>&1
set -x

cxx_args='-fno-builtin'
rm -rf "/tmp/testdir"
mkdir -p "/tmp/testdir"
cd "/tmp/testdir"

cat > main.cpp <<'EOF'
#include <stdio.h>
#include <math.h>  // double floor(double x);

int main(int argc, char *argv[], char *const envp[])
{
  printf("From inside C++: floor(2.12) %g\n", floor(2.12));
  return 0;
} // end main
EOF

/usr/bin/c++  -MD -DDEBUG -g  -fPIC  -Wall -Werror -Wsynth -Wno-comment -Wreturn-type $cxx_args main.cpp -c -o main.o
/usr/bin/c++  -MD -DDEBUG -g  -fPIC  -Wall -Werror -Wsynth -Wno-comment -Wreturn-type $cxx_args main.o -L. -L/usr/lib64 -lstdc++  -o main.exe
(./main.exe; exit 0)
cat > /tmp/gdb.commands <<EOF
# https://stackoverflow.com/a/60909020/257924
set trace-commands on
b main
r
info shared
p floor(2.12)
EOF

gdb -batch -x /tmp/gdb.commands main.exe

exit 0

是:

+ cxx_args=-fno-builtin
+ rm -rf /tmp/testdir
+ mkdir -p /tmp/testdir
+ cd /tmp/testdir
+ cat
+ /usr/bin/c++ -MD -DDEBUG -g -fPIC -Wall -Werror -Wsynth -Wno-comment -Wreturn-type -fno-builtin main.cpp -c -o main.o
+ /usr/bin/c++ -MD -DDEBUG -g -fPIC -Wall -Werror -Wsynth -Wno-comment -Wreturn-type -fno-builtin main.o -L. -L/usr/lib64 -lstdc++ -o main.exe
+ ./main.exe
From inside C++: floor(2.12) 2
+ exit 0
+ cat
+ gdb -batch -x /tmp/gdb.commands main.exe
+b main
Breakpoint 1 at 0x1169: file main.cpp, line 5.
+r

Breakpoint 1, main (argc=0, argv=0x7fffffffdbc0, envp=0x555555555080 <_start>) at main.cpp:5
5   {
+info shared
From                To                  Syms Read   Shared Object Library
0x00007ffff7fd1100  0x00007ffff7ff23f4  Yes         /lib64/ld-linux-x86-64.so.2
0x00007ffff7e553c0  0x00007ffff7efbe78  Yes         /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff7c7a670  0x00007ffff7def74f  Yes         /lib/x86_64-linux-gnu/libc.so.6
+p floor(2.12)
$1 = 2
+ exit 0

【问题讨论】:

  • 你能显示(gdb) info shared的输出吗?
  • 添加了更新1和2,其中2是添加info sharedgdb命令。
  • 添加了更新 3 以确认受雇俄罗斯人的回答。

标签: gdb debug-symbols


【解决方案1】:

我复制了这个。问题有两个方面:

  1. 编译器可以在不调用libm.so.6 的情况下评估floor(2.12),并且
  2. 编译器配置为将--as-needed 参数传递给链接器。

问题 1) 导致不需要 libm.so.6main的反汇编显示:

=> 0x0000555555555148 <+19>:    mov    0xee1(%rip),%rax        # 0x555555556030
   0x000055555555514f <+26>:    movq   %rax,%xmm0
   0x0000555555555154 <+31>:    lea    0xead(%rip),%rdi        # 0x555555556008
   0x000055555555515b <+38>:    mov    $0x1,%eax
   0x0000555555555160 <+43>:    callq  0x555555555030 <printf@plt>

(gdb) p *(double*)0x555555556030
$1 = 2

info shared 表明 GDB 没有加载 libm.so.6(因为它不需要),因此它的调试信息也从未加载。

稍微改变一下来源:

1       #include <stdio.h>
2       #include <math.h>  // double floor(double x);
3
4       int main(int argc, char *argv[], char *const envp[])
5       {
6         double d = 2.12;
7         printf("From inside C++: floor(2.12) %g\n", floor(d));
8         return 0;
9       } // end main

结果:

(gdb) start
Temporary breakpoint 1 at 0x1158: file main.cpp, line 6.
Starting program: /tmp/testdir/a.out 

Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdca8, envp=0x7fffffffdcb8) at main.cpp:6
6         double d = 2.12;
(gdb) n
7         printf("From inside C++: floor(2.12) %g\n", floor(d));
(gdb) p floor
$1 = {<text gnu-indirect-function variable, no debug info>} 0x7ffff7e8e820 <__floor_ifunc>
(gdb) p floor(d)
$2 = 2

附:除了修改源代码之外,您还可以禁止编译器知道 floor-fno-builtin-fno-builtin-floor 是什么。

【讨论】:

  • 这就是答案,谢谢!嗯,上面foor(2.12) 中的小拼写错误。
猜你喜欢
  • 2023-04-06
  • 1970-01-01
  • 2021-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-27
  • 2012-09-08
相关资源
最近更新 更多