From nobody Sat Oct 16 23:37:35 2021 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 5F37117F19E4; Sat, 16 Oct 2021 23:37:36 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4HX01D0Jn8z4f48; Sat, 16 Oct 2021 23:37:36 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id D1342229E4; Sat, 16 Oct 2021 23:37:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 19GNbZlc075816; Sat, 16 Oct 2021 23:37:35 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 19GNbZNi075815; Sat, 16 Oct 2021 23:37:35 GMT (envelope-from git) Date: Sat, 16 Oct 2021 23:37:35 GMT Message-Id: <202110162337.19GNbZNi075815@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Konstantin Belousov Subject: git: a7d137fcbcac - main - rtld: Support DT_RELR relative relocation format List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: a7d137fcbcac7182d4fcdc97a46b10edc5c7041d Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=a7d137fcbcac7182d4fcdc97a46b10edc5c7041d commit a7d137fcbcac7182d4fcdc97a46b10edc5c7041d Author: Fangrui Song AuthorDate: 2021-10-16 21:34:37 +0000 Commit: Konstantin Belousov CommitDate: 2021-10-16 23:37:13 +0000 rtld: Support DT_RELR relative relocation format PIE and shared objects usually have many relative relocations. In 2017/2018, a compact relative relocation format RELR was proposed on https://groups.google.com/g/generic-abi/c/bX460iggiKg/m/GxjM0L-PBAAJ ("Proposal for a new section type SHT_RELR") and is a pre-standard. RELR usually takes 3% or smaller space than R_*_RELATIVE relocations. The virtual memory size of a mostly statically linked PIE is typically 5~10% smaller. ld.lld --pack-dyn-relocs=relr emits RELR relocations. DT_RELR has been adopted by Android bionic, Linux kernel's arm64 port, Chrome OS (patched glibc). This patch adds DT_RELR support to FreeBSD rtld-elf. MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D32524 --- libexec/rtld-elf/rtld.c | 36 ++++++++++++++++++++++++++++++++++++ libexec/rtld-elf/rtld.h | 2 ++ 2 files changed, 38 insertions(+) diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 6c304f98253a..d598bb044f8e 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -1255,6 +1255,18 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath, assert(dynp->d_un.d_val == sizeof(Elf_Rela)); break; + case DT_RELR: + obj->relr = (const Elf_Relr *)(obj->relocbase + dynp->d_un.d_ptr); + break; + + case DT_RELRSZ: + obj->relrsize = dynp->d_un.d_val; + break; + + case DT_RELRENT: + assert(dynp->d_un.d_val == sizeof(Elf_Relr)); + break; + case DT_PLTREL: plttype = dynp->d_un.d_val; assert(dynp->d_un.d_val == DT_REL || plttype == DT_RELA); @@ -3148,6 +3160,29 @@ reloc_textrel_prot(Obj_Entry *obj, bool before) return (0); } +/* Process RELR relative relocations. */ +static void +reloc_relr(Obj_Entry *obj) +{ + const Elf_Relr *relr, *relrlim; + Elf_Addr *where; + + relrlim = (const Elf_Relr *)((const char *)obj->relr + obj->relrsize); + for (relr = obj->relr; relr < relrlim; relr++) { + Elf_Relr entry = *relr; + + if ((entry & 1) == 0) { + where = (Elf_Addr *)(obj->relocbase + entry); + *where++ += (Elf_Addr)obj->relocbase; + } else { + for (long i = 0; (entry >>= 1) != 0; i++) + if ((entry & 1) != 0) + where[i] += (Elf_Addr)obj->relocbase; + where += CHAR_BIT * sizeof(Elf_Relr) - 1; + } + } +} + /* * Relocate single object. * Returns 0 on success, or -1 on failure. @@ -3174,6 +3209,7 @@ relocate_object(Obj_Entry *obj, bool bind_now, Obj_Entry *rtldobj, /* Process the non-PLT non-IFUNC relocations. */ if (reloc_non_plt(obj, rtldobj, flags, lockstate)) return (-1); + reloc_relr(obj); /* Re-protected the text segment. */ if (obj->textrel && reloc_textrel_prot(obj, false) != 0) diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index 060b83b2cdad..b216e80115bc 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -174,6 +174,8 @@ typedef struct Struct_Obj_Entry { unsigned long relsize; /* Size in bytes of relocation info */ const Elf_Rela *rela; /* Relocation entries with addend */ unsigned long relasize; /* Size in bytes of addend relocation info */ + const Elf_Relr *relr; /* RELR relocation entries */ + unsigned long relrsize; /* Size in bytes of RELR relocations */ const Elf_Rel *pltrel; /* PLT relocation entries */ unsigned long pltrelsize; /* Size in bytes of PLT relocation info */ const Elf_Rela *pltrela; /* PLT relocation entries with addend */