Can someone help me to know how can i use dlopen to get handle of libc memory allocation functions? Especially, something like searching the libc path and then taking the handle. What modes should be used to invoke dlsym?
Idea is:
- Search libc path
- Invoke dlopen on it
- Use dlsym to access the memory functions (malloc, calloc etc) and
- use the functions
Please help me with 开发者_StackOverflowa code snippet of the above 4 steps.
Here's a code snippet, HTH
#include <dlfcn.h>
#include <stdio.h>
int main()
{
void *handle;
// dlopen will search the path for you
// /usr/lib/libc.so is a linker script, not an elf file
// so it won't work with dlopen.
handle = dlopen("libc.so.6", RTLD_LAZY);
if(handle){
void* (*mallocptr)(size_t);
void (*freeptr)(void*);
// Locate symbols
*(void**)(&mallocptr) = dlsym(handle, "malloc");
*(void**)(&freeptr) = dlsym(handle, "free");
if(!mallocptr || !freeptr){
printf("%s\n", dlerror());
return 1;
}
// Allocate and use memory
char *ptr = (*mallocptr)(4);
ptr[0] = 'H'; ptr[1] = 'i'; ptr[2] = '\n'; ptr[3] = '\0';
printf(ptr);
// Free it
(*freeptr)(ptr);
}
else{
printf("%s\n", dlerror());
return 1;
}
return 0;
}
This is an old question, but the question itself seems based on a false assumption that dlopen()
must be used to locate objects in the system's standard libc
.
There's no need to use dlopen()
unless you are deliberately loading your functions from a specific shared object that's not the default libc
. As noted in the comments to the other answer, forcing a specific path for what should likely just be the default libc
doesn't always work. Because the default libc
is almost certainly already loaded into your process's address space, and it doesn't have to be in the same location or even have the same name.
Just use dlsym( RTLD_NEXT, "malloc" )
to find malloc()
, for example.
Per the Linux dlsym()
man page:
There are two special pseudo-handles that may be specified in handle:
RTLD_DEFAULT
Find the first occurrence of the desired symbol using the default shared object search order. The search will include global symbols in the executable and its dependencies, as well as symbols in shared objects that were dynamically loaded with the RTLD_GLOBAL flag.
RTLD_NEXT
Find the next occurrence of the desired symbol in the search order after the current object. This allows one to provide a wrapper around a function in another shared object, so that, for example, the definition of a function in a preloaded shared object (see LD_PRELOAD in ld.so(8)) can find and invoke the "real" function provided in another shared object (or for that matter, the "next" definition of the function in cases where there are multiple layers of preloading).
The
_GNU_SOURCE
feature test macro must be defined in order to obtain the definitions ofRTLD_DEFAULT
andRTLD_NEXT
from<dlfcn.h>.
This is all that's necessary:
void* (*mallocptr)(size_t);
void (*freeptr)(void*);
// Locate symbols
mallocptr = dlsym(RTLD_NEXT, "malloc");
freeptr = dlsym(RTLD_NEXT, "free");
if(!mallocptr || !freeptr){
printf("%s\n", dlerror());
return 1;
}
// Allocate and use memory
char *ptr = mallocptr(4);
ptr[0] = 'H'; ptr[1] = 'i'; ptr[2] = '\n'; ptr[3] = '\0';
printf(ptr);
// Free it
freeptr(ptr);
Note that I removed the *(void**)(&mallocptr)
casts - those are not needed. If gcc
incorrectly complains about the assignment (gcc
will improperly issue warnings when assigning void *
pointers but the C standard specifies that a void *
pointer can be safely assigned to any pointer...),
精彩评论