Search code examples
elfdlsym

Static ELF alternative to dlsym


Is it possible to lookup the location of a function using ELF? Similar to what

void *f = dlopen(NULL,..);
void *func = dlsym(f, "myfunc");

does, but without requiring -rdynamic during compilation?

I can see using nm that the naming of the items is still present in a compiled binary?:

0000000000400716 T lookup
0000000000400759 T main

Can I use this information to locate the items once the program is loaded into memory?


Solution

  • Can I use this information to locate the items once the program is loaded into memory?

    You sure can: iterate over all symbols in the a.out until you find the matching one. Example code to iterate over symbols is here. Or use libelf.

    If you need to perform multiple symbol lookups, iterate once (slow) over all symbols, build a map from symbol name to its address, and perform lookups using that map.

    Update:

    The example you point to seems incomplete? It uses data and elf, where are they coming from?

    Yes, you need to apply a little bit of elbow grease to that example.

    The data is location in memory where the a.out is read into, or (better) mmaped.

    You can either mmap the a.out yourself, or find the existing mapping via e.g. getauxval(AT_PHDR) rounded down to page size.

    The ehdr is (ElfW(Ehdr) *)data (that is, data cast to Elf32_Ehdr or Elf64_Ehdr as appropriate.

    If this is not clear, then you probably should just use libelf, which takes care of the details for you.

    Also, does ELF only allow me to find the name of the symbol, or can it actually give me the pointer to the in memory location of the symbol?

    It can give you both: str + sym[i].st_name is the name, sym[i].st_value is the pointer (the value displayed by nm).

    (presumably the e.g. 0000000000400716 is some relative base address, not the actual in memory location, right?)

    No, actually (for this binary) it's the absolute address.

    Position-independent binaries do use relative addresses (so you'll need something like getauxval mentioned above to find the base location of such executable), but this particular binary looks like ET_EXEC (use readelf -h a.out to verify this). The address 0x400000 is typical address for loading of non-PIE executables on Linux x86_64 (which is probably what your system is).