簡體   English   中英

使用dlsym的Ansi C補丁在linux下編譯好但在Mac Os X上失敗

[英]Ansi C patch using dlsym compiles OK under linux but fails on Mac Os X

我已經構建了一個小補丁來附加到某個應用程序並跟蹤某些函數的調用。 其中,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下令人驚嘆! 但是當我回到家並嘗試在Mac下使用GCC編譯它時,它無法編譯並且LD_PRELOAd指令不起作用。 我應該改變什么? 非常感謝你。

在Mach上,您必須使用DYLD_INSERT_LIBRARIES宏而不是LD_PRELOAD來指定要預加載的共享庫列表(1 ... *)。

默認情況下,標准函數不會被共享對象中的函數替換,因為它們具有相同的名稱。 您必須明確說明使用DYLD_INTERPOSE宏覆蓋什么函數。 它允許您使用任何名稱聲明替換函數(例如,使用my_open覆蓋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)

Mac OS X(10.6.4)不包含對LD_PRELOAD的任何引用 - 因此它被忽略,因此您嘗試插入代碼失敗。 全世界都與Linux不同。

通過手冊頁,我發現:

$ man dyld

...

DYLD_INSERT_LIBRARIES這是一個冒號分隔的動態庫列表,要在程序中指定的動態庫之前加載。 這使您可以通過僅使用新模塊加載臨時動態共享庫來測試在平面命名空間映像中使用的現有動態共享庫的新模塊。 請注意,這對使用動態共享庫構建兩級命名空間映像的映像沒有影響,除非還使用了DYLD_FORCE_FLAT_NAMESPACE。

對於OSX,您必須使用DYLD_INSERT_LIBRARIES環境。 變量而不是LD_PRELOAD。

但是我相當肯定你不會讓壓倒性的工作。 我能找到的最接近的東西是你必須做一些神奇的裝配技巧,有人在mach_override下的代碼中整齊地打包了: http ://extendamac.svn.sourceforge.net/viewvc/extendamac/trunk/code /

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM