
d0rmvida
Tener problemas para entrar string.h
en GDB 7.5. Aquí hay un programa de ejemplo simple:
Código fuente:
#include <stdio.h>
#include <string.h>
int main() {
char str1[20];
strcpy(str1, "STEP INTO ME\n");
printf(str1);
}
compilado: ~$ gcc -g foo.c
invocado: ~$ gdb -q ./a.out
BGF:
(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);
¿No debería estar en la biblioteca de cadenas en este momento? En su lugar, continúa con printf().
EDITAR:
La sugerencia de Scott “funcionó”, pero no de la manera esperada.
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>
Estoy sorprendido por el directorio en 78
… esperaba algo como: /lib/.../cmov/libc.so.6
. Y la afirmación de que no existe tal archivo o directorio.

scott
Vuelva a compilar su código con gcc -fno-builtin -g foo.c
y el gdb step
el comando funcionará. (Ver -documentación incorporada de fno). De lo contrario pequeño strcpy()
, memcpy()
las llamadas a menudo se traducirían en instrucciones de movimiento de datos codificadas abiertas, por ejemplo, en 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 <printf@plt>
8 }
0x0000000000400563 <+55>: leaveq
0x0000000000400564 <+56>: retq
Puedes ver el strpcy()
llamada siendo compilada en múltiples MOVIMIENTO instrucciones.
gcc -fno-builtin
compila el mismo programa en:
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 <strcpy@plt>
7 printf(str1);
0x0000000000400595 <+25>: lea -0x20(%rbp),%rax
0x0000000000400599 <+29>: mov %rax,%rdi
0x000000000040059c <+32>: mov $0x0,%eax
0x00000000004005a1 <+37>: callq 0x400460 <printf@plt>
8 }
0x00000000004005a6 <+42>: leaveq
0x00000000004005a7 <+43>: retq
y puedes ver la llamada a <strcpy@plt>
.
Suponiendo que quisieras entrar strcpy()
para estudiar su implementación, querrá tener instalada la información de depuración para libc.so. Desafortunadamente, la forma de obtener información de depuración difiere entre las distribuciones de Linux. En Fedora es tan simple como debuginfo-install glibc
. Toma más pasos en Ubuntu y Debian. Esta RPM DPKG Piedra de Rosetta tiene enlaces a instrucciones para Fedora, Ubuntu y Debian (busque información de depuración).
Ya que estás en Ubuntu 12.10 y realmente quieres ver el strcpy()
código fuente de montaje:
$ 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. */

Tuxdude
Intentó establecer un punto de interrupción para una función definida en la biblioteca de cadenas que generalmente forma parte del standard C library - libc.so
Y como gdb
te informa:
(gdb) break strcpy
Function "strcpy" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (strcpy) pending.
la biblioteca aún no está cargada.
Pero el verdadero problema es que, incluso cuando la biblioteca está cargada, si la biblioteca, es decir, libc.so
no tiene símbolos de depuración, no podrá recorrer el código dentro de la biblioteca usando gdb
.
Puede habilitar el modo detallado para ver qué símbolos, gdb
es capaz de cargar:
(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;
Esta línea, por ejemplo, le dice si pudo obtener los símbolos para libc.so:
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Luego podría averiguar de dónde se recogen los símbolos de depuración usando show debug-file-directory
:
(gdb) show debug-file-directory
The directory where separate debug symbols are searched for is "/usr/lib/debug".
Como ves /usr/lib/debug
here no contiene el .so completo con símbolos de depuración. En cambio, solo tiene la información de depuración sin ninguna .text
o .data
secciones de la libc.so real que utiliza el programa para su ejecución.
La solución para instalar la información de depuración para las bibliotecas sería específica de la distribución.
creo que el paquete se llama libc6-dbg
en las distribuciones basadas en debian. En mi máquina openSUSE, parece llamarse glibc-debuginfo
Por cierto, +1 en scottt
la sugerencia de usar -fno-builtin
para que gcc no use sus métodos integrados para funciones como strcpy
y otros estándares definidos como parte del estándar C.
Probablemente no tenga ningún símbolo para su biblioteca C. Tratar stepi
pero prepárate para ver solo las instrucciones de montaje.
@skirkpatrick: Esto está mal, al menos en la mayoría de los sistemas (OS X, Debian, Ubuntu, Fedora…). bibliotecas compartidas están compilado con símbolos de depuración. La verdadera pregunta es si esos símbolos están instalados.
-Dietrich Epp
9 de marzo de 2013 a las 1:33
@DietrichEpp: después de una búsqueda rápida, parece que tienes razón. Perdón por la desinformación; Eliminaré mi comentario.
– skirkpatrick
9 de marzo de 2013 a las 1:38
Los símbolos de depuración no forman parte del .so que reside en su LD_LIBRARY_PATH. En cambio, residen en un directorio que gdb busca como
/usr/lib/debug
. Esta información se puede obtener ejecutandoshow debug-file-directory
engdb
. Estos archivos contienen solo información de depuración sin ninguna.text
o.data
secciones de la.so
. Y sí, es necesario instalarlos por separado.– Tuxdude
9 de marzo de 2013 a las 1:49