diff options
author | Pedro Alves <palves@redhat.com> | 2016-07-26 19:35:40 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2016-07-26 19:38:13 +0100 |
commit | 40c31709c6a51926fcb409611caa52b2da6515c0 (patch) | |
tree | 4b936b212e016bb58936f49178ce9d8a1136c19d /gdb/nat | |
parent | 9cf12d57c58a82cfe3e6fee26d1ea55dfe49f9c4 (diff) | |
download | gdb-40c31709c6a51926fcb409611caa52b2da6515c0.zip gdb-40c31709c6a51926fcb409611caa52b2da6515c0.tar.gz gdb-40c31709c6a51926fcb409611caa52b2da6515c0.tar.bz2 |
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.
Diffstat (limited to 'gdb/nat')
-rw-r--r-- | gdb/nat/linux-ptrace.c | 22 |
1 files changed, 10 insertions, 12 deletions
diff --git a/gdb/nat/linux-ptrace.c b/gdb/nat/linux-ptrace.c index 0eaf9a3..980ed53 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) ®s) < 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, |