Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.1:kernel-2.6.32
ltrace
ltrace.trunk-r50.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File ltrace.trunk-r50.patch of Package ltrace
------------------------------------------------------------------------ r50 | pmachata-guest | 2006-07-18 10:58:12 +0000 (Tue, 18 Jul 2006) | 2 lines Changed paths: M /ltrace/trunk/ChangeLog M /ltrace/trunk/elf.c M /ltrace/trunk/elf.h .gnu.hash ELF support ------------------------------------------------------------------------ --- ChangeLog | 5 ++ elf.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------- elf.h | 1 3 files changed, 94 insertions(+), 16 deletions(-) Index: elf.c =================================================================== --- elf.c.orig +++ elf.c @@ -169,6 +169,8 @@ static void do_init_elf(struct ltelf *lt Elf_Data *data; size_t j; + lte->hash_type = SHT_HASH; + data = elf_getdata(scn, NULL); if (data == NULL || elf_getdata(scn, data) != NULL || data->d_off || data->d_size != shdr.sh_size) @@ -209,6 +211,30 @@ static void do_init_elf(struct ltelf *lt error(EXIT_FAILURE, 0, "Unknown .hash sh_entsize in \"%s\"", filename); +#ifdef SHT_GNU_HASH + } else if (shdr.sh_type == SHT_GNU_HASH + && lte->hash == NULL) { + Elf_Data *data; + size_t j; + + lte->hash_type = SHT_GNU_HASH; + + if (shdr.sh_entsize != 0 + && shdr.sh_entsize != 4) { + error(EXIT_FAILURE, 0, + ".gnu.hash sh_entsize in \"%s\" should be 4, but is %d", + filename, shdr.sh_entsize); + } + + data = elf_getdata(scn, NULL); + if (data == NULL || elf_getdata(scn, data) != NULL + || data->d_off || data->d_size != shdr.sh_size) + error(EXIT_FAILURE, 0, + "Couldn't get .gnu.hash data from \"%s\"", + filename); + + lte->hash = (Elf32_Word *) data->d_buf; +#endif } else if (shdr.sh_type == SHT_PROGBITS || shdr.sh_type == SHT_NOBITS) { if (strcmp(name, ".plt") == 0) { @@ -301,33 +327,79 @@ static int in_load_libraries(const char { size_t i; unsigned long hash; +#ifdef SHT_GNU_HASH + unsigned long gnu_hash; +#endif if (!library_num) return 1; hash = elf_hash((const unsigned char *)name); +#ifdef SHT_GNU_HASH + gnu_hash = elf_gnu_hash((const unsigned char *)name); +#endif for (i = 1; i <= library_num; ++i) { - Elf32_Word nbuckets, symndx; - Elf32_Word *buckets, *chain; - if (lte[i].hash == NULL) continue; - nbuckets = lte[i].hash[0]; - buckets = <e[i].hash[2]; - chain = <e[i].hash[2 + nbuckets]; - for (symndx = buckets[hash % nbuckets]; - symndx != STN_UNDEF; symndx = chain[symndx]) { - GElf_Sym sym; +#ifdef SHT_GNU_HASH + if (lte[i].hash_type == SHT_GNU_HASH) { + Elf32_Word * hashbase = lte[i].hash; + Elf32_Word nbuckets = *hashbase++; + Elf32_Word symbias = *hashbase++; + Elf32_Word bitmask_nwords = *hashbase++; + Elf32_Word bitmask_idxbits = bitmask_nwords - 1; + Elf32_Word shift = *hashbase++; + Elf32_Word * buckets; + Elf32_Word * chain_zero; + Elf32_Word bucket; + + hashbase += lte[i].ehdr.e_ident[EI_CLASS] * bitmask_nwords; + buckets = hashbase; + hashbase += nbuckets; + chain_zero = hashbase - symbias; + bucket = buckets[gnu_hash % nbuckets]; + + if (bucket != 0) { + const Elf32_Word *hasharr = &chain_zero[bucket]; + do + if ((*hasharr & ~1u) == (gnu_hash & ~1u)) { + int symidx = hasharr - chain_zero; + GElf_Sym sym; + + if (gelf_getsym(lte[i].dynsym, symidx, &sym) == NULL) + error(EXIT_FAILURE, 0, + "Couldn't get symbol from .dynsym"); + + if (sym.st_value != 0 + && sym.st_shndx != SHN_UNDEF + && strcmp(name, lte[i].dynstr + sym.st_name) == 0) + return 1; + } + while ((*hasharr++ & 1u) == 0); + } + } else +#endif + { + Elf32_Word nbuckets, symndx; + Elf32_Word *buckets, *chain; + nbuckets = lte[i].hash[0]; + buckets = <e[i].hash[2]; + chain = <e[i].hash[2 + nbuckets]; + + for (symndx = buckets[hash % nbuckets]; + symndx != STN_UNDEF; symndx = chain[symndx]) { + GElf_Sym sym; - if (gelf_getsym(lte[i].dynsym, symndx, &sym) == NULL) - error(EXIT_FAILURE, 0, - "Couldn't get symbol from .dynsym"); + if (gelf_getsym(lte[i].dynsym, symndx, &sym) == NULL) + error(EXIT_FAILURE, 0, + "Couldn't get symbol from .dynsym"); - if (sym.st_value != 0 - && sym.st_shndx != SHN_UNDEF - && strcmp(name, lte[i].dynstr + sym.st_name) == 0) - return 1; + if (sym.st_value != 0 + && sym.st_shndx != SHN_UNDEF + && strcmp(name, lte[i].dynstr + sym.st_name) == 0) + return 1; + } } } return 0; Index: elf.h =================================================================== --- elf.h.orig +++ elf.h @@ -24,6 +24,7 @@ struct ltelf { GElf_Addr *opd_addr; size_t opd_size; Elf32_Word *hash; + int hash_type; int lte_flags; }; Index: ChangeLog =================================================================== --- ChangeLog.orig +++ ChangeLog @@ -1,3 +1,8 @@ +2006-07-18 Petr Machata <pmachata@redhat.com> + + * elf.c: support .gnu.hash ELF entry + * elf.h: likewise + 2006-07-18 Petr Machata <pmachata@redhat.com> * options.c: don't hardcode version number
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor