From nobody Sat Feb 7 22:55:20 2026 Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 48F1417578 for ; Thu, 15 Aug 2024 03:26:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723692380; cv=none; b=nPwVaZp2Jr3NwvYuz4jfXPuiwW1C5BW1D+PYQBS/WhM/6MuEIUZyMwYD7EVSveKg/N4DdYcsJBxLmsVmb0tSWZjlnd2Aet4aXzVfBtvN7ktwMxfY+kxrYZsLXxccIZ3AT2QQzf/HC/Uulgvg8j7lb36Ft8gfxY84wQ51By5MzmY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723692380; c=relaxed/simple; bh=eCrF4L7L013Lbyx/EqsJVmDCQSkeFCRdOB/AqI4sYCY=; h=Date:Mime-Version:Message-ID:Subject:From:To:Cc:Content-Type; b=AuquhxeQQJQuJKk9Xrpk2wkmaBtgwX0cOTr1qr2LEcFKiEqtgE7EF2hxfpeuOHz3UoVMIpqUEckvUIrQBDLdYxPyHN8ucf5KJNyPK/fx8M2jlcnJB/G36YMg8iX5u6shM1nv0Mbf0f3SOH/d+59EJx3fEShYCnsWqeRXx+zjRHg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--maskray.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=K8qJdV3h; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--maskray.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="K8qJdV3h" Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-66a2aee82a0so11248047b3.0 for ; Wed, 14 Aug 2024 20:26:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1723692377; x=1724297177; darn=vger.kernel.org; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date:message-id:reply-to; bh=ftLnDEOB7+9TeneBrUPUBNMhzAdIHafAcv7/yjdA9pg=; b=K8qJdV3hBnDp2nW1nS4/cJQFtVb2qzBySjRyCvN+GEi1BHKs6c+tudn9ykFsYk6rqD vS5iFzxfZnSeWcmqWVqLKcfeSHswnvopXrxXGYwG7bkrzQtM/cFBzy3lJq4Jem67Yl66 fse1ez0K39/sc2rIQaBXF4SAdrcvK7cXF9gCPFOUy0l9DHFk+0eUc1CAyZr8/kUiMVrS GOTpr0WXpvr7r2a0434I8DvJuj4xQjft2Kh9US02A/61o8w5X6gr6USfUttvtve41scW xQEuzghQDHySgIKl6NQvFt9axm/SGS16pUqhN6MVvCfb8DSHoXo26dkoK4Fontovj/mV GQjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723692377; x=1724297177; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=ftLnDEOB7+9TeneBrUPUBNMhzAdIHafAcv7/yjdA9pg=; b=g+itA9O+Aw7B0Fnuybmufqz/hbB1fTquXG7lhrzofsixevPAqwpeJgMz65du46zMW/ RIxs/RDA9H/Y2joNMELXkD6KPwX3uGJHkGlYwpJL+mxy5dtxsfPnn4eEsfHNGxtSNaZi pVebJs3xw7ldmdJ+xKZ2wUKNyt2zCrExnQwCiw/F/LejwFJUSRVJ5ql1azHEhS6z+OTa lVzdGqTKT0CPJNOqf9Af27KQIpD7KtumU9lgNFXnIs6PSP0fQj9iz8gJZB9t4TV8Y/+0 0O1ga6b58XOuiY6HpOEaNwwzSw8dD2I6+xBcTE7DH9T9bTo1zWwM6d4XdEWjGF+Iw2mp JJrg== X-Gm-Message-State: AOJu0YztwYmmuWXidpEOt5Y0t7B5Qce+iM5U5yf50rdnJx8YxMC0LAoG hMGadrmp0Hg6chmhGjYS+ZsF3EPuNUHuH3n9wUmqR1n0BLnC19uPusEd/p+HGe8jAhNqc2dz1WQ EWGOZfA== X-Google-Smtp-Source: AGHT+IHZRLmGS4QgdBXQheYH//g9x8s5N18YyOTKFZTVnJpqcP2g6jmzSv5bzIuH2R4EdR2G4T4jEB6oTTcY X-Received: from maskray.svl.corp.google.com ([2620:15c:2d3:205:aaf0:b9c8:2773:d92b]) (user=maskray job=sendgmr) by 2002:a25:acc2:0:b0:e0b:cb4a:3602 with SMTP id 3f1490d57ef6-e1155ab133cmr6193276.4.1723692377187; Wed, 14 Aug 2024 20:26:17 -0700 (PDT) Date: Wed, 14 Aug 2024 20:26:13 -0700 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 Message-ID: <20240815032614.2747224-1-maskray@google.com> Subject: [PATCH] selftests/vDSO: support DT_GNU_HASH From: Fangrui Song To: Shuah Khan , linux-kselftest@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Xi Ruoyao , Fangrui Song Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" glibc added support for DT_GNU_HASH in 2006 and DT_HASH has been obsoleted for more than one decade in many Linux distributions. Many vDSOs support DT_GNU_HASH. This patch adds selftests support. Signed-off-by: Fangrui Song Tested-by: Xi Ruoyao --- tools/testing/selftests/vDSO/parse_vdso.c | 105 ++++++++++++++++------ 1 file changed, 79 insertions(+), 26 deletions(-) diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/self= tests/vDSO/parse_vdso.c index 4ae417372e9e..35cb545da13e 100644 --- a/tools/testing/selftests/vDSO/parse_vdso.c +++ b/tools/testing/selftests/vDSO/parse_vdso.c @@ -47,6 +47,7 @@ static struct vdso_info /* Symbol table */ ELF(Sym) *symtab; const char *symstrings; + ELF(Word) *gnu_hash; ELF(Word) *bucket, *chain; ELF(Word) nbucket, nchain; =20 @@ -75,6 +76,16 @@ static unsigned long elf_hash(const char *name) return h; } =20 +static uint32_t gnu_hash(const char *name) +{ + const unsigned char *s =3D (void *)name; + uint32_t h =3D 5381; + + for (; *s; s++) + h +=3D h * 32 + *s; + return h; +} + void vdso_init_from_sysinfo_ehdr(uintptr_t base) { size_t i; @@ -117,6 +128,7 @@ void vdso_init_from_sysinfo_ehdr(uintptr_t base) */ ELF(Word) *hash =3D 0; vdso_info.symstrings =3D 0; + vdso_info.gnu_hash =3D 0; vdso_info.symtab =3D 0; vdso_info.versym =3D 0; vdso_info.verdef =3D 0; @@ -137,6 +149,11 @@ void vdso_init_from_sysinfo_ehdr(uintptr_t base) ((uintptr_t)dyn[i].d_un.d_ptr + vdso_info.load_offset); break; + case DT_GNU_HASH: + vdso_info.gnu_hash =3D + (ELF(Word) *)((uintptr_t)dyn[i].d_un.d_ptr + + vdso_info.load_offset); + break; case DT_VERSYM: vdso_info.versym =3D (ELF(Versym) *) ((uintptr_t)dyn[i].d_un.d_ptr @@ -149,17 +166,26 @@ void vdso_init_from_sysinfo_ehdr(uintptr_t base) break; } } - if (!vdso_info.symstrings || !vdso_info.symtab || !hash) + if (!vdso_info.symstrings || !vdso_info.symtab || + (!hash && !vdso_info.gnu_hash)) return; /* Failed */ =20 if (!vdso_info.verdef) vdso_info.versym =3D 0; =20 /* Parse the hash table header. */ - vdso_info.nbucket =3D hash[0]; - vdso_info.nchain =3D hash[1]; - vdso_info.bucket =3D &hash[2]; - vdso_info.chain =3D &hash[vdso_info.nbucket + 2]; + if (vdso_info.gnu_hash) { + vdso_info.nbucket =3D vdso_info.gnu_hash[0]; + /* The bucket array is located after the header (4 uint32) and the bloom + filter (size_t array of gnu_hash[2] elements). */ + vdso_info.bucket =3D vdso_info.gnu_hash + 4 + + sizeof(size_t) / 4 * vdso_info.gnu_hash[2]; + } else { + vdso_info.nbucket =3D hash[0]; + vdso_info.nchain =3D hash[1]; + vdso_info.bucket =3D &hash[2]; + vdso_info.chain =3D &hash[vdso_info.nbucket + 2]; + } =20 /* That's all we need. */ vdso_info.valid =3D true; @@ -203,6 +229,26 @@ static bool vdso_match_version(ELF(Versym) ver, && !strcmp(name, vdso_info.symstrings + aux->vda_name); } =20 +static bool check_sym(ELF(Sym) *sym, ELF(Word) i, const char *name, + const char *version, unsigned long ver_hash) +{ + /* Check for a defined global or weak function w/ right name. */ + if (ELF64_ST_TYPE(sym->st_info) !=3D STT_FUNC) + return false; + if (ELF64_ST_BIND(sym->st_info) !=3D STB_GLOBAL && + ELF64_ST_BIND(sym->st_info) !=3D STB_WEAK) + return false; + if (strcmp(name, vdso_info.symstrings + sym->st_name)) + return false; + + /* Check symbol version. */ + if (vdso_info.versym && + !vdso_match_version(vdso_info.versym[i], version, ver_hash)) + return false; + + return true; +} + void *vdso_sym(const char *version, const char *name) { unsigned long ver_hash; @@ -210,29 +256,36 @@ void *vdso_sym(const char *version, const char *name) return 0; =20 ver_hash =3D elf_hash(version); - ELF(Word) chain =3D vdso_info.bucket[elf_hash(name) % vdso_info.nbucket]; + ELF(Word) i; =20 - for (; chain !=3D STN_UNDEF; chain =3D vdso_info.chain[chain]) { - ELF(Sym) *sym =3D &vdso_info.symtab[chain]; + if (vdso_info.gnu_hash) { + uint32_t h1 =3D gnu_hash(name), h2, *hashval; =20 - /* Check for a defined global or weak function w/ right name. */ - if (ELF64_ST_TYPE(sym->st_info) !=3D STT_FUNC) - continue; - if (ELF64_ST_BIND(sym->st_info) !=3D STB_GLOBAL && - ELF64_ST_BIND(sym->st_info) !=3D STB_WEAK) - continue; - if (sym->st_shndx =3D=3D SHN_UNDEF) - continue; - if (strcmp(name, vdso_info.symstrings + sym->st_name)) - continue; - - /* Check symbol version. */ - if (vdso_info.versym - && !vdso_match_version(vdso_info.versym[chain], - version, ver_hash)) - continue; - - return (void *)(vdso_info.load_offset + sym->st_value); + i =3D vdso_info.bucket[h1 % vdso_info.nbucket]; + if (i =3D=3D 0) + return 0; + h1 |=3D 1; + hashval =3D vdso_info.bucket + vdso_info.nbucket + + (i - vdso_info.gnu_hash[1]); + for (;; i++) { + ELF(Sym) *sym =3D &vdso_info.symtab[i]; + h2 =3D *hashval++; + if (h1 =3D=3D (h2 | 1) && + check_sym(sym, i, name, version, ver_hash)) + return (void *)(vdso_info.load_offset + + sym->st_value); + if (h2 & 1) + break; + } + } else { + i =3D vdso_info.bucket[elf_hash(name) % vdso_info.nbucket]; + for (; i; i =3D vdso_info.chain[i]) { + ELF(Sym) *sym =3D &vdso_info.symtab[i]; + if (sym->st_shndx !=3D SHN_UNDEF && + check_sym(sym, i, name, version, ver_hash)) + return (void *)(vdso_info.load_offset + + sym->st_value); + } } =20 return 0; --=20 2.46.0.76.ge559c4bf1a-goog