即使安装了调试信息文件,如何让 gdb 允许我调用 "floor"?

How to make gdb allow me to call "floor" even when debug info files are installed?

作为对 的回应,我确认我确实有调试包,这些包应该提供足以从 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
# 
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

根据 中 Employed Russian 的帮助,我在 gdb 命令中使用了 set trace-command on

更新 2

根据 ,插入 info shared 到 gdb 命令中。

更新 3

根据 ,我使用 -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
# 
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)
 = 2
+ exit 0

我转载了这个。问题有两个:

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

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

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

(gdb) p *(double*)0x555555556030
 = 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
 = {<text gnu-indirect-function variable, no debug info>} 0x7ffff7e8e820 <__floor_ifunc>
(gdb) p floor(d)
 = 2

P.S。除了修改源代码,您还可以禁止编译器知道 floor-fno-builtin-fno-builtin-floor.

的含义