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 9932F385842E for ; Fri, 15 Oct 2021 13:59:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 9932F385842E 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 0D0E68380F; Fri, 15 Oct 2021 15:59:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=denx.de; s=phobos-20191101; t=1634306367; bh=yZAUWUgZpNietkc4uYIop81+7jA0vGPZhZx2weMhGZg=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=eqsLPhrUM3P/OJmgqV+H/qA7+ScPRGVKnMl3N1CrPk5iYnAtoxUfskt881C2JPl9w dT2J3BkkP79fzbppWrbgMIWvVPndY7HxuU38bYUWNjGM+NuOtOfGr5UraQUEYPSfmn kstRhWFuUPNxVwywDBU7qP2BfqMz5o9q+UxUPVsCk2pMlkWdX1ZiVXDzXkYjlAQrow 3b1vHgae2G+0zoEE2QXgH4gXKB4SJrMTG/bxZWL77dlbv7oeiKYEZ/HkIBr9kNbSAp AQBaJH/RVEEbs32hRvmHrUYsuxQBWuYSpbdAHxgj7MshPMa/P48E0j2CkH50TnnIMR LaDwl2o80YMgw== Date: Fri, 15 Oct 2021 15:59:19 +0200 From: Lukasz Majewski To: Szabolcs Nagy Cc: Adhemerval Zanella , Fangrui Song , Florian Weimer , Joseph Myers , Carlos O'Donell , Andreas Schwab , libc-alpha Subject: Re: [PATCH v2] dl: Use "adr" assembler command to get proper load address on ARM Message-ID: <20211015155919.20392561@ktm> In-Reply-To: <20211015120915.GD1982710@arm.com> References: <20210907131616.23472-1-lukma@denx.de> <20211015075417.29931-1-lukma@denx.de> <20211015120915.GD1982710@arm.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_/z__V5fww_78P1bx.I8pGr9n"; 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=-10.5 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: Fri, 15 Oct 2021 13:59:30 -0000 --Sig_/z__V5fww_78P1bx.I8pGr9n Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Hi Szabolcs, > The 10/15/2021 09:54, Lukasz Majewski wrote: > > This change is a partial revert of commit > > bca0f5cbc9257c13322b99e55235c4f21ba0bd82 > > "arm: Simplify elf_machine_{load_address,dynamic}" which imposed > > usage of __ehdr_start linker variable to get the address of loaded > > program. > >=20 > > The elf_machine_load_address() function is declared in the > > sysdeps/arm/dl-machine.h header. It is called from (very early) > > _dl_start() entry point for the program. It shall return the load > > address of the dynamic linker program. > >=20 > > With this revert the 'adr' assembler instruction is used instead of > > a place holder: > >=20 > > arm-poky-linux-gnueabi-objdump -t ld-linux-armhf.so.3 | grep ehdr > > 00000000 l .note.gnu.build-id 00000000 __ehdr_start > >=20 > > which is pre-set by binutils. > >=20 > > The problem starts when one runs 'prelink' on the rootfs created > > with for example OE/Yocto. > > Then the _ehdr_start stays as 0x0, but the ELF header's sections > > have different addresses - for example 0x41000000 instead of the > > originally set 0x0. > >=20 > > This is crucial when /sbin/init is executed. Value set in > > __ehdr_start symbol is not updated. This causes the program to > > crash very early when ld-linux-armhf.so.3's _dl_start is executed, > > as calculated offset for loader relocation is going to hit the > > kernel space (0xf7xxyyyy). > >=20 > > It looks like the correct way to obtain the _dl_start offset on ARM > > is to use assembler instruction 'adr' at execution time (so the > > prelink assigned offset is taken into consideration) instead of > > __ehdr_start. > >=20 > > With this patch we only modify the elf_machine_load_address() > > function, as it is called very early, before the > > ld-linux-armhf.so.3 is performing relocation (also its own one). =20 >=20 > i'd use an explanation like: >=20 > __ehdr_start is a linker created symbol that points to the elf header. > The elf header is at the beginning of the elf file and normally its > virtual address is 0 in a shared library. This means the runtime > address of __ehdr_start is the load address of the module. However if > prelinking is applied to ld.so then all virtual addresses are moved by > an offset so the runtime address of the elf header becomes the load > address + prelink offset. The kernel does not treat prelinked ld.so > specially so the load address is not 0, it still has to be computed, > but simply using __ehdr_start no longer gives a correct value for > that. >=20 > This issue affects all targets with prelinking support, but so far we > only got reports from OE/Yocto builds for arm that has prelinked > ld.so. >=20 Thanks for a very detailed description. > but i think a better fix is possible than revert: >=20 > ElfW(Addr) > elf_machine_load_address () > { > extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; > extern ElfW(Dyn) extern_DYNAMIC[] asm ("_DYNAMIC"); >=20 So the _DYNAMIC =3D GOT[0] (and it points into the .dynamic section) objdump -d -j .got ld-linux-armhf.so.3 Disassembly of section .got: 41036fbc <.got+0x41000000>: 41036fbc: 41036ef4 .word 0x41036ef4 So it indeed points into the [16] .dynamic DYNAMIC 41036ef4 > /* Uses pc-relative address computation. */ > ElfW(Addr) runtime_addr =3D (ElfW(Addr)) &_DYNAMIC; I guess that the &_DYNAMIC gives the address around which $pc runs=20 (e.g. 0xb6fc9504) - this is the actual address of run program. (A side question - is there any way to read the _DYNAMIC symbol value directly - via e.g. readelf or objdump?) >=20 > /* Loads an unrelocated GOT entry. */ > ElfW(Addr) linktime_addr =3D (ElfW(Addr)) &extern_DYNAMIC; >=20 This is the prelink'ed address -> 0x41036ef4 in our case? > return runtime_addr - linktime_addr; And the address to which we shall relocated would be: 0xb6fc9504 - 0x41036ef4 =3D 0x75f92610 - which is the address to which the ld.so (ld-linux-armhf.so.3) will re-relocate itself? > } >=20 > I expect this to work on most targets and very similar to the code > that was originally used on other targets: only a new GOT entry is > introduced instead of using GOT[0]. In fact we only rely on _DYNAMIC symbol -> which points into .dynamic section. > (that new got entry will have a > relative relocation which means there must be a dynamic section even > in a static PIE, so i expect _DYNAMIC to be defined. Ok. > this also means > that it's slightly more expensive than &__ehdr_start, so it is for > targets that want to support prelinked ld.so) >=20 > The original arm code used _dl_start symbol, likely because that's > within range for the adr instruction for more efficient pc-relative > computation. But that's a function symbol that requires fixups due > to thumb interworking issues and is not available in static PIE, so > using _DYNAMIC sounds better even on arm. +1. >=20 > >=20 > > HW: > > Hardware name: > > - ARM-Versatile Express (Run with QEMU) > > - Beagle Bone Black > >=20 > > Build Environment: OE/Yocto -> poky > > SHA1: 1e2e9a84d6dd81d7f6dd69c0d119d0149d10ade1 > >=20 > > Fixes: BZ #28293 > > --- > > sysdeps/arm/dl-machine.h | 28 +++++++++++++++++++++++++--- > > 1 file changed, 25 insertions(+), 3 deletions(-) > >=20 > > diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h > > index dfa05eee44..d6e5f1d5ec 100644 > > --- a/sysdeps/arm/dl-machine.h > > +++ b/sysdeps/arm/dl-machine.h > > @@ -39,11 +39,33 @@ elf_machine_matches_host (const Elf32_Ehdr > > *ehdr) } > > =20 > > /* 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; > > } > > =20 > > /* Return the link-time address of _DYNAMIC. */ > > --=20 > > 2.20.1 > > =20 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_/z__V5fww_78P1bx.I8pGr9n Content-Type: application/pgp-signature Content-Description: OpenPGP digital signature -----BEGIN PGP SIGNATURE----- iQEzBAEBCgAdFiEEgAyFJ+N6uu6+XupJAR8vZIA0zr0FAmFpiTcACgkQAR8vZIA0 zr384gf+O1Yx1PMhLvX/AYe242SWtfQggbZersg1rfCbmfl9A8MseKdWt99VD2qq QO+lmHsSXFMJlPUFBuscI9WLP2/Y1j/ymUfvay0gcJ/9RsWTmsyatLiUsaC9rkSU fVPqc67TMxOGZ2ABH1c/yTAX8tbCcQTZjChIDh1fyxnmyofhA3Nb/ckNC3CEm8Cz 6CwdfI5h8+LfeuePEQZvDhWKz/Xf5S/rSttybvhQZxsvdN/n2Opzm9j60VFETCg8 9Q3i9oZf21xnIXoYjnXQmi0kZWZSOWvYDk2J7x6f8YhcNznGyVy8QBNSifBOmWEy KdTD97jV+AdhGCHIv8n8a/xVVRKmrA== =sr/I -----END PGP SIGNATURE----- --Sig_/z__V5fww_78P1bx.I8pGr9n--