Ansi C патч с использованием dlsym компилируется нормально под Linux, но не работает на Mac Os X - PullRequest
3 голосов
/ 28 сентября 2010

Я создал небольшой патч для добавления в определенное приложение и отслеживания вызовов некоторых функций.Среди них malloc () и open ().Я использую dlsym, чтобы сохранить указатель на исходный символ и заменить имя функции своим собственным.Он компилируется и работает отлично под Linux.Вот код:

#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <dlfcn.h>

/**
 * Interponemos nuestra funcion open
 * 
 * @param   char*    filename
 * @param   int      flags
 **/

int open(char * filename, int flags)
{
    static int (*real_open)(char*, int) = NULL;
    if (!real_open)
        real_open = dlsym(RTLD_NEXT, "open");

    // Entero
    int p = real_open(filename, flags);
    fprintf(stderr, "Abrimos %s) = %i\n", filename, flags);

    // Devolvemos
    return p;
}

//--------------------------------------------------------

/**
 * Interponemos nuestra funcion malloc
 * 
 * @param   size_t    size
 */

void* malloc(size_t size)
{
    static void* (*real_malloc)(size_t) = NULL;
    if (!real_malloc)
        real_malloc = dlsym(RTLD_NEXT, "malloc");

    void *p = real_malloc(size);

    // Memoria reservada
    fprintf(stderr, "Reserva de memoria (%d) = %p\n", size, p);

    // Devolvemos
    return p;
}

Затем я компилирую его с помощью следующей инструкции, создавая pi.so.

gcc -Wall -O2 -fPIC -shared -ldl -o pi.so pi.c 

И затем я использую директиву LD_PRELOAD, чтобы вставить ее влюбое приложение.

LD_PRELOAD=/home/.../injection/pi.so <binary>

И это замечательно под Linux!Но когда я возвращаюсь домой и пытаюсь скомпилировать его с помощью GCC под Mac, он не скомпилируется и директива LD_PRELOAd не работает.Что я должен изменить?Большое спасибо.

Ответы [ 3 ]

4 голосов
/ 29 сентября 2010

На компьютере необходимо использовать макрос DYLD_INSERT_LIBRARIES вместо LD_PRELOAD, чтобы указать список общих библиотек для предварительной загрузки (1 ... *).

По умолчанию стандартные функциине заменяются функциями из общих объектов только потому, что они имеют одинаковые имена.Вы должны явно указать, какая функция переопределяет, с помощью макроса DYLD_INTERPOSE .Это позволяет вам объявить функцию замены с любым именем (например, переопределить open с помощью my_open) и иметь возможность вызывать оригинальную функцию, которую вы переопределяете.В дополнение к этому вам не нужно разрешать адреса реальных функций вручную.

В качестве альтернативы, для достижения поведения, подобного Linux, вы должны определить макрос DYLD_FORCE_FLAT_NAMESPACE.многое другое происходит, смотрите подробности в руководстве dyld .

Так что ваш код должен выглядеть примерно так:

#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <dlfcn.h>
#include <mach-o/dyld-interposing.h>

/**
 * Interponemos nuestra funcion open
 * 
 * @param   char*    filename
 * @param   int      flags
 **/

int my_open(char * filename, int flags)
{
    // Entero
    int p = open(filename, flags);
    fprintf(stderr, "Abrimos %s) = %i\n", filename, flags);

    // Devolvemos
    return p;
}
DYLD_INTERPOSE(my_open, open)

//--------------------------------------------------------

/**
 * Interponemos nuestra funcion malloc
 * 
 * @param   size_t    size
 */

void* my_malloc(size_t size)
{
    void *p = malloc(size);

    // Memoria reservada
    fprintf(stderr, "Reserva de memoria (%d) = %p\n", size, p);

    // Devolvemos
    return p;
}
DYLD_INTERPOSE(my_malloc, malloc)
1 голос
/ 28 сентября 2010

Для OSX вы должны использовать DYLD_INSERT_LIBRARIES env. переменная вместо LD_PRELOAD.

Однако я вполне уверен, что вы не получите переопределение на работу. Самое близкое, что я могу найти, это то, что вам придется сделать несколько магических сборок, которые кто-то аккуратно упаковал в коде под mach_override: http://extendamac.svn.sourceforge.net/viewvc/extendamac/trunk/code/

1 голос
/ 28 сентября 2010

Mac OS X (10.6.4) не содержит никаких ссылок на LD_PRELOAD - поэтому он игнорируется, и, следовательно, ваша попытка вставить ваш код не удалась.Весь мир отличается от Linux.

Просматривая справочные страницы, я обнаружил:

$ man dyld

...

DYLD_INSERT_LIBRARIES ЭтоРазделенный двоеточиями список динамических библиотек, загружаемых до тех, которые указаны в программе.Это позволяет тестировать новые модули существующих динамических общих библиотек, которые используются в изображениях с плоским пространством имен, путем загрузки временной динамической общей библиотеки только с новыми модулями.Обратите внимание, что это не влияет на изображения, построенные двухуровневые изображения пространства имен с использованием динамической общей библиотеки, если только не используется DYLD_FORCE_FLAT_NAMESPACE.

...