From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) by sourceware.org (Postfix) with ESMTPS id 8DF37385843B for ; Tue, 7 Sep 2021 17:32:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8DF37385843B Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=denx.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=denx.de Received: from ktm (85-222-111-42.dynamic.chello.pl [85.222.111.42]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: lukma@denx.de) by phobos.denx.de (Postfix) with ESMTPSA id 59E0A8323A; Tue, 7 Sep 2021 19:32:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=denx.de; s=phobos-20191101; t=1631035955; bh=Ti/Z1WJLqUefKuD+xePHCqEuqlonS6hHYlW2kyqTf0U=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=zbpYyvVpn1tbzSA+gw++c4qzh44g9j0CPB97OTglCTmuJ5YPxNx7nPNPEa5SJL4L9 8uflBqimpCcmZui9Ecp1vD6oVtncWmV1+npnzHCAjJBqyPGzG7akuqvh5nxqjV6ORy xt4uK+2XyEfNKYZSwYaoh3tEKDz5eiEvZZ7KXqmNhban73KoVtl5RCfjsJz9xaaqBf vVJMl8l+tnxQ/E0Qd/MSBKmPuac8RhsGAszpFlFMnCmRWcNRAxd3IfkAQ7WOx0OACT nhiLJxZkS75Hk27Pq8L/AvDD45XK134lr8/VK+Hgm+gjuIF66DID5J5sbzEYj2oPYX lcfjU1lXRi4wQ== Date: Tue, 7 Sep 2021 19:32:27 +0200 From: Lukasz Majewski To: Fangrui Song Cc: Adhemerval Zanella , Florian Weimer , Joseph Myers , Carlos O'Donell , libc-alpha Subject: Re: [PATCH] dl: Use "adr" assembler command to get proper load address Message-ID: <20210907193227.6047f9cc@ktm> In-Reply-To: <20210907164906.yt6nonvfyhvbrx6p@google.com> References: <20210907131616.23472-1-lukma@denx.de> <20210907164906.yt6nonvfyhvbrx6p@google.com> Organization: denx.de X-Mailer: Claws Mail 3.18.0 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; boundary="Sig_/ecWPrdK4AS=fqKPLpsUDNme"; protocol="application/pgp-signature" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_BARRACUDACENTRAL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 Sep 2021 17:32:39 -0000 --Sig_/ecWPrdK4AS=fqKPLpsUDNme Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Hi Fangrui, > On 2021-09-07, Lukasz Majewski wrote: > >This change is a partial revert of commit > >bca0f5cbc9257c13322b99e55235c4f21ba0bd82 which imposed usage of > >__ehdr_start linker variable to get the address of loaded program. > > > >The elf_machine_load_address() function is declared in the > >sysdeps/arm/dl-machine.h header. It is called from _dl_start() entry > >point for the program. It shall return the load address of the > >dynamic linker program. =20 >=20 > Yes. >=20 > >With this revert the 'adr' assembler instruction is used instead of a > >place holder: > > > >arm-poky-linux-gnueabi-objdump -t ld-linux-armhf.so.3 | grep ehdr > >00000000 l .note.gnu.build-id 00000000 __ehdr_start > > > >which shall be pre-set by binutils. =20 >=20 > I don't understand this. The sh_addr field of the binutils defined > __ehdr_start is 0. >=20 > Declararing __ehdr_start as hidden and accessing it with PC-relative > addressing generates computes the runtime address of __ehdr_start, > which equals the load base. Maybe I don't get it - but shouldn't this be filled in by binutils (linker ?) when the program is assembled before run? Or is the __ehdr_start used just as a relative offset to get the proper position of ld-linux-armh.so when called? >=20 > What's wrong with it? The objdump -t line doesn't tell why this change > is good. I'm also puzzled why this causes the QEMU versalite board to break. (/sbin/init dies with SIGSEGFAULT =3D 0xb [*]) It looks like the &__ehdr_start is not equal in the result to 'adr' assembler code in QEMU. I also thought that the issue is caused by fs/binfmt_elf.c changes in the Linux kernel (as mine is 5.1), so I've tested it with 5.10 and 5.14. No change. The QEMU is pretty recent - it is 6.0.0 version for ARM. > Can you compare objdump -dr output and show the incorrect > code sequences with C assessing __ehdr_start? Ok. I will explicitly compare _dl_start function with and without this patch. >=20 > >This is crucial in the QEMU ARM environment for which (when > >/sbin/init is executed) values set in __ehdr_start symbol are wrong. > >This causes the program to crash very early - when the > >/lib/ld-linux-armhf.so.3 is executed as a prerequisite to /sbin/init > >execution. =20 >=20 > >The kernel's fs/binfmt_elf.c is though responsible for setting > >up execution environment, not binutils. =20 >=20 > Whether the symbol entry __ehdr_start exists doesn't matter. > The hidden definition does not have any associated relocation. I'm also wondering if similar issue is visible with "normal" - i.e. not QEMU ARM run init. Maybe the "rough" environment in which /sbin/init is run is the culprit? >=20 > >It looks like the only robust way to obtain the _dl_start offset is > >to use assembler instruction - not rely on values provided by > >binutils. > > > >HW: > >Hardware name: ARM-Versatile Express (Run with QEMU) > >Tested (affected) kernels v5.1.12, v5.10.62 and v5.14.1 > > > >When the /sbin/init is setup for run from Linux kernel's very small > >environment with LD_DEBUG=3Dall the __ehdr_start is not shown at all. > > > >Fixes: BZ #28293 > >--- > > sysdeps/arm/dl-machine.h | 28 +++++++++++++++++++++++++--- > > 1 file changed, 25 insertions(+), 3 deletions(-) > > > >diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h > >index eb13cb8b57..58ebef6ecd 100644 > >--- a/sysdeps/arm/dl-machine.h > >+++ b/sysdeps/arm/dl-machine.h > >@@ -38,11 +38,33 @@ elf_machine_matches_host (const Elf32_Ehdr *ehdr) > > } > > > > /* Return the run-time load address of the shared object. */ > >-static inline ElfW(Addr) __attribute__ ((unused)) > >+static inline Elf32_Addr __attribute__ ((unused)) > > elf_machine_load_address (void) > > { > >- extern const ElfW(Ehdr) __ehdr_start attribute_hidden; > >- return (ElfW(Addr)) &__ehdr_start; > >+ Elf32_Addr pcrel_addr; > >+#ifdef SHARED > >+ extern Elf32_Addr __dl_start (void *) asm ("_dl_start"); > >+ Elf32_Addr got_addr =3D (Elf32_Addr) &__dl_start; > >+ asm ("adr %0, _dl_start" : "=3Dr" (pcrel_addr)); > >+#else > >+ extern Elf32_Addr __dl_relocate_static_pie (void *) > >+ asm ("_dl_relocate_static_pie") attribute_hidden; > >+ Elf32_Addr got_addr =3D (Elf32_Addr) &__dl_relocate_static_pie; > >+ asm ("adr %0, _dl_relocate_static_pie" : "=3Dr" (pcrel_addr)); > >+#endif > >+#ifdef __thumb__ > >+ /* Clear the low bit of the function address. > >+ > >+ NOTE: got_addr is from GOT table whose lsb is always set by > >linker if it's > >+ Thumb function address. PCREL_ADDR comes from PC-relative > >calculation > >+ which will finish during assembling. GAS assembler before the > >fix for > >+ PR gas/21458 was not setting the lsb but does after that. > >Always do the > >+ strip for both, so the code works with various combinations of > >glibc and > >+ Binutils. */ > >+ got_addr &=3D ~(Elf32_Addr) 1; > >+ pcrel_addr &=3D ~(Elf32_Addr) 1; > >+#endif > >+ return pcrel_addr - got_addr; > > } > > > > /* Return the link-time address of _DYNAMIC. */ > >--=20 > >2.20.1 > > =20 Note: [*] - the QEMU debugging is pretty difficult with /sbin/init. Qemu has good support for kernel debugging (-s -S switches). Then for user space program one could use the "on-board" gdb or gdbserver. However, /sbin/init needs to be debugged from linux and scheduler context switches needs to be taken into account to review how the code is executed. And such debugging scenario has issue with QEMU-arm. Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de --Sig_/ecWPrdK4AS=fqKPLpsUDNme Content-Type: application/pgp-signature Content-Description: OpenPGP digital signature -----BEGIN PGP SIGNATURE----- iQEzBAEBCgAdFiEEgAyFJ+N6uu6+XupJAR8vZIA0zr0FAmE3oisACgkQAR8vZIA0 zr0yXwgAzWRrNOCsEowBYdOQWZu7htLW3qYjh+BZC2Dm/+v0TQUBA2beZiwJ6sc0 dzKo43D1b3IMT6yTIMMduHjjjiAtwz9tk2K3MG+0oxy/5oZUwFoljBF2nZql9KVV EsHjJC9wBZIt4cqUHIbST1GsnhTu0IYys3e56ffqNi9/BUzj0sSw9JtVrALVl8fU JU4z7Pymo66miJUb9tlyDpyuQ8D4ON2HqUR34Wdlu9EUX9AJyA9fLYcppnJdY5k/ NcYRIPdP4nXwRcFlIQkUUbwLlsAc+vTF+n3TnoGiosySKdBx+fNh96AzN7gMcism G9r5pDHJZgpBYL796PuvHxYOffBxDg== =D4IM -----END PGP SIGNATURE----- --Sig_/ecWPrdK4AS=fqKPLpsUDNme--