44 (
int) pid, (
int) tracerpid);
48 "- the process has already terminated"),
57 static char *reason_string;
62 xfree (reason_string);
68 if (warnings[0] !=
'\0')
78 #if defined __i386__ || defined __x86_64__
81 EXTERN_C void linux_ptrace_test_ret_to_nx_instr (
void);
97 #if defined __i386__ || defined __x86_64__
103 return_address = mmap (NULL, 2, PROT_READ | PROT_WRITE,
104 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
107 warning (
_(
"linux_ptrace_test_ret_to_nx: Cannot mmap: %s"),
113 *return_address = 0xcc;
119 warning (
_(
"linux_ptrace_test_ret_to_nx: Cannot fork: %s"),
127 warning (
_(
"linux_ptrace_test_ret_to_nx: Cannot PTRACE_TRACEME: %s"),
132 asm volatile (
"pushl %0;"
133 ".globl linux_ptrace_test_ret_to_nx_instr;"
134 "linux_ptrace_test_ret_to_nx_instr:"
136 : :
"r" (return_address) :
"%esp",
"memory");
137 #elif defined __x86_64__
138 asm volatile (
"pushq %0;"
139 ".globl linux_ptrace_test_ret_to_nx_instr;"
140 "linux_ptrace_test_ret_to_nx_instr:"
142 : :
"r" ((uint64_t) (uintptr_t) return_address)
145 # error "!__i386__ && !__x86_64__"
154 got_pid = waitpid (child, &status, 0);
155 if (got_pid != child)
157 warning (
_(
"linux_ptrace_test_ret_to_nx: waitpid returned %ld: %s"),
165 warning (
_(
"linux_ptrace_test_ret_to_nx: WTERMSIG %d is not SIGKILL!"),
168 warning (
_(
"Cannot call inferior functions, Linux kernel PaX "
169 "protection forbids return to non-executable pages!"));
175 warning (
_(
"linux_ptrace_test_ret_to_nx: status %d is not WIFSTOPPED!"),
183 warning (
_(
"linux_ptrace_test_ret_to_nx: "
184 "WSTOPSIG %d is neither SIGTRAP nor SIGSEGV!"),
193 #elif defined __x86_64__
197 # error "!__i386__ && !__x86_64__"
201 warning (
_(
"linux_ptrace_test_ret_to_nx: Cannot PTRACE_PEEKUSER: %s"),
205 pc = (
void *) (uintptr_t) l;
207 kill (child, SIGKILL);
212 got_pid = waitpid (child, &kill_status, 0);
213 if (got_pid != child)
215 warning (
_(
"linux_ptrace_test_ret_to_nx: "
216 "PTRACE_KILL waitpid returned %ld: %s"),
222 warning (
_(
"linux_ptrace_test_ret_to_nx: "
223 "PTRACE_KILL status %d is not WIFSIGNALED!"),
229 if (
WSTOPSIG (status) == SIGTRAP && pc == return_address + 1)
236 if (
WSTOPSIG (status) == SIGSEGV && pc == return_address)
242 if ((
void (*) (
void)) pc != &linux_ptrace_test_ret_to_nx_instr)
243 warning (
_(
"linux_ptrace_test_ret_to_nx: PC %p is neither near return "
244 "address %p nor is the return instruction %p!"),
245 pc, return_address, &linux_ptrace_test_ret_to_nx_instr);
247 warning (
_(
"Cannot call inferior functions on this system - "
248 "Linux kernel with broken i386 NX (non-executable pages) "
249 "support detected!"));
269 #if defined(__UCLIBC__) && defined(HAS_NOMMU)
270 #define STACK_SIZE 4096
272 if (child_stack == NULL)
273 child_stack =
xmalloc (STACK_SIZE * 4);
277 child_pid = __clone2 (
function, child_stack, STACK_SIZE,
278 CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2);
280 child_pid = clone (
function, child_stack + STACK_SIZE,
281 CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2);
318 kill (getpid (), SIGSTOP);
337 int child_pid, ret,
status;
340 supported_ptrace_options = 0;
351 else if (ret != child_pid)
352 error (
_(
"linux_check_ptrace_features: waitpid: unexpected result %d."),
355 error (
_(
"linux_check_ptrace_features: waitpid: unexpected status %d."),
370 warning (
_(
"linux_check_ptrace_features: failed to kill child"));
430 warning (
_(
"linux_test_for_tracefork: failed to resume child"));
443 if (ret == 0 && second_pid != 0)
450 supported_ptrace_options |= (PTRACE_O_TRACEFORK
459 warning (
_(
"linux_test_for_tracefork: "
460 "failed to kill second child"));
465 warning (
_(
"linux_test_for_tracefork: unexpected result from waitpid "
466 "(%d, status 0x%x)"), ret, status);
493 if (supported_ptrace_options == -1)
523 if (supported_ptrace_options == -1)
526 return ((supported_ptrace_options & ptrace_options) == ptrace_options);
575 static int warned = 0;
589 return (wstat >> 16);
#define PTRACE_GETEVENTMSG
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)
static void linux_child_function(gdb_byte *child_stack)
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,...)
mach_port_t mach_port_t name mach_port_t mach_port_t name error_t err
#define PTRACE_O_TRACEVFORKDONE
#define PTRACE_O_TRACEVFORK
mach_port_t mach_port_t name mach_port_t mach_port_t name error_t int status
int linux_ptrace_get_extended_event(int wstat)
#define gdb_assert_not_reached(message)
static void linux_grandchild_function(gdb_byte *child_stack)
#define PTRACE_O_TRACEFORK
char * xstrprintf(const char *format,...)
#define PTRACE_O_TRACEEXEC
int linux_supports_tracefork(void)
static void linux_ptrace_test_ret_to_nx(void)
#define PTRACE_O_TRACECLONE
#define buffer_grow_str0(BUFFER, STRING)
static void linux_test_for_tracesysgood(int child_pid)
void void void void void void void void void perror_with_name(const char *string) ATTRIBUTE_NORETURN
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)
int my_waitpid(int pid, int *status, int flags)
#define PTRACE_O_TRACESYSGOOD
long ptid_get_lwp(ptid_t ptid)
static int linux_fork_to_function(gdb_byte *child_stack, void(*function)(gdb_byte *))
char * buffer_finish(struct buffer *buffer)
#define PTRACE_O_EXITKILL
void error(const char *fmt,...)
int linux_supports_tracesysgood(void)
mach_port_t mach_port_t name mach_port_t mach_port_t name error_t int int rusage_t pid_t pid