]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: fptr.c (_dl_read_access_allowed): New.
authorJohn David Anglin <danglin@gcc.gnu.org>
Sun, 11 Mar 2018 14:38:50 +0000 (14:38 +0000)
committerJohn David Anglin <danglin@gcc.gnu.org>
Sun, 11 Mar 2018 14:38:50 +0000 (14:38 +0000)
Backport from mainline
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.

From-SVN: r258431

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

index bd37acf21c2e352454b1510857b3bde2617f2049..f7910111d8182f1721222fc55b75c7b982fc4ca3 100644 (file)
@@ -1,3 +1,11 @@
+2018-03-11  John David Anglin  <danglin@gcc.gnu.org>
+
+       Backport from mainline
+       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-20  Max Filippov  <jcmvbkbc@gmail.com>
 
        Backport from mainline
index 3febc9062db5cc1fc830a2f4f097b131d85a41a5..761b98fa36463e278e69aad6fd0a89a03fad225e 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.  */