19#include "gdbsupport/common-defs.h"
23#include "gdbsupport/buffer.h"
24#ifdef HAVE_SYS_PROCFS_H
25#include <sys/procfs.h>
43 string_appendf (result,
44 _(
"process %d is already traced by process %d"),
45 (
int) pid, (
int) tracerpid);
48 string_appendf (result,
49 _(
"process %d is a zombie - the process has already "
61 long lwpid = ptid.lwp ();
65 return string_printf (
"%s (%d), %s", safe_strerror (err), err,
68 return string_printf (
"%s (%d)", safe_strerror (err), err);
71#if defined __i386__ || defined __x86_64__
74EXTERN_C
void linux_ptrace_test_ret_to_nx_instr (
void);
90 if (kill (child, SIGKILL) != 0)
92 warning (_(
"%s: failed to kill child pid %ld %s"),
93 who, (
long) child, safe_strerror (errno));
102 "kill waitpid returned %ld: %s"),
103 who, (
long) got_pid, safe_strerror (errno));
106 if (!WIFSIGNALED (kill_status))
109 "kill status %d is not WIFSIGNALED!"),
123#if defined __i386__ || defined __x86_64__
124 pid_t child, got_pid;
125 gdb_byte *return_address, *pc;
131 = (gdb_byte *) mmap (NULL, 2, PROT_READ | PROT_WRITE,
132 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
133 if (return_address == MAP_FAILED)
135 warning (_(
"linux_ptrace_test_ret_to_nx: Cannot mmap: %s"),
136 safe_strerror (errno));
141 *return_address = 0xcc;
147 warning (_(
"linux_ptrace_test_ret_to_nx: Cannot fork: %s"),
148 safe_strerror (errno));
155 warning (_(
"linux_ptrace_test_ret_to_nx: Cannot PTRACE_TRACEME: %s"),
156 safe_strerror (errno));
160 asm volatile (
"pushl %0;"
161 ".globl linux_ptrace_test_ret_to_nx_instr;"
162 "linux_ptrace_test_ret_to_nx_instr:"
164 : :
"r" (return_address) :
"memory");
165#elif defined __x86_64__
166 asm volatile (
"pushq %0;"
167 ".globl linux_ptrace_test_ret_to_nx_instr;"
168 "linux_ptrace_test_ret_to_nx_instr:"
170 : :
"r" ((uint64_t) (uintptr_t) return_address)
173# error "!__i386__ && !__x86_64__"
175 gdb_assert_not_reached (
"asm block did not terminate");
182 got_pid = waitpid (child, &status, 0);
183 if (got_pid != child)
185 warning (_(
"linux_ptrace_test_ret_to_nx: waitpid returned %ld: %s"),
186 (
long) got_pid, safe_strerror (errno));
190 if (WIFSIGNALED (status))
192 if (WTERMSIG (status) != SIGKILL)
193 warning (_(
"linux_ptrace_test_ret_to_nx: WTERMSIG %d is not SIGKILL!"),
194 (
int) WTERMSIG (status));
196 warning (_(
"Cannot call inferior functions, Linux kernel PaX "
197 "protection forbids return to non-executable pages!"));
201 if (!WIFSTOPPED (status))
203 warning (_(
"linux_ptrace_test_ret_to_nx: status %d is not WIFSTOPPED!"),
205 kill_child (child,
"linux_ptrace_test_ret_to_nx");
210 if (WSTOPSIG (status) != SIGTRAP && WSTOPSIG (status) != SIGSEGV)
212 warning (_(
"linux_ptrace_test_ret_to_nx: "
213 "WSTOPSIG %d is neither SIGTRAP nor SIGSEGV!"),
214 (
int) WSTOPSIG (status));
215 kill_child (child,
"linux_ptrace_test_ret_to_nx");
222 warning (_(
"linux_ptrace_test_ret_to_nx: Cannot PTRACE_GETREGS: %s"),
223 safe_strerror (errno));
226 pc = (gdb_byte *) (uintptr_t) regs[EIP];
227#elif defined __x86_64__
228 pc = (gdb_byte *) (uintptr_t) regs[RIP];
230# error "!__i386__ && !__x86_64__"
233 kill_child (child,
"linux_ptrace_test_ret_to_nx");
236 if (WSTOPSIG (status) == SIGTRAP && pc == return_address + 1)
243 if (WSTOPSIG (status) == SIGSEGV && pc == return_address)
249 if ((
void (*) (
void)) pc != &linux_ptrace_test_ret_to_nx_instr)
250 warning (_(
"linux_ptrace_test_ret_to_nx: PC %p is neither near return "
251 "address %p nor is the return instruction %p!"),
252 pc, return_address, &linux_ptrace_test_ret_to_nx_instr);
254 warning (_(
"Cannot call inferior functions on this system - "
255 "Linux kernel with broken i386 NX (non-executable pages) "
256 "support detected!"));
274 gdb_assert (function != NULL);
276#if defined(__UCLIBC__) && defined(HAS_NOMMU)
277#define STACK_SIZE 4096
279 if (child_stack == NULL)
280 child_stack = (gdb_byte *) xmalloc (STACK_SIZE * 4);
284 child_pid = __clone2 (function, child_stack, STACK_SIZE,
285 CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2);
287 child_pid = clone (function, child_stack + STACK_SIZE,
288 CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2);
298 perror_with_name ((
"fork"));
311 kill (getpid (), SIGSTOP);
325 int child_pid, ret, status;
345 perror_with_name ((
"waitpid"));
346 else if (ret != child_pid)
347 error (_(
"linux_check_ptrace_features: waitpid: unexpected result %d."),
349 if (! WIFSTOPPED (status))
350 error (_(
"linux_check_ptrace_features: waitpid: unexpected status %d."),
356 kill_child (child_pid,
"linux_check_ptrace_features");
412 static int warned = 0;
426 return (wstat >> 16);
442 return (WIFSTOPPED (wstat)
443 && (WSTOPSIG (wstat) == SIGTRAP
446 || WSTOPSIG (wstat) == SIGILL
447 || WSTOPSIG (wstat) == SIGSEGV));
#define ptrace(request, pid, addr, data)
int linux_proc_pid_is_zombie_nowarn(pid_t pid)
pid_t linux_proc_get_tracerpid_nowarn(pid_t lwpid)
static void linux_ptrace_test_ret_to_nx(void)
static int linux_fork_to_function(gdb_byte *child_stack, int(*function)(void *))
static void linux_test_for_exitkill(int child_pid)
int linux_is_extended_waitstatus(int wstat)
static void kill_child(pid_t child, const char *who)
void linux_enable_event_reporting(pid_t pid, int options)
static int supported_ptrace_options
static int linux_child_function(void *child_stack)
void linux_check_ptrace_features(void)
int linux_ptrace_get_extended_event(int wstat)
int linux_wstatus_maybe_breakpoint(int wstat)
void linux_ptrace_init_warnings(void)
void linux_disable_event_reporting(pid_t pid)
std::string linux_ptrace_attach_fail_reason_string(ptid_t ptid, int err)
std::string linux_ptrace_attach_fail_reason(pid_t pid)
#define PTRACE_O_TRACEEXEC
#define PTRACE_O_TRACEFORK
#define PTRACE_SETOPTIONS
#define PTRACE_O_TRACECLONE
#define PTRACE_O_EXITKILL
#define PTRACE_O_TRACEVFORK
#define PTRACE_O_TRACESYSGOOD
#define PTRACE_O_TRACEVFORKDONE
int my_waitpid(int pid, int *status, int flags)