[Ltrace-devel] [PATCH] include elf_gnu_hash function

Olaf Hering olh at suse.de
Fri Sep 15 06:52:50 UTC 2006


glibc mainline defines SHT_GNU_HASH.
If elfutils is not installed during build, linking will fail due to missing
elf_gnu_hash(). Its a simple function, so include it directly.

Enable the code inside SHT_GNU_HASH because it does not need special functions.
shdr.sh_entsize is u64 in our libelf, change the printf format specifier
in the error path.

---
 elf.c |   27 ++++++++++++++-------------
 elf.h |    3 +++
 2 files changed, 17 insertions(+), 13 deletions(-)

Index: ltrace-0.4/elf.c
===================================================================
--- ltrace-0.4.orig/elf.c
+++ ltrace-0.4/elf.c
@@ -211,18 +211,16 @@ 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",
+				      ".gnu.hash sh_entsize in \"%s\" should be 4, but is %llu",
 				      filename, shdr.sh_entsize);
 			}
 
@@ -234,7 +232,6 @@ static void do_init_elf(struct ltelf *lt
 				      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) {
@@ -323,26 +320,32 @@ add_library_symbol(GElf_Addr addr, const
 	debug(2, "addr: %p, symbol: \"%s\"", (void *)(uintptr_t) addr, name);
 }
 
+/* stolen from elfutils-0.123 */
+static unsigned long elf_gnu_hash(const char *name)
+{
+	unsigned long h = 5381;
+	const unsigned char *string = (const unsigned char *)name;
+	unsigned char c;
+	for (c = *string; c; c = *++string)
+		h = h * 33 + c;
+	return h & 0xffffffff;
+}
+
 static int in_load_libraries(const char *name, struct ltelf *lte)
 {
 	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
+	gnu_hash = elf_gnu_hash(name);
 	for (i = 1; i <= library_num; ++i) {
 		if (lte[i].hash == NULL)
 			continue;
 
-#ifdef SHT_GNU_HASH
 		if (lte[i].hash_type == SHT_GNU_HASH) {
 			Elf32_Word * hashbase = lte[i].hash;
 			Elf32_Word nbuckets = *hashbase++;
@@ -378,9 +381,7 @@ static int in_load_libraries(const char 
 					}
 				while ((*hasharr++ & 1u) == 0);
 			}
-		} else
-#endif
-		{
+		} else {
 			Elf32_Word nbuckets, symndx;
 			Elf32_Word *buckets, *chain;
 			nbuckets = lte[i].hash[0];
Index: ltrace-0.4/elf.h
===================================================================
--- ltrace-0.4.orig/elf.h
+++ ltrace-0.4/elf.h
@@ -40,4 +40,7 @@ extern struct library_symbol *read_elf(s
 
 extern GElf_Addr arch_plt_sym_val(struct ltelf *, size_t, GElf_Rela *);
 
+#ifndef SHT_GNU_HASH
+#define SHT_GNU_HASH	0x6ffffff6	/* GNU-style hash table. */
+#endif
 #endif



More information about the Ltrace-devel mailing list