Невозможно перейти в функцию string.h с помощью GDB

Не удается войти в string.h в GDB 7.5. Вот простая примерная программа:

Исходный код:

#include <stdio.h>
#include <string.h>

int main() {
    char str1[20];
    strcpy(str1, "STEP INTO ME\n");
    printf(str1);
}

Скомпилировано: ~$ gcc -g foo.c

Вызывается: ~$ gdb -q ./a.out

GDB:

(gdb) break 5
Breakpoint 1 at 0x8048471: file foo.c, line 6.
(gdb) break strcpy
Function "strcpy" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y

Breakpoint 2 (strcpy) pending.
(gdb) run 
Starting program: /home/user/a.out 

Breakpoint 1, main () at foo.c:6
6               strcpy(str_a, "Hello, world!\n");
(gdb) step
7               printf(str_a);

Должен ли я быть в строковой библиотеке на этом этапе? Вместо этого он продолжает printf().


EDIT:

Предложение Скотта "сработало", но не ожидалось.

Breakpoint 1, main () at foo.c:6
6               strcpy(str_a, "Hello, world!\n");
(gdb) i r $eip
eip            0x80484a1        0x80484a1 <main+21>
(gdb) step

Breakpoint 2, __strcpy_ssse3 () at ../sysdeps/i386/i686/multiarch/strcpy-ssse3.S:78
78      ../sysdeps/i386/i686/multiarch/strcpy-ssse3.S: No such file or directory.
(gdb) i r $eip
eip            0xb7e9c820       0xb7e9c820 <__strcpy_ssse3> 

Я удивлен в каталоге в 78... ожидал чего-то вроде: /lib/.../cmov/libc.so.6. И утверждение, что нет такого файла или каталога.

Ответ 1

Перекомпилируйте свой код с помощью gcc -fno-builtin -g foo.c, и команда gdb step будет работать. (См. -fno-встроенная документация). В противном случае небольшие вызовы strcpy(), memcpy() часто переводятся в инструкции по перемещению открытых кодированных данных, например. на x86-64:

4   int main() {
   0x000000000040052c <+0>: push   %rbp
   0x000000000040052d <+1>: mov    %rsp,%rbp
   0x0000000000400530 <+4>: sub    $0x20,%rsp

5       char str1[20];
6       strcpy(str1, "STEP INTO ME\n");
   0x0000000000400534 <+8>: lea    -0x20(%rbp),%rax
   0x0000000000400538 <+12>:    movl   $0x50455453,(%rax)
   0x000000000040053e <+18>:    movl   $0x544e4920,0x4(%rax)
   0x0000000000400545 <+25>:    movl   $0x454d204f,0x8(%rax)
   0x000000000040054c <+32>:    movw   $0xa,0xc(%rax)

7       printf(str1);
   0x0000000000400552 <+38>:    lea    -0x20(%rbp),%rax
   0x0000000000400556 <+42>:    mov    %rax,%rdi
   0x0000000000400559 <+45>:    mov    $0x0,%eax
   0x000000000040055e <+50>:    callq  0x400410 <[email protected]>

8   }
   0x0000000000400563 <+55>:    leaveq 
   0x0000000000400564 <+56>:    retq

Вы можете увидеть вызов strpcy(), скомпилированный в несколько инструкций MOV.

gcc -fno-builtin компилирует ту же программу в:

4   int main() {
   0x000000000040057c <+0>: push   %rbp
   0x000000000040057d <+1>: mov    %rsp,%rbp
   0x0000000000400580 <+4>: sub    $0x20,%rsp

5       char str1[20];
6       strcpy(str1, "STEP INTO ME\n");
   0x0000000000400584 <+8>: lea    -0x20(%rbp),%rax
   0x0000000000400588 <+12>:    mov    $0x400660,%esi
   0x000000000040058d <+17>:    mov    %rax,%rdi
   0x0000000000400590 <+20>:    callq  0x400450 <[email protected]>

7       printf(str1);
   0x0000000000400595 <+25>:    lea    -0x20(%rbp),%rax
   0x0000000000400599 <+29>:    mov    %rax,%rdi
   0x000000000040059c <+32>:    mov    $0x0,%eax
   0x00000000004005a1 <+37>:    callq  0x400460 <[email protected]>

8   }
   0x00000000004005a6 <+42>:    leaveq 
   0x00000000004005a7 <+43>:    retq 

и вы можете вызвать вызов <[email protected]>.

Предполагая, что вы хотите войти в strcpy(), чтобы изучить его реализацию, вам нужно иметь информацию об отладке для установки libc.so. К сожалению, способ получить информацию об отладке отличается от дистрибутивов Linux. На Fedora это так же просто, как debuginfo-install glibc. Для Ubuntu и Debian требуется больше шагов. Эта страница RPM DPKG Rosetta Stone содержит ссылки на инструкции для Fedora, Ubuntu и Debian (поиск debuginfo).

Поскольку вы находитесь на Ubuntu 12.10 и на самом деле хотите увидеть исходный код сборки strcpy():

$ sudo apt-get install libc6-dbg
$ sudo apt-get source libc6-dev
$ gdb ./a.out
(gdb) directory eglibc-2.15/sysdeps
Source directories searched: /home/scottt/eglibc-2.15/sysdeps:$cdir:$cwd
(gdb) break strcpy
Breakpoint 1 at 0x400450
(gdb) run
Starting program: /home/scottt/a.out 

Breakpoint 1, __strcpy_sse2 () at ../sysdeps/x86_64/multiarch/../strcpy.S:32
32      movq %rsi, %rcx     /* Source register. */

Ответ 2

Вы пытались установить точку останова для функции, определенной в библиотеке строк, обычно являющейся частью standard C library - libc.so

И как gdb сообщает вам:

(gdb) break strcpy
Function "strcpy" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y

Breakpoint 2 (strcpy) pending.

библиотека еще не загружена.

Но реальная проблема заключается в том, что даже когда библиотека загружается, если библиотека, т.е. libc.so, не имеет в ней отладочных символов, вы не сможете пройти через код внутри библиотеки, используя gdb.

Вы можете включить подробный режим, чтобы увидеть, какие символы gdb могут быть загружены:

(gdb) b main
Breakpoint 1 at 0x400914: file test.cpp, line 7.
(gdb) set verbose on
(gdb) run
Starting program: /home/agururaghave/.scratch/gdb-test/test 
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Reading symbols from system-supplied DSO at 0x7ffff7ffb000...(no debugging symbols found)...done.
Reading symbols from /usr/lib64/libstdc++.so.6...(no debugging symbols found)...done.
Registering libstdc++-v6 pretty-printer for /usr/lib64/libstdc++.so.6 ...
Loaded symbols for /usr/lib64/libstdc++.so.6
Reading symbols from /lib64/libm.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libm.so.6
Reading symbols from /lib64/libgcc_s.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/libgcc_s.so.1
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libc.so.6

Breakpoint 1, main () at test.cpp:7
7       bool result = myObj1 < myObj2;

Эта строка, например, говорит вам, удалось ли получить символы для libc.so:

Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.

Затем вы можете выяснить, откуда взялись символы отладки с помощью show debug-file-directory:

(gdb) show debug-file-directory 
The directory where separate debug symbols are searched for is "/usr/lib/debug".

Как вы видите, /usr/lib/debug здесь не содержит полного .so с отладочными символами. Вместо этого он имеет только информацию об отладке без каких-либо разделов .text или .data фактического libc.so, который программа использует для выполнения.

Решение установить информацию об отладке для библиотек будет специфичным для дистрибутива.

Я думаю, что пакет называется libc6-dbg на дистрибутивах на основе debian. На моей машине openSUSE она называется glibc-debuginfo

BTW, +1 on scottt предложение использовать -fno-builtin, чтобы gcc не использовал встроенные методы для таких функций, как strcpy и другие стандартные, определенные как часть стандарта C.

Ответ 3

У вас, вероятно, нет символов для вашей библиотеки C. Попробуйте stepi, но будьте готовы видеть только инструкции по сборке.