26 #ifdef HAVE_SYS_PROCFS_H 27 #include <sys/procfs.h> 48 (
int) pid, (
int) tracerpid);
52 "- the process has already terminated"),
61 static char *reason_string;
66 xfree (reason_string);
72 if (warnings[0] !=
'\0')
82 #if defined __i386__ || defined __x86_64__ 85 EXTERN_C void linux_ptrace_test_ret_to_nx_instr (
void);
101 #if defined __i386__ || defined __x86_64__ 102 pid_t child, got_pid;
105 int status, kill_status;
109 = (
gdb_byte *) mmap (NULL, 2, PROT_READ | PROT_WRITE,
110 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
111 if (return_address == MAP_FAILED)
113 warning (
_(
"linux_ptrace_test_ret_to_nx: Cannot mmap: %s"),
119 *return_address = 0xcc;
125 warning (
_(
"linux_ptrace_test_ret_to_nx: Cannot fork: %s"),
133 warning (
_(
"linux_ptrace_test_ret_to_nx: Cannot PTRACE_TRACEME: %s"),
138 asm volatile (
"pushl %0;" 139 ".globl linux_ptrace_test_ret_to_nx_instr;" 140 "linux_ptrace_test_ret_to_nx_instr:" 142 : :
"r" (return_address) :
"%esp",
"memory");
143 #elif defined __x86_64__ 144 asm volatile (
"pushq %0;" 145 ".globl linux_ptrace_test_ret_to_nx_instr;" 146 "linux_ptrace_test_ret_to_nx_instr:" 148 : :
"r" ((uint64_t) (uintptr_t) return_address)
151 # error "!__i386__ && !__x86_64__" 160 got_pid = waitpid (child, &status, 0);
161 if (got_pid != child)
163 warning (
_(
"linux_ptrace_test_ret_to_nx: waitpid returned %ld: %s"),
171 warning (
_(
"linux_ptrace_test_ret_to_nx: WTERMSIG %d is not SIGKILL!"),
174 warning (
_(
"Cannot call inferior functions, Linux kernel PaX " 175 "protection forbids return to non-executable pages!"));
181 warning (
_(
"linux_ptrace_test_ret_to_nx: status %d is not WIFSTOPPED!"),
189 warning (
_(
"linux_ptrace_test_ret_to_nx: " 190 "WSTOPSIG %d is neither SIGTRAP nor SIGSEGV!"),
198 warning (
_(
"linux_ptrace_test_ret_to_nx: Cannot PTRACE_GETREGS: %s"),
202 pc = (
gdb_byte *) (uintptr_t) regs[EIP];
203 #elif defined __x86_64__ 204 pc = (
gdb_byte *) (uintptr_t) regs[RIP];
206 # error "!__i386__ && !__x86_64__" 209 kill (child, SIGKILL);
214 got_pid = waitpid (child, &kill_status, 0);
215 if (got_pid != child)
217 warning (
_(
"linux_ptrace_test_ret_to_nx: " 218 "PTRACE_KILL waitpid returned %ld: %s"),
224 warning (
_(
"linux_ptrace_test_ret_to_nx: " 225 "PTRACE_KILL status %d is not WIFSIGNALED!"),
231 if (
WSTOPSIG (status) == SIGTRAP && pc == return_address + 1)
238 if (
WSTOPSIG (status) == SIGSEGV && pc == return_address)
244 if ((
void (*) (
void)) pc != &linux_ptrace_test_ret_to_nx_instr)
245 warning (
_(
"linux_ptrace_test_ret_to_nx: PC %p is neither near return " 246 "address %p nor is the return instruction %p!"),
247 pc, return_address, &linux_ptrace_test_ret_to_nx_instr);
249 warning (
_(
"Cannot call inferior functions on this system - " 250 "Linux kernel with broken i386 NX (non-executable pages) " 251 "support detected!"));
271 #if defined(__UCLIBC__) && defined(HAS_NOMMU) 272 #define STACK_SIZE 4096 274 if (child_stack == NULL)
279 child_pid = __clone2 (
function, child_stack, STACK_SIZE,
280 CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2);
282 child_pid = clone (
function, child_stack + STACK_SIZE,
283 CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2);
320 kill (getpid (), SIGSTOP);
339 int child_pid, ret, status;
353 else if (ret != child_pid)
354 error (
_(
"linux_check_ptrace_features: waitpid: unexpected result %d."),
357 error (
_(
"linux_check_ptrace_features: waitpid: unexpected status %d."),
372 warning (
_(
"linux_check_ptrace_features: failed to kill child"));
432 warning (
_(
"linux_test_for_tracefork: failed to resume child"));
445 if (ret == 0 && second_pid != 0)
461 warning (
_(
"linux_test_for_tracefork: " 462 "failed to kill second child"));
467 warning (
_(
"linux_test_for_tracefork: unexpected result from waitpid " 468 "(%d, status 0x%x)"), ret, status);
588 static int warned = 0;
602 return (wstat >> 16);
static int linux_fork_to_function(gdb_byte *child_stack, int(*function)(void *))
#define PTRACE_GETEVENTMSG
static void xfree(T *ptr)
void warning(const char *fmt,...)
int linux_wstatus_maybe_breakpoint(int wstat)
static void linux_test_for_tracefork(int child_pid)
int linux_is_extended_waitstatus(int wstat)
void linux_check_ptrace_features(void)
static int ptrace_supports_feature(int ptrace_options)
static int supported_ptrace_options
int linux_proc_pid_is_zombie_nowarn(pid_t pid)
void linux_ptrace_attach_fail_reason(pid_t pid, struct buffer *buffer)
#define PTRACE_EVENT_FORK
void linux_ptrace_init_warnings(void)
char * linux_ptrace_attach_fail_reason_string(ptid_t ptid, int err)
int linux_supports_traceclone(void)
void buffer_xml_printf(struct buffer *buffer, const char *format,...)
#define PTRACE_O_TRACEVFORKDONE
#define PTRACE_O_TRACEVFORK
int linux_ptrace_get_extended_event(int wstat)
static int linux_grandchild_function(void *child_stack)
#define gdb_assert_not_reached(message)
int linux_supports_traceexec(void)
#define PTRACE_O_TRACEFORK
char * xstrprintf(const char *format,...)
#define PTRACE_O_TRACEEXEC
long ptid_get_lwp(const ptid_t &ptid)
int linux_supports_tracefork(void)
static void linux_ptrace_test_ret_to_nx(void)
#define PTRACE_O_TRACECLONE
static int linux_child_function(void *child_stack)
#define buffer_grow_str0(BUFFER, STRING)
static void linux_test_for_tracesysgood(int child_pid)
void buffer_init(struct buffer *buffer)
void linux_enable_event_reporting(pid_t pid, int options)
pid_t linux_proc_get_tracerpid_nowarn(pid_t lwpid)
char * safe_strerror(int)
void linux_disable_event_reporting(pid_t pid)
#define PTRACE_SETOPTIONS
int linux_supports_tracevforkdone(void)
static void linux_test_for_exitkill(int child_pid)
void perror_with_name(const char *string)
int my_waitpid(int pid, int *status, int flags)
#define PTRACE_O_TRACESYSGOOD
char * buffer_finish(struct buffer *buffer)
#define PTRACE_O_EXITKILL
void error(const char *fmt,...)
int linux_supports_tracesysgood(void)