Names of source shared libraries for imported symbols in ELF format
i'm working on program that will analyze object files in ELF and PE formats (kind of school/research project). Right now i'm about to process dynamic import symbols in executable files. I would like to find as much info about symbol as possible.
In PE format, imports are stored in .idata
section. There are several tables with different information but what is interesting for me is, that there is no problem to find out in which library is symbol defined. There is always name of shared library and then names/ordinals of symbols imported from it.
I would like to find out this kind of information in ELF files as well. All imports/exports are in .dynsym
section - dynamic symbol table. Those symbols which are imported are marked as undefined, for example:
00000000 DF *UND* 00000000 GLIBC_2.0 fileno
But there are no information, what is source file of this symbol. All needed shared libraries are listed in .dynamic
section, for example:
Dynamic Section:
NEEDED libz.so.1
Only information about library in symbol is Version String = GLIBC_2.0
. I was thinking about getting to real library name through this, but when i look at output of objdump -p
i found out that GLIBC_2.0
can be connected with more than one library:
Version References:
required from libm.so.6:
0x0d696910 0x00 13 GLIBC_2.0
required from libgcc_s.so.1:开发者_StackOverflow中文版
0x0b792650 0x00 12 GLIBC_2.0
If i understand ELF dynamic linking process correctly, it should not be possible to find out this information in ELF executable file. Where exactly is the symbol imported from is determined by linker after it loads all symbol tables to memory. But i would like to be sure about this before i move on, so my question is: Is there any way how can I find out name of symbols shared library from ELF executable file?
Thank you for any advice.
A few months ago I was working on pretty similar stuff - I was able to answer all my questions by grabbing the source to nm and readelf. ( See http://ftp.gnu.org/gnu/binutils/ ) I found this useful as well -> http://www.skyfree.org/linux/references/ELF_Format.pdf
Ok, so it is probably generaly impossible to assign library name to each imported symbol. But i may have found the solution through Symbol Versioning. Of course sybol version sections do not have to be present in each ELF file.
struct elf_obj_tdata *pElf = bfdFile->tdata.elf_obj_data;
for (long i = 0; i < dynNumSyms; i++)
{
asymbol *dynSym = dynSymTab[i];
// If there is version information in file.
if (pElf->dynversym_section != 0
&& (pElf->dynverdef_section != 0
|| pElf->dynverref_section != 0))
{
unsigned int vernum;
const char *version_string;
const char *fileName;
vernum = ((elf_symbol_type *) dynSym)->version & VERSYM_VERSION;
if (vernum == 0) // local sym
version_string = "";
else if (vernum == 1) // global sym, defined in this object
version_string = "Base";
else if (vernum <= pElf->cverdefs)
version_string = pElf->verdef[vernum - 1].vd_nodename;
else
{
Elf_Internal_Verneed *t;
version_string = "";
fileName = "";
// Iterate through all Verneed entries - all libraries
for (t = pElf->verref; t != NULL; t = t->vn_nextref)
{
Elf_Internal_Vernaux *a;
// Iterate through all Vernaux entries
for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
{
// Find associated entry
if (a->vna_other == vernum)
{
version_string = a->vna_nodename;
fileName = t->vn_filename;
break;
}
}
}
// here we have got:
// name of symbol = dynSym->name
// version string = version_string
// name of library = fileName
}
}
}
So what do you think, is this correct?
精彩评论