|
|
4fb08dd |
diff -urpd ltrace-0.5-orig/elf.c ltrace-0.5/elf.c
|
|
|
4fb08dd |
--- ltrace-0.5-orig/elf.c 2006-07-14 12:28:32.000000000 -0400
|
|
|
4fb08dd |
+++ ltrace-0.5/elf.c 2006-07-14 16:47:31.000000000 -0400
|
|
|
4fb08dd |
@@ -169,6 +169,8 @@ static void do_init_elf(struct ltelf *lt
|
|
|
4fb08dd |
Elf_Data *data;
|
|
|
4fb08dd |
size_t j;
|
|
|
4fb08dd |
|
|
|
4fb08dd |
+ lte->hash_type = SHT_HASH;
|
|
|
4fb08dd |
+
|
|
|
4fb08dd |
data = elf_getdata(scn, NULL);
|
|
|
4fb08dd |
if (data == NULL || elf_getdata(scn, data) != NULL
|
|
|
4fb08dd |
|| data->d_off || data->d_size != shdr.sh_size)
|
|
|
b64f3cb |
@@ -209,6 +211,30 @@ static void do_init_elf(struct ltelf *lt
|
|
|
4fb08dd |
error(EXIT_FAILURE, 0,
|
|
|
4fb08dd |
"Unknown .hash sh_entsize in \"%s\"",
|
|
|
4fb08dd |
filename);
|
|
|
4fb08dd |
+#ifdef SHT_GNU_HASH
|
|
|
4fb08dd |
+ } else if (shdr.sh_type == SHT_GNU_HASH
|
|
|
4fb08dd |
+ && lte->hash == NULL) {
|
|
|
4fb08dd |
+ Elf_Data *data;
|
|
|
4fb08dd |
+ size_t j;
|
|
|
4fb08dd |
+
|
|
|
4fb08dd |
+ lte->hash_type = SHT_GNU_HASH;
|
|
|
4fb08dd |
+
|
|
|
b64f3cb |
+ if (shdr.sh_entsize != 0
|
|
|
b64f3cb |
+ && shdr.sh_entsize != 4) {
|
|
|
4fb08dd |
+ error(EXIT_FAILURE, 0,
|
|
|
b64f3cb |
+ ".gnu.hash sh_entsize in \"%s\" should be 4, but is %d",
|
|
|
b64f3cb |
+ filename, shdr.sh_entsize);
|
|
|
4fb08dd |
+ }
|
|
|
4fb08dd |
+
|
|
|
4fb08dd |
+ data = elf_getdata(scn, NULL);
|
|
|
4fb08dd |
+ if (data == NULL || elf_getdata(scn, data) != NULL
|
|
|
4fb08dd |
+ || data->d_off || data->d_size != shdr.sh_size)
|
|
|
4fb08dd |
+ error(EXIT_FAILURE, 0,
|
|
|
4fb08dd |
+ "Couldn't get .gnu.hash data from \"%s\"",
|
|
|
4fb08dd |
+ filename);
|
|
|
4fb08dd |
+
|
|
|
4fb08dd |
+ lte->hash = (Elf32_Word *) data->d_buf;
|
|
|
4fb08dd |
+#endif
|
|
|
4fb08dd |
} else if (shdr.sh_type == SHT_PROGBITS
|
|
|
4fb08dd |
|| shdr.sh_type == SHT_NOBITS) {
|
|
|
4fb08dd |
if (strcmp(name, ".plt") == 0) {
|
|
|
4fb08dd |
@@ -300,34 +329,81 @@ add_library_symbol(GElf_Addr addr, const
|
|
|
4fb08dd |
static int in_load_libraries(const char *name, struct ltelf *lte)
|
|
|
4fb08dd |
{
|
|
|
4fb08dd |
size_t i;
|
|
|
4fb08dd |
- unsigned long hash;
|
|
|
4fb08dd |
+ unsigned long hash
|
|
|
4fb08dd |
+#ifdef SHT_GNU_HASH
|
|
|
4fb08dd |
+ , gnu_hash
|
|
|
4fb08dd |
+#endif
|
|
|
4fb08dd |
+ ;
|
|
|
4fb08dd |
|
|
|
4fb08dd |
if (!library_num)
|
|
|
4fb08dd |
return 1;
|
|
|
4fb08dd |
|
|
|
4fb08dd |
hash = elf_hash((const unsigned char *)name);
|
|
|
4fb08dd |
+#ifdef SHT_GNU_HASH
|
|
|
4fb08dd |
+ gnu_hash = elf_gnu_hash((const unsigned char *)name);
|
|
|
4fb08dd |
+#endif
|
|
|
4fb08dd |
for (i = 1; i <= library_num; ++i) {
|
|
|
4fb08dd |
- Elf32_Word nbuckets, symndx;
|
|
|
4fb08dd |
- Elf32_Word *buckets, *chain;
|
|
|
4fb08dd |
-
|
|
|
4fb08dd |
if (lte[i].hash == NULL)
|
|
|
4fb08dd |
continue;
|
|
|
4fb08dd |
|
|
|
4fb08dd |
- nbuckets = lte[i].hash[0];
|
|
|
4fb08dd |
- buckets = <e[i].hash[2];
|
|
|
4fb08dd |
- chain = <e[i].hash[2 + nbuckets];
|
|
|
4fb08dd |
- for (symndx = buckets[hash % nbuckets];
|
|
|
4fb08dd |
- symndx != STN_UNDEF; symndx = chain[symndx]) {
|
|
|
4fb08dd |
- GElf_Sym sym;
|
|
|
4fb08dd |
+#ifdef SHT_GNU_HASH
|
|
|
4fb08dd |
+ if (lte[i].hash_type == SHT_GNU_HASH) {
|
|
|
4fb08dd |
+ Elf32_Word * hashbase = lte[i].hash;
|
|
|
4fb08dd |
+ Elf32_Word nbuckets = *hashbase++;
|
|
|
4fb08dd |
+ Elf32_Word symbias = *hashbase++;
|
|
|
4fb08dd |
+ Elf32_Word bitmask_nwords = *hashbase++;
|
|
|
4fb08dd |
+ Elf32_Word bitmask_idxbits = bitmask_nwords - 1;
|
|
|
4fb08dd |
+ Elf32_Word shift = *hashbase++;
|
|
|
4fb08dd |
+ Elf32_Word * buckets;
|
|
|
4fb08dd |
+ Elf32_Word * chain_zero;
|
|
|
4fb08dd |
+ Elf32_Word bucket;
|
|
|
4fb08dd |
|
|
|
4fb08dd |
- if (gelf_getsym(lte[i].dynsym, symndx, &sym) == NULL)
|
|
|
4fb08dd |
- error(EXIT_FAILURE, 0,
|
|
|
4fb08dd |
- "Couldn't get symbol from .dynsym");
|
|
|
8b29a3c |
+ hashbase += lte[i].ehdr.e_ident[EI_CLASS] * bitmask_nwords;
|
|
|
4fb08dd |
+ buckets = hashbase;
|
|
|
4fb08dd |
+ hashbase += nbuckets;
|
|
|
4fb08dd |
+ chain_zero = hashbase - symbias;
|
|
|
4fb08dd |
+ bucket = buckets[gnu_hash % nbuckets];
|
|
|
4fb08dd |
|
|
|
4fb08dd |
- if (sym.st_value != 0
|
|
|
4fb08dd |
- && sym.st_shndx != SHN_UNDEF
|
|
|
4fb08dd |
- && strcmp(name, lte[i].dynstr + sym.st_name) == 0)
|
|
|
4fb08dd |
- return 1;
|
|
|
4fb08dd |
+ if (bucket != 0) {
|
|
|
4fb08dd |
+ const Elf32_Word *hasharr = &chain_zero[bucket];
|
|
|
4fb08dd |
+ do
|
|
|
4fb08dd |
+ if ((*hasharr & ~1u) == (gnu_hash & ~1u)) {
|
|
|
4fb08dd |
+ int symidx = hasharr - chain_zero;
|
|
|
4fb08dd |
+ GElf_Sym sym;
|
|
|
4fb08dd |
+
|
|
|
4fb08dd |
+ if (gelf_getsym(lte[i].dynsym, symidx, &sym) == NULL)
|
|
|
4fb08dd |
+ error(EXIT_FAILURE, 0,
|
|
|
4fb08dd |
+ "Couldn't get symbol from .dynsym");
|
|
|
4fb08dd |
+
|
|
|
4fb08dd |
+ if (sym.st_value != 0
|
|
|
4fb08dd |
+ && sym.st_shndx != SHN_UNDEF
|
|
|
4fb08dd |
+ && strcmp(name, lte[i].dynstr + sym.st_name) == 0)
|
|
|
4fb08dd |
+ return 1;
|
|
|
4fb08dd |
+ }
|
|
|
4fb08dd |
+ while ((*hasharr++ & 1u) == 0);
|
|
|
4fb08dd |
+ }
|
|
|
4fb08dd |
+ } else
|
|
|
4fb08dd |
+#endif
|
|
|
4fb08dd |
+ {
|
|
|
4fb08dd |
+ Elf32_Word nbuckets, symndx;
|
|
|
4fb08dd |
+ Elf32_Word *buckets, *chain;
|
|
|
4fb08dd |
+ nbuckets = lte[i].hash[0];
|
|
|
4fb08dd |
+ buckets = <e[i].hash[2];
|
|
|
4fb08dd |
+ chain = <e[i].hash[2 + nbuckets];
|
|
|
4fb08dd |
+
|
|
|
4fb08dd |
+ for (symndx = buckets[hash % nbuckets];
|
|
|
4fb08dd |
+ symndx != STN_UNDEF; symndx = chain[symndx]) {
|
|
|
4fb08dd |
+ GElf_Sym sym;
|
|
|
4fb08dd |
+
|
|
|
4fb08dd |
+ if (gelf_getsym(lte[i].dynsym, symndx, &sym) == NULL)
|
|
|
4fb08dd |
+ error(EXIT_FAILURE, 0,
|
|
|
4fb08dd |
+ "Couldn't get symbol from .dynsym");
|
|
|
4fb08dd |
+
|
|
|
4fb08dd |
+ if (sym.st_value != 0
|
|
|
4fb08dd |
+ && sym.st_shndx != SHN_UNDEF
|
|
|
4fb08dd |
+ && strcmp(name, lte[i].dynstr + sym.st_name) == 0)
|
|
|
4fb08dd |
+ return 1;
|
|
|
4fb08dd |
+ }
|
|
|
4fb08dd |
}
|
|
|
4fb08dd |
}
|
|
|
4fb08dd |
return 0;
|
|
|
4fb08dd |
diff -urpd ltrace-0.5-orig/elf.h ltrace-0.5/elf.h
|
|
|
4fb08dd |
--- ltrace-0.5-orig/elf.h 2006-07-14 12:28:32.000000000 -0400
|
|
|
4fb08dd |
+++ ltrace-0.5/elf.h 2006-07-14 13:26:56.000000000 -0400
|
|
|
4fb08dd |
@@ -24,6 +24,7 @@ struct ltelf {
|
|
|
4fb08dd |
GElf_Addr *opd_addr;
|
|
|
4fb08dd |
size_t opd_size;
|
|
|
4fb08dd |
Elf32_Word *hash;
|
|
|
4fb08dd |
+ int hash_type;
|
|
|
4fb08dd |
int lte_flags;
|
|
|
4fb08dd |
};
|
|
|
4fb08dd |
|
|
|
4fb08dd |
diff -urpd ltrace-0.5-orig/options.c ltrace-0.5/options.c
|
|
|
4fb08dd |
--- ltrace-0.5-orig/options.c 2006-07-14 12:28:32.000000000 -0400
|
|
|
4fb08dd |
+++ ltrace-0.5/options.c 2006-07-14 16:46:01.000000000 -0400
|
|
|
4fb08dd |
@@ -3,7 +3,7 @@
|
|
|
4fb08dd |
#endif
|
|
|
4fb08dd |
|
|
|
4fb08dd |
#ifndef PACKAGE_VERSION
|
|
|
4fb08dd |
-# define PACKAGE_VERSION "0.3.32"
|
|
|
4fb08dd |
+# error need package version
|
|
|
4fb08dd |
#endif
|
|
|
4fb08dd |
|
|
|
4fb08dd |
#include <string.h>
|