X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fgdbserver%2Ftarget.c;h=25f91eeba739ce0a4cce3bd8300e4fba97811b87;hb=353ea2d106a51cfd1680f7d351f35eb8f69c9248;hp=08506e516bceb384a1787ac2cb5d4eef15b0d6d7;hpb=721ec300e1e27c2fa7540ef97f39b6c5ce65083f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/gdbserver/target.c b/gdb/gdbserver/target.c index 08506e516b..25f91eeba7 100644 --- a/gdb/gdbserver/target.c +++ b/gdb/gdbserver/target.c @@ -1,5 +1,5 @@ /* Target operations for the remote server for GDB. - Copyright (C) 2002-2014 Free Software Foundation, Inc. + Copyright (C) 2002-2019 Free Software Foundation, Inc. Contributed by MontaVista Software. @@ -23,20 +23,102 @@ struct target_ops *the_target; -void -set_desired_inferior (int use_general) +int +set_desired_thread () { - struct thread_info *found; + client_state &cs = get_client_state (); + thread_info *found = find_thread_ptid (cs.general_thread); - if (use_general == 1) - found = find_thread_ptid (general_thread); - else - found = find_thread_ptid (cont_thread); + current_thread = found; + return (current_thread != NULL); +} + +/* The thread that was current before prepare_to_access_memory was + called. done_accessing_memory uses this to restore the previous + selected thread. */ +static ptid_t prev_general_thread; + +/* See target.h. */ + +int +prepare_to_access_memory (void) +{ + client_state &cs = get_client_state (); + + /* The first thread found. */ + struct thread_info *first = NULL; + /* The first stopped thread found. */ + struct thread_info *stopped = NULL; + /* The current general thread, if found. */ + struct thread_info *current = NULL; + + /* Save the general thread value, since prepare_to_access_memory could change + it. */ + prev_general_thread = cs.general_thread; + + if (the_target->prepare_to_access_memory != NULL) + { + int res; + + res = the_target->prepare_to_access_memory (); + if (res != 0) + return res; + } - if (found == NULL) - current_inferior = get_first_thread (); + for_each_thread (prev_general_thread.pid (), [&] (thread_info *thread) + { + if (mythread_alive (thread->id)) + { + if (stopped == NULL && the_target->thread_stopped != NULL + && thread_stopped (thread)) + stopped = thread; + + if (first == NULL) + first = thread; + + if (current == NULL && prev_general_thread == thread->id) + current = thread; + } + }); + + /* The thread we end up choosing. */ + struct thread_info *thread; + + /* Prefer a stopped thread. If none is found, try the current + thread. Otherwise, take the first thread in the process. If + none is found, undo the effects of + target->prepare_to_access_memory() and return error. */ + if (stopped != NULL) + thread = stopped; + else if (current != NULL) + thread = current; + else if (first != NULL) + thread = first; else - current_inferior = found; + { + done_accessing_memory (); + return 1; + } + + current_thread = thread; + cs.general_thread = ptid_of (thread); + + return 0; +} + +/* See target.h. */ + +void +done_accessing_memory (void) +{ + client_state &cs = get_client_state (); + + if (the_target->done_accessing_memory != NULL) + the_target->done_accessing_memory (); + + /* Restore the previous selected thread. */ + cs.general_thread = prev_general_thread; + switch_to_thread (cs.general_thread); } int @@ -77,7 +159,7 @@ write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr, if (buffer != NULL) free (buffer); - buffer = xmalloc (len); + buffer = (unsigned char *) xmalloc (len); memcpy (buffer, myaddr, len); check_mem_write (memaddr, buffer, myaddr, len); res = (*the_target->write_memory) (memaddr, buffer, len); @@ -104,7 +186,7 @@ mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options, if (connected_wait) server_waiting = 1; - ret = (*the_target->wait) (ptid, ourstatus, options); + ret = target_wait (ptid, ourstatus, options); /* We don't expose _LOADED events to gdbserver core. See the `dlls_changed' global. */ @@ -134,6 +216,76 @@ mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options, return ret; } +/* See target/target.h. */ + +void +target_stop_and_wait (ptid_t ptid) +{ + struct target_waitstatus status; + int was_non_stop = non_stop; + struct thread_resume resume_info; + + resume_info.thread = ptid; + resume_info.kind = resume_stop; + resume_info.sig = GDB_SIGNAL_0; + (*the_target->resume) (&resume_info, 1); + + non_stop = 1; + mywait (ptid, &status, 0, 0); + non_stop = was_non_stop; +} + +/* See target/target.h. */ + +ptid_t +target_wait (ptid_t ptid, struct target_waitstatus *status, int options) +{ + return (*the_target->wait) (ptid, status, options); +} + +/* See target/target.h. */ + +void +target_mourn_inferior (ptid_t ptid) +{ + (*the_target->mourn) (find_process_pid (ptid.pid ())); +} + +/* See target/target.h. */ + +void +target_continue_no_signal (ptid_t ptid) +{ + struct thread_resume resume_info; + + resume_info.thread = ptid; + resume_info.kind = resume_continue; + resume_info.sig = GDB_SIGNAL_0; + (*the_target->resume) (&resume_info, 1); +} + +/* See target/target.h. */ + +void +target_continue (ptid_t ptid, enum gdb_signal signal) +{ + struct thread_resume resume_info; + + resume_info.thread = ptid; + resume_info.kind = resume_continue; + resume_info.sig = gdb_signal_to_host (signal); + (*the_target->resume) (&resume_info, 1); +} + +/* See target/target.h. */ + +int +target_supports_multi_process (void) +{ + return (the_target->supports_multi_process != NULL ? + (*the_target->supports_multi_process) () : 0); +} + int start_non_stop (int nonstop) { @@ -151,7 +303,7 @@ start_non_stop (int nonstop) void set_target_ops (struct target_ops *target) { - the_target = (struct target_ops *) xmalloc (sizeof (*the_target)); + the_target = XNEW (struct target_ops); memcpy (the_target, target, sizeof (*the_target)); } @@ -162,27 +314,99 @@ target_pid_to_str (ptid_t ptid) { static char buf[80]; - if (ptid_equal (ptid, minus_one_ptid)) + if (ptid == minus_one_ptid) xsnprintf (buf, sizeof (buf), ""); - else if (ptid_equal (ptid, null_ptid)) + else if (ptid == null_ptid) xsnprintf (buf, sizeof (buf), ""); - else if (ptid_get_tid (ptid) != 0) + else if (ptid.tid () != 0) xsnprintf (buf, sizeof (buf), "Thread %d.0x%lx", - ptid_get_pid (ptid), ptid_get_tid (ptid)); - else if (ptid_get_lwp (ptid) != 0) + ptid.pid (), ptid.tid ()); + else if (ptid.lwp () != 0) xsnprintf (buf, sizeof (buf), "LWP %d.%ld", - ptid_get_pid (ptid), ptid_get_lwp (ptid)); + ptid.pid (), ptid.lwp ()); else xsnprintf (buf, sizeof (buf), "Process %d", - ptid_get_pid (ptid)); + ptid.pid ()); return buf; } int -kill_inferior (int pid) +kill_inferior (process_info *proc) +{ + gdb_agent_about_to_close (proc->pid); + + return (*the_target->kill) (proc); +} + +/* Target can do hardware single step. */ + +int +target_can_do_hardware_single_step (void) +{ + return 1; +} + +/* Default implementation for breakpoint_kind_for_pc. + + The default behavior for targets that don't implement breakpoint_kind_for_pc + is to use the size of a breakpoint as the kind. */ + +int +default_breakpoint_kind_from_pc (CORE_ADDR *pcptr) { - gdb_agent_about_to_close (pid); + int size = 0; + + gdb_assert (the_target->sw_breakpoint_from_kind != NULL); + + (*the_target->sw_breakpoint_from_kind) (0, &size); + return size; +} - return (*the_target->kill) (pid); +/* Define it. */ + +target_terminal_state target_terminal::m_terminal_state + = target_terminal_state::is_ours; + +/* See target/target.h. */ + +void +target_terminal::init () +{ + /* Placeholder needed because of fork_inferior. Not necessary on + GDBserver. */ +} + +/* See target/target.h. */ + +void +target_terminal::inferior () +{ + /* Placeholder needed because of fork_inferior. Not necessary on + GDBserver. */ +} + +/* See target/target.h. */ + +void +target_terminal::ours () +{ + /* Placeholder needed because of fork_inferior. Not necessary on + GDBserver. */ +} + +/* See target/target.h. */ + +void +target_terminal::ours_for_output (void) +{ + /* Placeholder. */ +} + +/* See target/target.h. */ + +void +target_terminal::info (const char *arg, int from_tty) +{ + /* Placeholder. */ }