This is the mail archive of the
mailing list for the glibc project.
[ARM] Fix ld.so crash when built using Binutils 2.29
- From: Jiong Wang <jiong dot wang at foss dot arm dot com>
- To: libc-alpha at sourceware dot org
- Date: Wed, 12 Jul 2017 17:13:47 +0100
- Subject: [ARM] Fix ld.so crash when built using Binutils 2.29
- Authentication-results: sourceware.org; auth=none
There is bug report that ld.so in GLIBC 2.24 built by Binutils 2.29 will crash
on arm-linux-gnueabihf. This is confirmed, and the details is at:
And I could also reproduce this crash using GLIBC master.
As analyzed in the PR, the old code was with the assumption that assembler
won't set bit0 of thumb function address if it comes from PC-relative
instructions and the calculation can be finished during assembling. This
assumption however does not hold after PR gas/21458.
I think ARM backend in GLIBC should be fix to be more portable so it could
work with various combinations of GLIBC and Binutils.
OK for master and backport to all release branches?
2017-07-12 Jiong Wang <firstname.lastname@example.org>
* sysdeps/arm/dl-machine.h (elf_machine_load_address): Also strip bit 0
of pcrel_address under Thumb mode.
diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h
index 7053ead16ed0e7dac182660f7d88fa21f2b4799a..5b67e3d004818308d9bf93effb13d23a762e160f 100644
@@ -56,11 +56,19 @@ elf_machine_load_address (void)
extern Elf32_Addr internal_function __dl_start (void *) asm ("_dl_start");
Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
+ asm ("adr %0, _dl_start" : "=r" (pcrel_addr));
- /* Clear the low bit of the funciton address. */
+ /* Clear the low bit of the funciton 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 &= ~(Elf32_Addr) 1;
+ pcrel_addr &= ~(Elf32_Addr) 1;
- asm ("adr %0, _dl_start" : "=r" (pcrel_addr));
return pcrel_addr - got_addr;