summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>2018-03-11 14:37:40 +0000
committerdanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>2018-03-11 14:37:40 +0000
commit091246fb2c06cff963f3aa9820650e85b1f38d67 (patch)
treef36c19c272ccff188d24001e1ea448bd5910e1d9
parentf104c5aed5091db873d748534a6490bfb18f0acf (diff)
downloadgcc-091246fb2c06cff963f3aa9820650e85b1f38d67.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-7-branch@258430 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--libgcc/ChangeLog8
-rw-r--r--libgcc/config/pa/fptr.c20
2 files changed, 28 insertions, 0 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 9658cb68725..7ad7e9f1c54 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -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
diff --git a/libgcc/config/pa/fptr.c b/libgcc/config/pa/fptr.c
index 645fa5d833a..e145026df3e 100644
--- a/libgcc/config/pa/fptr.c
+++ b/libgcc/config/pa/fptr.c
@@ -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. */