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

独自空忆成欢 提交于 2020-04-16 02:59:26

问题


In response to Employed Russian's answer I verified that I do have debug packages that should provide debug info sufficient to call functions such as floor from the gdb command-line, but something is still behaving oddly in gdb.

I'm running this version of gdb via:

gdb --version

is:

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.

The Linux machine operating system info via:

lsb_release -r -i 

is:

Distributor ID: Ubuntu
Release:    19.10

Debug packages that I expect for gdb to use in order to find the floor symbol via:

dpkg --listfiles libc6-dbg | grep libm

is:

/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

Compiling, running, and then running 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

is:

+ 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

Even though I do have debug info installed as shown above, why is gdb unable to allow me to call a function that the program itself is able to call?

How do I fix that?

Update 1

Per help from Employed Russian in https://stackoverflow.com/a/60909020/257924, I used set trace-command on in the gdb commands.

Update 2

Per Employed Russian's comment, inserted in info shared into gdb commands.

Update 3

Per Employed Russian's answer, I rebuilt using -fno-builtin via:

#!/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

is:

+ 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

回答1:


I reproduced this. The problem is two-fold:

  1. The compiler can evaluate floor(2.12) without calling into libm.so.6, and
  2. The compiler is configured to pass --as-needed argument to the linker.

The issue 1) results in libm.so.6 not being needed. Disassembly of main shows:

=> 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

And info shared shows that GDB didn't load libm.so.6 (as it isn't needed), so the debug info for it was never loaded either.

Changing the source a bit:

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

Results in:

(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

P.S. Instead of modifying source, you could also prohibit the compiler from knowing what floor is with -fno-builtin or -fno-builtin-floor.



来源:https://stackoverflow.com/questions/60909184/how-to-make-gdb-allow-me-to-call-floor-even-when-debug-info-files-are-installe

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!