]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
[ARM] Fix ld.so crash when built using Binutils 2.29
authorJiong Wang <jiong.wang@arm.com>
Thu, 13 Jul 2017 14:48:41 +0000 (15:48 +0100)
committerSzabolcs Nagy <szabolcs.nagy@arm.com>
Thu, 13 Jul 2017 14:48:41 +0000 (15:48 +0100)
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.

ChangeLog
sysdeps/arm/dl-machine.h

index e3e979996554f88ba89cc5d4d590d2b21cdad7db..e2605cb9c39682a939668661ae1db898bd821902 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2017-07-12  Jiong Wang  <jiong.wang@arm.com>
+
+       * sysdeps/arm/dl-machine.h (elf_machine_load_address):  Also strip bit 0
+       of pcrel_address under Thumb mode.
+
 2017-07-12  Akhilesh Kumar <akhilesh.k@samsung.com>
 
        [BZ #21207]
index 7053ead16ed0e7dac182660f7d88fa21f2b4799a..0a126ce1178ccad7fdb6266c0eb90f1d7f691a71 100644 (file)
@@ -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;
 }