Assume you have a program that loads several shared objects/dynamic libraries using dlopen(). Given a pointer to a global object (e.g. static member variable), is it possible to determine the pointer is allocated in the boundary of which library?
Asked
Active
Viewed 181 times
4
-
Use a debugger to step through the program and watch which code allocates it? – deviantfan Nov 10 '14 at 13:13
-
The only way I can think of is to ensure that each library is using a different allocator (malloc & free). If you can access the symbol table (dlopen let you have that), and know its structure, you can probably patch the imported symbol for malloc to point to a dedicated function. – didierc Nov 10 '14 at 13:20
-
@sashoalm The question is tagged for linux – simonc Nov 10 '14 at 13:20
-
But if the library is using unconventional allocators, it will be much harder. However, it may help you discriminate its allocations. – didierc Nov 10 '14 at 13:25
-
[Valgrind](http://valgrind.org/) tracks allocations, probably it has means to debug them too. – Basilevs Nov 10 '14 at 13:40
-
@devianfan Obviously, but I was looking for a more programatical method. – CommanderHK Nov 11 '14 at 05:45
-
1@didierc dlopen etc. let resolve symbols and pointers back and forth to each other. But when you have to start with neither, can you enumerate all the pointers and check them one by one? Overloading malloc and free seems to be a practical idea, but let's leave it as the last resort. – CommanderHK Nov 11 '14 at 05:50
-
@CommanderHK I was merely responding to the title question, and didn't pay attention to the body with mention of the static entry. The answer about `/proc/self` is spot on. As for `malloc` diversions, it would indeed only work in the case when doing `dlopen` manually, which is of course not the usual case (note that it would work on any ELF based OS though). – didierc Nov 11 '14 at 06:41
1 Answers
5
You can parse the process maps with the file /proc/self/maps
and see where the pointer address is bounded, global variable will be located in the .data
or the .bss
segments.
Example library lib.c
:
static int object;
int *
dummy(void)
{
return &object;
}
The test.c
, errors not handled for simplicity:
#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);
}
Test:
$ gcc -Wall -shared lib.c -o lib.so
$ gcc -Wall test.c -ldl
$ ./a.out
0xb779f5f8 => /home/barakat/Desktop/lib.so
$