X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Flinux-nat.c;h=64015e75207939f29d3cf499e6f3c1463b8b83e6;hb=09ce46f230fee766c386384cd1f5672d12fde276;hp=dd5c6d2c4dae80f4f520be944fb446f465cb1c2b;hpb=61baf725eca99af2569262d10aca03dcde2698f6;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index dd5c6d2c4d..64015e7520 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -1,6 +1,6 @@ /* GNU/Linux native-dependent code common to multiple platforms. - Copyright (C) 2001-2017 Free Software Foundation, Inc. + Copyright (C) 2001-2018 Free Software Foundation, Inc. This file is part of GDB. @@ -186,42 +186,11 @@ leader. */ #define O_LARGEFILE 0 #endif +struct linux_nat_target *linux_target; + /* Does the current host support PTRACE_GETREGSET? */ enum tribool have_ptrace_getregset = TRIBOOL_UNKNOWN; -/* 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) (struct lwp_info *); - -/* The method to call, if any, when a new fork is attached. */ -static linux_nat_new_fork_ftype *linux_nat_new_fork; - -/* The method to call, if any, when a process is no longer - attached. */ -static linux_nat_forget_process_ftype *linux_nat_forget_process_hook; - -/* Hook to call prior to resuming a thread. */ -static void (*linux_nat_prepare_to_resume) (struct lwp_info *); - -/* The method to call, if any, when the siginfo object needs to be - converted between the layout returned by ptrace, and the layout in - the architecture of the inferior. */ -static int (*linux_nat_siginfo_fixup) (siginfo_t *, - gdb_byte *, - int); - -/* The saved to_xfer_partial method, inherited from inf-ptrace.c. - Called by our to_xfer_partial. */ -static target_xfer_partial_ftype *super_xfer_partial; - -/* The saved to_close method, inherited from inf-ptrace.c. - Called by our to_close. */ -static void (*super_close) (struct target_ops *); - static unsigned int debug_linux_nat; static void show_debug_linux_nat (struct ui_file *file, int from_tty, @@ -306,9 +275,6 @@ static struct lwp_info *find_lwp_pid (ptid_t ptid); static int lwp_status_pending_p (struct lwp_info *lp); -static int sigtrap_is_event (int status); -static int (*linux_nat_status_is_event) (int status) = sigtrap_is_event; - static void save_stop_reason (struct lwp_info *lp); @@ -414,30 +380,34 @@ linux_nat_ptrace_options (int attached) return options; } -/* Initialize ptrace warnings and check for supported ptrace - features given PID. +/* Initialize ptrace and procfs warnings and check for supported + ptrace features given PID. ATTACHED should be nonzero iff we attached to the inferior. */ static void -linux_init_ptrace (pid_t pid, int attached) +linux_init_ptrace_procfs (pid_t pid, int attached) { int options = linux_nat_ptrace_options (attached); linux_enable_event_reporting (pid, options); linux_ptrace_init_warnings (); + linux_proc_init_warnings (); } -static void -linux_child_post_attach (struct target_ops *self, int pid) +linux_nat_target::~linux_nat_target () +{} + +void +linux_nat_target::post_attach (int pid) { - linux_init_ptrace (pid, 1); + linux_init_ptrace_procfs (pid, 1); } -static void -linux_child_post_startup_inferior (struct target_ops *self, ptid_t ptid) +void +linux_nat_target::post_startup_inferior (ptid_t ptid) { - linux_init_ptrace (ptid_get_pid (ptid), 0); + linux_init_ptrace_procfs (ptid.pid (), 0); } /* Return the number of known LWPs in the tgid given by PID. */ @@ -449,7 +419,7 @@ num_lwps (int pid) struct lwp_info *lp; for (lp = lwp_list; lp; lp = lp->next) - if (ptid_get_pid (lp->ptid) == pid) + if (lp->ptid.pid () == pid) count++; return count; @@ -469,15 +439,12 @@ delete_lwp_cleanup (void *lp_voidp) ptid of the followed inferior. At return, inferior_ptid will be unchanged. */ -static int -linux_child_follow_fork (struct target_ops *ops, int follow_child, - int detach_fork) +int +linux_nat_target::follow_fork (int follow_child, int detach_fork) { if (!follow_child) { struct lwp_info *child_lp = NULL; - int status = W_STOPCODE (0); - struct cleanup *old_chain; int has_vforked; ptid_t parent_ptid, child_ptid; int parent_pid, child_pid; @@ -486,23 +453,23 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child, == TARGET_WAITKIND_VFORKED); parent_ptid = inferior_ptid; child_ptid = inferior_thread ()->pending_follow.value.related_pid; - parent_pid = ptid_get_lwp (parent_ptid); - child_pid = ptid_get_lwp (child_ptid); + parent_pid = parent_ptid.lwp (); + child_pid = child_ptid.lwp (); /* We're already attached to the parent, by default. */ - old_chain = save_inferior_ptid (); - inferior_ptid = child_ptid; - child_lp = add_lwp (inferior_ptid); + child_lp = add_lwp (child_ptid); child_lp->stopped = 1; child_lp->last_resume_kind = resume_stop; /* Detach new forked process? */ if (detach_fork) { - make_cleanup (delete_lwp_cleanup, child_lp); + int child_stop_signal = 0; + bool detach_child = true; + struct cleanup *old_chain = make_cleanup (delete_lwp_cleanup, + child_lp); - if (linux_nat_prepare_to_resume != NULL) - linux_nat_prepare_to_resume (child_lp); + linux_target->low_prepare_to_resume (child_lp); /* When debugging an inferior in an architecture that supports hardware single stepping on a kernel without commit @@ -512,38 +479,48 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child, To work around this, single step the child process once before detaching to clear the flags. */ + /* Note that we consult the parent's architecture instead of + the child's because there's no inferior for the child at + this point. */ if (!gdbarch_software_single_step_p (target_thread_architecture - (child_lp->ptid))) + (parent_ptid))) { + int status; + linux_disable_event_reporting (child_pid); if (ptrace (PTRACE_SINGLESTEP, child_pid, 0, 0) < 0) perror_with_name (_("Couldn't do single step")); if (my_waitpid (child_pid, &status, 0) < 0) perror_with_name (_("Couldn't wait vfork process")); + else + { + detach_child = WIFSTOPPED (status); + child_stop_signal = WSTOPSIG (status); + } } - if (WIFSTOPPED (status)) + if (detach_child) { - int signo; + int signo = child_stop_signal; - signo = WSTOPSIG (status); if (signo != 0 && !signal_pass_state (gdb_signal_from_host (signo))) signo = 0; ptrace (PTRACE_DETACH, child_pid, 0, signo); } - /* Resets value of inferior_ptid to parent ptid. */ do_cleanups (old_chain); } else { + scoped_restore save_inferior_ptid + = make_scoped_restore (&inferior_ptid); + inferior_ptid = child_ptid; + /* Let the thread_db layer learn about this new process. */ check_for_thread_db (); } - do_cleanups (old_chain); - if (has_vforked) { struct lwp_info *parent_lp; @@ -633,46 +610,45 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child, } -static int -linux_child_insert_fork_catchpoint (struct target_ops *self, int pid) +int +linux_nat_target::insert_fork_catchpoint (int pid) { return !linux_supports_tracefork (); } -static int -linux_child_remove_fork_catchpoint (struct target_ops *self, int pid) +int +linux_nat_target::remove_fork_catchpoint (int pid) { return 0; } -static int -linux_child_insert_vfork_catchpoint (struct target_ops *self, int pid) +int +linux_nat_target::insert_vfork_catchpoint (int pid) { return !linux_supports_tracefork (); } -static int -linux_child_remove_vfork_catchpoint (struct target_ops *self, int pid) +int +linux_nat_target::remove_vfork_catchpoint (int pid) { return 0; } -static int -linux_child_insert_exec_catchpoint (struct target_ops *self, int pid) +int +linux_nat_target::insert_exec_catchpoint (int pid) { return !linux_supports_tracefork (); } -static int -linux_child_remove_exec_catchpoint (struct target_ops *self, int pid) +int +linux_nat_target::remove_exec_catchpoint (int pid) { return 0; } -static int -linux_child_set_syscall_catchpoint (struct target_ops *self, - int pid, int needed, int any_count, - int table_size, int *table) +int +linux_nat_target::set_syscall_catchpoint (int pid, bool needed, int any_count, + gdb::array_view syscall_counts) { if (!linux_supports_tracesysgood ()) return 1; @@ -680,7 +656,7 @@ linux_child_set_syscall_catchpoint (struct target_ops *self, /* On GNU/Linux, we ignore the arguments. It means that we only enable the syscall catchpoints, but do not disable them. - Also, we do not use the `table' information because we do not + Also, we do not use the `syscall_counts' information because we do not filter system calls here. We let GDB do the logic for us. */ return 0; } @@ -696,7 +672,7 @@ static hashval_t lwp_info_hash (const void *ap) { const struct lwp_info *lp = (struct lwp_info *) ap; - pid_t pid = ptid_get_lwp (lp->ptid); + pid_t pid = lp->ptid.lwp (); return iterative_hash_object (pid, 0); } @@ -710,7 +686,7 @@ lwp_lwpid_htab_eq (const void *a, const void *b) const struct lwp_info *entry = (const struct lwp_info *) a; const struct lwp_info *element = (const struct lwp_info *) b; - return ptid_get_lwp (entry->ptid) == ptid_get_lwp (element->ptid); + return entry->ptid.lwp () == element->ptid.lwp (); } /* Create the lwp_lwpid_htab hash table. */ @@ -806,9 +782,8 @@ restore_child_signals_mask (sigset_t *prev_mask) static sigset_t pass_mask; /* Update signals to pass to the inferior. */ -static void -linux_nat_pass_signals (struct target_ops *self, - int numsigs, unsigned char *pass_signals) +void +linux_nat_target::pass_signals (int numsigs, unsigned char *pass_signals) { int signo; @@ -826,7 +801,6 @@ linux_nat_pass_signals (struct target_ops *self, /* Prototypes for local functions. */ static int stop_wait_callback (struct lwp_info *lp, void *data); -static char *linux_child_pid_to_exec_file (struct target_ops *self, int pid); static int resume_stopped_resumed_lwps (struct lwp_info *lp, void *data); static int check_ptrace_stopped_lwp_gone (struct lwp_info *lp); @@ -837,7 +811,9 @@ static int check_ptrace_stopped_lwp_gone (struct lwp_info *lp); static void lwp_free (struct lwp_info *lp) { - xfree (lp->arch_private); + /* Let the arch specific bits release arch_lwp_info. */ + linux_target->low_delete_thread (lp->arch_private); + xfree (lp); } @@ -849,7 +825,7 @@ lwp_lwpid_htab_remove_pid (void **slot, void *info) struct lwp_info *lp = (struct lwp_info *) *slot; int pid = *(int *) info; - if (ptid_get_pid (lp->ptid) == pid) + if (lp->ptid.pid () == pid) { htab_clear_slot (lwp_lwpid_htab, slot); lwp_list_remove (lp); @@ -886,7 +862,7 @@ add_initial_lwp (ptid_t ptid) { struct lwp_info *lp; - gdb_assert (ptid_lwp_p (ptid)); + gdb_assert (ptid.lwp_p ()); lp = XNEW (struct lwp_info); @@ -922,8 +898,7 @@ add_lwp (ptid_t ptid) clients of this callback take the opportunity to install watchpoints in the new thread. We don't do this for the first thread though. See add_initial_lwp. */ - if (linux_nat_new_thread != NULL) - linux_nat_new_thread (lp); + linux_target->low_new_thread (lp); return lp; } @@ -964,12 +939,12 @@ find_lwp_pid (ptid_t ptid) int lwp; struct lwp_info dummy; - if (ptid_lwp_p (ptid)) - lwp = ptid_get_lwp (ptid); + if (ptid.lwp_p ()) + lwp = ptid.lwp (); else - lwp = ptid_get_pid (ptid); + lwp = ptid.pid (); - dummy.ptid = ptid_build (0, lwp, 0); + dummy.ptid = ptid_t (0, lwp, 0); lp = (struct lwp_info *) htab_find (lwp_lwpid_htab, &dummy); return lp; } @@ -987,7 +962,7 @@ iterate_over_lwps (ptid_t filter, { lpnext = lp->next; - if (ptid_match (lp->ptid, filter)) + if (lp->ptid.matches (filter)) { if ((*callback) (lp, data) != 0) return lp; @@ -1007,7 +982,7 @@ linux_nat_switch_fork (ptid_t new_ptid) { struct lwp_info *lp; - purge_lwp_list (ptid_get_pid (inferior_ptid)); + purge_lwp_list (inferior_ptid.pid ()); lp = add_lwp (new_ptid); lp->stopped = 1; @@ -1035,7 +1010,7 @@ exit_lwp (struct lwp_info *lp) if (print_thread_events) printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (lp->ptid)); - delete_thread (lp->ptid); + delete_thread (th); } delete_lwp (lp->ptid); @@ -1045,9 +1020,9 @@ exit_lwp (struct lwp_info *lp) Returns a wait status for that LWP, to cache. */ static int -linux_nat_post_attach_wait (ptid_t ptid, int first, int *signalled) +linux_nat_post_attach_wait (ptid_t ptid, int *signalled) { - pid_t new_pid, pid = ptid_get_lwp (ptid); + pid_t new_pid, pid = ptid.lwp (); int status; if (linux_proc_pid_is_stopped (pid)) @@ -1103,23 +1078,21 @@ linux_nat_post_attach_wait (ptid_t ptid, int first, int *signalled) return status; } -static void -linux_nat_create_inferior (struct target_ops *ops, - char *exec_file, char *allargs, char **env, - int from_tty) +void +linux_nat_target::create_inferior (const char *exec_file, + const std::string &allargs, + char **env, int from_tty) { - struct cleanup *restore_personality - = maybe_disable_address_space_randomization (disable_randomization); + maybe_disable_address_space_randomization restore_personality + (disable_randomization); /* The fork_child mechanism is synchronous and calls target_wait, so we have to mask the async mode. */ /* Make sure we report all signals during startup. */ - linux_nat_pass_signals (ops, 0, NULL); - - linux_ops->to_create_inferior (ops, exec_file, allargs, env, from_tty); + pass_signals (0, NULL); - do_cleanups (restore_personality); + inf_ptrace_target::create_inferior (exec_file, allargs, env, from_tty); } /* Callback for linux_proc_attach_tgid_threads. Attach to PTID if not @@ -1135,7 +1108,7 @@ attach_proc_task_lwp_callback (ptid_t ptid) lp = find_lwp_pid (ptid); if (lp == NULL) { - int lwpid = ptid_get_lwp (ptid); + int lwpid = ptid.lwp (); if (ptrace (PTRACE_ATTACH, lwpid, 0, 0) < 0) { @@ -1159,10 +1132,11 @@ attach_proc_task_lwp_callback (ptid_t ptid) } else { + std::string reason + = linux_ptrace_attach_fail_reason_string (ptid, err); + warning (_("Cannot attach to lwp %d: %s"), - lwpid, - linux_ptrace_attach_fail_reason_string (ptid, - err)); + lwpid, reason.c_str ()); } } else @@ -1198,61 +1172,50 @@ attach_proc_task_lwp_callback (ptid_t ptid) return 0; } -static void -linux_nat_attach (struct target_ops *ops, const char *args, int from_tty) +void +linux_nat_target::attach (const char *args, int from_tty) { struct lwp_info *lp; int status; ptid_t ptid; /* Make sure we report all signals during attach. */ - linux_nat_pass_signals (ops, 0, NULL); + pass_signals (0, NULL); TRY { - linux_ops->to_attach (ops, args, from_tty); + inf_ptrace_target::attach (args, from_tty); } CATCH (ex, RETURN_MASK_ERROR) { pid_t pid = parse_pid_to_attach (args); - struct buffer buffer; - char *message, *buffer_s; - - message = xstrdup (ex.message); - make_cleanup (xfree, message); - - buffer_init (&buffer); - linux_ptrace_attach_fail_reason (pid, &buffer); + std::string reason = linux_ptrace_attach_fail_reason (pid); - buffer_grow_str0 (&buffer, ""); - buffer_s = buffer_finish (&buffer); - make_cleanup (xfree, buffer_s); - - if (*buffer_s != '\0') - throw_error (ex.error, "warning: %s\n%s", buffer_s, message); + if (!reason.empty ()) + throw_error (ex.error, "warning: %s\n%s", reason.c_str (), ex.message); else - throw_error (ex.error, "%s", message); + throw_error (ex.error, "%s", ex.message); } END_CATCH /* The ptrace base target adds the main thread with (pid,0,0) format. Decorate it with lwp info. */ - ptid = ptid_build (ptid_get_pid (inferior_ptid), - ptid_get_pid (inferior_ptid), - 0); + ptid = ptid_t (inferior_ptid.pid (), + inferior_ptid.pid (), + 0); thread_change_ptid (inferior_ptid, ptid); /* Add the initial process as the first LWP to the list. */ lp = add_initial_lwp (ptid); - status = linux_nat_post_attach_wait (lp->ptid, 1, &lp->signalled); + status = linux_nat_post_attach_wait (lp->ptid, &lp->signalled); if (!WIFSTOPPED (status)) { if (WIFEXITED (status)) { int exit_code = WEXITSTATUS (status); - target_terminal_ours (); + target_terminal::ours (); target_mourn_inferior (inferior_ptid); if (exit_code == 0) error (_("Unable to attach: program exited normally.")); @@ -1264,7 +1227,7 @@ linux_nat_attach (struct target_ops *ops, const char *args, int from_tty) { enum gdb_signal signo; - target_terminal_ours (); + target_terminal::ours (); target_mourn_inferior (inferior_ptid); signo = gdb_signal_from_host (WTERMSIG (status)); @@ -1276,7 +1239,7 @@ linux_nat_attach (struct target_ops *ops, const char *args, int from_tty) internal_error (__FILE__, __LINE__, _("unexpected status %d for PID %ld"), - status, (long) ptid_get_lwp (ptid)); + status, (long) ptid.lwp ()); } lp->stopped = 1; @@ -1286,7 +1249,7 @@ linux_nat_attach (struct target_ops *ops, const char *args, int from_tty) if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, "LNA: waitpid %ld, saving status %s\n", - (long) ptid_get_pid (lp->ptid), status_to_str (status)); + (long) lp->ptid.pid (), status_to_str (status)); lp->status = status; @@ -1297,7 +1260,7 @@ linux_nat_attach (struct target_ops *ops, const char *args, int from_tty) of threads/LWPs, and those structures may well be corrupted. Note that once thread_db is loaded, we'll still use it to list threads and associate pthread info with each LWP. */ - linux_proc_attach_tgid_threads (ptid_get_pid (lp->ptid), + linux_proc_attach_tgid_threads (lp->ptid.pid (), attach_proc_task_lwp_callback); if (target_can_async_p ()) @@ -1339,27 +1302,26 @@ get_detach_signal (struct lwp_info *lp) signo = GDB_SIGNAL_0; /* a pending ptrace event, not a real signal. */ else if (lp->status) signo = gdb_signal_from_host (WSTOPSIG (lp->status)); - else if (target_is_non_stop_p () && !is_executing (lp->ptid)) + else { struct thread_info *tp = find_thread_ptid (lp->ptid); - if (tp->suspend.waitstatus_pending_p) - signo = tp->suspend.waitstatus.value.sig; - else - signo = tp->suspend.stop_signal; - } - else if (!target_is_non_stop_p ()) - { - struct target_waitstatus last; - ptid_t last_ptid; - - get_last_target_status (&last_ptid, &last); - - if (ptid_get_lwp (lp->ptid) == ptid_get_lwp (last_ptid)) + if (target_is_non_stop_p () && !tp->executing) { - struct thread_info *tp = find_thread_ptid (lp->ptid); + if (tp->suspend.waitstatus_pending_p) + signo = tp->suspend.waitstatus.value.sig; + else + signo = tp->suspend.stop_signal; + } + else if (!target_is_non_stop_p ()) + { + struct target_waitstatus last; + ptid_t last_ptid; + + get_last_target_status (&last_ptid, &last); - signo = tp->suspend.stop_signal; + if (lp->ptid.lwp () == last_ptid.lwp ()) + signo = tp->suspend.stop_signal; } } @@ -1400,7 +1362,7 @@ get_detach_signal (struct lwp_info *lp) static void detach_one_lwp (struct lwp_info *lp, int *signo_p) { - int lwpid = ptid_get_lwp (lp->ptid); + int lwpid = lp->ptid.lwp (); int signo; gdb_assert (lp->status == 0 || WIFSTOPPED (lp->status)); @@ -1435,8 +1397,7 @@ detach_one_lwp (struct lwp_info *lp, int *signo_p) it below, when detach fails with ESRCH. */ TRY { - if (linux_nat_prepare_to_resume != NULL) - linux_nat_prepare_to_resume (lp); + linux_target->low_prepare_to_resume (lp); } CATCH (ex, RETURN_MASK_ERROR) { @@ -1493,35 +1454,33 @@ detach_callback (struct lwp_info *lp, void *data) /* We don't actually detach from the thread group leader just yet. If the thread group exits, we must reap the zombie clone lwps before we're able to reap the leader. */ - if (ptid_get_lwp (lp->ptid) != ptid_get_pid (lp->ptid)) + if (lp->ptid.lwp () != lp->ptid.pid ()) detach_one_lwp (lp, NULL); return 0; } -static void -linux_nat_detach (struct target_ops *ops, const char *args, int from_tty) +void +linux_nat_target::detach (inferior *inf, int from_tty) { - int pid; struct lwp_info *main_lwp; - - pid = ptid_get_pid (inferior_ptid); + int pid = inf->pid; /* Don't unregister from the event loop, as there may be other inferiors running. */ /* Stop all threads before detaching. ptrace requires that the thread is stopped to sucessfully detach. */ - iterate_over_lwps (pid_to_ptid (pid), stop_callback, NULL); + iterate_over_lwps (ptid_t (pid), stop_callback, NULL); /* ... and wait until all of them have reported back that they're no longer running. */ - iterate_over_lwps (pid_to_ptid (pid), stop_wait_callback, NULL); + iterate_over_lwps (ptid_t (pid), stop_wait_callback, NULL); - iterate_over_lwps (pid_to_ptid (pid), detach_callback, NULL); + iterate_over_lwps (ptid_t (pid), detach_callback, NULL); /* Only the initial process should be left right now. */ - gdb_assert (num_lwps (ptid_get_pid (inferior_ptid)) == 1); + gdb_assert (num_lwps (pid) == 1); - main_lwp = find_lwp_pid (pid_to_ptid (pid)); + main_lwp = find_lwp_pid (ptid_t (pid)); if (forks_exist_p ()) { @@ -1529,27 +1488,19 @@ linux_nat_detach (struct target_ops *ops, const char *args, int from_tty) from, but there are other viable forks to debug. Detach from the current fork, and context-switch to the first available. */ - linux_fork_detach (args, from_tty); + linux_fork_detach (from_tty); } else { - int signo; - target_announce_detach (from_tty); - /* Pass on any pending signal for the last LWP, unless the user - requested detaching with a different signal (most likely 0, - meaning, discard the signal). */ - if (args != NULL) - signo = atoi (args); - else - signo = get_detach_signal (main_lwp); + /* Pass on any pending signal for the last LWP. */ + int signo = get_detach_signal (main_lwp); detach_one_lwp (main_lwp, &signo); - inf_ptrace_detach_success (ops); + detach_success (inf); } - delete_lwp (main_lwp->ptid); } /* Resume execution of the inferior process. If STEP is nonzero, @@ -1573,9 +1524,8 @@ linux_resume_one_lwp_throw (struct lwp_info *lp, int step, else lp->stop_pc = 0; - if (linux_nat_prepare_to_resume != NULL) - linux_nat_prepare_to_resume (lp); - linux_ops->to_resume (linux_ops, lp->ptid, step, signo); + linux_target->low_prepare_to_resume (lp); + linux_target->low_resume (lp->ptid, step, signo); /* Successfully resumed. Clear state that no longer makes sense, and mark the LWP as running. Must not do this before resuming @@ -1611,7 +1561,7 @@ check_ptrace_stopped_lwp_gone (struct lwp_info *lp) other than ptrace-stopped. */ /* Don't assume anything if /proc/PID/status can't be read. */ - if (linux_proc_pid_is_trace_stopped_nowarn (ptid_get_lwp (lp->ptid)) == 0) + if (linux_proc_pid_is_trace_stopped_nowarn (lp->ptid.lwp ()) == 0) { lp->stop_reason = TARGET_STOPPED_BY_NO_REASON; lp->status = 0; @@ -1728,9 +1678,8 @@ resume_set_callback (struct lwp_info *lp, void *data) return 0; } -static void -linux_nat_resume (struct target_ops *ops, - ptid_t ptid, int step, enum gdb_signal signo) +void +linux_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signo) { struct lwp_info *lp; int resume_many; @@ -1745,8 +1694,8 @@ linux_nat_resume (struct target_ops *ops, target_pid_to_str (inferior_ptid)); /* A specific PTID means `step only this process id'. */ - resume_many = (ptid_equal (minus_one_ptid, ptid) - || ptid_is_pid (ptid)); + resume_many = (minus_one_ptid == ptid + || ptid.is_pid ()); /* Mark the lwps we're resuming as resumed. */ iterate_over_lwps (ptid, resume_set_callback, NULL); @@ -1855,7 +1804,8 @@ linux_handle_syscall_trap (struct lwp_info *lp, int stopping) { struct target_waitstatus *ourstatus = &lp->waitstatus; struct gdbarch *gdbarch = target_thread_architecture (lp->ptid); - int syscall_number = (int) gdbarch_get_syscall_number (gdbarch, lp->ptid); + thread_info *thread = find_thread_ptid (lp->ptid); + int syscall_number = (int) gdbarch_get_syscall_number (gdbarch, thread); if (stopping) { @@ -1885,10 +1835,10 @@ linux_handle_syscall_trap (struct lwp_info *lp, int stopping) "for LWP %ld (stopping threads), " "resuming with PTRACE_CONT for SIGSTOP\n", syscall_number, - ptid_get_lwp (lp->ptid)); + lp->ptid.lwp ()); lp->syscall_state = TARGET_WAITKIND_IGNORE; - ptrace (PTRACE_CONT, ptid_get_lwp (lp->ptid), 0, 0); + ptrace (PTRACE_CONT, lp->ptid.lwp (), 0, 0); lp->stopped = 0; return 1; } @@ -1918,7 +1868,7 @@ linux_handle_syscall_trap (struct lwp_info *lp, int stopping) == TARGET_WAITKIND_SYSCALL_ENTRY ? "entry" : "return", syscall_number, - ptid_get_lwp (lp->ptid)); + lp->ptid.lwp ()); return 0; } @@ -1929,7 +1879,7 @@ linux_handle_syscall_trap (struct lwp_info *lp, int stopping) lp->syscall_state == TARGET_WAITKIND_SYSCALL_ENTRY ? "entry" : "return", syscall_number, - ptid_get_lwp (lp->ptid)); + lp->ptid.lwp ()); } else { @@ -1955,7 +1905,7 @@ linux_handle_syscall_trap (struct lwp_info *lp, int stopping) "with no syscall catchpoints." " %d for LWP %ld, ignoring\n", syscall_number, - ptid_get_lwp (lp->ptid)); + lp->ptid.lwp ()); lp->syscall_state = TARGET_WAITKIND_IGNORE; } @@ -1979,7 +1929,7 @@ linux_handle_syscall_trap (struct lwp_info *lp, int stopping) static int linux_handle_extended_wait (struct lwp_info *lp, int status) { - int pid = ptid_get_lwp (lp->ptid); + int pid = lp->ptid.lwp (); struct target_waitstatus *ourstatus = &lp->waitstatus; int event = linux_ptrace_get_extended_event (status); @@ -2012,19 +1962,18 @@ linux_handle_extended_wait (struct lwp_info *lp, int status) _("wait returned unexpected status 0x%x"), status); } - ourstatus->value.related_pid = ptid_build (new_pid, new_pid, 0); + ourstatus->value.related_pid = ptid_t (new_pid, new_pid, 0); if (event == PTRACE_EVENT_FORK || event == PTRACE_EVENT_VFORK) { /* The arch-specific native code may need to know about new forks even if those end up never mapped to an inferior. */ - if (linux_nat_new_fork != NULL) - linux_nat_new_fork (lp, new_pid); + linux_target->low_new_fork (lp, new_pid); } if (event == PTRACE_EVENT_FORK - && linux_fork_checkpointing_p (ptid_get_pid (lp->ptid))) + && linux_fork_checkpointing_p (lp->ptid.pid ())) { /* Handle checkpointing by linux-fork.c here as a special case. We don't want the follow-fork-mode or 'catch fork' @@ -2032,7 +1981,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status) /* This won't actually modify the breakpoint list, but will physically remove the breakpoints from the child. */ - detach_breakpoints (ptid_build (new_pid, new_pid, 0)); + detach_breakpoints (ptid_t (new_pid, new_pid, 0)); /* Retain child fork in ptrace (stopped) state. */ if (!find_fork_pid (new_pid)) @@ -2063,7 +2012,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status) "from LWP %d, new child is LWP %ld\n", pid, new_pid); - new_lp = add_lwp (ptid_build (ptid_get_pid (lp->ptid), new_pid, 0)); + new_lp = add_lwp (ptid_t (lp->ptid.pid (), new_pid, 0)); new_lp->stopped = 1; new_lp->resumed = 1; @@ -2074,7 +2023,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status) { /* The process is not using thread_db. Add the LWP to GDB's list. */ - target_post_attach (ptid_get_lwp (new_lp->ptid)); + target_post_attach (new_lp->ptid.lwp ()); add_thread (new_lp->ptid); } @@ -2104,7 +2053,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status) fprintf_unfiltered (gdb_stdlog, "LHEW: waitpid of new LWP %ld, " "saving status %s\n", - (long) ptid_get_lwp (new_lp->ptid), + (long) new_lp->ptid.lwp (), status_to_str (status)); new_lp->status = status; } @@ -2125,11 +2074,11 @@ linux_handle_extended_wait (struct lwp_info *lp, int status) if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, "LHEW: Got exec event from LWP %ld\n", - ptid_get_lwp (lp->ptid)); + lp->ptid.lwp ()); ourstatus->kind = TARGET_WAITKIND_EXECD; ourstatus->value.execd_pathname - = xstrdup (linux_child_pid_to_exec_file (NULL, pid)); + = xstrdup (linux_proc_pid_to_exec_file (pid)); /* The thread that execed must have been resumed, but, when a thread execs, it changes its tid to the tgid, and the old @@ -2146,7 +2095,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status) fprintf_unfiltered (gdb_stdlog, "LHEW: Got expected PTRACE_EVENT_" "VFORK_DONE from LWP %ld: stopping\n", - ptid_get_lwp (lp->ptid)); + lp->ptid.lwp ()); ourstatus->kind = TARGET_WAITKIND_VFORK_DONE; return 0; @@ -2156,7 +2105,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status) fprintf_unfiltered (gdb_stdlog, "LHEW: Got PTRACE_EVENT_VFORK_DONE " "from LWP %ld: ignoring\n", - ptid_get_lwp (lp->ptid)); + lp->ptid.lwp ()); return 1; } @@ -2164,6 +2113,30 @@ linux_handle_extended_wait (struct lwp_info *lp, int status) _("unknown ptrace event %d"), event); } +/* Suspend waiting for a signal. We're mostly interested in + SIGCHLD/SIGINT. */ + +static void +wait_for_signal () +{ + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, "linux-nat: about to sigsuspend\n"); + sigsuspend (&suspend_mask); + + /* If the quit flag is set, it means that the user pressed Ctrl-C + and we're debugging a process that is running on a separate + terminal, so we must forward the Ctrl-C to the inferior. (If the + inferior is sharing GDB's terminal, then the Ctrl-C reaches the + inferior directly.) We must do this here because functions that + need to block waiting for a signal loop forever until there's an + event to report before returning back to the event loop. */ + if (!target_terminal::is_ours ()) + { + if (check_quit_flag ()) + target_pass_ctrlc (); + } +} + /* Wait for LP to stop. Returns the wait status, or 0 if the LWP has exited. */ @@ -2183,7 +2156,7 @@ wait_lwp (struct lwp_info *lp) for (;;) { - pid = my_waitpid (ptid_get_lwp (lp->ptid), &status, __WALL | WNOHANG); + pid = my_waitpid (lp->ptid.lwp (), &status, __WALL | WNOHANG); if (pid == -1 && errno == ECHILD) { /* The thread has previously exited. We need to delete it @@ -2212,8 +2185,8 @@ wait_lwp (struct lwp_info *lp) Therefore always use WNOHANG with sigsuspend - it is equivalent to waiting waitpid but linux_proc_pid_is_zombie is safe this way. */ - if (ptid_get_pid (lp->ptid) == ptid_get_lwp (lp->ptid) - && linux_proc_pid_is_zombie (ptid_get_lwp (lp->ptid))) + if (lp->ptid.pid () == lp->ptid.lwp () + && linux_proc_pid_is_zombie (lp->ptid.lwp ())) { thread_dead = 1; if (debug_linux_nat) @@ -2229,17 +2202,14 @@ wait_lwp (struct lwp_info *lp) linux_nat_wait_1 and there if we get called my_waitpid gets called again before it gets to sigsuspend so we can safely let the handlers get executed here. */ - - if (debug_linux_nat) - fprintf_unfiltered (gdb_stdlog, "WL: about to sigsuspend\n"); - sigsuspend (&suspend_mask); + wait_for_signal (); } restore_child_signals_mask (&prev_mask); if (!thread_dead) { - gdb_assert (pid == ptid_get_lwp (lp->ptid)); + gdb_assert (pid == lp->ptid.lwp ()); if (debug_linux_nat) { @@ -2253,11 +2223,11 @@ wait_lwp (struct lwp_info *lp) if (WIFEXITED (status) || WIFSIGNALED (status)) { if (report_thread_events - || ptid_get_pid (lp->ptid) == ptid_get_lwp (lp->ptid)) + || lp->ptid.pid () == lp->ptid.lwp ()) { if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, "WL: LWP %d exited.\n", - ptid_get_pid (lp->ptid)); + lp->ptid.pid ()); /* If this is the leader exiting, it means the whole process is gone. Store the status to report to the @@ -2285,10 +2255,10 @@ wait_lwp (struct lwp_info *lp) if (lp->must_set_ptrace_flags) { - struct inferior *inf = find_inferior_pid (ptid_get_pid (lp->ptid)); + struct inferior *inf = find_inferior_pid (lp->ptid.pid ()); int options = linux_nat_ptrace_options (inf->attach_flag); - linux_enable_event_reporting (ptid_get_lwp (lp->ptid), options); + linux_enable_event_reporting (lp->ptid.lwp (), options); lp->must_set_ptrace_flags = 0; } @@ -2341,7 +2311,7 @@ stop_callback (struct lwp_info *lp, void *data) target_pid_to_str (lp->ptid)); } errno = 0; - ret = kill_lwp (ptid_get_lwp (lp->ptid), SIGSTOP); + ret = kill_lwp (lp->ptid.lwp (), SIGSTOP); if (debug_linux_nat) { fprintf_unfiltered (gdb_stdlog, @@ -2431,7 +2401,7 @@ maybe_clear_ignore_sigint (struct lwp_info *lp) if (!lp->ignore_sigint) return; - if (!linux_nat_has_pending_sigint (ptid_get_lwp (lp->ptid))) + if (!linux_nat_has_pending_sigint (lp->ptid.lwp ())) { if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, @@ -2459,35 +2429,23 @@ maybe_clear_ignore_sigint (struct lwp_info *lp) static int check_stopped_by_watchpoint (struct lwp_info *lp) { - struct cleanup *old_chain; - - if (linux_ops->to_stopped_by_watchpoint == NULL) - return 0; - - old_chain = save_inferior_ptid (); + scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid); inferior_ptid = lp->ptid; - if (linux_ops->to_stopped_by_watchpoint (linux_ops)) + if (linux_target->low_stopped_by_watchpoint ()) { lp->stop_reason = TARGET_STOPPED_BY_WATCHPOINT; - - if (linux_ops->to_stopped_data_address != NULL) - lp->stopped_data_address_p = - linux_ops->to_stopped_data_address (¤t_target, - &lp->stopped_data_address); - else - lp->stopped_data_address_p = 0; + lp->stopped_data_address_p + = linux_target->low_stopped_data_address (&lp->stopped_data_address); } - do_cleanups (old_chain); - return lp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT; } /* Returns true if the LWP had stopped for a watchpoint. */ -static int -linux_nat_stopped_by_watchpoint (struct target_ops *ops) +bool +linux_nat_target::stopped_by_watchpoint () { struct lwp_info *lp = find_lwp_pid (inferior_ptid); @@ -2496,8 +2454,8 @@ linux_nat_stopped_by_watchpoint (struct target_ops *ops) return lp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT; } -static int -linux_nat_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p) +bool +linux_nat_target::stopped_data_address (CORE_ADDR *addr_p) { struct lwp_info *lp = find_lwp_pid (inferior_ptid); @@ -2510,23 +2468,12 @@ linux_nat_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p) /* Commonly any breakpoint / watchpoint generate only SIGTRAP. */ -static int -sigtrap_is_event (int status) +bool +linux_nat_target::low_status_is_event (int status) { return WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP; } -/* Set alternative SIGTRAP-like events recognizer. If - breakpoint_inserted_here_p there then gdbarch_decr_pc_after_break will be - applied. */ - -void -linux_nat_set_status_is_event (struct target_ops *t, - int (*status_is_event) (int status)) -{ - linux_nat_status_is_event = status_is_event; -} - /* Wait until LP is stopped. */ static int @@ -2553,7 +2500,7 @@ stop_wait_callback (struct lwp_info *lp, void *data) lp->ignore_sigint = 0; errno = 0; - ptrace (PTRACE_CONT, ptid_get_lwp (lp->ptid), 0, 0); + ptrace (PTRACE_CONT, lp->ptid.lwp (), 0, 0); lp->stopped = 0; if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, @@ -2584,17 +2531,23 @@ stop_wait_callback (struct lwp_info *lp, void *data) } else { - /* We caught the SIGSTOP that we intended to catch, so - there's no SIGSTOP pending. */ + /* We caught the SIGSTOP that we intended to catch. */ if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, "SWC: Expected SIGSTOP caught for %s.\n", target_pid_to_str (lp->ptid)); - /* Reset SIGNALLED only after the stop_wait_callback call - above as it does gdb_assert on SIGNALLED. */ lp->signalled = 0; + + /* If we are waiting for this stop so we can report the thread + stopped then we need to record this status. Otherwise, we can + now discard this stop event. */ + if (lp->last_resume_kind == resume_stop) + { + lp->status = status; + save_stop_reason (lp); + } } } @@ -2637,7 +2590,7 @@ status_callback (struct lwp_info *lp, void *data) } #if !USE_SIGTRAP_SIGINFO - else if (!breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc)) + else if (!breakpoint_inserted_here_p (regcache->aspace (), pc)) { if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, @@ -2741,11 +2694,11 @@ save_stop_reason (struct lwp_info *lp) gdb_assert (lp->stop_reason == TARGET_STOPPED_BY_NO_REASON); gdb_assert (lp->status != 0); - if (!linux_nat_status_is_event (lp->status)) + if (!linux_target->low_status_is_event (lp->status)) return; regcache = get_thread_regcache (lp->ptid); - gdbarch = get_regcache_arch (regcache); + gdbarch = regcache->arch (); pc = regcache_read_pc (regcache); sw_bp_pc = pc - gdbarch_decr_pc_after_break (gdbarch); @@ -2797,7 +2750,7 @@ save_stop_reason (struct lwp_info *lp) } #else if ((!lp->step || lp->stop_pc == sw_bp_pc) - && software_breakpoint_inserted_here_p (get_regcache_aspace (regcache), + && software_breakpoint_inserted_here_p (regcache->aspace (), sw_bp_pc)) { /* The LWP was either continued, or stepped a software @@ -2805,7 +2758,7 @@ save_stop_reason (struct lwp_info *lp) lp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; } - if (hardware_breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc)) + if (hardware_breakpoint_inserted_here_p (regcache->aspace (), pc)) lp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; if (lp->stop_reason == TARGET_STOPPED_BY_NO_REASON) @@ -2847,8 +2800,8 @@ save_stop_reason (struct lwp_info *lp) /* Returns true if the LWP had stopped for a software breakpoint. */ -static int -linux_nat_stopped_by_sw_breakpoint (struct target_ops *ops) +bool +linux_nat_target::stopped_by_sw_breakpoint () { struct lwp_info *lp = find_lwp_pid (inferior_ptid); @@ -2859,8 +2812,8 @@ linux_nat_stopped_by_sw_breakpoint (struct target_ops *ops) /* Implement the supports_stopped_by_sw_breakpoint method. */ -static int -linux_nat_supports_stopped_by_sw_breakpoint (struct target_ops *ops) +bool +linux_nat_target::supports_stopped_by_sw_breakpoint () { return USE_SIGTRAP_SIGINFO; } @@ -2868,8 +2821,8 @@ linux_nat_supports_stopped_by_sw_breakpoint (struct target_ops *ops) /* Returns true if the LWP had stopped for a hardware breakpoint/watchpoint. */ -static int -linux_nat_stopped_by_hw_breakpoint (struct target_ops *ops) +bool +linux_nat_target::stopped_by_hw_breakpoint () { struct lwp_info *lp = find_lwp_pid (inferior_ptid); @@ -2880,8 +2833,8 @@ linux_nat_stopped_by_hw_breakpoint (struct target_ops *ops) /* Implement the supports_stopped_by_hw_breakpoint method. */ -static int -linux_nat_supports_stopped_by_hw_breakpoint (struct target_ops *ops) +bool +linux_nat_target::supports_stopped_by_hw_breakpoint () { return USE_SIGTRAP_SIGINFO; } @@ -2971,7 +2924,7 @@ linux_nat_filter_event (int lwpid, int status) struct lwp_info *lp; int event = linux_ptrace_get_extended_event (status); - lp = find_lwp_pid (pid_to_ptid (lwpid)); + lp = find_lwp_pid (ptid_t (lwpid)); /* Check for stop events reported by a process we didn't already know about - anything not already in our LWP list. @@ -2995,7 +2948,7 @@ linux_nat_filter_event (int lwpid, int status) "LLW: Re-adding thread group leader LWP %d.\n", lwpid); - lp = add_lwp (ptid_build (lwpid, lwpid, 0)); + lp = add_lwp (ptid_t (lwpid, lwpid, 0)); lp->stopped = 1; lp->resumed = 1; add_thread (lp->ptid); @@ -3024,10 +2977,10 @@ linux_nat_filter_event (int lwpid, int status) if (WIFSTOPPED (status) && lp->must_set_ptrace_flags) { - struct inferior *inf = find_inferior_pid (ptid_get_pid (lp->ptid)); + struct inferior *inf = find_inferior_pid (lp->ptid.pid ()); int options = linux_nat_ptrace_options (inf->attach_flag); - linux_enable_event_reporting (ptid_get_lwp (lp->ptid), options); + linux_enable_event_reporting (lp->ptid.lwp (), options); lp->must_set_ptrace_flags = 0; } @@ -3065,7 +3018,7 @@ linux_nat_filter_event (int lwpid, int status) if (WIFEXITED (status) || WIFSIGNALED (status)) { if (!report_thread_events - && num_lwps (ptid_get_pid (lp->ptid)) > 1) + && num_lwps (lp->ptid.pid ()) > 1) { if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, @@ -3086,7 +3039,7 @@ linux_nat_filter_event (int lwpid, int status) if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, "LWP %ld exited (resumed=%d)\n", - ptid_get_lwp (lp->ptid), lp->resumed); + lp->ptid.lwp (), lp->resumed); /* Dead LWP's aren't expected to reported a pending sigstop. */ lp->signalled = 0; @@ -3176,7 +3129,7 @@ linux_nat_filter_event (int lwpid, int status) will receive it - unless they're using CLONE_THREAD to share signals. Since we only want to report it once, we mark it as ignored for all LWPs except this one. */ - iterate_over_lwps (pid_to_ptid (ptid_get_pid (lp->ptid)), + iterate_over_lwps (ptid_t (lp->ptid.pid ()), set_ignore_sigint, NULL); lp->ignore_sigint = 0; } @@ -3227,7 +3180,7 @@ check_zombie_leaders (void) if (inf->pid == 0) continue; - leader_lp = find_lwp_pid (pid_to_ptid (inf->pid)); + leader_lp = find_lwp_pid (ptid_t (inf->pid)); if (leader_lp != NULL /* Check if there are other threads in the group, as we may have raced with the inferior simply exiting. */ @@ -3278,7 +3231,7 @@ filter_exit_event (struct lwp_info *event_child, { ptid_t ptid = event_child->ptid; - if (num_lwps (ptid_get_pid (ptid)) > 1) + if (num_lwps (ptid.pid ()) > 1) { if (report_thread_events) ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED; @@ -3292,8 +3245,7 @@ filter_exit_event (struct lwp_info *event_child, } static ptid_t -linux_nat_wait_1 (struct target_ops *ops, - ptid_t ptid, struct target_waitstatus *ourstatus, +linux_nat_wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus, int target_options) { sigset_t prev_mask; @@ -3307,12 +3259,12 @@ linux_nat_wait_1 (struct target_ops *ops, /* 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 (ptid_is_pid (inferior_ptid)) + if (inferior_ptid.is_pid ()) { /* Upgrade the main thread's ptid. */ thread_change_ptid (inferior_ptid, - ptid_build (ptid_get_pid (inferior_ptid), - ptid_get_pid (inferior_ptid), 0)); + ptid_t (inferior_ptid.pid (), + inferior_ptid.pid (), 0)); lp = add_initial_lwp (inferior_ptid); lp->resumed = 1; @@ -3420,9 +3372,7 @@ linux_nat_wait_1 (struct target_ops *ops, gdb_assert (lp == NULL); /* Block until we get an event reported with SIGCHLD. */ - if (debug_linux_nat) - fprintf_unfiltered (gdb_stdlog, "LNW: about to sigsuspend\n"); - sigsuspend (&suspend_mask); + wait_for_signal (); } gdb_assert (lp); @@ -3443,7 +3393,7 @@ linux_nat_wait_1 (struct target_ops *ops, /* If we're not waiting for a specific LWP, choose an event LWP from among those that have had events. Giving equal priority to all LWPs that have had events helps prevent starvation. */ - if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid)) + if (ptid == minus_one_ptid || ptid.is_pid ()) select_event_lwp (ptid, &lp, &status); gdb_assert (lp != NULL); @@ -3455,7 +3405,7 @@ linux_nat_wait_1 (struct target_ops *ops, && !USE_SIGTRAP_SIGINFO) { struct regcache *regcache = get_thread_regcache (lp->ptid); - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); int decr_pc = gdbarch_decr_pc_after_break (gdbarch); if (decr_pc != 0) @@ -3483,7 +3433,7 @@ linux_nat_wait_1 (struct target_ops *ops, resume_clear_callback (lp, NULL); } - if (linux_nat_status_is_event (status)) + if (linux_target->low_status_is_event (status)) { if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, @@ -3558,7 +3508,7 @@ resume_stopped_resumed_lwps (struct lwp_info *lp, void *data) else { struct regcache *regcache = get_thread_regcache (lp->ptid); - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); TRY { @@ -3567,9 +3517,9 @@ resume_stopped_resumed_lwps (struct lwp_info *lp, void *data) /* Don't bother if there's a breakpoint at PC that we'd hit immediately, and we're not waiting for this LWP. */ - if (!ptid_match (lp->ptid, *wait_ptid_p)) + if (!lp->ptid.matches (*wait_ptid_p)) { - if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc)) + if (breakpoint_inserted_here_p (regcache->aspace (), pc)) leave_stopped = 1; } @@ -3597,23 +3547,19 @@ resume_stopped_resumed_lwps (struct lwp_info *lp, void *data) return 0; } -static ptid_t -linux_nat_wait (struct target_ops *ops, - ptid_t ptid, struct target_waitstatus *ourstatus, - int target_options) +ptid_t +linux_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, + int target_options) { ptid_t event_ptid; if (debug_linux_nat) { - char *options_string; - - options_string = target_options_to_string (target_options); + std::string options_string = target_options_to_string (target_options); fprintf_unfiltered (gdb_stdlog, "linux_nat_wait: [%s], [%s]\n", target_pid_to_str (ptid), - options_string); - xfree (options_string); + options_string.c_str ()); } /* Flush the async file first. */ @@ -3630,7 +3576,7 @@ linux_nat_wait (struct target_ops *ops, if (target_is_non_stop_p ()) iterate_over_lwps (minus_one_ptid, resume_stopped_resumed_lwps, &ptid); - event_ptid = linux_nat_wait_1 (ops, ptid, ourstatus, target_options); + event_ptid = linux_nat_wait_1 (ptid, ourstatus, target_options); /* If we requested any event, and something came out, assume there may be more. If we requested a specific lwp or process, also @@ -3638,7 +3584,7 @@ linux_nat_wait (struct target_ops *ops, if (target_is_async_p () && ((ourstatus->kind != TARGET_WAITKIND_IGNORE && ourstatus->kind != TARGET_WAITKIND_NO_RESUMED) - || !ptid_equal (ptid, minus_one_ptid))) + || ptid != minus_one_ptid)) async_file_mark (); return event_ptid; @@ -3713,7 +3659,7 @@ kill_wait_one_lwp (pid_t pid) static int kill_callback (struct lwp_info *lp, void *data) { - kill_one_lwp (ptid_get_lwp (lp->ptid)); + kill_one_lwp (lp->ptid.lwp ()); return 0; } @@ -3722,7 +3668,7 @@ kill_callback (struct lwp_info *lp, void *data) static int kill_wait_callback (struct lwp_info *lp, void *data) { - kill_wait_one_lwp (ptid_get_lwp (lp->ptid)); + kill_wait_one_lwp (lp->ptid.lwp ()); return 0; } @@ -3743,21 +3689,21 @@ kill_unfollowed_fork_children (struct inferior *inf) || ws->kind == TARGET_WAITKIND_VFORKED) { ptid_t child_ptid = ws->value.related_pid; - int child_pid = ptid_get_pid (child_ptid); - int child_lwp = ptid_get_lwp (child_ptid); + int child_pid = child_ptid.pid (); + int child_lwp = child_ptid.lwp (); kill_one_lwp (child_lwp); kill_wait_one_lwp (child_lwp); /* Let the arch-specific native code know this process is gone. */ - linux_nat_forget_process (child_pid); + linux_target->low_forget_process (child_pid); } } } -static void -linux_nat_kill (struct target_ops *ops) +void +linux_nat_target::kill () { /* If we're stopped while forking and we haven't followed yet, kill the other task. We need to do this first because the @@ -3768,7 +3714,7 @@ linux_nat_kill (struct target_ops *ops) linux_fork_killall (); else { - ptid_t ptid = pid_to_ptid (ptid_get_pid (inferior_ptid)); + ptid_t ptid = ptid_t (inferior_ptid.pid ()); /* Stop all threads before killing them, since ptrace requires that the thread is stopped to sucessfully PTRACE_KILL. */ @@ -3787,16 +3733,16 @@ linux_nat_kill (struct target_ops *ops) target_mourn_inferior (inferior_ptid); } -static void -linux_nat_mourn_inferior (struct target_ops *ops) +void +linux_nat_target::mourn_inferior () { - int pid = ptid_get_pid (inferior_ptid); + int pid = inferior_ptid.pid (); purge_lwp_list (pid); if (! forks_exist_p ()) /* Normal case, no other forks available. */ - linux_ops->to_mourn_inferior (ops); + inf_ptrace_target::mourn_inferior (); else /* Multi-fork case. The current inferior_ptid has exited, but there are other viable forks to debug. Delete the exiting @@ -3804,7 +3750,7 @@ linux_nat_mourn_inferior (struct target_ops *ops) linux_fork_mourn_inferior (); /* Let the arch-specific native code know this process is gone. */ - linux_nat_forget_process (pid); + linux_target->low_forget_process (pid); } /* Convert a native/host siginfo object, into/from the siginfo in the @@ -3813,14 +3759,9 @@ linux_nat_mourn_inferior (struct target_ops *ops) static void siginfo_fixup (siginfo_t *siginfo, gdb_byte *inf_siginfo, int direction) { - int done = 0; - - if (linux_nat_siginfo_fixup != NULL) - done = linux_nat_siginfo_fixup (siginfo, inf_siginfo, direction); - - /* If there was no callback, or the callback didn't do anything, - then just do a straight memcpy. */ - if (!done) + /* If the low target didn't do anything, then just do a straight + memcpy. */ + if (!linux_target->low_siginfo_fixup (siginfo, inf_siginfo, direction)) { if (direction == 1) memcpy (siginfo, inf_siginfo, sizeof (siginfo_t)); @@ -3830,7 +3771,7 @@ siginfo_fixup (siginfo_t *siginfo, gdb_byte *inf_siginfo, int direction) } static enum target_xfer_status -linux_xfer_siginfo (struct target_ops *ops, enum target_object object, +linux_xfer_siginfo (enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) @@ -3842,9 +3783,9 @@ linux_xfer_siginfo (struct target_ops *ops, enum target_object object, gdb_assert (object == TARGET_OBJECT_SIGNAL_INFO); gdb_assert (readbuf || writebuf); - pid = ptid_get_lwp (inferior_ptid); + pid = inferior_ptid.lwp (); if (pid == 0) - pid = ptid_get_pid (inferior_ptid); + pid = inferior_ptid.pid (); if (offset > sizeof (siginfo)) return TARGET_XFER_E_IO; @@ -3885,38 +3826,79 @@ linux_xfer_siginfo (struct target_ops *ops, enum target_object object, } static enum target_xfer_status -linux_nat_xfer_partial (struct target_ops *ops, enum target_object object, - const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, - ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) +linux_nat_xfer_osdata (enum target_object object, + const char *annex, gdb_byte *readbuf, + const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, + ULONGEST *xfered_len); + +static enum target_xfer_status +linux_proc_xfer_spu (enum target_object object, + const char *annex, gdb_byte *readbuf, + const gdb_byte *writebuf, + ULONGEST offset, ULONGEST len, ULONGEST *xfered_len); + +static enum target_xfer_status +linux_proc_xfer_partial (enum target_object object, + const char *annex, gdb_byte *readbuf, + const gdb_byte *writebuf, + ULONGEST offset, LONGEST len, ULONGEST *xfered_len); + +enum target_xfer_status +linux_nat_target::xfer_partial (enum target_object object, + const char *annex, gdb_byte *readbuf, + const gdb_byte *writebuf, + ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) { - struct cleanup *old_chain; enum target_xfer_status xfer; if (object == TARGET_OBJECT_SIGNAL_INFO) - return linux_xfer_siginfo (ops, object, annex, readbuf, writebuf, + return linux_xfer_siginfo (object, annex, readbuf, writebuf, offset, len, xfered_len); /* The target is connected but no live inferior is selected. Pass this request down to a lower stratum (e.g., the executable file). */ - if (object == TARGET_OBJECT_MEMORY && ptid_equal (inferior_ptid, null_ptid)) + if (object == TARGET_OBJECT_MEMORY && inferior_ptid == null_ptid) return TARGET_XFER_EOF; - old_chain = save_inferior_ptid (); + if (object == TARGET_OBJECT_AUXV) + return memory_xfer_auxv (this, object, annex, readbuf, writebuf, + offset, len, xfered_len); - if (ptid_lwp_p (inferior_ptid)) - inferior_ptid = pid_to_ptid (ptid_get_lwp (inferior_ptid)); + if (object == TARGET_OBJECT_OSDATA) + return linux_nat_xfer_osdata (object, annex, readbuf, writebuf, + offset, len, xfered_len); - xfer = linux_ops->to_xfer_partial (ops, object, annex, readbuf, writebuf, - offset, len, xfered_len); + if (object == TARGET_OBJECT_SPU) + return linux_proc_xfer_spu (object, annex, readbuf, writebuf, + offset, len, xfered_len); - do_cleanups (old_chain); - return xfer; + /* GDB calculates all addresses in the largest possible address + width. + The address width must be masked before its final use - either by + linux_proc_xfer_partial or inf_ptrace_target::xfer_partial. + + Compare ADDR_BIT first to avoid a compiler warning on shift overflow. */ + + if (object == TARGET_OBJECT_MEMORY) + { + int addr_bit = gdbarch_addr_bit (target_gdbarch ()); + + if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT)) + offset &= ((ULONGEST) 1 << addr_bit) - 1; + } + + xfer = linux_proc_xfer_partial (object, annex, readbuf, writebuf, + offset, len, xfered_len); + if (xfer != TARGET_XFER_EOF) + return xfer; + + return inf_ptrace_target::xfer_partial (object, annex, readbuf, writebuf, + offset, len, xfered_len); } -static int -linux_nat_thread_alive (struct target_ops *ops, ptid_t ptid) +bool +linux_nat_target::thread_alive (ptid_t ptid) { /* As long as a PTID is in lwp list, consider it alive. */ return find_lwp_pid (ptid) != NULL; @@ -3925,8 +3907,8 @@ linux_nat_thread_alive (struct target_ops *ops, ptid_t ptid) /* Implement the to_update_thread_list target method for this target. */ -static void -linux_nat_update_thread_list (struct target_ops *ops) +void +linux_nat_target::update_thread_list () { struct lwp_info *lwp; @@ -3947,24 +3929,24 @@ linux_nat_update_thread_list (struct target_ops *ops) } } -static char * -linux_nat_pid_to_str (struct target_ops *ops, ptid_t ptid) +const char * +linux_nat_target::pid_to_str (ptid_t ptid) { static char buf[64]; - if (ptid_lwp_p (ptid) - && (ptid_get_pid (ptid) != ptid_get_lwp (ptid) - || num_lwps (ptid_get_pid (ptid)) > 1)) + if (ptid.lwp_p () + && (ptid.pid () != ptid.lwp () + || num_lwps (ptid.pid ()) > 1)) { - snprintf (buf, sizeof (buf), "LWP %ld", ptid_get_lwp (ptid)); + snprintf (buf, sizeof (buf), "LWP %ld", ptid.lwp ()); return buf; } return normal_pid_to_str (ptid); } -static const char * -linux_nat_thread_name (struct target_ops *self, struct thread_info *thr) +const char * +linux_nat_target::thread_name (struct thread_info *thr) { return linux_proc_tid_get_name (thr->ptid); } @@ -3972,19 +3954,18 @@ linux_nat_thread_name (struct target_ops *self, struct thread_info *thr) /* Accepts an integer PID; Returns a string representing a file that can be opened to get the symbols for the child process. */ -static char * -linux_child_pid_to_exec_file (struct target_ops *self, int pid) +char * +linux_nat_target::pid_to_exec_file (int pid) { return linux_proc_pid_to_exec_file (pid); } -/* Implement the to_xfer_partial interface for memory reads using the /proc - filesystem. Because we can use a single read() call for /proc, this - can be much more efficient than banging away at PTRACE_PEEKTEXT, - but it doesn't support writes. */ +/* Implement the to_xfer_partial target method using /proc//mem. + Because we can use a single read/write call, this can be much more + efficient than banging away at PTRACE_PEEKTEXT. */ static enum target_xfer_status -linux_proc_xfer_partial (struct target_ops *ops, enum target_object object, +linux_proc_xfer_partial (enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, LONGEST len, ULONGEST *xfered_len) @@ -3993,7 +3974,7 @@ linux_proc_xfer_partial (struct target_ops *ops, enum target_object object, int fd; char filename[64]; - if (object != TARGET_OBJECT_MEMORY || !readbuf) + if (object != TARGET_OBJECT_MEMORY) return TARGET_XFER_EOF; /* Don't bother for one word. */ @@ -4002,28 +3983,29 @@ linux_proc_xfer_partial (struct target_ops *ops, enum target_object object, /* We could keep this file open and cache it - possibly one per thread. That requires some juggling, but is even faster. */ - xsnprintf (filename, sizeof filename, "/proc/%d/mem", - ptid_get_pid (inferior_ptid)); - fd = gdb_open_cloexec (filename, O_RDONLY | O_LARGEFILE, 0); + xsnprintf (filename, sizeof filename, "/proc/%ld/mem", + inferior_ptid.lwp ()); + fd = gdb_open_cloexec (filename, ((readbuf ? O_RDONLY : O_WRONLY) + | O_LARGEFILE), 0); if (fd == -1) return TARGET_XFER_EOF; - /* If pread64 is available, use it. It's faster if the kernel - supports it (only one syscall), and it's 64-bit safe even on - 32-bit platforms (for instance, SPARC debugging a SPARC64 - application). */ + /* Use pread64/pwrite64 if available, since they save a syscall and can + handle 64-bit offsets even on 32-bit platforms (for instance, SPARC + debugging a SPARC64 application). */ #ifdef HAVE_PREAD64 - if (pread64 (fd, readbuf, len, offset) != len) + ret = (readbuf ? pread64 (fd, readbuf, len, offset) + : pwrite64 (fd, writebuf, len, offset)); #else - if (lseek (fd, offset, SEEK_SET) == -1 || read (fd, readbuf, len) != len) + ret = lseek (fd, offset, SEEK_SET); + if (ret != -1) + ret = (readbuf ? read (fd, readbuf, len) + : write (fd, writebuf, len)); #endif - ret = 0; - else - ret = len; close (fd); - if (ret == 0) + if (ret == -1 || ret == 0) return TARGET_XFER_EOF; else { @@ -4087,7 +4069,7 @@ spu_enumerate_spu_ids (int pid, gdb_byte *buf, ULONGEST offset, ULONGEST len) object type, using the /proc file system. */ static enum target_xfer_status -linux_proc_xfer_spu (struct target_ops *ops, enum target_object object, +linux_proc_xfer_spu (enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) @@ -4095,7 +4077,7 @@ linux_proc_xfer_spu (struct target_ops *ops, enum target_object object, char buf[128]; int fd = 0; int ret = -1; - int pid = ptid_get_pid (inferior_ptid); + int pid = inferior_ptid.lwp (); if (!annex) { @@ -4195,20 +4177,17 @@ void linux_proc_pending_signals (int pid, sigset_t *pending, sigset_t *blocked, sigset_t *ignored) { - FILE *procfile; char buffer[PATH_MAX], fname[PATH_MAX]; - struct cleanup *cleanup; sigemptyset (pending); sigemptyset (blocked); sigemptyset (ignored); xsnprintf (fname, sizeof fname, "/proc/%d/status", pid); - procfile = gdb_fopen_cloexec (fname, "r"); + gdb_file_up procfile = gdb_fopen_cloexec (fname, "r"); if (procfile == NULL) error (_("Could not open %s"), fname); - cleanup = make_cleanup_fclose (procfile); - while (fgets (buffer, PATH_MAX, procfile) != NULL) + while (fgets (buffer, PATH_MAX, procfile.get ()) != NULL) { /* Normal queued signals are on the SigPnd line in the status file. However, 2.6 kernels also have a "shared" pending @@ -4227,12 +4206,10 @@ linux_proc_pending_signals (int pid, sigset_t *pending, else if (startswith (buffer, "SigIgn:\t")) add_line_to_sigset (buffer + 8, ignored); } - - do_cleanups (cleanup); } static enum target_xfer_status -linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object, +linux_nat_xfer_osdata (enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) @@ -4246,49 +4223,6 @@ linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object, return TARGET_XFER_OK; } -static enum target_xfer_status -linux_xfer_partial (struct target_ops *ops, enum target_object object, - const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, - ULONGEST *xfered_len) -{ - enum target_xfer_status xfer; - - if (object == TARGET_OBJECT_AUXV) - return memory_xfer_auxv (ops, object, annex, readbuf, writebuf, - offset, len, xfered_len); - - if (object == TARGET_OBJECT_OSDATA) - return linux_nat_xfer_osdata (ops, object, annex, readbuf, writebuf, - offset, len, xfered_len); - - if (object == TARGET_OBJECT_SPU) - return linux_proc_xfer_spu (ops, object, annex, readbuf, writebuf, - offset, len, xfered_len); - - /* GDB calculates all the addresses in possibly larget width of the address. - Address width needs to be masked before its final use - either by - linux_proc_xfer_partial or inf_ptrace_xfer_partial. - - Compare ADDR_BIT first to avoid a compiler warning on shift overflow. */ - - if (object == TARGET_OBJECT_MEMORY) - { - int addr_bit = gdbarch_addr_bit (target_gdbarch ()); - - if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT)) - offset &= ((ULONGEST) 1 << addr_bit) - 1; - } - - xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf, - offset, len, xfered_len); - if (xfer != TARGET_XFER_EOF) - return xfer; - - return super_xfer_partial (ops, object, annex, readbuf, writebuf, - offset, len, xfered_len); -} - static void cleanup_target_stop (void *arg) { @@ -4300,17 +4234,16 @@ cleanup_target_stop (void *arg) target_continue_no_signal (*ptid); } -static VEC(static_tracepoint_marker_p) * -linux_child_static_tracepoint_markers_by_strid (struct target_ops *self, - const char *strid) +std::vector +linux_nat_target::static_tracepoint_markers_by_strid (const char *strid) { char s[IPA_CMD_BUF_SIZE]; struct cleanup *old_chain; - int pid = ptid_get_pid (inferior_ptid); - VEC(static_tracepoint_marker_p) *markers = NULL; - struct static_tracepoint_marker *marker = NULL; - char *p = s; - ptid_t ptid = ptid_build (pid, 0, 0); + int pid = inferior_ptid.pid (); + std::vector markers; + const char *p = s; + ptid_t ptid = ptid_t (pid, 0, 0); + static_tracepoint_marker marker; /* Pause all */ target_stop (ptid); @@ -4320,29 +4253,16 @@ linux_child_static_tracepoint_markers_by_strid (struct target_ops *self, agent_run_command (pid, s, strlen (s) + 1); - old_chain = make_cleanup (free_current_marker, &marker); - make_cleanup (cleanup_target_stop, &ptid); + old_chain = make_cleanup (cleanup_target_stop, &ptid); while (*p++ == 'm') { - if (marker == NULL) - marker = XCNEW (struct static_tracepoint_marker); - do { - parse_static_tracepoint_marker_definition (p, &p, marker); + parse_static_tracepoint_marker_definition (p, &p, &marker); - if (strid == NULL || strcmp (strid, marker->str_id) == 0) - { - VEC_safe_push (static_tracepoint_marker_p, - markers, marker); - marker = NULL; - } - else - { - release_static_tracepoint_marker (marker); - memset (marker, 0, sizeof (*marker)); - } + if (strid == NULL || marker.str_id == strid) + markers.push_back (std::move (marker)); } while (*p++ == ','); /* comma-separated list */ @@ -4357,82 +4277,34 @@ linux_child_static_tracepoint_markers_by_strid (struct target_ops *self, return markers; } -/* Create a prototype generic GNU/Linux target. The client can override - it with local methods. */ - -static void -linux_target_install_ops (struct target_ops *t) -{ - t->to_insert_fork_catchpoint = linux_child_insert_fork_catchpoint; - t->to_remove_fork_catchpoint = linux_child_remove_fork_catchpoint; - t->to_insert_vfork_catchpoint = linux_child_insert_vfork_catchpoint; - t->to_remove_vfork_catchpoint = linux_child_remove_vfork_catchpoint; - t->to_insert_exec_catchpoint = linux_child_insert_exec_catchpoint; - t->to_remove_exec_catchpoint = linux_child_remove_exec_catchpoint; - t->to_set_syscall_catchpoint = linux_child_set_syscall_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; - - super_xfer_partial = t->to_xfer_partial; - t->to_xfer_partial = linux_xfer_partial; - - t->to_static_tracepoint_markers_by_strid - = linux_child_static_tracepoint_markers_by_strid; -} - -struct target_ops * -linux_target (void) -{ - struct target_ops *t; - - t = inf_ptrace_target (); - linux_target_install_ops (t); - - 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; -} - /* target_is_async_p implementation. */ -static int -linux_nat_is_async_p (struct target_ops *ops) +bool +linux_nat_target::is_async_p () { return linux_is_async_p (); } /* target_can_async_p implementation. */ -static int -linux_nat_can_async_p (struct target_ops *ops) +bool +linux_nat_target::can_async_p () { - /* NOTE: palves 2008-03-21: We're only async when the user requests - it explicitly with the "set target-async" command. - Someday, linux will always be async. */ + /* We're always async, unless the user explicitly prevented it with the + "maint set target-async" command. */ return target_async_permitted; } -static int -linux_nat_supports_non_stop (struct target_ops *self) +bool +linux_nat_target::supports_non_stop () { return 1; } /* to_always_non_stop_p implementation. */ -static int -linux_nat_always_non_stop_p (struct target_ops *self) +bool +linux_nat_target::always_non_stop_p () { return 1; } @@ -4442,14 +4314,14 @@ linux_nat_always_non_stop_p (struct target_ops *self) int linux_multi_process = 1; -static int -linux_nat_supports_multi_process (struct target_ops *self) +bool +linux_nat_target::supports_multi_process () { return linux_multi_process; } -static int -linux_nat_supports_disable_randomization (struct target_ops *self) +bool +linux_nat_target::supports_disable_randomization () { #ifdef HAVE_PERSONALITY return 1; @@ -4458,49 +4330,6 @@ linux_nat_supports_disable_randomization (struct target_ops *self) #endif } -static int async_terminal_is_ours = 1; - -/* target_terminal_inferior implementation. - - This is a wrapper around child_terminal_inferior to add async support. */ - -static void -linux_nat_terminal_inferior (struct target_ops *self) -{ - child_terminal_inferior (self); - - /* Calls to target_terminal_*() are meant to be idempotent. */ - if (!async_terminal_is_ours) - return; - - async_terminal_is_ours = 0; - set_sigint_trap (); -} - -/* target_terminal_ours implementation. - - This is a wrapper around child_terminal_ours to add async support (and - implement the target_terminal_ours vs target_terminal_ours_for_output - distinction). child_terminal_ours is currently no different than - child_terminal_ours_for_output. - We leave target_terminal_ours_for_output alone, leaving it to - child_terminal_ours_for_output. */ - -static void -linux_nat_terminal_ours (struct target_ops *self) -{ - /* GDB should never give the terminal to the inferior if the - inferior is running in the background (run&, continue&, etc.), - but claiming it sure should. */ - child_terminal_ours (self); - - if (async_terminal_is_ours) - return; - - clear_sigint_trap (); - async_terminal_is_ours = 1; -} - /* SIGCHLD handler that serves two purposes: In non-stop/async mode, so we notice when any child changes state, and notify the event-loop; it allows us to use sigsuspend in linux_nat_wait_1 @@ -4571,8 +4400,8 @@ linux_async_pipe (int enable) /* target_async implementation. */ -static void -linux_nat_async (struct target_ops *ops, int enable) +void +linux_nat_target::async (int enable) { if (enable) { @@ -4613,7 +4442,7 @@ linux_nat_stop_lwp (struct lwp_info *lwp, void *data) fprintf_unfiltered (gdb_stdlog, "linux-nat: already stopping LWP %ld at " "GDB's request\n", - ptid_get_lwp (lwp->ptid)); + lwp->ptid.lwp ()); return 0; } @@ -4640,23 +4469,20 @@ linux_nat_stop_lwp (struct lwp_info *lwp, void *data) return 0; } -static void -linux_nat_stop (struct target_ops *self, ptid_t ptid) +void +linux_nat_target::stop (ptid_t ptid) { iterate_over_lwps (ptid, linux_nat_stop_lwp, NULL); } -static void -linux_nat_close (struct target_ops *self) +void +linux_nat_target::close () { /* Unregister from the event loop. */ - if (linux_nat_is_async_p (self)) - linux_nat_async (self, 0); - - if (linux_ops->to_close) - linux_ops->to_close (linux_ops); + if (is_async_p ()) + async (0); - super_close (self); + inf_ptrace_target::close (); } /* When requests are passed down from the linux-nat layer to the @@ -4666,24 +4492,24 @@ linux_nat_close (struct target_ops *self) lwpid is a "main" process id or not (it assumes so). We reverse look up the "main" process id from the lwp here. */ -static struct address_space * -linux_nat_thread_address_space (struct target_ops *t, ptid_t ptid) +struct address_space * +linux_nat_target::thread_address_space (ptid_t ptid) { struct lwp_info *lwp; struct inferior *inf; int pid; - if (ptid_get_lwp (ptid) == 0) + if (ptid.lwp () == 0) { /* An (lwpid,0,0) ptid. Look up the lwp object to get at the tgid. */ lwp = find_lwp_pid (ptid); - pid = ptid_get_pid (lwp->ptid); + pid = lwp->ptid.pid (); } else { /* A (pid,lwpid,0) ptid. */ - pid = ptid_get_pid (ptid); + pid = ptid.pid (); } inf = find_inferior_pid (pid); @@ -4693,8 +4519,8 @@ linux_nat_thread_address_space (struct target_ops *t, ptid_t ptid) /* Return the cached value of the processor core for thread PTID. */ -static int -linux_nat_core_of_thread (struct target_ops *ops, ptid_t ptid) +int +linux_nat_target::core_of_thread (ptid_t ptid) { struct lwp_info *info = find_lwp_pid (ptid); @@ -4705,13 +4531,13 @@ linux_nat_core_of_thread (struct target_ops *ops, ptid_t ptid) /* Implementation of to_filesystem_is_local. */ -static int -linux_nat_filesystem_is_local (struct target_ops *ops) +bool +linux_nat_target::filesystem_is_local () { struct inferior *inf = current_inferior (); if (inf->fake_pid_p || inf->pid == 0) - return 1; + return true; return linux_ns_same (inf->pid, LINUX_NS_MNT); } @@ -4735,11 +4561,10 @@ linux_nat_fileio_pid_of (struct inferior *inf) /* Implementation of to_fileio_open. */ -static int -linux_nat_fileio_open (struct target_ops *self, - struct inferior *inf, const char *filename, - int flags, int mode, int warn_if_slow, - int *target_errno) +int +linux_nat_target::fileio_open (struct inferior *inf, const char *filename, + int flags, int mode, int warn_if_slow, + int *target_errno) { int nat_flags; mode_t nat_mode; @@ -4762,35 +4587,29 @@ linux_nat_fileio_open (struct target_ops *self, /* Implementation of to_fileio_readlink. */ -static char * -linux_nat_fileio_readlink (struct target_ops *self, - struct inferior *inf, const char *filename, - int *target_errno) +gdb::optional +linux_nat_target::fileio_readlink (struct inferior *inf, const char *filename, + int *target_errno) { char buf[PATH_MAX]; int len; - char *ret; len = linux_mntns_readlink (linux_nat_fileio_pid_of (inf), filename, buf, sizeof (buf)); if (len < 0) { *target_errno = host_to_fileio_error (errno); - return NULL; + return {}; } - ret = (char *) xmalloc (len + 1); - memcpy (ret, buf, len); - ret[len] = '\0'; - return ret; + return std::string (buf, len); } /* Implementation of to_fileio_unlink. */ -static int -linux_nat_fileio_unlink (struct target_ops *self, - struct inferior *inf, const char *filename, - int *target_errno) +int +linux_nat_target::fileio_unlink (struct inferior *inf, const char *filename, + int *target_errno) { int ret; @@ -4804,141 +4623,19 @@ linux_nat_fileio_unlink (struct target_ops *self, /* Implementation of the to_thread_events method. */ -static void -linux_nat_thread_events (struct target_ops *ops, int enable) +void +linux_nat_target::thread_events (int enable) { report_thread_events = enable; } -void -linux_nat_add_target (struct target_ops *t) -{ - /* 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_create_inferior = linux_nat_create_inferior; - 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_pass_signals = linux_nat_pass_signals; - 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_update_thread_list = linux_nat_update_thread_list; - t->to_pid_to_str = linux_nat_pid_to_str; - t->to_thread_name = linux_nat_thread_name; - t->to_has_thread_control = tc_schedlock; - t->to_thread_address_space = linux_nat_thread_address_space; - t->to_stopped_by_watchpoint = linux_nat_stopped_by_watchpoint; - t->to_stopped_data_address = linux_nat_stopped_data_address; - t->to_stopped_by_sw_breakpoint = linux_nat_stopped_by_sw_breakpoint; - t->to_supports_stopped_by_sw_breakpoint = linux_nat_supports_stopped_by_sw_breakpoint; - t->to_stopped_by_hw_breakpoint = linux_nat_stopped_by_hw_breakpoint; - t->to_supports_stopped_by_hw_breakpoint = linux_nat_supports_stopped_by_hw_breakpoint; - t->to_thread_events = linux_nat_thread_events; - - t->to_can_async_p = linux_nat_can_async_p; - t->to_is_async_p = linux_nat_is_async_p; - t->to_supports_non_stop = linux_nat_supports_non_stop; - t->to_always_non_stop_p = linux_nat_always_non_stop_p; - t->to_async = linux_nat_async; - t->to_terminal_inferior = linux_nat_terminal_inferior; - t->to_terminal_ours = linux_nat_terminal_ours; - - super_close = t->to_close; - t->to_close = linux_nat_close; - - t->to_stop = linux_nat_stop; - - t->to_supports_multi_process = linux_nat_supports_multi_process; - - t->to_supports_disable_randomization - = linux_nat_supports_disable_randomization; - - t->to_core_of_thread = linux_nat_core_of_thread; - - t->to_filesystem_is_local = linux_nat_filesystem_is_local; - t->to_fileio_open = linux_nat_fileio_open; - t->to_fileio_readlink = linux_nat_fileio_readlink; - t->to_fileio_unlink = linux_nat_fileio_unlink; - +linux_nat_target::linux_nat_target () +{ /* 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); -} - -/* Register a method to call whenever a new thread is attached. */ -void -linux_nat_set_new_thread (struct target_ops *t, - void (*new_thread) (struct lwp_info *)) -{ - /* 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; -} - -/* See declaration in linux-nat.h. */ - -void -linux_nat_set_new_fork (struct target_ops *t, - linux_nat_new_fork_ftype *new_fork) -{ - /* Save the pointer. */ - linux_nat_new_fork = new_fork; -} - -/* See declaration in linux-nat.h. */ - -void -linux_nat_set_forget_process (struct target_ops *t, - linux_nat_forget_process_ftype *fn) -{ - /* Save the pointer. */ - linux_nat_forget_process_hook = fn; -} - -/* See declaration in linux-nat.h. */ - -void -linux_nat_forget_process (pid_t pid) -{ - if (linux_nat_forget_process_hook != NULL) - linux_nat_forget_process_hook (pid); -} - -/* Register a method that converts a siginfo object between the layout - that ptrace returns, and the layout in the architecture of the - inferior. */ -void -linux_nat_set_siginfo_fixup (struct target_ops *t, - int (*siginfo_fixup) (siginfo_t *, - gdb_byte *, - int)) -{ - /* Save the pointer. */ - linux_nat_siginfo_fixup = siginfo_fixup; -} - -/* Register a method to call prior to resuming a thread. */ - -void -linux_nat_set_prepare_to_resume (struct target_ops *t, - void (*prepare_to_resume) (struct lwp_info *)) -{ - /* Save the pointer. */ - linux_nat_prepare_to_resume = prepare_to_resume; } /* See linux-nat.h. */ @@ -4948,9 +4645,9 @@ linux_nat_get_siginfo (ptid_t ptid, siginfo_t *siginfo) { int pid; - pid = ptid_get_lwp (ptid); + pid = ptid.lwp (); if (pid == 0) - pid = ptid_get_pid (ptid); + pid = ptid.pid (); errno = 0; ptrace (PTRACE_GETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, siginfo); @@ -4967,13 +4664,10 @@ linux_nat_get_siginfo (ptid_t ptid, siginfo_t *siginfo) ptid_t current_lwp_ptid (void) { - gdb_assert (ptid_lwp_p (inferior_ptid)); + gdb_assert (inferior_ptid.lwp_p ()); return inferior_ptid; } -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern initialize_file_ftype _initialize_linux_nat; - void _initialize_linux_nat (void) {