fptr.c (_dl_read_access_allowed): Change argument to unsigned int.
authorJohn David Anglin <danglin@gcc.gnu.org>
Tue, 15 Oct 2019 22:17:14 +0000 (22:17 +0000)
committerJohn David Anglin <danglin@gcc.gnu.org>
Tue, 15 Oct 2019 22:17:14 +0000 (22:17 +0000)
* config/pa/fptr.c (_dl_read_access_allowed): Change argument to
unsigned int.  Adjust callers.
(__canonicalize_funcptr_for_compare): Change plabel type to volatile
unsigned int *.  Load relocation offset before function pointer.
Add barrier to ensure ordering.

From-SVN: r277015

libgcc/ChangeLog
libgcc/config/pa/fptr.c

index 4d2a32ccb9731a4719ea7d33a4c151b1bfdf19fc..ed0e900637719012dba26dcb10945f92578c447f 100644 (file)
@@ -1,3 +1,11 @@
+2019-10-15  John David Anglin  <danglin@gcc.gnu.org>
+
+       * config/pa/fptr.c (_dl_read_access_allowed): Change argument to
+       unsigned int.  Adjust callers.
+       (__canonicalize_funcptr_for_compare): Change plabel type to volatile
+       unsigned int *.  Load relocation offset before function pointer.
+       Add barrier to ensure ordering.
+
 2019-10-12  John David Anglin  <danglin@gcc.gnu.org>
 
        * config/pa/lib2funcs.S (__gcc_plt_call): Load branch target to %r21.
index 6cca747ece27a813e18a23a04a17482176c49965..9d2bb73ec98bbbb54d3883081e52e06d97878d3a 100644 (file)
@@ -53,7 +53,7 @@ typedef int (*fixup_t) (struct link_map *, unsigned int);
 extern unsigned int _GLOBAL_OFFSET_TABLE_;
 
 static inline int
-_dl_read_access_allowed (unsigned int *addr)
+_dl_read_access_allowed (unsigned int addr)
 {
   int result;
 
@@ -79,7 +79,8 @@ __canonicalize_funcptr_for_compare (fptr_t fptr)
 {
   static unsigned int fixup_plabel[2] __attribute__((used));
   fixup_t fixup;
-  unsigned int *got, *iptr, *plabel;
+  volatile unsigned int *plabel;
+  unsigned int *got, *iptr, reloc_offset;
   int i;
 
   /* -1 and page 0 are special.  -1 is used in crtend to mark the end of
@@ -94,17 +95,20 @@ __canonicalize_funcptr_for_compare (fptr_t fptr)
      to the entry of the PLT stub just before the global offset table.
      The second word in the plabel contains the relocation offset for the
      function.  */
-  plabel = (unsigned int *) ((unsigned int) fptr & ~3);
-  if (!_dl_read_access_allowed (plabel))
+  plabel = (volatile unsigned int *) ((unsigned int) fptr & ~3);
+  if (!_dl_read_access_allowed ((unsigned int)plabel))
     return (unsigned int) fptr;
 
   /* Load first word of candidate descriptor.  It should be a pointer
      with word alignment and point to memory that can be read.  */
   got = (unsigned int *) plabel[0];
   if (((unsigned int) got & 3) != 0
-      || !_dl_read_access_allowed (got))
+      || !_dl_read_access_allowed ((unsigned int)got))
     return (unsigned int) fptr;
 
+  /* We need to load the relocation offset before the function address.  */
+  reloc_offset = plabel[1];
+  __sync_synchronize();
   got = (unsigned int *) (plabel[0] + GOT_FROM_PLT_STUB);
 
   /* Return the address of the function if the plabel has been resolved.  */
@@ -140,7 +144,7 @@ __canonicalize_funcptr_for_compare (fptr_t fptr)
 
   /* 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]);
+  fixup ((struct link_map *) got[1], reloc_offset);
 
   return plabel[0];
 }