2014-11-10 4 views
4

Предположим, у вас есть программа, которая загружает несколько общих объектов/динамических библиотек, используя dlopen(). Учитывая указатель на глобальный объект (например, статическую переменную-член), можно ли определить, что указатель выделен на границе той библиотеки?Как определить, какая динамическая библиотека отвечает за создание указателя?

+0

Используйте отладчик к шагу через программу и посмотреть, который код выделяет его? – deviantfan

+0

Единственный способ, которым я могу думать, это обеспечить, чтобы каждая библиотека использовала другой распределитель (malloc & free). Если вы можете получить доступ к таблице символов (dlopen let have that) и узнать ее структуру, вы можете, вероятно, исправить импортированный символ для malloc, чтобы указать на выделенную функцию. – didierc

+0

@sashoalm Вопрос помечен для linux – simonc

ответ

5

Вы можете проанализировать карты процессов с файлом /proc/self/maps и увидеть, где указатель адрес ограничен, глобальная переменная будет расположена в сегментах .data или .bss.

Пример библиотеки lib.c:

static int object; 

int * 
dummy(void) 
{ 
    return &object; 
} 

test.c, ошибки не обрабатываются для простоты:

#include <stdio.h> 
#include <dlfcn.h> 
#include <unistd.h> 
#include <inttypes.h> 
#include <assert.h> 
#include <linux/limits.h> 

static void which_library(void *p); 

int 
main(int argc, char **argv) 
{ 
    void *handle; 
    void *object; 

    handle = dlopen("./lib.so", RTLD_NOW); 
    assert(handle); 

    object = ((int *(*)(void)) dlsym(handle, "dummy"))(); 
    which_library(object); 
    dlclose(handle); 

    return 0; 
} 

static void 
which_library(void *p) 
{ 
    FILE *maps; 
    char buffer[49+PATH_MAX+1]; 

    maps = fopen("/proc/self/maps", "r"); 
    assert(maps); 

    while(fgets(buffer, sizeof(buffer) - 1, maps)) { 
    char path[PATH_MAX+1]; 
    uintptr_t starts; 
    uintptr_t ends; 

    sscanf(buffer, "%" PRIxPTR "-%" PRIxPTR " %*s %*x %*x:%*x %*d %s", &starts, &ends, path); 
    if((uintptr_t)p >= starts && (uintptr_t)p < ends) { 
     printf("%p => %s\n", p, path); 
     break; 
    } 
    } 

    fclose(maps); 
} 

Тест:

$ gcc -Wall -shared lib.c -o lib.so 
$ gcc -Wall test.c -ldl 
$ ./a.out 
0xb779f5f8 => /home/barakat/Desktop/lib.so 
$ 
+0

Это гениальный человек! Приветствуйте работу! – CommanderHK