* 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.
	(linux_nat_add_target): New.
	(_initialize_linux_nat): Don't initialize the linux native target
	here.
	* linux-nat.h (linux_nat_add_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
	linux_nat_add_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.
This commit is contained in:
Daniel Jacobowitz 2006-03-24 23:08:16 +00:00
parent 57b126a363
commit f973ed9c9f
18 changed files with 205 additions and 321 deletions

View File

@ -1,3 +1,47 @@
2006-03-24 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.
(linux_nat_add_target): New.
(_initialize_linux_nat): Don't initialize the linux native target
here.
* linux-nat.h (linux_nat_add_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
linux_nat_add_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.
2006-03-24 Daniel Jacobowitz <dan@codesourcery.com>
* linux-fork.c: Include "gdb_assert.h".

View File

@ -2190,7 +2190,8 @@ linespec.o: linespec.c $(defs_h) $(symtab_h) $(frame_h) $(command_h) \
$(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) \

View File

@ -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 (void);
void
_initialize_alpha_linux_nat (void)
{
add_target (linux_target ());
linux_nat_add_target (linux_target ());
}

View File

@ -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);
linux_nat_add_target (t);
}

View File

@ -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);
linux_nat_add_target (t);
}

View File

@ -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);
linux_nat_add_target (t);
}

View File

@ -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);
linux_nat_add_target (t);
}

View File

@ -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);
linux_nat_add_target (t);
}

View File

@ -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>
@ -84,7 +85,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;
@ -241,6 +242,8 @@ fork_load_infrun_state (struct fork_info *fp)
inferior_ptid = fp->ptid;
linux_nat_switch_fork (inferior_ptid);
if (fp->savedregs && fp->clobber_regs)
regcache_cpy (current_regcache, fp->savedregs);

View File

@ -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) (struct target_ops *,
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,54 +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 ();
}
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
@ -686,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)
@ -701,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
@ -768,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)
@ -792,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;
}
@ -814,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)
@ -867,6 +805,21 @@ iterate_over_lwps (int (*callback) (struct lwp_info *, void *), void *data)
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
@ -1046,7 +999,8 @@ linux_nat_attach (char *args, int from_tty)
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
@ -1848,134 +1802,6 @@ resumed_callback (struct lwp_info *lp, void *data)
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
@ -2007,6 +1833,19 @@ linux_nat_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
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. */
@ -2018,9 +1857,8 @@ linux_nat_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
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)
@ -2159,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))
{
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);
}
add_thread (lp->ptid);
printf_unfiltered (_("[New %s]\n"),
target_pid_to_str (lp->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. */
@ -2377,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",
@ -2399,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
@ -2464,22 +2296,37 @@ kill_wait_callback (struct lwp_info *lp, void *data)
static void
linux_nat_kill (void)
{
/* Kill all LWP's ... */
iterate_over_lwps (kill_callback, NULL);
struct target_waitstatus last;
ptid_t last_ptid;
int status;
/* ... and wait until we've flushed all events. */
iterate_over_lwps (kill_wait_callback, NULL);
/* 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);
}
if (forks_exist_p ())
linux_fork_killall ();
else
{
/* Kill all LWP's ... */
iterate_over_lwps (kill_callback, NULL);
/* ... and wait until we've flushed all events. */
iterate_over_lwps (kill_wait_callback, NULL);
}
target_mourn_inferior ();
}
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)
{
@ -2492,7 +2339,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
@ -2537,7 +2391,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;
@ -2546,59 +2400,6 @@ linux_nat_pid_to_str (ptid_t ptid)
return normal_pid_to_str (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)
{
@ -3310,8 +3111,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;
@ -3325,18 +3124,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
linux_nat_add_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\
@ -3347,10 +3178,6 @@ Specify any of the following keywords for detailed info:\n\
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);

View File

@ -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 (*callback) (struct lwp_info *,
/* 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 linux_nat_add_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);

View File

@ -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);
linux_nat_add_target (t);
}

View File

@ -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);
linux_nat_add_target (t);
deprecated_add_core_fns (&linux_elf_core_fns);
}

View File

@ -259,5 +259,5 @@ _initialize_mips_linux_nat (void)
t->to_fetch_registers = mips64_linux_fetch_registers;
t->to_store_registers = mips64_linux_store_registers;
add_target (t);
linux_nat_add_target (t);
}

View File

@ -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);
linux_nat_add_target (t);
}

View File

@ -388,5 +388,5 @@ _initialize_s390_nat (void)
t->to_remove_watchpoint = s390_remove_watchpoint;
/* Register the target. */
add_target (t);
linux_nat_add_target (t);
}

View File

@ -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);
linux_nat_add_target (t);
}

View File

@ -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);
linux_nat_add_target (t);
sparc_gregset = &sparc64_linux_ptrace_gregset;
}