2010-09-28 6 views
3

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

#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 не работает. Что я должен изменить? Большое спасибо.

+0

Только так вы знаете, произошла техническая опечатка опубликовал работу вокруг того, что C не определяет поведение для преобразования указателя ничтожным в указатель на функцию , См. Пример на странице POSIX для [dlsym] (http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html), чтобы узнать, как использовать его в соответствии с требованиями. – dreamlax

ответ

1

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

Просматривая человека страниц, я нашел:

$ man dyld 

...

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

1

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

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

+0

Привет :-) Действительно? Является ли это сложным при mac os x? Я загрузил mach_override, и я изучаю исходный код, но я не понимаю, как его использовать. Пакет не содержит текстовой документации: P Спасибо вам. Любые примеры использования приветствуются: P – flaab

+0

http://github.com/rentzsch/mach_star, кажется, проще – flaab

4

На Махе, вы должны использовать 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) 
+0

Я получил его работу :-) Большое спасибо! Dyld также полезен для интерполяции классов? :) – flaab

+0

@flaab Добро пожаловать. Это, вероятно, не будет полезно для классов из-за изменения имени (в зависимости от имени класса, пространства имен и т. Д.). Технически можно переопределить метод класса, но это было бы почти невозможно поддерживать, поскольку изменение имени не стандартизировано. – 2010-09-29 13:36:30

+0

Привет, Влад :) Мне удалось заменить функции без проблем. теперь мне действительно нужно переопределить определенную функцию класса. – flaab

 Смежные вопросы

  • Нет связанных вопросов^_^