about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-04-10 12:57:48 -0700
committerDavid S. Miller <davem@davemloft.net>2012-04-10 17:47:59 -0700
commitd7dd44133f53e8bcc81e18c11694bee985cd86d0 (patch)
tree4d1991e4bce3a4a0359e78516e60dead17648cbb
parentb46068fcf2e915d740dab7993253c0ec8f84fe5d (diff)
downloadglibc-d7dd44133f53e8bcc81e18c11694bee985cd86d0.tar.gz
glibc-d7dd44133f53e8bcc81e18c11694bee985cd86d0.tar.xz
glibc-d7dd44133f53e8bcc81e18c11694bee985cd86d0.zip
Fix ld.so regression.
	[BZ #13967]
	* elf/dynamic-link.h (_ELF_DYNAMIC_DO_RELOC): Handle the case
	where the is a gap between DT_REL(A) and DT_JMPREL.
-rw-r--r--ChangeLog6
-rw-r--r--NEWS2
-rw-r--r--elf/dynamic-link.h14
3 files changed, 15 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index d6c9964beb..0bd15aac5c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2012-04-10  David S. Miller  <davem@davemloft.net>
+
+	[BZ #13967]
+	* elf/dynamic-link.h (_ELF_DYNAMIC_DO_RELOC): Handle the case
+	where the is a gap between DT_REL(A) and DT_JMPREL.
+
 2012-04-10  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* sysdeps/x86_64/bits/byteswap.h: Include <features.h>.
diff --git a/NEWS b/NEWS
index 357f3b4e69..fb5fd4ce7a 100644
--- a/NEWS
+++ b/NEWS
@@ -21,7 +21,7 @@ Version 2.16
   13824, 13840, 13841, 13844, 13846, 13851, 13852, 13854, 13871, 13872,
   13873, 13879, 13883, 13892, 13895, 13908, 13910, 13911, 13912, 13913,
   13915, 13916, 13917, 13918, 13919, 13920, 13921, 13926, 13928, 13938,
-  13963
+  13963, 13967
 
 * ISO C11 support:
 
diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
index ef01c61f3e..44f53b3c70 100644
--- a/elf/dynamic-link.h
+++ b/elf/dynamic-link.h
@@ -252,9 +252,10 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
 /* On some machines, notably SPARC, DT_REL* includes DT_JMPREL in its
    range.  Note that according to the ELF spec, this is completely legal!
 
-   We are guarenteed that we have one of two situations.  Either DT_JMPREL
+   We are guarenteed that we have one of three situations.  Either DT_JMPREL
    comes immediately after DT_REL*, or there is overlap and DT_JMPREL
-   consumes precisely the very end of the DT_REL*.  */
+   consumes precisely the very end of the DT_REL*, or DT_JMPREL and DT_REL*
+   are completely separate and there is a gap between them.  */
 
 # define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \
   do {									      \
@@ -275,19 +276,20 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
 	&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
       {									      \
 	ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]);		      \
+	ElfW(Addr) size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val;	      \
 									      \
-	if (__builtin_expect (ranges[0].size, 1))			      \
-	  ranges[0].size = (start - ranges[0].start);			      \
+	if (ranges[0].start + ranges[0].size == (start + size))		      \
+	  ranges[0].size -= size;					      \
 	if (! ELF_DURING_STARTUP && ((do_lazy) || ranges[0].size == 0))	      \
 	  {								      \
 	    ranges[1].start = start;					      \
-	    ranges[1].size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val;	      \
+	    ranges[1].size = size;					      \
 	    ranges[1].lazy = (do_lazy);					      \
 	  }								      \
 	else								      \
 	  {								      \
 	    /* Combine processing the sections.  */			      \
-	    ranges[0].size += (map)->l_info[DT_PLTRELSZ]->d_un.d_val;	      \
+	    ranges[0].size += size;					      \
 	  }								      \
       }									      \
 									      \