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 2 of the License, or
+ 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,
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, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "inferior.h"
static struct target_ops *linux_ops;
static struct target_ops linux_ops_saved;
+/* The method to call, if any, when a new thread is attached. */
+static void (*linux_nat_new_thread) (ptid_t);
+
/* The saved to_xfer_partial method, inherited from inf-ptrace.c.
Called by our to_xfer_partial. */
static LONGEST (*super_xfer_partial) (struct target_ops *,
ptrace (PTRACE_SETOPTIONS, pid, 0, options);
}
-void
-child_post_attach (int pid)
+static void
+linux_child_post_attach (int pid)
{
linux_enable_event_reporting (pid_to_ptid (pid));
check_for_thread_db ();
check_for_thread_db ();
}
-int
-child_follow_fork (struct target_ops *ops, int follow_child)
+static int
+linux_child_follow_fork (struct target_ops *ops, int follow_child)
{
ptid_t last_ptid;
struct target_waitstatus last_status;
target_detach (NULL, 0);
}
- inferior_ptid = pid_to_ptid (child_pid);
+ inferior_ptid = ptid_build (child_pid, child_pid, 0);
/* Reinstall ourselves, since we might have been removed in
target_detach (which does other necessary cleanup). */
push_target (ops);
+ linux_nat_switch_fork (inferior_ptid);
/* Reset breakpoints in the child as appropriate. */
follow_inferior_reset_breakpoints ();
}
\f
-void
-child_insert_fork_catchpoint (int pid)
+static void
+linux_child_insert_fork_catchpoint (int pid)
{
if (! linux_supports_tracefork (pid))
error (_("Your system does not support fork catchpoints."));
}
-void
-child_insert_vfork_catchpoint (int pid)
+static void
+linux_child_insert_vfork_catchpoint (int pid)
{
if (!linux_supports_tracefork (pid))
error (_("Your system does not support vfork catchpoints."));
}
-void
-child_insert_exec_catchpoint (int pid)
+static void
+linux_child_insert_exec_catchpoint (int pid)
{
if (!linux_supports_tracefork (pid))
error (_("Your system does not support exec catchpoints."));
because the "zombies" stay around. */
/* List of known LWPs. */
-static struct lwp_info *lwp_list;
+struct lwp_info *lwp_list;
/* Number of LWPs in the list. */
static int num_lwps;
/* Prototypes for local functions. */
static int stop_wait_callback (struct lwp_info *lp, void *data);
static int linux_nat_thread_alive (ptid_t ptid);
+static char *linux_child_pid_to_exec_file (int pid);
\f
/* Convert wait status STATUS to a string. Used for printing debug
messages only. */
}
/* Add the LWP specified by PID to the list. Return a pointer to the
- structure describing the new LWP. */
+ structure describing the new LWP. The LWP should already be stopped
+ (with an exception for the very first LWP). */
static struct lwp_info *
add_lwp (ptid_t ptid)
lwp_list = lp;
++num_lwps;
+ if (num_lwps > 1 && linux_nat_new_thread != NULL)
+ linux_nat_new_thread (ptid);
+
return lp;
}
{
pid_t pid;
int status;
+ int cloned = 0;
if (ptrace (PTRACE_ATTACH, GET_LWP (ptid), 0, 0) < 0)
{
return -1;
}
- if (lp == NULL)
- lp = add_lwp (ptid);
-
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"LLAL: PTRACE_ATTACH %s, 0, 0 (OK)\n",
{
/* Try again with __WCLONE to check cloned processes. */
pid = my_waitpid (GET_LWP (ptid), &status, __WCLONE);
- lp->cloned = 1;
+ cloned = 1;
}
gdb_assert (pid == GET_LWP (ptid)
&& WIFSTOPPED (status) && WSTOPSIG (status));
+ if (lp == NULL)
+ lp = add_lwp (ptid);
+ lp->cloned = cloned;
+
target_post_attach (pid);
lp->stopped = 1;
struct lwp_info *lp;
pid_t pid;
int status;
+ int cloned = 0;
/* FIXME: We should probably accept a list of process id's, and
attach all of them. */
linux_ops->to_attach (args, from_tty);
- /* Add the initial process as the first LWP to the list. */
- 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
work if things haven't stabilized yet. */
/* Try again with __WCLONE to check cloned processes. */
pid = my_waitpid (GET_PID (inferior_ptid), &status, __WCLONE);
- lp->cloned = 1;
+ cloned = 1;
}
gdb_assert (pid == GET_PID (inferior_ptid)
&& WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP);
+ /* Add the initial process as the first LWP to the list. */
+ inferior_ptid = BUILD_LWP (GET_PID (inferior_ptid), GET_PID (inferior_ptid));
+ lp = add_lwp (inferior_ptid);
+ lp->cloned = cloned;
+
lp->stopped = 1;
/* Fake the SIGSTOP that core GDB expects. */
{
if (lp->stopped && lp->status == 0)
{
- struct thread_info *tp;
-
linux_ops->to_resume (pid_to_ptid (GET_LWP (lp->ptid)),
0, TARGET_SIGNAL_0);
if (debug_linux_nat)
target_pid_to_str (lp->ptid));
lp->stopped = 0;
lp->step = 0;
+ memset (&lp->siginfo, 0, sizeof (lp->siginfo));
}
return 0;
ptid = inferior_ptid;
lp = find_lwp_pid (ptid);
- if (lp)
- {
- ptid = pid_to_ptid (GET_LWP (lp->ptid));
+ gdb_assert (lp != NULL);
- /* Remember if we're stepping. */
- lp->step = step;
+ ptid = pid_to_ptid (GET_LWP (lp->ptid));
- /* Mark this LWP as resumed. */
- lp->resumed = 1;
+ /* Remember if we're stepping. */
+ lp->step = step;
- /* If we have a pending wait status for this thread, there is no
- point in resuming the process. But first make sure that
- linux_nat_wait won't preemptively handle the event - we
- should never take this short-circuit if we are going to
- leave LP running, since we have skipped resuming all the
- other threads. This bit of code needs to be synchronized
- with linux_nat_wait. */
+ /* Mark this LWP as resumed. */
+ lp->resumed = 1;
- if (lp->status && WIFSTOPPED (lp->status))
- {
- int saved_signo = target_signal_from_host (WSTOPSIG (lp->status));
+ /* If we have a pending wait status for this thread, there is no
+ point in resuming the process. But first make sure that
+ linux_nat_wait won't preemptively handle the event - we
+ should never take this short-circuit if we are going to
+ leave LP running, since we have skipped resuming all the
+ other threads. This bit of code needs to be synchronized
+ with linux_nat_wait. */
- if (signal_stop_state (saved_signo) == 0
- && signal_print_state (saved_signo) == 0
- && signal_pass_state (saved_signo) == 1)
- {
- if (debug_linux_nat)
- fprintf_unfiltered (gdb_stdlog,
- "LLR: Not short circuiting for ignored "
- "status 0x%x\n", lp->status);
-
- /* FIXME: What should we do if we are supposed to continue
- this thread with a signal? */
- gdb_assert (signo == TARGET_SIGNAL_0);
- signo = saved_signo;
- lp->status = 0;
- }
- }
+ if (lp->status && WIFSTOPPED (lp->status))
+ {
+ int saved_signo = target_signal_from_host (WSTOPSIG (lp->status));
- if (lp->status)
+ if (signal_stop_state (saved_signo) == 0
+ && signal_print_state (saved_signo) == 0
+ && signal_pass_state (saved_signo) == 1)
{
+ if (debug_linux_nat)
+ fprintf_unfiltered (gdb_stdlog,
+ "LLR: Not short circuiting for ignored "
+ "status 0x%x\n", lp->status);
+
/* FIXME: What should we do if we are supposed to continue
this thread with a signal? */
gdb_assert (signo == TARGET_SIGNAL_0);
+ signo = saved_signo;
+ lp->status = 0;
+ }
+ }
- if (debug_linux_nat)
- fprintf_unfiltered (gdb_stdlog,
- "LLR: Short circuiting for status 0x%x\n",
- lp->status);
+ if (lp->status)
+ {
+ /* FIXME: What should we do if we are supposed to continue
+ this thread with a signal? */
+ gdb_assert (signo == TARGET_SIGNAL_0);
- return;
- }
+ if (debug_linux_nat)
+ fprintf_unfiltered (gdb_stdlog,
+ "LLR: Short circuiting for status 0x%x\n",
+ lp->status);
- /* Mark LWP as not stopped to prevent it from being continued by
- resume_callback. */
- lp->stopped = 0;
+ return;
}
+ /* Mark LWP as not stopped to prevent it from being continued by
+ resume_callback. */
+ lp->stopped = 0;
+
if (resume_all)
iterate_over_lwps (resume_callback, NULL);
linux_ops->to_resume (ptid, step, signo);
+ memset (&lp->siginfo, 0, sizeof (lp->siginfo));
+
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"LLR: %s %s, %s (resume event thread)\n",
{
ourstatus->kind = TARGET_WAITKIND_EXECD;
ourstatus->value.execd_pathname
- = xstrdup (child_pid_to_exec_file (pid));
+ = xstrdup (linux_child_pid_to_exec_file (pid));
if (linux_parent_pid)
{
return status;
}
+/* Save the most recent siginfo for LP. This is currently only called
+ for SIGTRAP; some ports use the si_addr field for
+ target_stopped_data_address. In the future, it may also be used to
+ restore the siginfo of requeued signals. */
+
+static void
+save_siginfo (struct lwp_info *lp)
+{
+ errno = 0;
+ ptrace (PTRACE_GETSIGINFO, GET_LWP (lp->ptid),
+ (PTRACE_TYPE_ARG3) 0, &lp->siginfo);
+
+ if (errno != 0)
+ memset (&lp->siginfo, 0, sizeof (lp->siginfo));
+}
+
/* Send a SIGSTOP to LP. */
static int
user will delete or disable the breakpoint, but the
thread will have already tripped on it. */
+ /* Save the trap's siginfo in case we need it later. */
+ save_siginfo (lp);
+
/* Now resume this LWP and get the SIGSTOP event. */
errno = 0;
ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
if (lp->status != 0
&& WIFSTOPPED (lp->status) && WSTOPSIG (lp->status) == SIGTRAP
&& breakpoint_inserted_here_p (read_pc_pid (lp->ptid) -
- DECR_PC_AFTER_BREAK))
+ gdbarch_decr_pc_after_break
+ (current_gdbarch)))
{
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
target_pid_to_str (lp->ptid));
/* Back up the PC if necessary. */
- if (DECR_PC_AFTER_BREAK)
- write_pc_pid (read_pc_pid (lp->ptid) - DECR_PC_AFTER_BREAK, lp->ptid);
+ if (gdbarch_decr_pc_after_break (current_gdbarch))
+ write_pc_pid (read_pc_pid (lp->ptid) - gdbarch_decr_pc_after_break
+ (current_gdbarch),
+ lp->ptid);
/* Throw away the SIGTRAP. */
lp->status = 0;
target_pid_to_str (lp->ptid));
}
+ /* Save the trap's siginfo in case we need it later. */
+ if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP)
+ save_siginfo (lp);
+
/* Handle GNU/Linux's extended waitstatus for trace events. */
if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
{
/* Accepts an integer PID; Returns a string representing a file that
can be opened to get the symbols for the child process. */
-char *
-child_pid_to_exec_file (int pid)
+static char *
+linux_child_pid_to_exec_file (int pid)
{
char *name1, *name2;
gdb_fpxregset_t fpxregs;
#endif
unsigned long lwp = ptid_get_lwp (ptid);
- struct gdbarch *gdbarch = current_gdbarch;
+ struct regcache *regcache = get_thread_regcache (ptid);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
const struct regset *regset;
int core_regset_p;
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_ptid ();
+ inferior_ptid = ptid;
+ target_fetch_registers (regcache, -1);
+ do_cleanups (old_chain);
core_regset_p = gdbarch_regset_from_core_section_p (gdbarch);
if (core_regset_p
&& (regset = gdbarch_regset_from_core_section (gdbarch, ".reg",
sizeof (gregs))) != NULL
&& regset->collect_regset != NULL)
- regset->collect_regset (regset, current_regcache, -1,
+ regset->collect_regset (regset, regcache, -1,
&gregs, sizeof (gregs));
else
- fill_gregset (current_regcache, &gregs, -1);
+ fill_gregset (regcache, &gregs, -1);
note_data = (char *) elfcore_write_prstatus (obfd,
note_data,
&& (regset = gdbarch_regset_from_core_section (gdbarch, ".reg2",
sizeof (fpregs))) != NULL
&& regset->collect_regset != NULL)
- regset->collect_regset (regset, current_regcache, -1,
+ regset->collect_regset (regset, regcache, -1,
&fpregs, sizeof (fpregs));
else
- fill_fpregset (current_regcache, &fpregs, -1);
+ fill_fpregset (regcache, &fpregs, -1);
note_data = (char *) elfcore_write_prfpreg (obfd,
note_data,
&& (regset = gdbarch_regset_from_core_section (gdbarch, ".reg-xfp",
sizeof (fpxregs))) != NULL
&& regset->collect_regset != NULL)
- regset->collect_regset (regset, current_regcache, -1,
+ regset->collect_regset (regset, regcache, -1,
&fpxregs, sizeof (fpxregs));
else
- fill_fpxregset (current_regcache, &fpxregs, -1);
+ fill_fpxregset (regcache, &fpxregs, -1);
note_data = (char *) elfcore_write_prxfpreg (obfd,
note_data,
linux_nat_corefile_thread_callback (struct lwp_info *ti, void *data)
{
struct linux_nat_corefile_thread_data *args = data;
- ptid_t saved_ptid = inferior_ptid;
- inferior_ptid = ti->ptid;
- registers_changed ();
- /* FIXME should not be necessary; fill_gregset should do it automatically. */
- target_fetch_registers (current_regcache, -1);
args->note_data = linux_nat_do_thread_registers (args->obfd,
ti->ptid,
args->note_data,
args->note_size);
args->num_notes++;
- inferior_ptid = saved_ptid;
- registers_changed ();
- /* FIXME should not be necessary; fill_gregset should do it automatically. */
- target_fetch_registers (current_regcache, -1);
return 0;
}
linux_nat_do_registers (bfd *obfd, ptid_t ptid,
char *note_data, int *note_size)
{
- registers_changed ();
- /* FIXME should not be necessary; fill_gregset should do it automatically. */
- target_fetch_registers (current_regcache, -1);
return linux_nat_do_thread_registers (obfd,
ptid_build (ptid_get_pid (inferior_ptid),
ptid_get_pid (inferior_ptid),
0),
note_data, note_size);
- return note_data;
}
/* Fills the "to_make_corefile_note" target vector. Builds the note
{
struct linux_nat_corefile_thread_data thread_args;
struct cleanup *old_chain;
+ /* The variable size must be >= sizeof (prpsinfo_t.pr_fname). */
char fname[16] = { '\0' };
+ /* The variable size must be >= sizeof (prpsinfo_t.pr_psargs). */
char psargs[80] = { '\0' };
char *note_data = NULL;
ptid_t current_ptid = inferior_ptid;
strncpy (psargs, get_exec_file (0), sizeof (psargs));
if (get_inferior_args ())
{
- strncat (psargs, " ", sizeof (psargs) - strlen (psargs));
- strncat (psargs, get_inferior_args (),
- sizeof (psargs) - strlen (psargs));
+ char *string_end;
+ char *psargs_end = psargs + sizeof (psargs);
+
+ /* linux_elfcore_write_prpsinfo () handles zero unterminated
+ strings fine. */
+ string_end = memchr (psargs, 0, sizeof (psargs));
+ if (string_end != NULL)
+ {
+ *string_end++ = ' ';
+ strncpy (string_end, get_inferior_args (),
+ psargs_end - string_end);
+ }
}
note_data = (char *) elfcore_write_prpsinfo (obfd,
note_data,
char permissions[8], device[8], filename[MAXPATHLEN];
printf_filtered (_("Mapped address spaces:\n\n"));
- if (TARGET_ADDR_BIT == 32)
+ if (gdbarch_addr_bit (current_gdbarch) == 32)
{
printf_filtered ("\t%10s %10s %10s %10s %7s\n",
"Start Addr",
a generic local_address_string instead to print out
the addresses; that makes sense to me, too. */
- if (TARGET_ADDR_BIT == 32)
+ if (gdbarch_addr_bit (current_gdbarch) == 32)
{
printf_filtered ("\t%#10lx %#10lx %#10x %#10x %7s\n",
(unsigned long) addr, /* FIXME: pr_addr */
{
int itmp;
char ctmp;
+ long ltmp;
if (fscanf (procfile, "%d ", &itmp) > 0)
printf_filtered (_("Process: %d\n"), itmp);
- if (fscanf (procfile, "%s ", &buffer[0]) > 0)
+ if (fscanf (procfile, "(%[^)]) ", &buffer[0]) > 0)
printf_filtered (_("Exec file: %s\n"), buffer);
if (fscanf (procfile, "%c ", &ctmp) > 0)
printf_filtered (_("State: %c\n"), ctmp);
printf_filtered (_("TTY: %d\n"), itmp);
if (fscanf (procfile, "%d ", &itmp) > 0)
printf_filtered (_("TTY owner process group: %d\n"), itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0)
- printf_filtered (_("Flags: 0x%x\n"), itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0)
- printf_filtered (_("Minor faults (no memory page): %u\n"),
- (unsigned int) itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0)
- printf_filtered (_("Minor faults, children: %u\n"),
- (unsigned int) itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0)
- printf_filtered (_("Major faults (memory page faults): %u\n"),
- (unsigned int) itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0)
- printf_filtered (_("Major faults, children: %u\n"),
- (unsigned int) itmp);
- if (fscanf (procfile, "%d ", &itmp) > 0)
- printf_filtered ("utime: %d\n", itmp);
- if (fscanf (procfile, "%d ", &itmp) > 0)
- printf_filtered ("stime: %d\n", itmp);
- if (fscanf (procfile, "%d ", &itmp) > 0)
- printf_filtered ("utime, children: %d\n", itmp);
- if (fscanf (procfile, "%d ", &itmp) > 0)
- printf_filtered ("stime, children: %d\n", itmp);
- if (fscanf (procfile, "%d ", &itmp) > 0)
- printf_filtered (_("jiffies remaining in current time slice: %d\n"),
- itmp);
- if (fscanf (procfile, "%d ", &itmp) > 0)
- printf_filtered ("'nice' value: %d\n", itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0)
- printf_filtered (_("jiffies until next timeout: %u\n"),
- (unsigned int) itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0)
- printf_filtered ("jiffies until next SIGALRM: %u\n",
- (unsigned int) itmp);
- if (fscanf (procfile, "%d ", &itmp) > 0)
- printf_filtered (_("start time (jiffies since system boot): %d\n"),
- itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0)
- printf_filtered (_("Virtual memory size: %u\n"),
- (unsigned int) itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0)
- printf_filtered (_("Resident set size: %u\n"), (unsigned int) itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0)
- printf_filtered ("rlim: %u\n", (unsigned int) itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0)
- printf_filtered (_("Start of text: 0x%x\n"), itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0)
- printf_filtered (_("End of text: 0x%x\n"), itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0)
- printf_filtered (_("Start of stack: 0x%x\n"), itmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0)
+ printf_filtered (_("Flags: 0x%lx\n"), ltmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0)
+ printf_filtered (_("Minor faults (no memory page): %lu\n"),
+ (unsigned long) ltmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0)
+ printf_filtered (_("Minor faults, children: %lu\n"),
+ (unsigned long) ltmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0)
+ printf_filtered (_("Major faults (memory page faults): %lu\n"),
+ (unsigned long) ltmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0)
+ printf_filtered (_("Major faults, children: %lu\n"),
+ (unsigned long) ltmp);
+ if (fscanf (procfile, "%ld ", <mp) > 0)
+ printf_filtered (_("utime: %ld\n"), ltmp);
+ if (fscanf (procfile, "%ld ", <mp) > 0)
+ printf_filtered (_("stime: %ld\n"), ltmp);
+ if (fscanf (procfile, "%ld ", <mp) > 0)
+ printf_filtered (_("utime, children: %ld\n"), ltmp);
+ if (fscanf (procfile, "%ld ", <mp) > 0)
+ printf_filtered (_("stime, children: %ld\n"), ltmp);
+ if (fscanf (procfile, "%ld ", <mp) > 0)
+ printf_filtered (_("jiffies remaining in current time slice: %ld\n"),
+ ltmp);
+ if (fscanf (procfile, "%ld ", <mp) > 0)
+ printf_filtered (_("'nice' value: %ld\n"), ltmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0)
+ printf_filtered (_("jiffies until next timeout: %lu\n"),
+ (unsigned long) ltmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0)
+ printf_filtered (_("jiffies until next SIGALRM: %lu\n"),
+ (unsigned long) ltmp);
+ if (fscanf (procfile, "%ld ", <mp) > 0)
+ printf_filtered (_("start time (jiffies since system boot): %ld\n"),
+ ltmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0)
+ printf_filtered (_("Virtual memory size: %lu\n"),
+ (unsigned long) ltmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0)
+ printf_filtered (_("Resident set size: %lu\n"), (unsigned long) ltmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0)
+ printf_filtered (_("rlim: %lu\n"), (unsigned long) ltmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0)
+ printf_filtered (_("Start of text: 0x%lx\n"), ltmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0)
+ printf_filtered (_("End of text: 0x%lx\n"), ltmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0)
+ printf_filtered (_("Start of stack: 0x%lx\n"), ltmp);
#if 0 /* Don't know how architecture-dependent the rest is...
Anyway the signal bitmap info is available from "status". */
- if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
- printf_filtered (_("Kernel stack pointer: 0x%x\n"), itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
- printf_filtered (_("Kernel instr pointer: 0x%x\n"), itmp);
- if (fscanf (procfile, "%d ", &itmp) > 0)
- printf_filtered (_("Pending signals bitmap: 0x%x\n"), itmp);
- if (fscanf (procfile, "%d ", &itmp) > 0)
- printf_filtered (_("Blocked signals bitmap: 0x%x\n"), itmp);
- if (fscanf (procfile, "%d ", &itmp) > 0)
- printf_filtered (_("Ignored signals bitmap: 0x%x\n"), itmp);
- if (fscanf (procfile, "%d ", &itmp) > 0)
- printf_filtered (_("Catched signals bitmap: 0x%x\n"), itmp);
- if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
- printf_filtered (_("wchan (system call): 0x%x\n"), itmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0) /* FIXME arch? */
+ printf_filtered (_("Kernel stack pointer: 0x%lx\n"), ltmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0) /* FIXME arch? */
+ printf_filtered (_("Kernel instr pointer: 0x%lx\n"), ltmp);
+ if (fscanf (procfile, "%ld ", <mp) > 0)
+ printf_filtered (_("Pending signals bitmap: 0x%lx\n"), ltmp);
+ if (fscanf (procfile, "%ld ", <mp) > 0)
+ printf_filtered (_("Blocked signals bitmap: 0x%lx\n"), ltmp);
+ if (fscanf (procfile, "%ld ", <mp) > 0)
+ printf_filtered (_("Ignored signals bitmap: 0x%lx\n"), ltmp);
+ if (fscanf (procfile, "%ld ", <mp) > 0)
+ printf_filtered (_("Catched signals bitmap: 0x%lx\n"), ltmp);
+ if (fscanf (procfile, "%lu ", <mp) > 0) /* FIXME arch? */
+ printf_filtered (_("wchan (system call): 0x%lx\n"), ltmp);
#endif
fclose (procfile);
}
static void
linux_target_install_ops (struct target_ops *t)
{
- 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;
- t->to_pid_to_exec_file = child_pid_to_exec_file;
+ t->to_insert_fork_catchpoint = linux_child_insert_fork_catchpoint;
+ t->to_insert_vfork_catchpoint = linux_child_insert_vfork_catchpoint;
+ t->to_insert_exec_catchpoint = linux_child_insert_exec_catchpoint;
+ t->to_pid_to_exec_file = linux_child_pid_to_exec_file;
t->to_post_startup_inferior = linux_child_post_startup_inferior;
- t->to_post_attach = child_post_attach;
- t->to_follow_fork = child_follow_fork;
+ t->to_post_attach = linux_child_post_attach;
+ t->to_follow_fork = linux_child_follow_fork;
t->to_find_memory_regions = linux_nat_find_memory_regions;
t->to_make_corefile_notes = linux_nat_make_corefile_notes;
}
struct target_ops *
-linux_trad_target (CORE_ADDR (*register_u_offset)(int))
+linux_trad_target (CORE_ADDR (*register_u_offset)(struct gdbarch *, int, int))
{
struct target_ops *t;
thread_db_init (t);
}
+/* Register a method to call whenever a new thread is attached. */
+void
+linux_nat_set_new_thread (struct target_ops *t, void (*new_thread) (ptid_t))
+{
+ /* Save the pointer. We only support a single registered instance
+ of the GNU/Linux native target, so we do not need to map this to
+ T. */
+ linux_nat_new_thread = new_thread;
+}
+
+/* Return the saved siginfo associated with PTID. */
+struct siginfo *
+linux_nat_get_siginfo (ptid_t ptid)
+{
+ struct lwp_info *lp = find_lwp_pid (ptid);
+
+ gdb_assert (lp != NULL);
+
+ return &lp->siginfo;
+}
+
void
_initialize_linux_nat (void)
{