diff mbox

[committed] Tighten runtime initialization check in __canonicalize_funcptr_for_compare on hppa-linux

Message ID B462AB35-645E-4AC6-A21D-A2D32814142D@bell.net
State New
Headers show

Commit Message

John David Anglin Dec. 10, 2015, 1:46 a.m. UTC
On 2015-12-01, at 7:15 PM, John David Anglin wrote:

> The attached change fixes a startup issue of emacs24 on Debian hppa-linux.  The emacs24 build does some tricky
> stuff to preinitialize values, so that standard static initialization check is skipped.  However, the global offset table has
> moved in the final executable and emacs24 crashes.

Actually, this didn't work any better than the original code.  The only check that would work is checking that the
dynamic linker routine _dl_fixup is still in the same location.  This essentially requires the full plabel computation.
So, this version removes the attempt at just initializing the call to _dl_fixup once.

Tested on hppa-unknown-linux-gnu with no observed testsuite regressions.  Committed to trunk, gcc-5 and 4.9.

Dave
--
John David Anglin	dave.anglin@bell.net
2015-12-09  John David Anglin  <danglin@gcc.gnu.org>

	* config/pa/fptr.c (__canonicalize_funcptr_for_compare): Remove code
	to initialize call to __dl_fixup once.
diff mbox

Patch

Index: config/pa/fptr.c
===================================================================
--- config/pa/fptr.c	(revision 231455)
+++ config/pa/fptr.c	(working copy)
@@ -64,10 +64,10 @@ 
 unsigned int
 __canonicalize_funcptr_for_compare (fptr_t fptr)
 {
-  static unsigned int fixup_plabel[2];
-  static fixup_t fixup;
-  static unsigned int *init_fixup;
-  unsigned int *plabel, *got;
+  static unsigned int fixup_plabel[2] __attribute__((used));
+  fixup_t fixup;
+  unsigned int *got, *iptr, *plabel;
+  int i;
 
   /* -1 and page 0 are special.  -1 is used in crtend to mark the end of
      a list of function pointers.  Also return immediately if the plabel
@@ -88,47 +88,33 @@ 
   if (got !=  &_GLOBAL_OFFSET_TABLE_)
     return plabel[0];
 
-  /* Initialize our plabel for calling fixup if we haven't done so already.
-     We can't rely on static initialization so we check that any previous
-     initialization was done for the current got address.  This code needs
-     to be thread safe but we don't have to be too careful as the result
-     is invariant.  */
-  if (init_fixup != got)
+  /* Find the first "bl" branch in the offset search list.  This is a
+     call to _dl_fixup or a magic branch to fixup at the beginning of the
+     trampoline template.  The fixup function does the actual runtime
+     resolution of function descriptors.  We only look for "bl" branches
+     with a 17-bit pc-relative displacement.  */
+  for (i = 0; i < NOFFSETS; i++)
     {
-      int i;
-      unsigned int *iptr;
+      iptr = (unsigned int *) (got[-2] + fixup_branch_offset[i]);
+      if ((*iptr & 0xfc00e000) == 0xe8000000)
+	break;
+    }
 
-      /* Find the first "bl" branch in the offset search list.  This is a
-	 call to fixup or a magic branch to fixup at the beginning of the
-	 trampoline template.  The fixup function does the actual runtime
-	 resolution of function descriptors.  We only look for "bl" branches
-	 with a 17-bit pc-relative displacement.  */
-      for (i = 0; i < NOFFSETS; i++)
-	{
-	  iptr = (unsigned int *) (got[-2] + fixup_branch_offset[i]);
-	  if ((*iptr & 0xfc00e000) == 0xe8000000)
-	    break;
-	}
+  /* This should not happen... */
+  if (i == NOFFSETS)
+    return ~0;
 
-      /* This should not happen... */
-      if (i == NOFFSETS)
-	return ~0;
+  /* Extract the 17-bit displacement from the instruction.  */
+  iptr += SIGN_EXTEND (GET_FIELD (*iptr, 19, 28) |
+		       GET_FIELD (*iptr, 29, 29) << 10 |
+		       GET_FIELD (*iptr, 11, 15) << 11 |
+		       GET_FIELD (*iptr, 31, 31) << 16, 17);
 
-      /* Extract the 17-bit displacement from the instruction.  */
-      iptr += SIGN_EXTEND (GET_FIELD (*iptr, 19, 28) |
-			   GET_FIELD (*iptr, 29, 29) << 10 |
-			   GET_FIELD (*iptr, 11, 15) << 11 |
-			   GET_FIELD (*iptr, 31, 31) << 16, 17);
+  /* Build a plabel for an indirect call to _dl_fixup.  */
+  fixup_plabel[0] = (unsigned int) iptr + 8;	/* address of fixup */
+  fixup_plabel[1] = got[-1];			/* ltp for fixup */
+  fixup = (fixup_t) ((int) fixup_plabel | 3);
 
-      /* Build a plabel for an indirect call to fixup.  */
-      fixup_plabel[0] = (unsigned int) iptr + 8;  /* address of fixup */
-      fixup_plabel[1] = got[-1];		  /* ltp for fixup */
-      fixup = (fixup_t) ((int) fixup_plabel | 3);
-
-      /* Save address of the global offset table.  */
-      init_fixup = got;
-    }
-
   /* Call fixup to resolve the function address.  got[1] contains the
      link_map pointer and plabel[1] the relocation offset.  */
   fixup ((struct link_map *) got[1], plabel[1]);