X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Flinux-nat.c;h=584bffa6c5e4e9acc5fc6f39bf0ec59c4514f3eb;hb=97725dc4f67140bd0b914a4cb9b92fe94799509c;hp=a60d8e0cacac2e7013c9bdea3fd0fb9dc8793534;hpb=9c0dd46b95f82899ba2648fb6c1e7561382098dc;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index a60d8e0cac..584bffa6c5 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -36,6 +36,7 @@ #include "gdbthread.h" #include "gdbcmd.h" #include "regcache.h" +#include "regset.h" #include "inf-ptrace.h" #include "auxv.h" #include /* for MAXPATHLEN */ @@ -275,6 +276,7 @@ linux_test_for_tracefork (int original_pid) ret = ptrace (PTRACE_KILL, second_pid, 0, 0); if (ret != 0) warning (_("linux_test_for_tracefork: failed to kill second child")); + my_waitpid (second_pid, &status, 0); } } else @@ -899,10 +901,13 @@ exit_lwp (struct lwp_info *lp) struct thread_info *thr; thr = iterate_over_threads (find_thread_from_lwp, &lp->ptid); - if (thr && !ptid_equal (thr->ptid, inferior_ptid)) - delete_thread (thr->ptid); - else - record_dead_thread (thr->ptid); + if (thr) + { + if (!ptid_equal (thr->ptid, inferior_ptid)) + delete_thread (thr->ptid); + else + record_dead_thread (thr->ptid); + } } delete_lwp (lp->ptid); @@ -1278,10 +1283,11 @@ kill_lwp (int lwpid, int signo) just pass off to linux_handle_extended_wait, but if it reports a clone event we need to add the new LWP to our list (and not report the trap to higher layers). This function returns non-zero if - the event should be ignored and we should wait again. */ + the event should be ignored and we should wait again. If STOPPING + is true, the new LWP remains stopped, otherwise it is continued. */ static int -linux_nat_handle_extended (struct lwp_info *lp, int status) +linux_nat_handle_extended (struct lwp_info *lp, int status, int stopping) { linux_handle_extended_wait (GET_LWP (lp->ptid), status, &lp->waitstatus); @@ -1293,7 +1299,11 @@ linux_nat_handle_extended (struct lwp_info *lp, int status) new_lp = add_lwp (BUILD_LWP (lp->waitstatus.value.related_pid, GET_PID (inferior_ptid))); new_lp->cloned = 1; - new_lp->stopped = 1; + + if (stopping) + new_lp->stopped = 1; + else + ptrace (PTRACE_CONT, lp->waitstatus.value.related_pid, 0, 0); lp->waitstatus.kind = TARGET_WAITKIND_IGNORE; @@ -1377,7 +1387,7 @@ wait_lwp (struct lwp_info *lp) fprintf_unfiltered (gdb_stdlog, "WL: Handling extended status 0x%06x\n", status); - if (linux_nat_handle_extended (lp, status)) + if (linux_nat_handle_extended (lp, status, 1)) return wait_lwp (lp); } @@ -2022,7 +2032,7 @@ retry: fprintf_unfiltered (gdb_stdlog, "LLW: Handling extended status 0x%06x\n", status); - if (linux_nat_handle_extended (lp, status)) + if (linux_nat_handle_extended (lp, status, 0)) { status = 0; continue; @@ -2154,7 +2164,10 @@ retry: { int signo = target_signal_from_host (WSTOPSIG (status)); - if (signal_stop_state (signo) == 0 + /* If we get a signal while single-stepping, we may need special + care, e.g. to skip the signal handler. Defer to common code. */ + if (!lp->step + && signal_stop_state (signo) == 0 && signal_print_state (signo) == 0 && signal_pass_state (signo) == 1) { @@ -2388,7 +2401,7 @@ linux_nat_thread_alive (ptid_t ptid) will first do a lookup for the process based upon the passed-in pid. If that fails we will get either -ESRCH or -EPERM, otherwise the child exists and is alive. */ - if (errno == -ESRCH || errno == -EPERM) + if (errno == ESRCH || errno == EPERM) return 0; return 1; @@ -2535,21 +2548,50 @@ 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; + const struct regset *regset; + int core_regset_p; + + 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, + &gregs, sizeof (gregs)); + else + fill_gregset (&gregs, -1); - fill_gregset (&gregs, -1); note_data = (char *) elfcore_write_prstatus (obfd, note_data, note_size, lwp, stop_signal, &gregs); - fill_fpregset (&fpregs, -1); + if (core_regset_p + && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg2", + sizeof (fpregs))) != NULL + && regset->collect_regset != NULL) + regset->collect_regset (regset, current_regcache, -1, + &fpregs, sizeof (fpregs)); + else + fill_fpregset (&fpregs, -1); + note_data = (char *) elfcore_write_prfpreg (obfd, note_data, note_size, &fpregs, sizeof (fpregs)); + #ifdef FILL_FPXREGSET - fill_fpxregset (&fpxregs, -1); + if (core_regset_p + && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg-xfp", + sizeof (fpxregs))) != NULL + && regset->collect_regset != NULL) + regset->collect_regset (regset, current_regcache, -1, + &fpxregs, sizeof (fpxregs)); + else + fill_fpxregset (&fpxregs, -1); + note_data = (char *) elfcore_write_prxfpreg (obfd, note_data, note_size, @@ -2656,7 +2698,8 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size) note_data = thread_args.note_data; } - auxv_len = target_auxv_read (¤t_target, &auxv); + auxv_len = target_read_alloc (¤t_target, TARGET_OBJECT_AUXV, + NULL, &auxv); if (auxv_len > 0) { note_data = elfcore_write_note (obfd, note_data, note_size, @@ -3138,8 +3181,6 @@ linux_target (void) 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