2015-01-01 17:32:14 +08:00
|
|
|
/* Copyright (C) 2011-2015 Free Software Foundation, Inc.
|
2011-04-26 23:36:04 +08: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 23:02:25 +08:00
|
|
|
struct buffer;
|
|
|
|
|
2015-07-24 21:57:20 +08:00
|
|
|
#include "nat/gdb_ptrace.h"
|
2011-04-26 23:36:04 +08:00
|
|
|
|
2013-08-23 07:46:30 +08: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 23:36:04 +08:00
|
|
|
#ifndef PTRACE_GETSIGINFO
|
|
|
|
# define PTRACE_GETSIGINFO 0x4202
|
|
|
|
# define PTRACE_SETSIGINFO 0x4203
|
|
|
|
#endif /* PTRACE_GETSIGINF */
|
|
|
|
|
2015-06-01 19:13:02 +08:00
|
|
|
#ifndef PTRACE_GETREGSET
|
|
|
|
#define PTRACE_GETREGSET 0x4204
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef PTRACE_SETREGSET
|
|
|
|
#define PTRACE_SETREGSET 0x4205
|
|
|
|
#endif
|
|
|
|
|
2011-04-26 23:36:04 +08: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 14:07:21 +08:00
|
|
|
#ifndef PTRACE_O_EXITKILL
|
|
|
|
/* Only defined in Linux Kernel 3.8 or later. */
|
|
|
|
#define PTRACE_O_EXITKILL 0x00100000
|
|
|
|
#endif
|
|
|
|
|
2011-09-30 08:01:59 +08: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 23:36:04 +08: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-05 04:41:16 +08: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:
|
|
|
|
|
|
|
|
| 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_HWBPT |
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
The generic Linux target code should use GDB_ARCH_TRAP_BRKPT
|
|
|
|
instead of TRAP_BRKPT to abstract out this x86 peculiarity. */
|
|
|
|
#if defined __i386__ || defined __x86_64__
|
|
|
|
# define GDB_ARCH_TRAP_BRKPT SI_KERNEL
|
|
|
|
#else
|
|
|
|
# define GDB_ARCH_TRAP_BRKPT TRAP_BRKPT
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef TRAP_HWBKPT
|
|
|
|
# define TRAP_HWBKPT 4
|
|
|
|
#endif
|
|
|
|
|
PR server/16255: gdbserver cannot attach to a second inferior that is multi-threaded.
On Linux, we need to explicitly ptrace attach to all lwps of a
process. Because GDB might not be connected yet when an attach is
requested, and thus it may not be possible to activate thread_db, as
that requires access to symbols (IOW, gdbserver --attach), a while ago
we make linux_attach loop over the lwps as listed by /proc/PID/task to
find the lwps to attach to.
linux_attach_lwp_1 has:
...
if (initial)
/* If lwp is the tgid, we handle adding existing threads later.
Otherwise we just add lwp without bothering about any other
threads. */
ptid = ptid_build (lwpid, lwpid, 0);
else
{
/* Note that extracting the pid from the current inferior is
safe, since we're always called in the context of the same
process as this new thread. */
int pid = pid_of (current_inferior);
ptid = ptid_build (pid, lwpid, 0);
}
That "safe" comment referred to linux_attach_lwp being called by
thread-db.c. But this was clearly missed when a new call to
linux_attach_lwp_1 was added to linux_attach. As a result,
current_inferior will be set to some random process, and non-initial
lwps of the second inferior get assigned the pid of the wrong
inferior. E.g., in the case of attaching to two inferiors, for the
second inferior (and so on), non-initial lwps of the second inferior
get assigned the pid of the first inferior. This doesn't trigger on
the first inferior, when current_inferior is NULL, add_thread switches
the current inferior to the newly added thread.
Rather than making linux_attach switch current_inferior temporarily
(thus avoiding further reliance on global state), or making
linux_attach_lwp_1 get the tgid from /proc, which add extra syscalls,
and will be wrong in case of the user having originally attached
directly to a non-tgid lwp, and then that lwp spawning new clones (the
ptid.pid field of further new clones should be the same as the
original lwp's pid, which is not the tgid), we note that callers of
linux_attach_lwp/linux_attach_lwp_1 always have the right pid handy
already, so they can pass it down along with the lwpid.
The only other reason for the "initial" parameter is to error out
instead of warn in case of attach failure, when we're first attaching
to a process. There are only three callers of
linux_attach_lwp/linux_attach_lwp_1, and each wants to print a
different warn/error string, so we can just move the error/warn out of
linux_attach_lwp_1 to the callers, thus getting rid of the "initial"
parameter.
There really nothing gdbserver-specific about attaching to two
threaded processes, so this adds a new test under gdb.multi/. The
test passes cleanly against the native GNU/Linux target, but
fails/triggers the bug against GDBserver (before the patch), with the
native-extended-remote board (as plain remote doesn't support
multi-process).
Tested on x86_64 Fedora 17, with the native-extended-gdbserver board.
gdb/gdbserver/
2014-04-25 Pedro Alves <palves@redhat.com>
PR server/16255
* linux-low.c (linux_attach_fail_reason_string): New function.
(linux_attach_lwp): Delete.
(linux_attach_lwp_1): Rename to ...
(linux_attach_lwp): ... this. Take a ptid instead of a pid as
argument. Remove "initial" parameter. Return int instead of
void. Don't error or warn here.
(linux_attach): Adjust to call linux_attach_lwp. Call error on
failure to attach to the tgid. Call warning when failing to
attach to an lwp.
* linux-low.h (linux_attach_lwp): Take a ptid instead of a pid as
argument. Remove "initial" parameter. Return int instead of
void. Don't error or warn here.
(linux_attach_fail_reason_string): New declaration.
* thread-db.c (attach_thread): Adjust to linux_attach_lwp's
interface change. Use linux_attach_fail_reason_string.
gdb/
2014-04-25 Pedro Alves <palves@redhat.com>
PR server/16255
* common/linux-ptrace.c (linux_ptrace_attach_warnings): Rename to ...
(linux_ptrace_attach_fail_reason): ... this. Remove "warning: "
and newline from built string.
* common/linux-ptrace.h (linux_ptrace_attach_warnings): Rename to ...
(linux_ptrace_attach_fail_reason): ... this.
* linux-nat.c (linux_nat_attach): Adjust to use
linux_ptrace_attach_fail_reason.
gdb/testsuite/
2014-04-25 Simon Marchi <simon.marchi@ericsson.com>
Pedro Alves <palves@redhat.com>
PR server/16255
* gdb.multi/multi-attach.c: New file.
* gdb.multi/multi-attach.exp: New file.
2014-04-26 02:07:33 +08:00
|
|
|
extern void linux_ptrace_attach_fail_reason (pid_t pid, struct buffer *buffer);
|
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-17 00:12:24 +08: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
|
|
|
|
with (an errno). The result is stored in a static buffer. This
|
|
|
|
string should be copied into a buffer by the client if the string
|
|
|
|
will not be immediately used, or if it must persist. */
|
|
|
|
extern char *linux_ptrace_attach_fail_reason_string (ptid_t ptid, int err);
|
|
|
|
|
2012-07-07 20:13:57 +08: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-13 00:52:41 +08:00
|
|
|
extern void linux_check_ptrace_features (void);
|
2014-11-11 14:07:21 +08:00
|
|
|
extern void linux_enable_event_reporting (pid_t pid, int attached);
|
2014-06-08 19:11:09 +08:00
|
|
|
extern void linux_disable_event_reporting (pid_t pid);
|
2013-08-23 07:46:30 +08:00
|
|
|
extern int linux_supports_tracefork (void);
|
|
|
|
extern int linux_supports_traceclone (void);
|
|
|
|
extern int linux_supports_tracevforkdone (void);
|
|
|
|
extern int linux_supports_tracesysgood (void);
|
2014-09-20 01:54:34 +08:00
|
|
|
extern int linux_ptrace_get_extended_event (int wstat);
|
|
|
|
extern int linux_is_extended_waitstatus (int wstat);
|
2015-02-13 03:55:08 +08:00
|
|
|
extern int linux_wstatus_maybe_breakpoint (int wstat);
|
2012-03-13 23:02:25 +08:00
|
|
|
|
2011-04-26 23:36:04 +08:00
|
|
|
#endif /* COMMON_LINUX_PTRACE_H */
|