aboutsummaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
authordanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>2018-03-07 00:17:32 +0000
committerdanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>2018-03-07 00:17:32 +0000
commit94fc4b64ad2aa13b9aa9dc8c43fefcc9fc133eab (patch)
treeaf52292cd811e7eb3d43b1bf5802824a723adb96 /libgcc
parent7158995e77c2b5882fab2ec290fe5d8508b8da50 (diff)
* 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/trunk@258310 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/ChangeLog5
-rw-r--r--libgcc/config/pa/fptr.c20
2 files changed, 25 insertions, 0 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index e93967799ea..c8c87c6211b 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -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
diff --git a/libgcc/config/pa/fptr.c b/libgcc/config/pa/fptr.c
index 02f7e4b0e4b..944ed4495d9 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. */