This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
RFC: Unify the GNU/Linux native targets
- From: Daniel Jacobowitz <drow at false dot org>
- To: gdb-patches at sourceware dot org
- Date: Mon, 27 Feb 2006 14:28:07 -0500
- Subject: RFC: Unify the GNU/Linux native targets
A wart I've been meaning to come back to for ages; I have some fixes for
thread debugging in static binaries that would have been quite ugly
without this, so I took a day to do it.
There are two target vectors in the current incarnation of linux-nat.c. The
one returned by linux_target () and inherited by target-specific files is
used for non-threaded applications; it handles basic operations including
target-specific extensions to them. The one built in linux_nat_ops
handles clone and can be used with libthread_db, and delegates to the
single-threaded variant for basic tasks.
This is a bit silly :-) We still need the separation between single and
multi-threaded vectors for the moment, because targets want to override
the single-threaded primitives rather than the complex multi-threaded
layer. However, that's all we need the single-threaded vector for. We
don't ever need to _use_ it.
This patch kills most of the single-threaded vector and arranges to
use the multi-threaded version in all cases. Some duplicated code
goes away, and it is suddenly much easier to switch back and forth
between "threaded" and "non-threaded" debugging.
One oddity: the Linux native target remains at process_stratum even
though it supports threads. I think this is right; the thread_stratum
gets used for linux-thread-db.c support which delegates to the process
stratum. If we had arbitrary stacking instead of strata I might
stack the linux multithreaded bits above the linux single-threaded
bits, but I think this is more natural.
Tested on x86_64-pc-linux-gnu. Any comments? Seems like progress?
Depends on my previous linux-fork.c patch, but only trivially.
--
Daniel Jacobowitz
CodeSourcery
2006-02-27 Daniel Jacobowitz <dan@codesourcery.com>
* linux-nat.c (linux_ops_saved): New.
(super_mourn_inferior, kill_inferior, threaded, linux_nat_ops)
(child_mourn_inferior, child_wait, linux_nat_create_inferior)
(linux_nat_fetch_registers, linux_nat_store_registers)
(linux_nat_child_post_startup_inferior, init_linux_nat_ops): Delete.
(init_lwp_list): Don't set threaded.
(add_lwp): Don't modify threaded.
(delete_lwp): Don't mention non-threaded mode.
(linux_nat_switch_fork): New.
(linux_nat_attach): Update inferior_ptid.
(linux_nat_wait): Handle num_lwps == 0 at entry. Don't check
threaded flag.
(linux_nat_kill): Handle pending forks and saved forks.
(linux_nat_mourn_inferior): Handle saved forks.
(linux_nat_pid_to_str): Don't use the LWP form when there is
only one thread.
(linux_target): Don't set to_wait, to_kill, or to_mourn_inferior.
(set_linux_target): New.
(_initialize_linux_nat): Don't initialize the linux native target
here.
* linux-nat.h (set_linux_target, linux_nat_switch_fork): New
prototypes.
* linux-fork.c: Include "linux-nat.h".
(add_fork): Update initial PID.
(fork_load_infrun_state): Call linux_nat_switch_fork.
* Makefile.in (linux-fork.o): Update.
* alpha-linux-nat.c (_initialize_alpha_linux_nat): Use
set_linux_target instead of add_target.
* amd64-linux-nat.c (_initialize_amd64_linux_nat): Likewise.
* arm-linux-nat.c (_initialize_arm_linux_nat): Likewise.
* hppa-linux-nat.c (_initialize_hppa_linux_nat): Likewise.
* ia64-linux-nat.c (_initialize_ia64_linux_nat): Likewise.
* i386-linux-nat.c (_initialize_i386_linux_nat): Likewise.
* m32r-linux-nat.c (_initialize_m32r_linux_nat): Likewise.
* m68klinux-nat.c (_initialize_m68k_linux_nat): Likewise.
* mips-linux-nat.c (_initialize_mips_linux_nat): Likewise.
* ppc-linux-nat.c (_initialize_ppc_linux_nat): Likewise.
* s390-nat.c (_initialize_s390_nat): Likewise.
* sparc-linux-nat.c (_initialize_sparc_linux_nat): Likewise.
* sparc64-linux-nat.c (_initialize_sparc64_linux_nat): Likewise.
Index: src/gdb/i386-linux-nat.c
===================================================================
--- src.orig/gdb/i386-linux-nat.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/i386-linux-nat.c 2006-02-27 12:56:15.000000000 -0500
@@ -1,6 +1,6 @@
/* Native-dependent code for GNU/Linux i386.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@@ -844,5 +844,5 @@ _initialize_i386_linux_nat (void)
t->to_store_registers = i386_linux_store_inferior_registers;
/* Register the target. */
- add_target (t);
+ set_linux_target (t);
}
Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/linux-nat.c 2006-02-27 12:47:52.000000000 -0500
@@ -88,6 +88,7 @@
/* The single-threaded native GNU/Linux target_ops. We save a pointer for
the use of the multi-threaded target. */
static struct target_ops *linux_ops;
+static struct target_ops linux_ops_saved;
/* The saved to_xfer_partial method, inherited from inf-ptrace.c.
Called by our to_xfer_partial. */
@@ -97,10 +98,6 @@ static LONGEST (*super_xfer_partial) (st
const gdb_byte *,
ULONGEST, LONGEST);
-/* The saved to_mourn_inferior method, inherited from inf-ptrace.c.
- Called by our to_mourn_inferior. */
-static void (*super_mourn_inferior) (void);
-
static int debug_linux_nat;
static void
show_debug_linux_nat (struct ui_file *file, int from_tty,
@@ -600,56 +597,6 @@ child_insert_exec_catchpoint (int pid)
error (_("Your system does not support exec catchpoints."));
}
-void
-kill_inferior (void)
-{
- int status;
- int pid = PIDGET (inferior_ptid);
- struct target_waitstatus last;
- ptid_t last_ptid;
- int ret;
-
- if (pid == 0)
- return;
-
- /* First cut -- let's crudely do everything inline. */
- if (forks_exist_p ())
- {
- linux_fork_killall ();
- pop_target ();
- generic_mourn_inferior ();
- }
- else
- {
- /* If we're stopped while forking and we haven't followed yet,
- kill the other task. We need to do this first because the
- parent will be sleeping if this is a vfork. */
-
- get_last_target_status (&last_ptid, &last);
-
- if (last.kind == TARGET_WAITKIND_FORKED
- || last.kind == TARGET_WAITKIND_VFORKED)
- {
- ptrace (PT_KILL, last.value.related_pid, 0, 0);
- wait (&status);
- }
-
- /* Kill the current process. */
- ptrace (PT_KILL, pid, 0, 0);
- ret = wait (&status);
-
- /* We might get a SIGCHLD instead of an exit status. This is
- aggravated by the first kill above - a child has just died. */
-
- while (ret == pid && WIFSTOPPED (status))
- {
- ptrace (PT_KILL, pid, 0, 0);
- ret = wait (&status);
- }
- target_mourn_inferior ();
- }
-}
-
/* On GNU/Linux there are no real LWP's. The closest thing to LWP's
are processes sharing the same VM space. A multi-threaded process
is basically a group of such processes. However, such a grouping
@@ -688,9 +635,6 @@ static struct lwp_info *lwp_list;
/* Number of LWPs in the list. */
static int num_lwps;
-
-/* Non-zero if we're running in "threaded" mode. */
-static int threaded;
#define GET_LWP(ptid) ptid_get_lwp (ptid)
@@ -703,9 +647,6 @@ static int threaded;
ptid_t trap_ptid;
-/* This module's target-specific operations. */
-static struct target_ops linux_nat_ops;
-
/* Since we cannot wait (in linux_nat_wait) for the initial process and
any cloned processes with a single call to waitpid, we have to use
the WNOHANG flag and call waitpid in a loop. To optimize
@@ -770,12 +711,10 @@ init_lwp_list (void)
lwp_list = NULL;
num_lwps = 0;
- threaded = 0;
}
-/* Add the LWP specified by PID to the list. If this causes the
- number of LWPs to become larger than one, go into "threaded" mode.
- Return a pointer to the structure describing the new LWP. */
+/* Add the LWP specified by PID to the list. Return a pointer to the
+ structure describing the new LWP. */
static struct lwp_info *
add_lwp (ptid_t ptid)
@@ -794,8 +733,7 @@ add_lwp (ptid_t ptid)
lp->next = lwp_list;
lwp_list = lp;
- if (++num_lwps > 1)
- threaded = 1;
+ ++num_lwps;
return lp;
}
@@ -816,8 +754,6 @@ delete_lwp (ptid_t ptid)
if (!lp)
return;
- /* We don't go back to "non-threaded" mode if the number of threads
- becomes less than two. */
num_lwps--;
if (lpprev)
@@ -869,6 +805,21 @@ iterate_over_lwps (int (*callback) (stru
return NULL;
}
+/* Update our internal state when changing from one fork (checkpoint,
+ et cetera) to another indicated by NEW_PTID. We can only switch
+ single-threaded applications, so we only create one new LWP, and
+ the previous list is discarded. */
+
+void
+linux_nat_switch_fork (ptid_t new_ptid)
+{
+ struct lwp_info *lp;
+
+ init_lwp_list ();
+ lp = add_lwp (new_ptid);
+ lp->stopped = 1;
+}
+
/* Record a PTID for later deletion. */
struct saved_ptids
@@ -1048,7 +999,8 @@ linux_nat_attach (char *args, int from_t
linux_ops->to_attach (args, from_tty);
/* Add the initial process as the first LWP to the list. */
- lp = add_lwp (BUILD_LWP (GET_PID (inferior_ptid), GET_PID (inferior_ptid)));
+ inferior_ptid = BUILD_LWP (GET_PID (inferior_ptid), GET_PID (inferior_ptid));
+ lp = add_lwp (inferior_ptid);
/* Make sure the initial process is stopped. The user-level threads
layer might want to poke around in the inferior, and that won't
@@ -1850,134 +1802,6 @@ resumed_callback (struct lwp_info *lp, v
return lp->resumed;
}
-/* Local mourn_inferior -- we need to override mourn_inferior
- so that we can do something clever if one of several forks
- has exited. */
-
-static void
-child_mourn_inferior (void)
-{
- int status;
-
- if (! forks_exist_p ())
- {
- /* Normal case, no other forks available. */
- super_mourn_inferior ();
- return;
- }
- else
- {
- /* Multi-fork case. The current inferior_ptid has exited, but
- there are other viable forks to debug. Delete the exiting
- one and context-switch to the first available. */
- linux_fork_mourn_inferior ();
- }
-}
-
-/* We need to override child_wait to support attaching to cloned
- processes, since a normal wait (as done by the default version)
- ignores those processes. */
-
-/* Wait for child PTID to do something. Return id of the child,
- minus_one_ptid in case of error; store status into *OURSTATUS. */
-
-ptid_t
-child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
-{
- int save_errno;
- int status;
- pid_t pid;
-
- ourstatus->kind = TARGET_WAITKIND_IGNORE;
-
- do
- {
- set_sigint_trap (); /* Causes SIGINT to be passed on to the
- attached process. */
- set_sigio_trap ();
-
- pid = my_waitpid (GET_PID (ptid), &status, 0);
- if (pid == -1 && errno == ECHILD)
- /* Try again with __WCLONE to check cloned processes. */
- pid = my_waitpid (GET_PID (ptid), &status, __WCLONE);
-
- if (debug_linux_nat)
- {
- fprintf_unfiltered (gdb_stdlog,
- "CW: waitpid %ld received %s\n",
- (long) pid, status_to_str (status));
- }
-
- save_errno = errno;
-
- /* Make sure we don't report an event for the exit of the
- original program, if we've detached from it. */
- if (pid != -1 && !WIFSTOPPED (status) && pid != GET_PID (inferior_ptid))
- {
- pid = -1;
- save_errno = EINTR;
- }
-
- /* Check for stop events reported by a process we didn't already
- know about - in this case, anything other than inferior_ptid.
-
- If we're expecting to receive stopped processes after fork,
- vfork, and clone events, then we'll just add the new one to
- our list and go back to waiting for the event to be reported
- - the stopped process might be returned from waitpid before
- or after the event is. If we want to handle debugging of
- CLONE_PTRACE processes we need to do more here, i.e. switch
- to multi-threaded mode. */
- if (pid != -1 && WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP
- && pid != GET_PID (inferior_ptid))
- {
- linux_record_stopped_pid (pid);
- pid = -1;
- save_errno = EINTR;
- }
-
- /* Handle GNU/Linux's extended waitstatus for trace events. */
- if (pid != -1 && WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP
- && status >> 16 != 0)
- {
- linux_handle_extended_wait (pid, status, ourstatus);
-
- /* If we see a clone event, detach the child, and don't
- report the event. It would be nice to offer some way to
- switch into a non-thread-db based threaded mode at this
- point. */
- if (ourstatus->kind == TARGET_WAITKIND_SPURIOUS)
- {
- ptrace (PTRACE_DETACH, ourstatus->value.related_pid, 0, 0);
- ourstatus->kind = TARGET_WAITKIND_IGNORE;
- ptrace (PTRACE_CONT, pid, 0, 0);
- pid = -1;
- save_errno = EINTR;
- }
- }
-
- clear_sigio_trap ();
- clear_sigint_trap ();
- }
- while (pid == -1 && save_errno == EINTR);
-
- if (pid == -1)
- {
- warning (_("Child process unexpectedly missing: %s"),
- safe_strerror (errno));
-
- /* Claim it exited with unknown signal. */
- ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
- ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
- return minus_one_ptid;
- }
-
- if (ourstatus->kind == TARGET_WAITKIND_IGNORE)
- store_waitstatus (ourstatus, status);
-
- return pid_to_ptid (pid);
-}
-
/* Stop an active thread, verify it still exists, then resume it. */
static int
@@ -2009,6 +1833,19 @@ linux_nat_wait (ptid_t ptid, struct targ
pid_t pid = PIDGET (ptid);
sigset_t flush_mask;
+ /* The first time we get here after starting a new inferior, we may
+ not have added it to the LWP list yet - this is the earliest
+ moment at which we know its PID. */
+ if (num_lwps == 0)
+ {
+ gdb_assert (!is_lwp (inferior_ptid));
+
+ inferior_ptid = BUILD_LWP (GET_PID (inferior_ptid),
+ GET_PID (inferior_ptid));
+ lp = add_lwp (inferior_ptid);
+ lp->resumed = 1;
+ }
+
sigemptyset (&flush_mask);
/* Make sure SIGCHLD is blocked. */
@@ -2020,9 +1857,8 @@ linux_nat_wait (ptid_t ptid, struct targ
retry:
- /* Make sure there is at least one LWP that has been resumed, at
- least if there are any LWPs at all. */
- gdb_assert (num_lwps == 0 || iterate_over_lwps (resumed_callback, NULL));
+ /* Make sure there is at least one LWP that has been resumed. */
+ gdb_assert (iterate_over_lwps (resumed_callback, NULL));
/* First check if there is a LWP with a wait status pending. */
if (pid == -1)
@@ -2161,23 +1997,20 @@ retry:
if (options & __WCLONE)
lp->cloned = 1;
- if (threaded)
- {
- gdb_assert (WIFSTOPPED (status)
- && WSTOPSIG (status) == SIGSTOP);
- lp->signalled = 1;
-
- if (!in_thread_list (inferior_ptid))
- {
- inferior_ptid = BUILD_LWP (GET_PID (inferior_ptid),
- GET_PID (inferior_ptid));
- add_thread (inferior_ptid);
- }
+ gdb_assert (WIFSTOPPED (status)
+ && WSTOPSIG (status) == SIGSTOP);
+ lp->signalled = 1;
- add_thread (lp->ptid);
- printf_unfiltered (_("[New %s]\n"),
- target_pid_to_str (lp->ptid));
+ if (!in_thread_list (inferior_ptid))
+ {
+ inferior_ptid = BUILD_LWP (GET_PID (inferior_ptid),
+ GET_PID (inferior_ptid));
+ add_thread (inferior_ptid);
}
+
+ add_thread (lp->ptid);
+ printf_unfiltered (_("[New %s]\n"),
+ target_pid_to_str (lp->ptid));
}
/* Handle GNU/Linux's extended waitstatus for trace events. */
@@ -2379,12 +2212,9 @@ retry:
the comment in cancel_breakpoints_callback to find out why. */
iterate_over_lwps (cancel_breakpoints_callback, lp);
- /* If we're not running in "threaded" mode, we'll report the bare
- process id. */
-
if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP)
{
- trap_ptid = (threaded ? lp->ptid : pid_to_ptid (GET_LWP (lp->ptid)));
+ trap_ptid = lp->ptid;
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"LLW: trap_ptid is %s.\n",
@@ -2401,7 +2231,7 @@ retry:
else
store_waitstatus (ourstatus, status);
- return (threaded ? lp->ptid : pid_to_ptid (GET_LWP (lp->ptid)));
+ return lp->ptid;
}
static int
@@ -2466,6 +2296,32 @@ kill_wait_callback (struct lwp_info *lp,
static void
linux_nat_kill (void)
{
+ struct target_waitstatus last;
+ ptid_t last_ptid;
+ int status;
+
+ /* If we're stopped while forking and we haven't followed yet,
+ kill the other task. We need to do this first because the
+ parent will be sleeping if this is a vfork. */
+
+ get_last_target_status (&last_ptid, &last);
+
+ if (last.kind == TARGET_WAITKIND_FORKED
+ || last.kind == TARGET_WAITKIND_VFORKED)
+ {
+ ptrace (PT_KILL, last.value.related_pid, 0, 0);
+ wait (&status);
+ }
+
+ /* First cut -- let's crudely do everything inline. */
+ if (forks_exist_p ())
+ {
+ linux_fork_killall ();
+ pop_target ();
+ generic_mourn_inferior ();
+ return;
+ }
+
/* Kill all LWP's ... */
iterate_over_lwps (kill_callback, NULL);
@@ -2476,13 +2332,6 @@ linux_nat_kill (void)
}
static void
-linux_nat_create_inferior (char *exec_file, char *allargs, char **env,
- int from_tty)
-{
- linux_ops->to_create_inferior (exec_file, allargs, env, from_tty);
-}
-
-static void
linux_nat_mourn_inferior (void)
{
trap_ptid = null_ptid;
@@ -2494,7 +2343,14 @@ linux_nat_mourn_inferior (void)
sigprocmask (SIG_SETMASK, &normal_mask, NULL);
sigemptyset (&blocked_mask);
- linux_ops->to_mourn_inferior ();
+ if (! forks_exist_p ())
+ /* Normal case, no other forks available. */
+ linux_ops->to_mourn_inferior ();
+ else
+ /* Multi-fork case. The current inferior_ptid has exited, but
+ there are other viable forks to debug. Delete the exiting
+ one and context-switch to the first available. */
+ linux_fork_mourn_inferior ();
}
static LONGEST
@@ -2539,7 +2395,7 @@ linux_nat_pid_to_str (ptid_t ptid)
{
static char buf[64];
- if (is_lwp (ptid))
+ if (lwp_list && lwp_list->next && is_lwp (ptid))
{
snprintf (buf, sizeof (buf), "LWP %ld", GET_LWP (ptid));
return buf;
@@ -2549,59 +2405,6 @@ linux_nat_pid_to_str (ptid_t ptid)
}
static void
-linux_nat_fetch_registers (int regnum)
-{
- /* to_fetch_registers will honor the LWP ID, so we can use it directly. */
- linux_ops->to_fetch_registers (regnum);
-}
-
-static void
-linux_nat_store_registers (int regnum)
-{
- /* to_store_registers will honor the LWP ID, so we can use it directly. */
- linux_ops->to_store_registers (regnum);
-}
-
-static void
-linux_nat_child_post_startup_inferior (ptid_t ptid)
-{
- linux_ops->to_post_startup_inferior (ptid);
-}
-
-static void
-init_linux_nat_ops (void)
-{
-#if 0
- linux_nat_ops.to_open = linux_nat_open;
-#endif
- linux_nat_ops.to_shortname = "lwp-layer";
- linux_nat_ops.to_longname = "lwp-layer";
- linux_nat_ops.to_doc = "Low level threads support (LWP layer)";
- linux_nat_ops.to_attach = linux_nat_attach;
- linux_nat_ops.to_detach = linux_nat_detach;
- linux_nat_ops.to_resume = linux_nat_resume;
- linux_nat_ops.to_wait = linux_nat_wait;
- linux_nat_ops.to_fetch_registers = linux_nat_fetch_registers;
- linux_nat_ops.to_store_registers = linux_nat_store_registers;
- linux_nat_ops.to_xfer_partial = linux_nat_xfer_partial;
- linux_nat_ops.to_kill = linux_nat_kill;
- linux_nat_ops.to_create_inferior = linux_nat_create_inferior;
- linux_nat_ops.to_mourn_inferior = linux_nat_mourn_inferior;
- linux_nat_ops.to_thread_alive = linux_nat_thread_alive;
- linux_nat_ops.to_pid_to_str = linux_nat_pid_to_str;
- linux_nat_ops.to_post_startup_inferior
- = linux_nat_child_post_startup_inferior;
- linux_nat_ops.to_post_attach = child_post_attach;
- linux_nat_ops.to_insert_fork_catchpoint = child_insert_fork_catchpoint;
- linux_nat_ops.to_insert_vfork_catchpoint = child_insert_vfork_catchpoint;
- linux_nat_ops.to_insert_exec_catchpoint = child_insert_exec_catchpoint;
-
- linux_nat_ops.to_stratum = thread_stratum;
- linux_nat_ops.to_has_thread_control = tc_schedlock;
- linux_nat_ops.to_magic = OPS_MAGIC;
-}
-
-static void
sigchld_handler (int signo)
{
/* Do nothing. The only reason for this handler is that it allows
@@ -3312,8 +3115,6 @@ linux_target (void)
#else
t = inf_ptrace_trad_target (linux_register_u_offset);
#endif
- t->to_wait = child_wait;
- t->to_kill = kill_inferior;
t->to_insert_fork_catchpoint = child_insert_fork_catchpoint;
t->to_insert_vfork_catchpoint = child_insert_vfork_catchpoint;
t->to_insert_exec_catchpoint = child_insert_exec_catchpoint;
@@ -3327,18 +3128,50 @@ linux_target (void)
super_xfer_partial = t->to_xfer_partial;
t->to_xfer_partial = linux_xfer_partial;
- super_mourn_inferior = t->to_mourn_inferior;
- t->to_mourn_inferior = child_mourn_inferior;
-
- linux_ops = t;
return t;
}
void
+set_linux_target (struct target_ops *t)
+{
+ extern void thread_db_init (struct target_ops *);
+
+ /* Save the provided single-threaded target. We save this in a separate
+ variable because another target we've inherited from (e.g. inf-ptrace)
+ may have saved a pointer to T; we want to use it for the final
+ process stratum target. */
+ linux_ops_saved = *t;
+ linux_ops = &linux_ops_saved;
+
+ /* Override some methods for multithreading. */
+ t->to_attach = linux_nat_attach;
+ t->to_detach = linux_nat_detach;
+ t->to_resume = linux_nat_resume;
+ t->to_wait = linux_nat_wait;
+ t->to_xfer_partial = linux_nat_xfer_partial;
+ t->to_kill = linux_nat_kill;
+ t->to_mourn_inferior = linux_nat_mourn_inferior;
+ t->to_thread_alive = linux_nat_thread_alive;
+ t->to_pid_to_str = linux_nat_pid_to_str;
+ t->to_has_thread_control = tc_schedlock;
+
+ /* We don't change the stratum; this target will sit at
+ process_stratum and thread_db will set at thread_stratum. This
+ is a little strange, since this is a multi-threaded-capable
+ target, but we want to be on the stack below thread_db, and we
+ also want to be used for single-threaded processes. */
+
+ add_target (t);
+
+ /* TODO: Eliminate this and have libthread_db use
+ find_target_beneath. */
+ thread_db_init (t);
+}
+
+void
_initialize_linux_nat (void)
{
struct sigaction action;
- extern void thread_db_init (struct target_ops *);
add_info ("proc", linux_nat_info_proc_cmd, _("\
Show /proc process information about any running process.\n\
@@ -3349,10 +3182,6 @@ Specify any of the following keywords fo
status -- list a different bunch of random process info.\n\
all -- list all available /proc info."));
- init_linux_nat_ops ();
- add_target (&linux_nat_ops);
- thread_db_init (&linux_nat_ops);
-
/* Save the original signal mask. */
sigprocmask (SIG_SETMASK, NULL, &normal_mask);
Index: src/gdb/linux-nat.h
===================================================================
--- src.orig/gdb/linux-nat.h 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/linux-nat.h 2006-02-27 12:56:19.000000000 -0500
@@ -1,6 +1,6 @@
/* Native debugging support for GNU/Linux (LWP layer).
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@@ -83,3 +83,11 @@ struct lwp_info *iterate_over_lwps (int
/* Create a prototype generic Linux target. The client can override
it with local methods. */
struct target_ops * linux_target (void);
+
+/* Register the customized Linux target. This should be used
+ instead of calling add_target directly. */
+void set_linux_target (struct target_ops *);
+
+/* Update linux-nat internal state when changing from one fork
+ to another. */
+void linux_nat_switch_fork (ptid_t new_ptid);
Index: src/gdb/alpha-linux-nat.c
===================================================================
--- src.orig/gdb/alpha-linux-nat.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/alpha-linux-nat.c 2006-02-27 12:56:21.000000000 -0500
@@ -1,5 +1,5 @@
/* Low level Alpha GNU/Linux interface, for GDB when running native.
- Copyright (C) 2005
+ Copyright (C) 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@@ -28,5 +28,5 @@ void _initialialize_alpha_linux_nat (voi
void
_initialize_alpha_linux_nat (void)
{
- add_target (linux_target ());
+ set_linux_target (linux_target ());
}
Index: src/gdb/amd64-linux-nat.c
===================================================================
--- src.orig/gdb/amd64-linux-nat.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/amd64-linux-nat.c 2006-02-27 12:56:29.000000000 -0500
@@ -1,6 +1,7 @@
/* Native-dependent code for GNU/Linux x86-64.
- Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
Contributed by Jiri Smid, SuSE Labs.
This file is part of GDB.
@@ -399,5 +400,5 @@ _initialize_amd64_linux_nat (void)
t->to_store_registers = amd64_linux_store_inferior_registers;
/* Register the target. */
- add_target (t);
+ set_linux_target (t);
}
Index: src/gdb/arm-linux-nat.c
===================================================================
--- src.orig/gdb/arm-linux-nat.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/arm-linux-nat.c 2006-02-27 12:56:33.000000000 -0500
@@ -1,5 +1,5 @@
/* GNU/Linux on ARM native support.
- Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005
+ Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@@ -736,5 +736,5 @@ _initialize_arm_linux_nat (void)
t->to_store_registers = arm_linux_store_inferior_registers;
/* Register the target. */
- add_target (t);
+ set_linux_target (t);
}
Index: src/gdb/hppa-linux-nat.c
===================================================================
--- src.orig/gdb/hppa-linux-nat.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/hppa-linux-nat.c 2006-02-27 12:56:37.000000000 -0500
@@ -1,6 +1,6 @@
/* Functions specific to running GDB native on HPPA running GNU/Linux.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GDB.
@@ -392,5 +392,5 @@ _initialize_hppa_linux_nat (void)
t->to_store_registers = hppa_linux_store_inferior_registers;
/* Register the target. */
- add_target (t);
+ set_linux_target (t);
}
Index: src/gdb/ia64-linux-nat.c
===================================================================
--- src.orig/gdb/ia64-linux-nat.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/ia64-linux-nat.c 2006-02-27 12:56:40.000000000 -0500
@@ -1,7 +1,7 @@
/* Functions specific to running gdb native on IA-64 running
GNU/Linux.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@@ -700,5 +700,5 @@ _initialize_ia64_linux_nat (void)
t->to_xfer_partial = ia64_linux_xfer_partial;
/* Register the target. */
- add_target (t);
+ set_linux_target (t);
}
Index: src/gdb/m32r-linux-nat.c
===================================================================
--- src.orig/gdb/m32r-linux-nat.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/m32r-linux-nat.c 2006-02-27 12:56:44.000000000 -0500
@@ -1,6 +1,6 @@
/* Native-dependent code for GNU/Linux m32r.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GDB.
@@ -250,5 +250,5 @@ _initialize_m32r_linux_nat (void)
t->to_store_registers = m32r_linux_store_inferior_registers;
/* Register the target. */
- add_target (t);
+ set_linux_target (t);
}
Index: src/gdb/m68klinux-nat.c
===================================================================
--- src.orig/gdb/m68klinux-nat.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/m68klinux-nat.c 2006-02-27 12:56:48.000000000 -0500
@@ -1,6 +1,6 @@
/* Motorola m68k native support for GNU/Linux.
- Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@@ -633,7 +633,7 @@ _initialize_m68k_linux_nat (void)
t->to_store_registers = m68k_linux_store_inferior_registers;
/* Register the target. */
- add_target (t);
+ set_linux_target (t);
deprecated_add_core_fns (&linux_elf_core_fns);
}
Index: src/gdb/mips-linux-nat.c
===================================================================
--- src.orig/gdb/mips-linux-nat.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/mips-linux-nat.c 2006-02-27 12:56:55.000000000 -0500
@@ -1,6 +1,7 @@
/* Native-dependent code for GNU/Linux on MIPS processors.
- Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GDB.
@@ -70,5 +71,5 @@ void _initialize_mips_linux_nat (void);
void
_initialize_mips_linux_nat (void)
{
- add_target (linux_target ());
+ set_linux_target (linux_target ());
}
Index: src/gdb/ppc-linux-nat.c
===================================================================
--- src.orig/gdb/ppc-linux-nat.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/ppc-linux-nat.c 2006-02-27 12:44:45.000000000 -0500
@@ -1037,5 +1037,5 @@ _initialize_ppc_linux_nat (void)
t->to_stopped_data_address = ppc_linux_stopped_data_address;
/* Register the target. */
- add_target (t);
+ set_linux_target (t);
}
Index: src/gdb/s390-nat.c
===================================================================
--- src.orig/gdb/s390-nat.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/s390-nat.c 2006-02-27 12:44:45.000000000 -0500
@@ -388,5 +388,5 @@ _initialize_s390_nat (void)
t->to_remove_watchpoint = s390_remove_watchpoint;
/* Register the target. */
- add_target (t);
+ set_linux_target (t);
}
Index: src/gdb/sparc-linux-nat.c
===================================================================
--- src.orig/gdb/sparc-linux-nat.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/sparc-linux-nat.c 2006-02-27 12:57:02.000000000 -0500
@@ -1,5 +1,5 @@
/* Native-dependent code for GNU/Linux SPARC.
- Copyright (C) 2005
+ Copyright (C) 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@@ -39,5 +39,5 @@ _initialize_sparc_linux_nat (void)
t->to_store_registers = store_inferior_registers;
/* Register the target. */
- add_target (t);
+ set_linux_target (t);
}
Index: src/gdb/sparc64-linux-nat.c
===================================================================
--- src.orig/gdb/sparc64-linux-nat.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/sparc64-linux-nat.c 2006-02-27 12:57:05.000000000 -0500
@@ -1,6 +1,6 @@
/* Native-dependent code for GNU/Linux UltraSPARC.
- Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc.
This file is part of GDB.
@@ -57,7 +57,7 @@ _initialize_sparc64_linux_nat (void)
t->to_store_registers = store_inferior_registers;
/* Register the target. */
- add_target (t);
+ set_linux_target (t);
sparc_gregset = &sparc64_linux_ptrace_gregset;
}
Index: src/gdb/linux-fork.c
===================================================================
--- src.orig/gdb/linux-fork.c 2006-02-27 12:44:42.000000000 -0500
+++ src/gdb/linux-fork.c 2006-02-27 12:44:45.000000000 -0500
@@ -27,6 +27,7 @@
#include "gdb_assert.h"
#include "gdb_string.h"
#include "linux-fork.h"
+#include "linux-nat.h"
#include <sys/ptrace.h>
#include <sys/wait.h>
@@ -85,7 +86,7 @@ add_fork (pid_t pid)
}
fp = XZALLOC (struct fork_info);
- fp->ptid = pid_to_ptid (pid);
+ fp->ptid = ptid_build (pid, pid, 0);
fp->num = ++highest_fork_num;
fp->next = fork_list;
fork_list = fp;
@@ -242,6 +243,8 @@ fork_load_infrun_state (struct fork_info
inferior_ptid = fp->ptid;
+ linux_nat_switch_fork (inferior_ptid);
+
if (fp->savedregs && fp->clobber_regs)
regcache_cpy (current_regcache, fp->savedregs);
Index: src/gdb/Makefile.in
===================================================================
--- src.orig/gdb/Makefile.in 2006-02-27 12:44:41.000000000 -0500
+++ src/gdb/Makefile.in 2006-02-27 14:16:21.000000000 -0500
@@ -2188,7 +2188,8 @@ linespec.o: linespec.c $(defs_h) $(symta
$(completer_h) $(cp_abi_h) $(parser_defs_h) $(block_h) \
$(objc_lang_h) $(linespec_h) $(exceptions_h)
linux-fork.o: linux-fork.c $(defs_h) $(inferior_h) $(regcache_h) $(gdbcmd_h) \
- $(infcall_h) $(gdb_assert_h) $(gdb_string_h) $(linux_fork_h)
+ $(infcall_h) $(gdb_assert_h) $(gdb_string_h) $(linux_fork_h) \
+ $(linux_nat_h)
linux-nat.o: linux-nat.c $(defs_h) $(inferior_h) $(target_h) $(gdb_string_h) \
$(gdb_wait_h) $(gdb_assert_h) $(linux_nat_h) $(gdbthread_h) \
$(gdbcmd_h) $(regcache_h) $(inf_ptrace.h) $(auxv.h) $(elf_bfd_h) \