2018-01-01 05:43:02 +01:00
|
|
|
/* Copyright (C) 2011-2018 Free Software Foundation, Inc.
|
2011-04-26 17:36:04 +02:00
|
|
|
|
|
|
|
This file is part of GDB.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
#ifndef COMMON_LINUX_PTRACE_H
|
|
|
|
#define COMMON_LINUX_PTRACE_H
|
|
|
|
|
2012-03-13 16:02:25 +01:00
|
|
|
struct buffer;
|
|
|
|
|
2015-07-24 15:57:20 +02:00
|
|
|
#include "nat/gdb_ptrace.h"
|
2018-01-19 18:22:49 +01:00
|
|
|
#include "gdb_wait.h"
|
2011-04-26 17:36:04 +02:00
|
|
|
|
2013-08-23 01:46:30 +02:00
|
|
|
#ifdef __UCLIBC__
|
|
|
|
#if !(defined(__UCLIBC_HAS_MMU__) || defined(__ARCH_HAS_MMU__))
|
|
|
|
/* PTRACE_TEXT_ADDR and friends. */
|
|
|
|
#include <asm/ptrace.h>
|
|
|
|
#define HAS_NOMMU
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !defined(PTRACE_TYPE_ARG3)
|
|
|
|
#define PTRACE_TYPE_ARG3 void *
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !defined(PTRACE_TYPE_ARG4)
|
|
|
|
#define PTRACE_TYPE_ARG4 void *
|
|
|
|
#endif
|
|
|
|
|
2011-04-26 17:36:04 +02:00
|
|
|
#ifndef PTRACE_GETSIGINFO
|
|
|
|
# define PTRACE_GETSIGINFO 0x4202
|
|
|
|
# define PTRACE_SETSIGINFO 0x4203
|
|
|
|
#endif /* PTRACE_GETSIGINF */
|
|
|
|
|
2015-06-01 13:13:02 +02:00
|
|
|
#ifndef PTRACE_GETREGSET
|
|
|
|
#define PTRACE_GETREGSET 0x4204
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef PTRACE_SETREGSET
|
|
|
|
#define PTRACE_SETREGSET 0x4205
|
|
|
|
#endif
|
|
|
|
|
2011-04-26 17:36:04 +02:00
|
|
|
/* If the system headers did not provide the constants, hard-code the normal
|
|
|
|
values. */
|
|
|
|
#ifndef PTRACE_EVENT_FORK
|
|
|
|
|
|
|
|
#define PTRACE_SETOPTIONS 0x4200
|
|
|
|
#define PTRACE_GETEVENTMSG 0x4201
|
|
|
|
|
|
|
|
/* options set using PTRACE_SETOPTIONS */
|
|
|
|
#define PTRACE_O_TRACESYSGOOD 0x00000001
|
|
|
|
#define PTRACE_O_TRACEFORK 0x00000002
|
|
|
|
#define PTRACE_O_TRACEVFORK 0x00000004
|
|
|
|
#define PTRACE_O_TRACECLONE 0x00000008
|
|
|
|
#define PTRACE_O_TRACEEXEC 0x00000010
|
|
|
|
#define PTRACE_O_TRACEVFORKDONE 0x00000020
|
|
|
|
#define PTRACE_O_TRACEEXIT 0x00000040
|
|
|
|
|
|
|
|
/* Wait extended result codes for the above trace options. */
|
|
|
|
#define PTRACE_EVENT_FORK 1
|
|
|
|
#define PTRACE_EVENT_VFORK 2
|
|
|
|
#define PTRACE_EVENT_CLONE 3
|
|
|
|
#define PTRACE_EVENT_EXEC 4
|
|
|
|
#define PTRACE_EVENT_VFORK_DONE 5
|
|
|
|
#define PTRACE_EVENT_EXIT 6
|
|
|
|
|
|
|
|
#endif /* PTRACE_EVENT_FORK */
|
|
|
|
|
2014-11-11 07:07:21 +01:00
|
|
|
#ifndef PTRACE_O_EXITKILL
|
|
|
|
/* Only defined in Linux Kernel 3.8 or later. */
|
|
|
|
#define PTRACE_O_EXITKILL 0x00100000
|
|
|
|
#endif
|
|
|
|
|
2011-09-30 02:01:59 +02:00
|
|
|
#if (defined __bfin__ || defined __frv__ || defined __sh__) \
|
|
|
|
&& !defined PTRACE_GETFDPIC
|
|
|
|
#define PTRACE_GETFDPIC 31
|
|
|
|
#define PTRACE_GETFDPIC_EXEC 0
|
|
|
|
#define PTRACE_GETFDPIC_INTERP 1
|
|
|
|
#endif
|
|
|
|
|
2011-04-26 17:36:04 +02:00
|
|
|
/* We can't always assume that this flag is available, but all systems
|
|
|
|
with the ptrace event handlers also have __WALL, so it's safe to use
|
|
|
|
in some contexts. */
|
|
|
|
#ifndef __WALL
|
|
|
|
#define __WALL 0x40000000 /* Wait for any child. */
|
|
|
|
#endif
|
|
|
|
|
2015-03-04 21:41:16 +01:00
|
|
|
/* True if whether a breakpoint/watchpoint triggered can be determined
|
|
|
|
from the si_code of SIGTRAP's siginfo_t (TRAP_BRKPT/TRAP_HWBKPT).
|
|
|
|
That is, if the kernel can tell us whether the thread executed a
|
|
|
|
software breakpoint, we trust it. The kernel will be determining
|
|
|
|
that from the hardware (e.g., from which exception was raised in
|
|
|
|
the CPU). Relying on whether a breakpoint is planted in memory at
|
|
|
|
the time the SIGTRAP is processed to determine whether the thread
|
|
|
|
stopped for a software breakpoint can be too late. E.g., the
|
|
|
|
breakpoint could have been removed since. Or the thread could have
|
|
|
|
stepped an instruction the size of a breakpoint instruction, and
|
|
|
|
before the stop is processed a breakpoint is inserted at its
|
|
|
|
address. Getting these wrong is disastrous on decr_pc_after_break
|
|
|
|
architectures. The moribund location mechanism helps with that
|
|
|
|
somewhat but it is an heuristic, and can well fail. Getting that
|
|
|
|
information out of the kernel and ultimately out of the CPU is the
|
|
|
|
way to go. That said, some architecture may get the si_code wrong,
|
|
|
|
and as such we're leaving fallback code in place. We'll remove
|
|
|
|
this after a while if no problem is reported. */
|
|
|
|
#define USE_SIGTRAP_SIGINFO 1
|
|
|
|
|
|
|
|
/* The x86 kernel gets some of the si_code values backwards, like
|
|
|
|
this:
|
|
|
|
|
2016-02-24 23:52:06 +01:00
|
|
|
| what | si_code |
|
|
|
|
|------------------------------------------+-------------|
|
|
|
|
| software breakpoints (int3) | SI_KERNEL |
|
|
|
|
| single-steps | TRAP_TRACE |
|
|
|
|
| single-stepping a syscall | TRAP_BRKPT |
|
|
|
|
| user sent SIGTRAP | 0 |
|
|
|
|
| exec SIGTRAP (when no PTRACE_EVENT_EXEC) | 0 |
|
|
|
|
| hardware breakpoints/watchpoints | TRAP_HWBKPT |
|
2015-03-04 21:41:16 +01:00
|
|
|
|
|
|
|
That is, it reports SI_KERNEL for software breakpoints (and only
|
|
|
|
for those), and TRAP_BRKPT for single-stepping a syscall... If the
|
|
|
|
kernel is ever fixed, we'll just have to detect it like we detect
|
|
|
|
optional ptrace features: by forking and debugging ourselves,
|
|
|
|
running to a breakpoint and checking what comes out of
|
|
|
|
siginfo->si_code.
|
|
|
|
|
2015-08-27 19:20:29 +02:00
|
|
|
The ppc kernel does use TRAP_BRKPT for software breakpoints
|
|
|
|
in PowerPC code, but it uses SI_KERNEL for software breakpoints
|
|
|
|
in SPU code on a Cell/B.E. However, SI_KERNEL is never seen
|
|
|
|
on a SIGTRAP for any other reason.
|
|
|
|
|
2016-04-16 00:52:00 +02:00
|
|
|
The MIPS kernel up until 4.5 used SI_KERNEL for all kernel
|
|
|
|
generated traps. Since:
|
2016-02-24 23:52:06 +01:00
|
|
|
|
|
|
|
- MIPS doesn't do hardware single-step.
|
|
|
|
- We don't need to care about exec SIGTRAPs --- we assume
|
|
|
|
PTRACE_EVENT_EXEC is available.
|
|
|
|
- The MIPS kernel doesn't support hardware breakpoints.
|
|
|
|
|
|
|
|
on MIPS, all we need to care about is distinguishing between
|
|
|
|
software breakpoints and hardware watchpoints, which can be done by
|
|
|
|
peeking the debug registers.
|
|
|
|
|
2016-04-16 00:52:00 +02:00
|
|
|
Beginning with Linux 4.6, the MIPS port reports proper TRAP_BRKPT and
|
|
|
|
TRAP_HWBKPT codes, so we also match them.
|
|
|
|
|
2016-02-24 23:52:06 +01:00
|
|
|
The generic Linux target code should use GDB_ARCH_IS_TRAP_* instead
|
|
|
|
of TRAP_* to abstract out these peculiarities. */
|
2015-03-04 21:41:16 +01:00
|
|
|
#if defined __i386__ || defined __x86_64__
|
2015-08-27 19:20:29 +02:00
|
|
|
# define GDB_ARCH_IS_TRAP_BRKPT(X) ((X) == SI_KERNEL)
|
2016-02-24 23:52:06 +01:00
|
|
|
# define GDB_ARCH_IS_TRAP_HWBKPT(X) ((X) == TRAP_HWBKPT)
|
2015-08-27 19:20:29 +02:00
|
|
|
#elif defined __powerpc__
|
|
|
|
# define GDB_ARCH_IS_TRAP_BRKPT(X) ((X) == SI_KERNEL || (X) == TRAP_BRKPT)
|
2016-02-24 23:52:06 +01:00
|
|
|
# define GDB_ARCH_IS_TRAP_HWBKPT(X) ((X) == TRAP_HWBKPT)
|
|
|
|
#elif defined __mips__
|
2016-04-16 00:52:00 +02:00
|
|
|
# define GDB_ARCH_IS_TRAP_BRKPT(X) ((X) == SI_KERNEL || (X) == TRAP_BRKPT)
|
|
|
|
# define GDB_ARCH_IS_TRAP_HWBKPT(X) ((X) == SI_KERNEL || (X) == TRAP_HWBKPT)
|
2015-03-04 21:41:16 +01:00
|
|
|
#else
|
2015-08-27 19:20:29 +02:00
|
|
|
# define GDB_ARCH_IS_TRAP_BRKPT(X) ((X) == TRAP_BRKPT)
|
2016-02-24 23:52:06 +01:00
|
|
|
# define GDB_ARCH_IS_TRAP_HWBKPT(X) ((X) == TRAP_HWBKPT)
|
2015-03-04 21:41:16 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef TRAP_HWBKPT
|
|
|
|
# define TRAP_HWBKPT 4
|
|
|
|
#endif
|
|
|
|
|
2018-01-17 18:33:57 +01:00
|
|
|
extern std::string linux_ptrace_attach_fail_reason (pid_t pid);
|
Linux: on attach, attach to lwps listed under /proc/$pid/task/
... instead of relying on libthread_db.
I wrote a test that attaches to a program that constantly spawns
short-lived threads, which exposed several issues. This is one of
them.
On Linux, we need to attach to all threads of a process (thread group)
individually. We currently rely on libthread_db to list the threads,
but that is problematic, because libthread_db relies on reading data
structures out of the inferior (which may well be corrupted). If
threads are being created or exiting just while we try to attach, we
may trip on inconsistencies in the inferior's thread list. To work
around that, when we see a seemingly corrupt list, we currently retry
a few times:
static void
thread_db_find_new_threads_2 (ptid_t ptid, int until_no_new)
{
...
if (until_no_new)
{
/* Require 4 successive iterations which do not find any new threads.
The 4 is a heuristic: there is an inherent race here, and I have
seen that 2 iterations in a row are not always sufficient to
"capture" all threads. */
...
That heuristic may well fail, and when it does, we end up with threads
in the program that aren't under GDB's control. That's obviously bad
and results in quite mistifying failures, like e.g., the process dying
for seeminly no reason when a thread that wasn't attached trips on a
breakpoint.
There's really no reason to rely on libthread_db for this nowadays
when we have /proc mounted. In that case, which is the usual case, we
can list the LWPs from /proc/PID/task/. In fact, GDBserver is already
doing this. The patch factors out that code that knows to walk the
task/ directory out of GDBserver, and makes GDB use it too.
Like GDBserver, the patch makes GDB attach to LWPs and _not_ wait for
them to stop immediately. Instead, we just tag the LWP as having an
expected stop. Because we can only set the ptrace options when the
thread stops, we need a new flag in the lwp structure to keep track of
whether we've already set the ptrace options, just like in GDBserver.
Note that nothing issues any ptrace command to the threads between the
PTRACE_ATTACH and the stop, so this is safe (unlike one scenario
described in gdbserver's linux-low.c).
When we attach to a program that has threads exiting while we attach,
it's easy to race with a thread just exiting as we try to attach to
it, like:
#1 - get current list of threads
#2 - attach to each listed thread
#3 - ooops, attach failed, thread is already gone
As this is pretty normal, we shouldn't be issuing a scary warning in
step #3.
When #3 happens, PTRACE_ATTACH usually fails with ESRCH, but sometimes
we'll see EPERM as well. That happens when the kernel still has the
thread in its task list, but the thread is marked as dead.
Unfortunately, EPERM is ambiguous and we'll get it also on other
scenarios where the thread isn't dead, and in those cases, it's useful
to get a warning. To distiguish the cases, when we get an EPERM
failure, we open /proc/PID/status, and check the thread's state -- if
the /proc file no longer exists, or the state is "Z (Zombie)" or "X
(Dead)", we ignore the EPERM error silently; otherwise, we'll warn.
Unfortunately, there seems to be a kernel race here. Sometimes I get
EPERM, and then the /proc state still indicates "R (Running)"... If
we wait a bit and retry, we do end up seeing X or Z state, or get an
ESRCH. I thought of making GDB retry the attach a few times, but even
with a 500ms wait and 4 retries, I still see the warning sometimes. I
haven't been able to identify the kernel path that causes this yet,
but in any case, it looks like a kernel bug to me. As this just
results failure to suppress a warning that we've been printing since
about forever anyway, I'm just making the test cope with it, and issue
an XFAIL.
gdb/gdbserver/
2015-01-09 Pedro Alves <palves@redhat.com>
* linux-low.c (linux_attach_fail_reason_string): Move to
nat/linux-ptrace.c, and rename.
(linux_attach_lwp): Update comment.
(attach_proc_task_lwp_callback): New function.
(linux_attach): Adjust to rename and use
linux_proc_attach_tgid_threads.
(linux_attach_fail_reason_string): Delete declaration.
gdb/
2015-01-09 Pedro Alves <palves@redhat.com>
* linux-nat.c (attach_proc_task_lwp_callback): New function.
(linux_nat_attach): Use linux_proc_attach_tgid_threads.
(wait_lwp, linux_nat_filter_event): If not set yet, set the lwp's
ptrace option flags.
* linux-nat.h (struct lwp_info) <must_set_ptrace_flags>: New
field.
* nat/linux-procfs.c: Include <dirent.h>.
(linux_proc_get_int): New parameter "warn". Handle it.
(linux_proc_get_tgid): Adjust.
(linux_proc_get_tracerpid): Rename to ...
(linux_proc_get_tracerpid_nowarn): ... this.
(linux_proc_pid_get_state): New function, factored out from
(linux_proc_pid_has_state): ... this. Add new parameter "warn"
and handle it.
(linux_proc_pid_is_gone): New function.
(linux_proc_pid_is_stopped): Adjust.
(linux_proc_pid_is_zombie_maybe_warn)
(linux_proc_pid_is_zombie_nowarn): New functions.
(linux_proc_pid_is_zombie): Use
linux_proc_pid_is_zombie_maybe_warn.
(linux_proc_attach_tgid_threads): New function.
* nat/linux-procfs.h (linux_proc_get_tgid): Update comment.
(linux_proc_get_tracerpid): Rename to ...
(linux_proc_get_tracerpid_nowarn): ... this, and update comment.
(linux_proc_pid_is_gone): New declaration.
(linux_proc_pid_is_zombie): Update comment.
(linux_proc_pid_is_zombie_nowarn): New declaration.
(linux_proc_attach_lwp_func): New typedef.
(linux_proc_attach_tgid_threads): New declaration.
* nat/linux-ptrace.c (linux_ptrace_attach_fail_reason): Adjust to
use nowarn functions.
(linux_ptrace_attach_fail_reason_string): Move here from
gdbserver/linux-low.c and rename.
(ptrace_supports_feature): If the current ptrace options are not
known yet, check them now, instead of asserting.
* nat/linux-ptrace.h (linux_ptrace_attach_fail_reason_string):
Declare.
2014-12-16 17:12:24 +01:00
|
|
|
|
|
|
|
/* Find all possible reasons we could have failed to attach to PTID
|
|
|
|
and return them as a string. ERR is the error PTRACE_ATTACH failed
|
2018-01-17 18:33:57 +01:00
|
|
|
with (an errno). */
|
|
|
|
extern std::string linux_ptrace_attach_fail_reason_string (ptid_t ptid, int err);
|
Linux: on attach, attach to lwps listed under /proc/$pid/task/
... instead of relying on libthread_db.
I wrote a test that attaches to a program that constantly spawns
short-lived threads, which exposed several issues. This is one of
them.
On Linux, we need to attach to all threads of a process (thread group)
individually. We currently rely on libthread_db to list the threads,
but that is problematic, because libthread_db relies on reading data
structures out of the inferior (which may well be corrupted). If
threads are being created or exiting just while we try to attach, we
may trip on inconsistencies in the inferior's thread list. To work
around that, when we see a seemingly corrupt list, we currently retry
a few times:
static void
thread_db_find_new_threads_2 (ptid_t ptid, int until_no_new)
{
...
if (until_no_new)
{
/* Require 4 successive iterations which do not find any new threads.
The 4 is a heuristic: there is an inherent race here, and I have
seen that 2 iterations in a row are not always sufficient to
"capture" all threads. */
...
That heuristic may well fail, and when it does, we end up with threads
in the program that aren't under GDB's control. That's obviously bad
and results in quite mistifying failures, like e.g., the process dying
for seeminly no reason when a thread that wasn't attached trips on a
breakpoint.
There's really no reason to rely on libthread_db for this nowadays
when we have /proc mounted. In that case, which is the usual case, we
can list the LWPs from /proc/PID/task/. In fact, GDBserver is already
doing this. The patch factors out that code that knows to walk the
task/ directory out of GDBserver, and makes GDB use it too.
Like GDBserver, the patch makes GDB attach to LWPs and _not_ wait for
them to stop immediately. Instead, we just tag the LWP as having an
expected stop. Because we can only set the ptrace options when the
thread stops, we need a new flag in the lwp structure to keep track of
whether we've already set the ptrace options, just like in GDBserver.
Note that nothing issues any ptrace command to the threads between the
PTRACE_ATTACH and the stop, so this is safe (unlike one scenario
described in gdbserver's linux-low.c).
When we attach to a program that has threads exiting while we attach,
it's easy to race with a thread just exiting as we try to attach to
it, like:
#1 - get current list of threads
#2 - attach to each listed thread
#3 - ooops, attach failed, thread is already gone
As this is pretty normal, we shouldn't be issuing a scary warning in
step #3.
When #3 happens, PTRACE_ATTACH usually fails with ESRCH, but sometimes
we'll see EPERM as well. That happens when the kernel still has the
thread in its task list, but the thread is marked as dead.
Unfortunately, EPERM is ambiguous and we'll get it also on other
scenarios where the thread isn't dead, and in those cases, it's useful
to get a warning. To distiguish the cases, when we get an EPERM
failure, we open /proc/PID/status, and check the thread's state -- if
the /proc file no longer exists, or the state is "Z (Zombie)" or "X
(Dead)", we ignore the EPERM error silently; otherwise, we'll warn.
Unfortunately, there seems to be a kernel race here. Sometimes I get
EPERM, and then the /proc state still indicates "R (Running)"... If
we wait a bit and retry, we do end up seeing X or Z state, or get an
ESRCH. I thought of making GDB retry the attach a few times, but even
with a 500ms wait and 4 retries, I still see the warning sometimes. I
haven't been able to identify the kernel path that causes this yet,
but in any case, it looks like a kernel bug to me. As this just
results failure to suppress a warning that we've been printing since
about forever anyway, I'm just making the test cope with it, and issue
an XFAIL.
gdb/gdbserver/
2015-01-09 Pedro Alves <palves@redhat.com>
* linux-low.c (linux_attach_fail_reason_string): Move to
nat/linux-ptrace.c, and rename.
(linux_attach_lwp): Update comment.
(attach_proc_task_lwp_callback): New function.
(linux_attach): Adjust to rename and use
linux_proc_attach_tgid_threads.
(linux_attach_fail_reason_string): Delete declaration.
gdb/
2015-01-09 Pedro Alves <palves@redhat.com>
* linux-nat.c (attach_proc_task_lwp_callback): New function.
(linux_nat_attach): Use linux_proc_attach_tgid_threads.
(wait_lwp, linux_nat_filter_event): If not set yet, set the lwp's
ptrace option flags.
* linux-nat.h (struct lwp_info) <must_set_ptrace_flags>: New
field.
* nat/linux-procfs.c: Include <dirent.h>.
(linux_proc_get_int): New parameter "warn". Handle it.
(linux_proc_get_tgid): Adjust.
(linux_proc_get_tracerpid): Rename to ...
(linux_proc_get_tracerpid_nowarn): ... this.
(linux_proc_pid_get_state): New function, factored out from
(linux_proc_pid_has_state): ... this. Add new parameter "warn"
and handle it.
(linux_proc_pid_is_gone): New function.
(linux_proc_pid_is_stopped): Adjust.
(linux_proc_pid_is_zombie_maybe_warn)
(linux_proc_pid_is_zombie_nowarn): New functions.
(linux_proc_pid_is_zombie): Use
linux_proc_pid_is_zombie_maybe_warn.
(linux_proc_attach_tgid_threads): New function.
* nat/linux-procfs.h (linux_proc_get_tgid): Update comment.
(linux_proc_get_tracerpid): Rename to ...
(linux_proc_get_tracerpid_nowarn): ... this, and update comment.
(linux_proc_pid_is_gone): New declaration.
(linux_proc_pid_is_zombie): Update comment.
(linux_proc_pid_is_zombie_nowarn): New declaration.
(linux_proc_attach_lwp_func): New typedef.
(linux_proc_attach_tgid_threads): New declaration.
* nat/linux-ptrace.c (linux_ptrace_attach_fail_reason): Adjust to
use nowarn functions.
(linux_ptrace_attach_fail_reason_string): Move here from
gdbserver/linux-low.c and rename.
(ptrace_supports_feature): If the current ptrace options are not
known yet, check them now, instead of asserting.
* nat/linux-ptrace.h (linux_ptrace_attach_fail_reason_string):
Declare.
2014-12-16 17:12:24 +01:00
|
|
|
|
2012-07-07 14:13:57 +02:00
|
|
|
extern void linux_ptrace_init_warnings (void);
|
Identify remote fork event support
This patch implements a mechanism for GDB to determine whether fork
events are supported in gdbserver. This is a preparatory patch for
remote fork and exec event support.
Two new RSP packets are defined to represent fork and vfork event
support. These packets are used just like PACKET_multiprocess_feature
to denote whether the corresponding event is supported. GDB sends
fork-events+ and vfork-events+ to gdbserver to inquire about fork
event support. If the response enables these packets, then GDB
knows that gdbserver supports the corresponding events and will
enable them.
Target functions used to query for support are included along with
each new packet.
In order for gdbserver to know whether the events are supported at the
point where the qSupported packet arrives, the code in nat/linux-ptrace.c
had to be reorganized. Previously it would test for fork/exec event
support, then enable the events using the pid of the inferior. When the
qSupported packet arrives there may not be an inferior. So the mechanism
was split into two parts: a function that checks whether the events are
supported, called when gdbserver starts up, and another that enables the
events when the inferior stops for the first time.
Another gdbserver change was to add some global variables similar to
multi_process, one per new packet. These are used to control whether
the corresponding fork events are enabled. If GDB does not inquire
about the event support in the qSupported packet, then gdbserver will
not set these "report the event" flags. If the flags are not set, the
events are ignored like they were in the past. Thus, gdbserver will
never send fork event notification to an older GDB that doesn't
recognize fork events.
Tested on Ubuntu x64, native/remote/extended-remote, and as part of
subsequent patches in the series.
gdb/gdbserver/ChangeLog:
* linux-low.c (linux_supports_fork_events): New function.
(linux_supports_vfork_events): New function.
(linux_target_ops): Initialize new structure members.
(initialize_low): Call linux_check_ptrace_features.
* lynx-low.c (lynx_target_ops): Initialize new structure
members.
* server.c (report_fork_events, report_vfork_events):
New global flags.
(handle_query): Add new features to qSupported packet and
response.
(captured_main): Initialize new global variables.
* target.h (struct target_ops) <supports_fork_events>:
New member.
<supports_vfork_events>: New member.
(target_supports_fork_events): New macro.
(target_supports_vfork_events): New macro.
* win32-low.c (win32_target_ops): Initialize new structure
members.
gdb/ChangeLog:
* nat/linux-ptrace.c (linux_check_ptrace_features): Change
from static to extern.
* nat/linux-ptrace.h (linux_check_ptrace_features): Declare.
* remote.c (anonymous enum): <PACKET_fork_event_feature,
* PACKET_vfork_event_feature>: New enumeration constants.
(remote_protocol_features): Add table entries for new packets.
(remote_query_supported): Add new feature queries to qSupported
packet.
(_initialize_remote): Exempt new packets from the requirement
to have 'set remote' commands.
2015-05-12 18:52:41 +02:00
|
|
|
extern void linux_check_ptrace_features (void);
|
2014-11-11 07:07:21 +01:00
|
|
|
extern void linux_enable_event_reporting (pid_t pid, int attached);
|
2014-06-08 13:11:09 +02:00
|
|
|
extern void linux_disable_event_reporting (pid_t pid);
|
2013-08-23 01:46:30 +02:00
|
|
|
extern int linux_supports_tracefork (void);
|
Extended-remote follow-exec
This patch implements support for exec events on extended-remote Linux
targets. Follow-exec-mode and rerun behave as expected. Catchpoints and
test updates are implemented in subsequent patches.
This patch was derived from a patch posted last October:
https://sourceware.org/ml/gdb-patches/2014-10/msg00877.html.
It was originally based on some work done by Luis Machado in 2013.
IMPLEMENTATION
----------------
Exec events are enabled via ptrace options.
When an exec event is detected by gdbserver, the existing process
data, along with all its associated lwp and thread data, is deleted
and replaced by data for a new single-threaded process. The new
process data is initialized with the appropriate parts of the state
of the execing process. This approach takes care of several potential
pitfalls, including:
* deleting the data for an execing non-leader thread before any
wait/sigsuspend occurs
* correctly initializing the architecture of the execed process
We then report the exec event using a new RSP stop reason, "exec".
When GDB receives an "exec" event, it saves the status in the event
structure's target_waitstatus field, like what is done for remote fork
events. Because the original and execed programs may have different
architectures, we skip parsing the section of the stop reply packet
that contains register data. The register data will be retrieved
later after the inferior's architecture has been set up by
infrun.c:follow_exec.
At that point the exec event is handled by the existing event handling
in GDB. However, a few changes were necessary so that
infrun.c:follow_exec could accommodate the remote target.
* Where follow-exec-mode "new" is handled, we now call
add_inferior_with_spaces instead of add_inferior with separate calls
to set up the program and address spaces. The motivation for this
is that add_inferior_with_spaces also sets up the initial architecture
for the inferior, which is needed later by target_find_description
when it calls target_gdbarch.
* We call a new target function, target_follow_exec. This function
allows us to store the execd_pathname in the inferior, instead of
using the static string remote_exec_file from remote.c. The static
string didn't work for follow-exec-mode "new", since once you switched
to the execed program, the original remote exec-file was lost. The
execd_pathname is now stored in the inferior's program space as a
REGISTRY field. All of the requisite mechanisms for this are
defined in remote.c.
gdb/gdbserver/ChangeLog:
* linux-low.c (linux_mourn): Static declaration.
(linux_arch_setup): Move in front of
handle_extended_wait.
(linux_arch_setup_thread): New function.
(handle_extended_wait): Handle exec events. Call
linux_arch_setup_thread. Make event_lwp argument a
pointer-to-a-pointer.
(check_zombie_leaders): Do not check stopped threads.
(linux_low_ptrace_options): Add PTRACE_O_TRACEEXEC.
(linux_low_filter_event): Add lwp and thread for exec'ing
non-leader thread if leader thread has been deleted.
Refactor code into linux_arch_setup_thread and call it.
Pass child lwp pointer by reference to handle_extended_wait.
(linux_wait_for_event_filtered): Update comment.
(linux_wait_1): Prevent clobbering exec event status.
(linux_supports_exec_events): New function.
(linux_target_ops) <supports_exec_events>: Initialize new member.
* lynx-low.c (lynx_target_ops) <supports_exec_events>: Initialize
new member.
* remote-utils.c (prepare_resume_reply): New stop reason 'exec'.
* server.c (report_exec_events): New global variable.
(handle_query): Handle qSupported query for exec-events feature.
(captured_main): Initialize report_exec_events.
* server.h (report_exec_events): Declare new global variable.
* target.h (struct target_ops) <supports_exec_events>: New
member.
(target_supports_exec_events): New macro.
* win32-low.c (win32_target_ops) <supports_exec_events>:
Initialize new member.
gdb/ChangeLog:
* infrun.c (follow_exec): Use process-style ptid for
exec message. Call add_inferior_with_spaces and
target_follow_exec.
* nat/linux-ptrace.c (linux_supports_traceexec): New function.
* nat/linux-ptrace.h (linux_supports_traceexec): Declare.
* remote.c (remote_pspace_data): New static variable.
(remote_pspace_data_cleanup): New function.
(get_remote_exec_file): New function.
(set_remote_exec_file_1): New function.
(set_remote_exec_file): New function.
(show_remote_exec_file): New function.
(remote_exec_file): Delete static variable.
(anonymous enum) <PACKET_exec_event_feature> New
enumeration constant.
(remote_protocol_features): Add entry for exec-events feature.
(remote_query_supported): Add client side of qSupported query
for exec-events feature.
(remote_follow_exec): New function.
(remote_parse_stop_reply): Handle 'exec' stop reason.
(extended_remote_run, extended_remote_create_inferior): Call
get_remote_exec_file and set_remote_exec_file_1.
(init_extended_remote_ops) <to_follow_exec>: Initialize new
member.
(_initialize_remote): Call
register_program_space_data_with_cleanup. Call
add_packet_config_cmd for remote exec-events feature.
Modify call to add_setshow_string_noescape_cmd for exec-file
to use new functions set_remote_exec_file and
show_remote_exec_file.
* target-debug.h, target-delegates.c: Regenerated.
* target.c (target_follow_exec): New function.
* target.h (struct target_ops) <to_follow_exec>: New member.
(target_follow_exec): Declare new function.
2015-09-11 20:06:02 +02:00
|
|
|
extern int linux_supports_traceexec (void);
|
2013-08-23 01:46:30 +02:00
|
|
|
extern int linux_supports_traceclone (void);
|
|
|
|
extern int linux_supports_tracevforkdone (void);
|
|
|
|
extern int linux_supports_tracesysgood (void);
|
2014-09-19 19:54:34 +02:00
|
|
|
extern int linux_ptrace_get_extended_event (int wstat);
|
|
|
|
extern int linux_is_extended_waitstatus (int wstat);
|
2015-02-12 20:55:08 +01:00
|
|
|
extern int linux_wstatus_maybe_breakpoint (int wstat);
|
2012-03-13 16:02:25 +01:00
|
|
|
|
2011-04-26 17:36:04 +02:00
|
|
|
#endif /* COMMON_LINUX_PTRACE_H */
|