X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Flinux-nat.c;h=b79e40fe0fc797702cd5833e46913c8d7f187a47;hb=82cf6c60c4bc7bb2d18eed69d5f61bfddde6e4f8;hp=0162e7e1686b9dd38119e8ceae52de9c44cb25a2;hpb=6aba47ca06d9150c6196a374b745c2711b46e045;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 0162e7e168..b79e40fe0f 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -1,13 +1,13 @@ /* GNU/Linux native-dependent code common to multiple platforms. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. 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 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, @@ -16,9 +16,7 @@ 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 . */ #include "defs.h" #include "inferior.h" @@ -86,11 +84,18 @@ #define __WALL 0x40000000 /* Wait for any child. */ #endif +#ifndef PTRACE_GETSIGINFO +#define PTRACE_GETSIGINFO 0x4202 +#endif + /* 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 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 *, @@ -335,8 +340,8 @@ linux_enable_event_reporting (ptid_t ptid) 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 (); @@ -349,8 +354,8 @@ linux_child_post_startup_inferior (ptid_t ptid) 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; @@ -505,12 +510,14 @@ child_follow_fork (struct target_ops *ops, int follow_child) 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); + check_for_thread_db (); /* Reset breakpoints in the child as appropriate. */ follow_inferior_reset_breakpoints (); @@ -520,22 +527,22 @@ child_follow_fork (struct target_ops *ops, int follow_child) } -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.")); @@ -575,7 +582,7 @@ child_insert_exec_catchpoint (int pid) 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; @@ -616,6 +623,7 @@ static sigset_t blocked_mask; /* 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); /* Convert wait status STATUS to a string. Used for printing debug messages only. */ @@ -658,7 +666,8 @@ init_lwp_list (void) } /* 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) @@ -679,6 +688,9 @@ 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; } @@ -885,12 +897,13 @@ lin_lwp_attach_lwp (ptid_t ptid, int verbose) { pid_t pid; int status; + int cloned = 0; if (ptrace (PTRACE_ATTACH, GET_LWP (ptid), 0, 0) < 0) { /* If we fail to attach to the thread, issue a warning, but continue. One way this can happen is if thread - creation is interrupted; as of Linux 2.6.19, a kernel + creation is interrupted; as of Linux kernel 2.6.19, a bug may place threads in the thread list and then fail to create them. */ warning (_("Can't attach %s: %s"), target_pid_to_str (ptid), @@ -898,9 +911,6 @@ lin_lwp_attach_lwp (ptid_t ptid, int verbose) 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", @@ -911,12 +921,16 @@ lin_lwp_attach_lwp (ptid_t ptid, int verbose) { /* 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; @@ -954,15 +968,12 @@ linux_nat_attach (char *args, int from_tty) 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. */ @@ -973,12 +984,17 @@ linux_nat_attach (char *args, int from_tty) /* 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. */ @@ -1078,8 +1094,6 @@ resume_callback (struct lwp_info *lp, void *data) { 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) @@ -1088,6 +1102,7 @@ resume_callback (struct lwp_info *lp, void *data) target_pid_to_str (lp->ptid)); lp->stopped = 0; lp->step = 0; + memset (&lp->siginfo, 0, sizeof (lp->siginfo)); } return 0; @@ -1137,68 +1152,69 @@ linux_nat_resume (ptid_t ptid, int step, enum target_signal signo) 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", @@ -1325,7 +1341,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status, { 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) { @@ -1417,6 +1433,22 @@ wait_lwp (struct lwp_info *lp) 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 @@ -1502,6 +1534,9 @@ stop_wait_callback (struct lwp_info *lp, void *data) 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); @@ -1766,7 +1801,8 @@ cancel_breakpoints_callback (struct lwp_info *lp, void *data) 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, @@ -1774,8 +1810,10 @@ cancel_breakpoints_callback (struct lwp_info *lp, void *data) 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; @@ -2056,6 +2094,10 @@ retry: 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) { @@ -2463,8 +2505,8 @@ sigchld_handler (int signo) /* 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; @@ -2553,7 +2595,7 @@ linux_nat_find_memory_regions (int (*func) (CORE_ADDR, size, paddr_nz (addr), read ? 'r' : ' ', write ? 'w' : ' ', exec ? 'x' : ' '); - if (filename && filename[0]) + if (filename[0]) fprintf_filtered (gdb_stdout, " for %s", filename); fprintf_filtered (gdb_stdout, "\n"); } @@ -2579,19 +2621,26 @@ linux_nat_do_thread_registers (bfd *obfd, ptid_t ptid, 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 (&gregs, -1); + fill_gregset (regcache, &gregs, -1); note_data = (char *) elfcore_write_prstatus (obfd, note_data, @@ -2603,10 +2652,10 @@ linux_nat_do_thread_registers (bfd *obfd, ptid_t ptid, && (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 (&fpregs, -1); + fill_fpregset (regcache, &fpregs, -1); note_data = (char *) elfcore_write_prfpreg (obfd, note_data, @@ -2618,10 +2667,10 @@ linux_nat_do_thread_registers (bfd *obfd, ptid_t ptid, && (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 (&fpxregs, -1); + fill_fpxregset (regcache, &fpxregs, -1); note_data = (char *) elfcore_write_prxfpreg (obfd, note_data, @@ -2646,21 +2695,13 @@ static int 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 (); - target_fetch_registers (-1); /* FIXME should not be necessary; - fill_gregset should do it automatically. */ 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 (); - target_fetch_registers (-1); /* FIXME should not be necessary; - fill_gregset should do it automatically. */ + return 0; } @@ -2670,15 +2711,11 @@ static char * linux_nat_do_registers (bfd *obfd, ptid_t ptid, char *note_data, int *note_size) { - registers_changed (); - target_fetch_registers (-1); /* FIXME should not be necessary; - fill_gregset should do it automatically. */ 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 @@ -2689,7 +2726,9 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size) { 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; @@ -2702,9 +2741,18 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size) 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, @@ -2857,7 +2905,7 @@ linux_nat_info_proc_cmd (char *args, int from_tty) 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", @@ -2883,7 +2931,7 @@ linux_nat_info_proc_cmd (char *args, int from_tty) 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 */ @@ -2927,10 +2975,11 @@ linux_nat_info_proc_cmd (char *args, int from_tty) { 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); @@ -2944,71 +2993,71 @@ linux_nat_info_proc_cmd (char *args, int from_tty) 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); } @@ -3164,47 +3213,44 @@ linux_xfer_partial (struct target_ops *ops, enum target_object object, offset, len); } -#ifndef FETCH_INFERIOR_REGISTERS - -/* Return the address in the core dump or inferior of register - REGNO. */ +/* Create a prototype generic GNU/Linux target. The client can override + it with local methods. */ -static CORE_ADDR -linux_register_u_offset (int regno) +static void +linux_target_install_ops (struct target_ops *t) { - /* FIXME drow/2005-09-04: The hardcoded use of register_addr should go - away. This requires disentangling the various definitions of it - (particularly alpha-nat.c's). */ - return register_addr (regno, 0); -} - -#endif + 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 = 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; -/* Create a prototype generic Linux target. The client can override - it with local methods. */ + super_xfer_partial = t->to_xfer_partial; + t->to_xfer_partial = linux_xfer_partial; +} struct target_ops * linux_target (void) { struct target_ops *t; -#ifdef FETCH_INFERIOR_REGISTERS t = inf_ptrace_target (); -#else - t = inf_ptrace_trad_target (linux_register_u_offset); -#endif - 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_post_startup_inferior = linux_child_post_startup_inferior; - t->to_post_attach = child_post_attach; - t->to_follow_fork = child_follow_fork; - t->to_find_memory_regions = linux_nat_find_memory_regions; - t->to_make_corefile_notes = linux_nat_make_corefile_notes; + linux_target_install_ops (t); - super_xfer_partial = t->to_xfer_partial; - t->to_xfer_partial = linux_xfer_partial; + return t; +} + +struct target_ops * +linux_trad_target (CORE_ADDR (*register_u_offset)(struct gdbarch *, int, int)) +{ + struct target_ops *t; + + t = inf_ptrace_trad_target (register_u_offset); + linux_target_install_ops (t); return t; } @@ -3244,6 +3290,27 @@ linux_nat_add_target (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) {