From 1347154cdc5c18518383ad64dda5531aedac6020 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hulata?= Date: Sat, 23 Aug 2025 00:54:04 +0200 Subject: vdso: add support for GNU hash tables on some kernel builds, the vdso exports symbols with DT_GNU_HASH but omits DT_HASH, causing the vdso not to get used and for clock_gettime to fall back to using a syscall. our vdso resolver does not use the hash table anyway, but does need the symbol count from the standard sysv hash table. if it's missing, use the GNU hashtable to calculate the number of symbols. --- src/internal/vdso.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/internal/vdso.c b/src/internal/vdso.c index d46d3228..2b6e1ae2 100644 --- a/src/internal/vdso.c +++ b/src/internal/vdso.c @@ -40,6 +40,24 @@ static int checkver(Verdef *def, int vsym, const char *vername, char *strings) #define OK_TYPES (1< nsym) + nsym = buckets[i]; + } + if (nsym) { + hashval = buckets + gh[0] + (nsym - gh[1]); + do nsym++; + while (!(*hashval++ & 1)); + } + return nsym; +} + + void *__vdsosym(const char *vername, const char *name) { size_t i; @@ -60,6 +78,7 @@ void *__vdsosym(const char *vername, const char *name) char *strings = 0; Sym *syms = 0; Elf_Symndx *hashtab = 0; + uint32_t *ghashtab = 0; uint16_t *versym = 0; Verdef *verdef = 0; @@ -69,15 +88,20 @@ void *__vdsosym(const char *vername, const char *name) case DT_STRTAB: strings = p; break; case DT_SYMTAB: syms = p; break; case DT_HASH: hashtab = p; break; + case DT_GNU_HASH: ghashtab = p; break; case DT_VERSYM: versym = p; break; case DT_VERDEF: verdef = p; break; } } - if (!strings || !syms || !hashtab) return 0; + if (!strings || !syms) return 0; if (!verdef) versym = 0; + size_t nsym = 0; + + if (hashtab) nsym = hashtab[1]; + else if (ghashtab) nsym = count_syms_gnu(ghashtab); - for (i=0; i>4) & OK_BINDS)) continue; if (!syms[i].st_shndx) continue; -- cgit v1.2.1