Interposición de funciones en C con un ejemplo de malloc() definido por el usuario

La interposición de funciones es el concepto de reemplazar llamadas a funciones en bibliotecas dinámicas con llamadas a contenedores definidos por el usuario.

¿Qué son las aplicaciones?

  1. Podemos contar el número de llamadas para funcionar.
  2. Almacene la información de la persona que llama y los argumentos pasados ​​a la función para rastrear el uso.
  3. Detectar fugas de memoria, podemos anular malloc() y realizar un seguimiento de los espacios asignados.
  4. Podemos añadir nuestras propias políticas de seguridad. Por ejemplo, podemos agregar una política de que no se puede llamar a la bifurcación con más de la profundidad de recursión especificada.

¿Cómo hacer la interposición de funciones?
La tarea es escribir nuestro propio malloc() y asegurarse de que nuestro propio malloc() se llame en lugar de la biblioteca malloc(). A continuación se muestra un programa controlador para probar diferentes tipos de interposiciones de malloc().

// File Name : hello.c
  
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
  
int main(void)
{
    // Call to user defined malloc
    void *ptr = malloc(4);
      
    printf("Hello World\n");
    return 0;
}
  1. Tiempo de compilación: reemplace la llamada a la biblioteca con nuestra propia función cuando se compila el código fuente.

    /* Compile-time interposition of malloc using C preprocessor. 
       A local malloc.h file defines malloc as wrapper */
      
    // A file that contains our own malloc function
    // File Name : mymalloc.c
    #include <stdio.h>
    #include <malloc.h>
    void *mymalloc(size_t s)
    {
       printf("My malloc called");
       return NULL;
    }

    // filename : malloc.h
    // To replace all calls to malloc with mymalloc
    #define malloc(size) mymalloc(size)
    void *mymalloc(size_t size);

    Pasos para ejecutar arriba en Linux:

    // Compile the file containing user defined malloc()
    :~$gcc  -c mymalloc.c
    
    // Compile hello.c with output file name as helloc. 
    // -I. is used to include current folder (.) for header
    // files to make sure our malloc.h is becomes available.
    :~$gcc  -I. -o helloc hello.c mymalloc.o
    
    // Run the generated executable
    :~$./helloc
    My malloc called
    Hello World 
  2. .

  3. Tiempo de vinculación : cuando los archivos de objeto reubicables están vinculados estáticamente para formar un archivo de objeto ejecutable.

    // filename : mymalloc.c
    /* Link-time interposition of malloc using the
       static linker’s (ld) "--wrap symbol" flag. */
    #include <stdio.h>
      
    // __real_malloc() is used to called actual library
    // malloc()
    void *__real_malloc(size_t size);
      
    // User defined wrapper for malloc()
    void *__wrap_malloc(size_t size)
    {
       printf("My malloc called");
       return NULL;
    }

    Pasos para ejecutar arriba en Linux:

    // Compile the file containing user defined malloc()
    :~$gcc  -c mymalloc.c
    
    // Compile hello.c with output name as hellol  
    // "-Wl,--wrap=malloc" is used tell the linker to use
    //  malloc() to call __wrap_malloc(). And to use 
    // __real_malloc() to actual library malloc() 
    :~$gcc  -Wl,--wrap=malloc -o hellol hello.c mymalloc.o
    
    // Run the generated executable
    :~$./hellol
    My malloc called
    Hello World 
  4. .

  5. Tiempo de carga/ejecución: cuando un archivo de objeto ejecutable se carga en la memoria, se vincula dinámicamente y luego se ejecuta.

    La variable de entorno LD_PRELOAD le da al cargador una lista de bibliotecas para cargar antes de un comando o ejecutable.
    Creamos una biblioteca dinámica y nos aseguramos de que esté cargada antes que nuestro ejecutable para hello.c.

    /* Run-time interposition of malloc based on dynamic linker’s
       (ld-linux.so) LD_PRELOAD mechanism */
    #define _GNU_SOURCE
    #include <stdio.h>
      
    void *malloc(size_t s)
    {
       printf("My malloc called\n");
       return NULL;
    }

    Pasos para ejecutar arriba en Linux:

    // Compile hello.c with output name as helloc
    :~$gcc -o hellor hello.c
    
    // Generate a shared library myalloc.so. Refer
    // https://www.geeksforgeeks.org/working-with-shared-libraries-set-2/
    // for details.
    :~$gcc -shared -fPIC -o mymalloc.so mymalloc.c
    
    // Make sure shared library is loaded and run before .
    :~$LD_PRELOAD=./mymalloc.so ./hellor
    My malloc called
    Hello World
    
  6. .

    El código para malloc definido por el usuario se mantiene pequeño para una mejor legibilidad. Idealmente, debería asignar memoria haciendo una llamada a la biblioteca malloc().

    Fuente:
    https://www.utdallas.edu/~zxl111930/spring2012/public/lec18-handout.pdf

    Este artículo es una contribución de Aditya Chatterjee . Si le gusta GeeksforGeeks y le gustaría contribuir, también puede escribir un artículo y enviarlo por correo electrónico a contribuya@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.

    Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *