No se puede ingresar a la función string.h con GDB

9 minutos de lectura

avatar de usuario
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.

  • @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 ejecutando show debug-file-directory en gdb. 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


avatar de usuario
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. */

  • Es t.c se supone que representa foo.c (en este caso) o es un archivo con el que se supone que debo vincularme?

    – d0rmLife

    9 de marzo de 2013 a las 1:41

  • Intenté esto. Interviene, pero va a un directorio inesperado y dice El fichero o directorio no existe. Publicaré los resultados en mi pregunta… el formato será brutal en un comentario.

    – d0rmLife

    9 de marzo de 2013 a las 1:50

  • @d0rmLife: parece que strcpy está implementado en ensamblaje en glibc

    – tépico

    9 de marzo de 2013 a las 1:52

  • @d0rmLife, t.c de hecho era solo mi nombre más corto para foo.c 🙂 Después de entrar en una implementación optimizada de strcpy() es donde realmente desea tener información de depuración para libc.so instalada para dar sentido a las cosas.

    – scott

    9 de marzo de 2013 a las 1:53

  • ¡Quería asegurarme de que no fuera un archivo inusual! 🙂 …publicó el resultado en mi pregunta. Le agradecería cualquier idea que pueda tener sobre el directorio.

    – d0rmLife

    9 de marzo de 2013 a las 1:56

avatar de usuario
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 scotttla 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.

  • Si libc.so tiene información de depuración no es el problema aquí. Dado que el programa está vinculado dinámicamente, si existe una llamada a strcpy() que pasa por el PLT, gdb la detectará. El problema aquí es que la opción gcc -fno-buitin no se pasó, y la llamada a strcpy() en la fuente se tradujo en instrucciones de la tienda.

    – scott

    9 de marzo de 2013 a las 1:38


  • ¿Alguna idea de cómo se podría llamar el paquete para Ubuntu 12?

    – d0rmLife

    9 de marzo de 2013 a las 1:40

  • Tratar sudo apt-get install libc6-dbg

    – Tuxdude

    9 de marzo de 2013 a las 1:40

  • @scottt – Buena captura, en realidad tienes razón. No sabía que gcc usa funciones integradas para funciones como strcpy.

    – Tuxdude

    9 de marzo de 2013 a las 1:44

  • Obtuve el paquete, todavía no intervine. ¿Requiere opciones especiales para compilar/invocar?

    – d0rmLife

    9 de marzo de 2013 a las 1:45

Probablemente no tenga ningún símbolo para su biblioteca C. Tratar stepipero prepárate para ver solo las instrucciones de montaje.

  • @d0rmLife, ¿estás seguro? ¿Cómo comprobaste?

    –Carl Norum

    9 de marzo de 2013 a las 1:33


  • Mediante la ejecución GDB y usando stepi. No, supongo que no estoy seguro, pero no lo parecía. Al menos, no de la manera habitual…

    – d0rmLife

    9 de marzo de 2013 a las 1:36


  • @d0rmLife, ¿y la PC no cambió cuando hiciste eso? Eso me sorprende.

    –Carl Norum

    9 de marzo de 2013 a las 1:37

  • La salida fue diferente, pero no reconoció estar en una biblioteca diferente (se esperaba algo como /lib/...libc.so...)

    – d0rmLife

    9 de marzo de 2013 a las 1:38


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad