I want to simulate loading symbols from a shared library for testing purposes.
Is there a way to define a symbol at runtime programmatically such that dlsym
will find it?
For example:
dl_define_symbol("foobar")
....
void* f = dlsym("foobar",RTLD_NEXT);
The question is does anything (dl, ld, elfutils?) expose API functions that would make this possible?
Such functionality probably exists inside ld
but it is possibly not exposed.
Put another way is there a symmetric API for dlsym()
et al?
For context, I am writing automated tests for the behaviour of an application involving library interposition using LD_PRELOAD and dlsym(RTLD_NEXT)
.
This is actually a malloc interposer along the lines of the linked questions:
- https://mcmap.net/q/206353/-an-alternative-for-the-deprecated-__malloc_hook-functionality-of-glibc
- How to correctly interpose malloc allowing for LD_PRELOAD chaining
I want to test the case where different symbols come from different libraries.
This can be detected by using dladdr
on the symbols.
Pseudo-code:
void* f1 = dlsym(RTLD_NEXT,"malloc");
void* f2 = dlsym(RTLD_NEXT,"malloc_usable_size");
// handle failures...
Dl_info info1;
dladdr(f1,&info1);
Dl_info info2;
dladdr(f2,&info2);
// handle failures...
if (info1.dli_fbase != info2.dli_fbase)
{
// malloc_usable_size() is provided by a different library than malloc()
// so we probably shouldn't use it
f2 = nullptr;
// set flags accordingly
}
An example of this in practice is electric-fence. If I chain:
LD_PRELOAD="mymalloc.so electric-fence.so"
You find that malloc_usable_size()
comes from libc
while malloc
comes from electric-fence
.
Granted electric-fence is not so common any more.
This is of course possible by using a real shared library in the tests. This question asks if there is a shortcut. Another approach would to try and interpose dlsym() itself. This is somewhat scary. Though see - How can I intercept dlsym calls using LD_PRELOAD?