¿Qué hace exactamente -fno-builtin aquí?

7 minutos de lectura

Así que estaba leyendo Hackeando el arte de la explotación y en el libro, usan el strcpy() función en su código C:

1   #include <stdio.h>
2   #include <string.h>
3   
4       int main() {
5           char str_a[20];
6   
7           strcpy(str_a, "Hello, world!\n");
8           printf(str_a);
9       }

Luego proceden a compilar su código fuente y analizarlo con gdb. Establece un punto de corte en la línea 6, el strcpy función, y la línea 8, pero al establecer un descanso en strcpy se lee lo siguiente:

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

Entiendo que esto se debe a que la biblioteca aún no se ha cargado, por lo que le pregunta si quiere tenerla como un punto de interrupción pendiente. Luego ejecuta el programa y continúa a través de los puntos de interrupción:

imagen

Todo funciona bien para él, pero cuando traté de recrear esto en mi computadora, obtengo lo siguiente:

frinto@kali:~/Documents/theclang/programs/helloworld$ gcc -m32 -g -o char_array char_array.c 
frinto@kali:~/Documents/theclang/programs/helloworld$ gdb -q char_array
Reading symbols from char_array...done.
(gdb) list
1   #include <stdio.h>
2   #include <string.h>
3   
4       int main() {
5           char str_a[20];
6   
7           strcpy(str_a, "Hello, world!\n");
8           printf(str_a);
9       }
(gdb) break 6
Breakpoint 1 at 0x11b6: file char_array.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) break 8
Breakpoint 3 at 0x11d7: file char_array.c, line 8.
(gdb) run
Starting program: /home/frinto/Documents/theclang/programs/helloworld/char_array 

Breakpoint 1, main () at char_array.c:7
7           strcpy(str_a, "Hello, world!\n");
(gdb) cont
Continuing.

Breakpoint 3, main () at char_array.c:8
8           printf(str_a);
(gdb) cont
Continuing.
Hello, world!
[Inferior 1 (process 4021) exited normally]
(gdb) 

Observe cómo se saltó por completo el strcpy punto de ruptura? Bueno, le pregunté a un amigo mío cuál era el problema aquí, y me dijo que me estaba perdiendo el argumento. -fno-builtin al compilar. Hice algunas búsquedas mínimas en Google sobre este argumento y todo lo que realmente entendí es que le permite establecer puntos de interrupción en funciones integradas. Así que compilé el programa con el -fno-builtin argumento y luego trató de volver a crear esto de nuevo:

frinto@kali:~/Documents/theclang/programs/helloworld$ gcc -m32 -fno-builtin -g -o char_array char_array.c 
frinto@kali:~/Documents/theclang/programs/helloworld$ gdb -q char_array
Reading symbols from char_array...done.
(gdb) list
1   #include <stdio.h>
2   #include <string.h>
3   
4       int main() {
5           char str_a[20];
6   
7           strcpy(str_a, "Hello, world!\n");
8           printf(str_a);
9       }
(gdb) break 6
Breakpoint 1 at 0x11c6: file char_array.c, line 6.
(gdb) break strcpy
Breakpoint 2 at 0x1040
(gdb) break 8
Breakpoint 3 at 0x11dc: file char_array.c, line 8.
(gdb) run
Starting program: /home/frinto/Documents/theclang/programs/helloworld/char_array 

Breakpoint 1, main () at char_array.c:7
7           strcpy(str_a, "Hello, world!\n");
(gdb) cont
Continuing.

Breakpoint 2, 0xf7e510b0 in ?? () from /lib/i386-linux-gnu/libc.so.6
(gdb) cont
Continuing.

Breakpoint 3, main () at char_array.c:8
8           printf(str_a);
(gdb) cont
Continuing.
Hello, world!
[Inferior 1 (process 3969) exited normally]
(gdb) 

¡Ahora funciona! Tengo tres preguntas:

  1. ¿Qué es exactamente el -fno-builtin argumento haciendo?
  2. ¿Por qué muestra signos de interrogación en lugar de la strcpy función en

Breakpoint 2, 0xf7e510b0 in ?? () from /lib/i386-linux-gnu/libc.so.6

  1. ¿Por qué no pide configurar el strcpy punto de interrupción como pendiente cuando uso el -fno-builtin ¿argumento?

Perdón por la extensión del hilo, solo quería asegurarme de que se entendiera todo.

  • 2. No ha instalado la información de depuración para su libc. 3. Sabe dónde encontrar strcpy, no tiene que esperar en estado “pendiente”.

    – Marc Glisse

    20/01/2019 a las 23:30

¿Que hace exactamente fno builtin aqui
Alain Mérigot

Del hombre gcc

-fno-builtin
-fno-builtin-function

   Don't recognize built-in functions that do not begin with
   __builtin_ as prefix.  GCC normally generates special code to
   handle certain built-in functions more efficiently; for
   instance, calls to "alloca" may become single instructions
   which adjust the stack directly, and calls to "memcpy" may
   become inline copy loops.  The resulting code is often both
   smaller and faster, but since the function calls no longer
   appear as such, you cannot set a breakpoint on those calls, nor
   can you change the behavior of the functions by linking with a
   different library.  In addition, when a function is recognized
   as a built-in function, GCC may use information about that
   function to warn about problems with calls to that function, or
   to generate more efficient code, even if the resulting code
   still contains calls to that function.  For example, warnings
   are given with -Wformat for bad calls to "printf" when "printf"
   is built in and "strlen" is known not to modify global memory.

   With the -fno-builtin-function option only the built-in
   function function is disabled.  function must not begin with
   __builtin_.  If a function is named that is not built-in in
   this version of GCC, this option is ignored.  There is no
   corresponding -fbuiltin-function option; if you wish to enable
   built-in functions selectively when using -fno-builtin or
   -ffreestanding, you may define macros such as:

           #define abs(n)          __builtin_abs ((n))
           #define strcpy(d, s)    __builtin_strcpy ((d), (s))

Las funciones incorporadas permiten generar un código más rápido al alinear la función, pero como se indica en el manual

you cannot set a breakpoint on those calls

Insertar una función significa que, en lugar de generar una llamada de función, sus efectos se reemplazan por código insertado directamente por el compilador. Esto ahorra una llamada de función y se puede optimizar de manera más eficiente y, en general, conduce a una gran mejora en el rendimiento.

Pero, la función en línea ya no existe en el código. Los puntos de interrupción del depurador se implementan reemplazando las instrucciones en direcciones específicas por algunas trampas de software o utilizando hardware específico para reconocer cuándo se alcanza la dirección del punto de interrupción. Pero como la función ya no existe, no se le asocia ninguna dirección y no hay forma de interrumpirla.

Los puntos de interrupción pendientes son un medio para establecer un punto de interrupción en algún código que el programa cargará dinámicamente más adelante. Con -fno-builtin, strcpy está disponible directamente y gdb puede configurar directamente el bp.

Tenga en cuenta que la depuración requiere información específica en el ejecutable generado por el indicador -g. Por lo general, las bibliotecas del sistema como libc no tienen la información de depuración incrustada y, al ingresar la función en estas bibliotecas, gdb indica la falta de información de depuración mediante ??.

  • Respondió solo una de las 3 preguntas que hizo OP, y su respuesta es profundamente insatisfactoria: estoy seguro de que OP puede leer el manual por sí mismo, pero tiene problemas para entender lo que significa.

    – Ruso empleado

    21 de enero de 2019 a las 16:57

  • @Employed Russian Gracias por sus recomendaciones. Realmente no estoy acostumbrado a los estándares SO y estoy de acuerdo con sus críticos. La entrada manual es muy clara, pero es posible que el usuario no sepa por qué una función en línea no se puede interrumpir o por qué la función de biblioteca no se puede depurar. Actualicé la respuesta en consecuencia.

    – Alain Mérigot

    21 de enero de 2019 a las 18:15

¿Qué es exactamente el -fno-builtin argumento haciendo?

-fno-builtin significa que gcc no intentará reemplazar las funciones de la biblioteca con el código compilado incorporado, y no obtendrá ninguna rareza debido a dichos reemplazos. He sido mordido por reemplazos de printf("%s", mystr) por puts(mystr)por ejemplo, incluso cuando no estaba incluyendo stdio.h ¡en absoluto!

¿Por qué muestra signos de interrogación en lugar de la función strcpy?

Debido a que no hay un archivo fuente o una línea desde la cual el “código” de strcpy() fue tomado: gcc simplemente conectó algún ensamblaje o su GIMPLE IR o lo que sea, en lugar de la glibc strcpy() implementación.

¿Por qué no pide establecer el punto de interrupción de strcpy como pendiente cuando uso el -fno-builtin ¿argumento?

Porque entonces estás en el caso normal de una simple llamada de función Vanilla con un punto de interrupción, y el depurador no tiene que rascarse la cabeza y reflexionar sobre qué hacer.

¿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