From: Jiong Wang Date: Thu, 13 Jul 2017 14:48:41 +0000 (+0100) Subject: [ARM] Fix ld.so crash when built using Binutils 2.29 X-Git-Tag: glibc-2.26~99 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5ba6405338c280a3d84dcab1a11dcd1df9b5bee8;p=thirdparty%2Fglibc.git [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. --- diff --git a/ChangeLog b/ChangeLog index e3e97999655..e2605cb9c39 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2017-07-12 Jiong Wang + + * sysdeps/arm/dl-machine.h (elf_machine_load_address): Also strip bit 0 + of pcrel_address under Thumb mode. + 2017-07-12 Akhilesh Kumar [BZ #21207] diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h index 7053ead16ed..0a126ce1178 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; }