summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2016-07-26 19:35:40 +0100
committerPedro Alves <palves@redhat.com>2016-07-26 19:38:13 +0100
commit40c31709c6a51926fcb409611caa52b2da6515c0 (patch)
tree4b936b212e016bb58936f49178ce9d8a1136c19d
parent9cf12d57c58a82cfe3e6fee26d1ea55dfe49f9c4 (diff)
downloadbinutils-gdb-40c31709c6a51926fcb409611caa52b2da6515c0.tar.gz
Fix PR gdb/20413 - x32: linux_ptrace_test_ret_to_nx: Cannot PTRACE_PEEKUSER
An x32 gdb always issues this warning: (gdb) start Temporary breakpoint 1 at 0x4043e9: file foo.c, line 25. Starting program: a.out warning: linux_ptrace_test_ret_to_nx: Cannot PTRACE_PEEKUSER: Input/output error Temporary breakpoint 1, main (argc=1, argv=0xffffd544) at foo.c:25 25 { (gdb) As described in Linux commit 55283e253771 (x32: Add ptrace for x32): [...] PTRACE_PEEKUSR and PTRACE_POKEUSR are only allowed to access segment and debug registers. [...] The fix is to use PTRACE_GETREGS instead. gdb/ChangeLog: 2016-07-26 Pedro Alves <palves@redhat.com> * nat/linux-ptrace.c: Include "gregset.h". (linux_ptrace_test_ret_to_nx): Use PTRACE_GETREGS instead of PTRACE_PEEKUSER.
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/nat/linux-ptrace.c22
2 files changed, 16 insertions, 12 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3a5e8707a3c..2f3710d9e49 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
2016-07-26 Pedro Alves <palves@redhat.com>
+ * nat/linux-ptrace.c: Include "gregset.h".
+ (linux_ptrace_test_ret_to_nx): Use PTRACE_GETREGS instead of
+ PTRACE_PEEKUSER.
+
+2016-07-26 Pedro Alves <palves@redhat.com>
+
* amd64-linux-nat.c (amd64_linux_siginfo_fixup): Rename 'native'
parameter to 'ptrace'.
* nat/amd64-linux-siginfo.c (GDB_SI_SIZE): New define.
diff --git a/gdb/nat/linux-ptrace.c b/gdb/nat/linux-ptrace.c
index 0eaf9a30ff4..980ed53c73f 100644
--- a/gdb/nat/linux-ptrace.c
+++ b/gdb/nat/linux-ptrace.c
@@ -23,6 +23,7 @@
#include "buffer.h"
#include "gdb_wait.h"
#include "gdb_ptrace.h"
+#include "gregset.h"
/* Stores the ptrace options supported by the running kernel.
A value of -1 means we did not check for features yet. A value
@@ -100,6 +101,7 @@ linux_ptrace_test_ret_to_nx (void)
gdb_byte *return_address, *pc;
long l;
int status, kill_status;
+ elf_gregset_t regs;
return_address
= (gdb_byte *) mmap (NULL, 2, PROT_READ | PROT_WRITE,
@@ -188,23 +190,19 @@ linux_ptrace_test_ret_to_nx (void)
return;
}
- errno = 0;
+ if (ptrace (PTRACE_GETREGS, child, (PTRACE_TYPE_ARG3) 0,
+ (PTRACE_TYPE_ARG4) &regs) < 0)
+ {
+ warning (_("linux_ptrace_test_ret_to_nx: Cannot PTRACE_GETREGS: %s"),
+ safe_strerror (errno));
+ }
#if defined __i386__
- l = ptrace (PTRACE_PEEKUSER, child, (PTRACE_TYPE_ARG3) (uintptr_t) (EIP * 4),
- (PTRACE_TYPE_ARG4) NULL);
+ pc = (gdb_byte *) (uintptr_t) regs[EIP];
#elif defined __x86_64__
- l = ptrace (PTRACE_PEEKUSER, child, (PTRACE_TYPE_ARG3) (uintptr_t) (RIP * 8),
- (PTRACE_TYPE_ARG4) NULL);
+ pc = (gdb_byte *) (uintptr_t) regs[RIP];
#else
# error "!__i386__ && !__x86_64__"
#endif
- if (errno != 0)
- {
- warning (_("linux_ptrace_test_ret_to_nx: Cannot PTRACE_PEEKUSER: %s"),
- safe_strerror (errno));
- return;
- }
- pc = (gdb_byte *) (uintptr_t) l;
kill (child, SIGKILL);
ptrace (PTRACE_KILL, child, (PTRACE_TYPE_ARG3) NULL,