Sebagai tanggapan atas Jawaban mempekerjakan orang Rusia saya memverifikasi bahwa saya memiliki paket debug yang seharusnya menyediakan info debug yang cukup untuk memanggil fungsi seperti floor dari baris perintah gdb, tetapi ada sesuatu yang masih berperilaku aneh di gdb.

Saya menjalankan versi gdb ini melalui:

gdb --version

Aku s:

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.

Info sistem operasi mesin Linux melalui:

lsb_release -r -i 

Aku s:

Distributor ID: Ubuntu
Release:    19.10

Paket debug yang saya harapkan untuk digunakan gdb untuk menemukan simbol floor melalui:

dpkg --listfiles libc6-dbg | grep libm

Aku s:

/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

Mengkompilasi, menjalankan, dan kemudian menjalankan gdb melalui:

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

Aku s:

+ 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

Meskipun saya telah menginstal info debug seperti yang ditunjukkan di atas, mengapa gdb tidak dapat mengizinkan saya untuk memanggil fungsi yang dapat dipanggil oleh program itu sendiri?

Bagaimana cara memperbaikinya?

Perbarui 1

Per bantuan dari Employed Russian di https://stackoverflow.com/a/60909020/257924, saya menggunakan set trace-command on dalam perintah gdb.

Perbarui 2

Per Menggunakan komentar Rusia, dimasukkan dalam info shared ke dalam perintah gdb.

Perbarui 3

Per Jawaban mempekerjakan orang Rusia, saya membuat ulang menggunakan -fno-builtin melalui:

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

Aku s:

+ 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
bgoodr 29 Maret 2020, 04:35

1 menjawab

Jawaban Terbaik

Saya mereproduksi ini. Masalahnya ada dua:

  1. Kompiler dapat mengevaluasi floor(2.12) tanpa memanggil libm.so.6, dan
  2. Kompiler dikonfigurasi untuk meneruskan argumen --as-needed ke linker.

Masalah 1) mengakibatkan libm.so.6 tidak diperlukan. Pembongkaran main menunjukkan:

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

Dan info shared menunjukkan bahwa GDB tidak memuat libm.so.6 (karena tidak diperlukan), jadi info debug untuknya juga tidak pernah dimuat.

Mengubah sumber sedikit:

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

Hasil dalam:

(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. Alih-alih memodifikasi sumber, Anda juga dapat melarang kompiler mengetahui apa floor dengan -fno-builtin atau -fno-builtin-floor.

2
Employed Russian 30 Maret 2020, 17:10