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.