diff options
author | Peder Andersen | 2012-03-09 00:08:38 +0000 |
---|---|---|
committer | Eugene Tarassov | 2012-03-12 17:53:00 +0000 |
commit | bca72ff48dbcbc597d5d00cf72c9ce6c391a49dc (patch) | |
tree | 0148f399275369f90fdf07b381a3d1ed8d5a048d | |
parent | 283d960758ffb3b542a99f6ab6d175c3039fab99 (diff) | |
download | org.eclipse.tcf.agent-bca72ff48dbcbc597d5d00cf72c9ce6c391a49dc.tar.gz org.eclipse.tcf.agent-bca72ff48dbcbc597d5d00cf72c9ce6c391a49dc.tar.xz org.eclipse.tcf.agent-bca72ff48dbcbc597d5d00cf72c9ce6c391a49dc.zip |
ELF parser: use dynamic symbol table as a fallback
Shared libraries will often have their regular symbol tables stripped,
while retaining their dynamic symbol table for the purposes of runtime
linking. If no symbol table is found, this change allows TCF clients to
use the object's dynamic symbol table for lookup. Note that in the
case where an object has both static and dynamic symbol tables, the
dynamic entries aren't added to the object's symbol list because they
would simply duplicate existing static entries.
-rw-r--r-- | agent/tcf/services/tcf_elf.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/agent/tcf/services/tcf_elf.c b/agent/tcf/services/tcf_elf.c index 4b129914..fbf5915d 100644 --- a/agent/tcf/services/tcf_elf.c +++ b/agent/tcf/services/tcf_elf.c @@ -380,6 +380,9 @@ static ELF_File * create_elf_cache(const char * file_name) { if (error == 0) { Elf32_Ehdr hdr; + int symtab_found; + ELF_Section * dynsym_section; + memset(&hdr, 0, sizeof(hdr)); if (read(file->fd, (char *)&hdr, sizeof(hdr)) < 0) error = errno; if (error == 0 && strncmp((char *)hdr.e_ident, ELFMAG, SELFMAG) != 0) { @@ -397,6 +400,9 @@ static ELF_File * create_elf_cache(const char * file_name) { } file->byte_swap = file->big_endian != big_endian_host(); } + + symtab_found = 0; + dynsym_section = NULL; if (error != 0) { /* Nothing */ } @@ -466,7 +472,14 @@ static ELF_File * create_elf_cache(const char * file_name) { sec->link = shdr.sh_link; sec->info = shdr.sh_info; sec->entsize = shdr.sh_entsize; - if (sec->type == SHT_SYMTAB) sec->sym_count = (unsigned)(sec->size / sizeof(Elf32_Sym)); + if (sec->type == SHT_SYMTAB) { + sec->sym_count = (unsigned int)(sec->size / sizeof(Elf32_Sym)); + symtab_found = 1; + } else if (sec->type == SHT_DYNSYM) { + assert(dynsym_section == NULL); + sec->sym_count = (unsigned int)(sec->size / sizeof(Elf32_Sym)); + dynsym_section = sec; + } cnt++; } } @@ -580,7 +593,15 @@ static ELF_File * create_elf_cache(const char * file_name) { sec->link = shdr.sh_link; sec->info = shdr.sh_info; sec->entsize = (U4_T)shdr.sh_entsize; - if (sec->type == SHT_SYMTAB) sec->sym_count = (unsigned)(sec->size / sizeof(Elf64_Sym)); + if (sec->type == SHT_SYMTAB) { + sec->sym_count = (unsigned)(sec->size / sizeof(Elf64_Sym)); + symtab_found = 1; + } else if (sec->type == SHT_DYNSYM) { + assert(dynsym_section == NULL); + sec->sym_count = (unsigned int)(sec->size / sizeof(Elf64_Sym)); + dynsym_section = sec; + } + cnt++; } } @@ -642,6 +663,9 @@ static ELF_File * create_elf_cache(const char * file_name) { } } } + + if ((dynsym_section != NULL) && (symtab_found == 1)) + dynsym_section->sym_count = 0; } file->debug_info_file = is_debug_info_file(file); if (error == 0 && !file->debug_info_file) { |