it's very easy to find how to use dlsym() and other functions from this family, but how does it work internally? Is it possible to write own, easy implementation of dlsym()?
I'm wondering if it is possible to achieve similar behavior but without linking with -ldl (lets say I can't do this).
how does it work internally?
As this answer explains, in GLIBC the first parameter is actually a pointer to struct link_map
, which contains enough info to locate the dynamic symbol table of the shared library. Once the symbol table and DT_HASH
or DT_GNU_HASH
are located, dlsym
uses one or the other hash table to find the given symbol name.
Is it possible to write own, easy implementation of dlsym()?
Yes. If you don't care about the speed of lookup, you can simply do linear search of the dynamic symbol table. The code to do so is quite simple, especially if the shared library has (optional) section header: all you need to do is find location of .dynsym
and .dynstr
sections in memory, and then (assuming you are looking for symbol "foo"
)
const char *strtab = ... /* locate .dynstr */
const ElfW(Sym) *sym = ... /* locate .dynsym */
for (; sym < end_of_dynsym; ++sym) {
if (strcmp(strtab + sym->st_name, "foo") == 0) {
/* found it */
return load_address + sym->st_value;
}
}
/* symbol not found */
return NULL;
If you do care about lookup speed (dlsym
certainly does), you'll need to decode .hash
or .gnu_hash
, which is a bit more complicated. You could start here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With