aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorJiong Wang <jiong.wang@arm.com>2017-07-13 15:48:41 +0100
committerSzabolcs Nagy <szabolcs.nagy@arm.com>2017-07-13 15:48:41 +0100
commit5ba6405338c280a3d84dcab1a11dcd1df9b5bee8 (patch)
tree91058ccecdbeea948e8d2763924bd0f9c355274c /sysdeps
parent1dd577fd3382868d03ff4756dd5f7d3b8099b76a (diff)
downloadglibc-5ba6405338c280a3d84dcab1a11dcd1df9b5bee8.zip
glibc-5ba6405338c280a3d84dcab1a11dcd1df9b5bee8.tar.gz
glibc-5ba6405338c280a3d84dcab1a11dcd1df9b5bee8.tar.bz2
[ARM] Fix ld.so crash when built using Binutils 2.29
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: https://sourceware.org/bugzilla/show_bug.cgi?id=21725. 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. * sysdeps/arm/dl-machine.h (elf_machine_load_address): Also strip bit 0 of pcrel_address under Thumb mode.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/arm/dl-machine.h12
1 files changed, 10 insertions, 2 deletions
diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h
index 7053ead..0a126ce 100644
--- a/sysdeps/arm/dl-machine.h
+++ b/sysdeps/arm/dl-machine.h
@@ -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;
Elf32_Addr pcrel_addr;
+ asm ("adr %0, _dl_start" : "=r" (pcrel_addr));
#ifdef __thumb__
- /* Clear the low bit of the funciton address. */
+ /* 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 &= ~(Elf32_Addr) 1;
+ pcrel_addr &= ~(Elf32_Addr) 1;
#endif
- asm ("adr %0, _dl_start" : "=r" (pcrel_addr));
return pcrel_addr - got_addr;
}