fptr.c (_dl_read_access_allowed): New.
authorJohn David Anglin <danglin@gcc.gnu.org>
Wed, 7 Mar 2018 00:17:32 +0000 (00:17 +0000)
committerJohn David Anglin <danglin@gcc.gnu.org>
Wed, 7 Mar 2018 00:17:32 +0000 (00:17 +0000)
* config/pa/fptr.c (_dl_read_access_allowed): New.
(__canonicalize_funcptr_for_compare): Use it.

From-SVN: r258310

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

index e93967799eade8ab0d7a698275452f2365bfdf29..c8c87c6211bc6ee63a212cd12630516401bbf447 100644 (file)
@@ -1,3 +1,8 @@
+2018-03-06  John David Anglin  <danglin@gcc.gnu.org>
+
+       * config/pa/fptr.c (_dl_read_access_allowed): New.
+       (__canonicalize_funcptr_for_compare): Use it.
+       
 2018-02-28  Jakub Jelinek  <jakub@redhat.com>
 
        PR debug/83917
index 02f7e4b0e4b30bf39596cd5bd28ee5c810d55030..944ed4495d9c3ec40abac93e59ddcb9e60a7936f 100644 (file)
@@ -52,6 +52,16 @@ typedef int (*fptr_t) (void);
 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)
+{
+  int result;
+
+  asm ("proberi (%1),3,%0" : "=r" (result) : "r" (addr) : );
+
+  return result;
+}
+
 /* __canonicalize_funcptr_for_compare must be hidden so that it is not
    placed in the dynamic symbol table.  Like millicode functions, it
    must be linked into all binaries in order access the got table of 
@@ -82,6 +92,16 @@ __canonicalize_funcptr_for_compare (fptr_t fptr)
      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))
+    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))
+    return (unsigned int) fptr;
+
   got = (unsigned int *) (plabel[0] + GOT_FROM_PLT_STUB);
 
   /* Return the address of the function if the plabel has been resolved.  */