Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib/librumpuser Support binaries which use DT_GNU_HASH inste...
details: https://anonhg.NetBSD.org/src/rev/2e6d54ed9006
branches: trunk
changeset: 783225:2e6d54ed9006
user: pooka <pooka%NetBSD.org@localhost>
date: Tue Dec 11 21:16:22 2012 +0000
description:
Support binaries which use DT_GNU_HASH instead of DT_HASH.
diffstat:
lib/librumpuser/rumpuser_dl.c | 51 +++++++++++++++++++++++++++++++++++++++++-
1 files changed, 49 insertions(+), 2 deletions(-)
diffs (72 lines):
diff -r a9ff3cc9a1cc -r 2e6d54ed9006 lib/librumpuser/rumpuser_dl.c
--- a/lib/librumpuser/rumpuser_dl.c Tue Dec 11 19:29:29 2012 +0000
+++ b/lib/librumpuser/rumpuser_dl.c Tue Dec 11 21:16:22 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rumpuser_dl.c,v 1.10 2012/11/26 17:55:11 pooka Exp $ */
+/* $NetBSD: rumpuser_dl.c,v 1.11 2012/12/11 21:16:22 pooka Exp $ */
/*
* Copyright (c) 2009 Antti Kantee. All Rights Reserved.
@@ -33,7 +33,7 @@
#include "rumpuser_port.h"
#if !defined(lint)
-__RCSID("$NetBSD: rumpuser_dl.c,v 1.10 2012/11/26 17:55:11 pooka Exp $");
+__RCSID("$NetBSD: rumpuser_dl.c,v 1.11 2012/12/11 21:16:22 pooka Exp $");
#endif /* !lint */
#include <sys/types.h>
@@ -213,6 +213,53 @@
hashtab = (Elf_Symindx *)adjptr(map, edptr);
cursymcount = hashtab[1];
break;
+#ifdef DT_GNU_HASH
+ /*
+ * DT_GNU_HASH is a bit more complicated than DT_HASH
+ * in this regard since apparently there is no field
+ * telling us the total symbol count. Instead, we look
+ * for the last valid hash bucket and add its chain lenght
+ * to the bucket's base index.
+ */
+ case DT_GNU_HASH: {
+ Elf32_Word nbuck, symndx, maskwords, maxchain = 0;
+ Elf32_Word *gnuhash, *buckets, *ptr;
+ int bi;
+
+ DYNn_GETMEMBER(ed_base, i, d_un.d_ptr, edptr);
+ gnuhash = (Elf32_Word *)adjptr(map, edptr);
+
+ nbuck = gnuhash[0];
+ symndx = gnuhash[1];
+ maskwords = gnuhash[2];
+
+ /*
+ * First, find the last valid bucket and grab its index
+ */
+ if (eident == ELFCLASS64)
+ maskwords *= 2; /* sizeof(*buckets) == 4 */
+ buckets = gnuhash + 4 + maskwords;
+ for (bi = nbuck-1; bi >= 0; bi--) {
+ if (buckets[bi] != 0) {
+ maxchain = buckets[bi];
+ break;
+ }
+ }
+ if (maxchain == 0 || maxchain < symndx)
+ break;
+
+ /*
+ * Then, traverse the last chain and count symbols.
+ */
+
+ cursymcount = maxchain;
+ ptr = buckets + nbuck + (maxchain - symndx);
+ do {
+ cursymcount++;
+ } while ((*ptr++ & 1) == 0);
+ }
+ break;
+#endif
case DT_SYMENT:
DYNn_GETMEMBER(ed_base, i, d_un.d_val, edval);
assert(edval == SYM_GETSIZE());
Home |
Main Index |
Thread Index |
Old Index