X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftarget.c;h=9fd6b4ba9e13d0c9f86504cc5d015c6fdf694cf8;hb=5bb6e9dd7090cacb02bbe9f20d8b101a59a3bf99;hp=78bdfeb49a4a034a7a51f1b19cd044fac5d383a7;hpb=fd3619828e94a24a92cddec42cbc0ab33352eeb4;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/target.c b/gdb/target.c index 78bdfeb49a..9fd6b4ba9e 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1,6 +1,6 @@ /* Select target systems and architectures at runtime for GDB. - Copyright (C) 1990-2019 Free Software Foundation, Inc. + Copyright (C) 1990-2020 Free Software Foundation, Inc. Contributed by Cygnus Support. @@ -49,6 +49,8 @@ #include "gdbsupport/byte-vector.h" #include "terminal.h" #include +#include "target-connection.h" +#include "valprint.h" static void generic_tls_error (void) ATTRIBUTE_NORETURN; @@ -65,9 +67,6 @@ static void default_rcmd (struct target_ops *, const char *, struct ui_file *); static ptid_t default_get_ada_task_ptid (struct target_ops *self, long lwp, long tid); -static int default_follow_fork (struct target_ops *self, int follow_child, - int detach_fork); - static void default_mourn_inferior (struct target_ops *self); static int default_search_memory (struct target_ops *ops, @@ -110,10 +109,6 @@ static std::unordered_map static struct target_ops *the_debug_target; -/* The target stack. */ - -static target_stack g_target_stack; - /* Top of target stack. */ /* The target structure we are currently using to talk to a process or file or whatever "inferior" we have. */ @@ -121,7 +116,7 @@ static target_stack g_target_stack; target_ops * current_top_target () { - return g_target_stack.top (); + return current_inferior ()->top_target (); } /* Command list for target. */ @@ -140,7 +135,7 @@ static int show_memory_breakpoints = 0; /* These globals control whether GDB attempts to perform these operations; they are useful for targets that need to prevent - inadvertant disruption, such as in non-stop mode. */ + inadvertent disruption, such as in non-stop mode. */ bool may_write_registers = true; @@ -174,15 +169,6 @@ show_targetdebug (struct ui_file *file, int from_tty, fprintf_filtered (file, _("Target debugging is %s.\n"), value); } -/* The user just typed 'target' without the name of a target. */ - -static void -target_command (const char *arg, int from_tty) -{ - fputs_filtered ("Argument required (target name). Try `help target'\n", - gdb_stdout); -} - int target_has_all_memory_1 (void) { @@ -223,20 +209,22 @@ target_has_registers_1 (void) return 0; } -int -target_has_execution_1 (ptid_t the_ptid) +bool +target_has_execution_1 (inferior *inf) { - for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ()) - if (t->has_execution (the_ptid)) - return 1; + for (target_ops *t = inf->top_target (); + t != nullptr; + t = inf->find_target_beneath (t)) + if (t->has_execution (inf)) + return true; - return 0; + return false; } int target_has_execution_current (void) { - return target_has_execution_1 (inferior_ptid); + return target_has_execution_1 (current_inferior ()); } /* This is used to implement the various target commands. */ @@ -273,13 +261,13 @@ add_target (const target_info &t, target_open_ftype *func, func_slot = func; if (targetlist == NULL) - add_prefix_cmd ("target", class_run, target_command, _("\ + add_basic_prefix_cmd ("target", class_run, _("\ Connect to a target machine or process.\n\ The first argument is the type or protocol of the target machine.\n\ Remaining arguments are interpreted by the target protocol. For more\n\ information on the arguments for a particular protocol, type\n\ `help target ' followed by the protocol name."), - &targetlist, "target ", 0, &cmdlist); + &targetlist, "target ", 0, &cmdlist); c = add_cmd (t.shortname, no_class, t.doc, &targetlist); set_cmd_context (c, (void *) &t); set_cmd_sfunc (c, open_target); @@ -501,13 +489,16 @@ target_terminal::info (const char *arg, int from_tty) bool target_supports_terminal_ours (void) { - /* This can be called before there is any target, so we must check - for nullptr here. */ - target_ops *top = current_top_target (); + /* The current top target is the target at the top of the target + stack of the current inferior. While normally there's always an + inferior, we must check for nullptr here because we can get here + very early during startup, before the initial inferior is first + created. */ + inferior *inf = current_inferior (); - if (top == nullptr) + if (inf == nullptr) return false; - return top->supports_terminal_ours (); + return inf->top_target ()->supports_terminal_ours (); } static void @@ -555,18 +546,34 @@ to_execution_direction must be implemented for reverse async"); /* See target.h. */ +void +decref_target (target_ops *t) +{ + t->decref (); + if (t->refcount () == 0) + { + if (t->stratum () == process_stratum) + connection_list_remove (as_process_stratum_target (t)); + target_close (t); + } +} + +/* See target.h. */ + void target_stack::push (target_ops *t) { - /* If there's already a target at this stratum, remove it. */ + t->incref (); + strata stratum = t->stratum (); + if (stratum == process_stratum) + connection_list_add (as_process_stratum_target (t)); + + /* If there's already a target at this stratum, remove it. */ + if (m_stack[stratum] != NULL) - { - target_ops *prev = m_stack[stratum]; - m_stack[stratum] = NULL; - target_close (prev); - } + unpush (m_stack[stratum]); /* Now add the new one. */ m_stack[stratum] = t; @@ -580,15 +587,15 @@ target_stack::push (target_ops *t) void push_target (struct target_ops *t) { - g_target_stack.push (t); + current_inferior ()->push_target (t); } -/* See target.h */ +/* See target.h. */ void push_target (target_ops_up &&t) { - g_target_stack.push (t.get ()); + current_inferior ()->push_target (t.get ()); t.release (); } @@ -597,7 +604,7 @@ push_target (target_ops_up &&t) int unpush_target (struct target_ops *t) { - return g_target_stack.unpush (t); + return current_inferior ()->unpush_target (t); } /* See target.h. */ @@ -629,10 +636,13 @@ target_stack::unpush (target_ops *t) if (m_top == stratum) m_top = t->beneath ()->stratum (); - /* Finally close the target. Note we do this after unchaining, so - any target method calls from within the target_close - implementation don't end up in T anymore. */ - target_close (t); + /* Finally close the target, if there are no inferiors + referencing this target still. Note we do this after unchaining, + so any target method calls from within the target_close + implementation don't end up in T anymore. Do leave the target + open if we have are other inferiors referencing this target + still. */ + decref_target (t); return true; } @@ -674,12 +684,13 @@ pop_all_targets (void) pop_all_targets_above (dummy_stratum); } -/* Return 1 if T is now pushed in the target stack. Return 0 otherwise. */ +/* Return true if T is now pushed in the current inferior's target + stack. Return false otherwise. */ -int -target_is_pushed (struct target_ops *t) +bool +target_is_pushed (target_ops *t) { - return g_target_stack.is_pushed (t); + return current_inferior ()->target_is_pushed (t); } /* Default implementation of to_get_thread_local_address. */ @@ -793,81 +804,24 @@ target_xfer_status_to_string (enum target_xfer_status status) }; -#undef MIN -#define MIN(A, B) (((A) <= (B)) ? (A) : (B)) - -/* target_read_string -- read a null terminated string, up to LEN bytes, - from MEMADDR in target. Set *ERRNOP to the errno code, or 0 if successful. - Set *STRING to a pointer to malloc'd memory containing the data; the caller - is responsible for freeing it. Return the number of bytes successfully - read. */ +/* See target.h. */ -int -target_read_string (CORE_ADDR memaddr, gdb::unique_xmalloc_ptr *string, - int len, int *errnop) +gdb::unique_xmalloc_ptr +target_read_string (CORE_ADDR memaddr, int len, int *bytes_read) { - int tlen, offset, i; - gdb_byte buf[4]; - int errcode = 0; - char *buffer; - int buffer_allocated; - char *bufptr; - unsigned int nbytes_read = 0; + gdb::unique_xmalloc_ptr buffer; - gdb_assert (string); + int ignore; + if (bytes_read == nullptr) + bytes_read = &ignore; - /* Small for testing. */ - buffer_allocated = 4; - buffer = (char *) xmalloc (buffer_allocated); - bufptr = buffer; - - while (len > 0) - { - tlen = MIN (len, 4 - (memaddr & 3)); - offset = memaddr & 3; - - errcode = target_read_memory (memaddr & ~3, buf, sizeof buf); - if (errcode != 0) - { - /* The transfer request might have crossed the boundary to an - unallocated region of memory. Retry the transfer, requesting - a single byte. */ - tlen = 1; - offset = 0; - errcode = target_read_memory (memaddr, buf, 1); - if (errcode != 0) - goto done; - } - - if (bufptr - buffer + tlen > buffer_allocated) - { - unsigned int bytes; - - bytes = bufptr - buffer; - buffer_allocated *= 2; - buffer = (char *) xrealloc (buffer, buffer_allocated); - bufptr = buffer + bytes; - } - - for (i = 0; i < tlen; i++) - { - *bufptr++ = buf[i + offset]; - if (buf[i + offset] == '\000') - { - nbytes_read += i + 1; - goto done; - } - } + /* Note that the endian-ness does not matter here. */ + int errcode = read_string (memaddr, -1, 1, len, BFD_ENDIAN_LITTLE, + &buffer, bytes_read); + if (errcode != 0) + return {}; - memaddr += tlen; - len -= tlen; - nbytes_read += tlen; - } -done: - string->reset (buffer); - if (errnop != NULL) - *errnop = errcode; - return nbytes_read; + return gdb::unique_xmalloc_ptr ((char *) buffer.release ()); } struct target_section_table * @@ -971,8 +925,11 @@ raw_memory_xfer_partial (struct target_ops *ops, gdb_byte *readbuf, if (res == TARGET_XFER_UNAVAILABLE) break; - /* We want to continue past core files to executables, but not - past a running target's memory. */ + /* Don't continue past targets which have all the memory. + At one time, this code was necessary to read data from + executables / shared libraries when data for the requested + addresses weren't available in the core file. But now the + core target handles this case itself. */ if (ops->has_all_memory ()) break; @@ -1026,11 +983,17 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object, const char *section_name = section->the_bfd_section->name; memaddr = overlay_mapped_address (memaddr, section); + + auto match_cb = [=] (const struct target_section *s) + { + return (strcmp (section_name, s->the_bfd_section->name) == 0); + }; + return section_table_xfer_memory_partial (readbuf, writebuf, memaddr, len, xfered_len, table->sections, table->sections_end, - section_name); + match_cb); } } @@ -1048,8 +1011,7 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object, return section_table_xfer_memory_partial (readbuf, writebuf, memaddr, len, xfered_len, table->sections, - table->sections_end, - NULL); + table->sections_end); } } @@ -1951,33 +1913,6 @@ target_pre_inferior (int from_tty) agent_capability_invalidate (); } -/* Callback for iterate_over_inferiors. Gets rid of the given - inferior. */ - -static int -dispose_inferior (struct inferior *inf, void *args) -{ - /* Not all killed inferiors can, or will ever be, removed from the - inferior list. Killed inferiors clearly don't need to be killed - again, so, we're done. */ - if (inf->pid == 0) - return 0; - - thread_info *thread = any_thread_of_inferior (inf); - if (thread != NULL) - { - switch_to_thread (thread); - - /* Core inferiors actually should be detached, not killed. */ - if (target_has_execution) - target_kill (); - else - target_detach (inf, 0); - } - - return 0; -} - /* This is to be called by the open routine before it does anything. */ @@ -1986,12 +1921,19 @@ target_preopen (int from_tty) { dont_repeat (); - if (have_inferiors ()) + if (current_inferior ()->pid != 0) { if (!from_tty - || !have_live_inferiors () + || !target_has_execution || query (_("A program is being debugged already. Kill it? "))) - iterate_over_inferiors (dispose_inferior, NULL); + { + /* Core inferiors actually should be detached, not + killed. */ + if (target_has_execution) + target_kill (); + else + target_detach (current_inferior (), 0); + } else error (_("Program not killed.")); } @@ -2033,9 +1975,16 @@ target_detach (inferior *inf, int from_tty) prepare_for_detach (); + /* Hold a strong reference because detaching may unpush the + target. */ + auto proc_target_ref = target_ops_ref::new_reference (inf->process_target ()); + current_top_target ()->detach (inf, from_tty); - registers_changed_ptid (save_pid_ptid); + process_stratum_target *proc_target + = as_process_stratum_target (proc_target_ref.get ()); + + registers_changed_ptid (proc_target, save_pid_ptid); /* We have to ensure we have no frame cache left. Normally, registers_changed_ptid (save_pid_ptid) calls reinit_frame_cache when @@ -2058,7 +2007,8 @@ target_disconnect (const char *args, int from_tty) /* See target/target.h. */ ptid_t -target_wait (ptid_t ptid, struct target_waitstatus *status, int options) +target_wait (ptid_t ptid, struct target_waitstatus *status, + target_wait_flags options) { return current_top_target ()->wait (ptid, status, options); } @@ -2068,7 +2018,7 @@ target_wait (ptid_t ptid, struct target_waitstatus *status, int options) ptid_t default_target_wait (struct target_ops *ops, ptid_t ptid, struct target_waitstatus *status, - int options) + target_wait_flags options) { status->kind = TARGET_WAITKIND_IGNORE; return minus_one_ptid; @@ -2083,6 +2033,8 @@ target_pid_to_str (ptid_t ptid) const char * target_thread_name (struct thread_info *info) { + gdb_assert (info->inf == current_inferior ()); + return current_top_target ()->thread_name (info); } @@ -2106,16 +2058,18 @@ target_thread_info_to_thread_handle (struct thread_info *tip) void target_resume (ptid_t ptid, int step, enum gdb_signal signal) { + process_stratum_target *curr_target = current_inferior ()->process_target (); + target_dcache_invalidate (); current_top_target ()->resume (ptid, step, signal); - registers_changed_ptid (ptid); + registers_changed_ptid (curr_target, ptid); /* We only set the internal executing state here. The user/frontend running state is set at a higher level. This also clears the thread's stop_pc as side effect. */ - set_executing (ptid, 1); - clear_inline_frame_state (ptid); + set_executing (curr_target, ptid, true); + clear_inline_frame_state (curr_target, ptid); } /* If true, target_commit_resume is a nop. */ @@ -2152,9 +2106,9 @@ target_program_signals (gdb::array_view program_signals) current_top_target ()->program_signals (program_signals); } -static int -default_follow_fork (struct target_ops *self, int follow_child, - int detach_fork) +static bool +default_follow_fork (struct target_ops *self, bool follow_child, + bool detach_fork) { /* Some target returned a fork event, but did not know how to follow it. */ internal_error (__FILE__, __LINE__, @@ -2164,8 +2118,8 @@ default_follow_fork (struct target_ops *self, int follow_child, /* Look through the list of possible targets for a target that can follow forks. */ -int -target_follow_fork (int follow_child, int detach_fork) +bool +target_follow_fork (bool follow_child, bool detach_fork) { return current_top_target ()->follow_fork (follow_child, detach_fork); } @@ -2540,7 +2494,6 @@ target_get_osdata (const char *type) return target_read_stralloc (t, TARGET_OBJECT_OSDATA, type); } - /* Determine the current address space of thread PTID. */ struct address_space * @@ -2559,7 +2512,7 @@ target_thread_address_space (ptid_t ptid) target_ops * target_ops::beneath () const { - return g_target_stack.find_beneath (this); + return current_inferior ()->find_target_beneath (this); } void @@ -2775,13 +2728,11 @@ target_ops::fileio_readlink (struct inferior *inf, const char *filename, return {}; } -/* Helper for target_fileio_open and - target_fileio_open_warn_if_slow. */ +/* See target.h. */ -static int -target_fileio_open_1 (struct inferior *inf, const char *filename, - int flags, int mode, int warn_if_slow, - int *target_errno) +int +target_fileio_open (struct inferior *inf, const char *filename, + int flags, int mode, bool warn_if_slow, int *target_errno) { for (target_ops *t = default_fileio_target (); t != NULL; t = t->beneath ()) { @@ -2813,27 +2764,6 @@ target_fileio_open_1 (struct inferior *inf, const char *filename, /* See target.h. */ -int -target_fileio_open (struct inferior *inf, const char *filename, - int flags, int mode, int *target_errno) -{ - return target_fileio_open_1 (inf, filename, flags, mode, 0, - target_errno); -} - -/* See target.h. */ - -int -target_fileio_open_warn_if_slow (struct inferior *inf, - const char *filename, - int flags, int mode, int *target_errno) -{ - return target_fileio_open_1 (inf, filename, flags, mode, 1, - target_errno); -} - -/* See target.h. */ - int target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len, ULONGEST offset, int *target_errno) @@ -3036,7 +2966,7 @@ target_fileio_read_alloc_1 (struct inferior *inf, const char *filename, int target_errno; scoped_target_fd fd (target_fileio_open (inf, filename, FILEIO_O_RDONLY, - 0700, &target_errno)); + 0700, false, &target_errno)); if (fd.get () == -1) return -1; @@ -3155,7 +3085,7 @@ target_stack::find_beneath (const target_ops *t) const struct target_ops * find_target_at (enum strata stratum) { - return g_target_stack.at (stratum); + return current_inferior ()->target_at (stratum); } @@ -3187,7 +3117,7 @@ generic_mourn_inferior (void) { inferior *inf = current_inferior (); - inferior_ptid = null_ptid; + switch_to_no_thread (); /* Mark breakpoints uninserted in case something tries to delete a breakpoint while we delete the inferior's threads (which would @@ -3251,6 +3181,14 @@ dummy_make_corefile_notes (struct target_ops *self, static dummy_target the_dummy_target; +/* See target.h. */ + +target_ops * +get_dummy_target () +{ + return &the_dummy_target; +} + static const target_info dummy_target_info = { "None", N_("None"), @@ -3337,7 +3275,33 @@ target_interrupt () void target_pass_ctrlc (void) { - current_top_target ()->pass_ctrlc (); + /* Pass the Ctrl-C to the first target that has a thread + running. */ + for (inferior *inf : all_inferiors ()) + { + target_ops *proc_target = inf->process_target (); + if (proc_target == NULL) + continue; + + for (thread_info *thr : inf->non_exited_threads ()) + { + /* A thread can be THREAD_STOPPED and executing, while + running an infcall. */ + if (thr->state == THREAD_RUNNING || thr->executing) + { + /* We can get here quite deep in target layers. Avoid + switching thread context or anything that would + communicate with the target (e.g., to fetch + registers), or flushing e.g., the frame cache. We + just switch inferior in order to be able to call + through the target_stack. */ + scoped_restore_current_inferior restore_inferior; + set_current_inferior (inf); + current_top_target ()->pass_ctrlc (); + return; + } + } + } } /* See target.h. */ @@ -3397,8 +3361,8 @@ str_comma_list_concat_elem (std::string *list, const char *elem) OPT is removed from TARGET_OPTIONS. */ static void -do_option (int *target_options, std::string *ret, - int opt, const char *opt_str) +do_option (target_wait_flags *target_options, std::string *ret, + target_wait_flag opt, const char *opt_str) { if ((*target_options & opt) != 0) { @@ -3410,7 +3374,7 @@ do_option (int *target_options, std::string *ret, /* See target.h. */ std::string -target_options_to_string (int target_options) +target_options_to_string (target_wait_flags target_options) { std::string ret; @@ -3888,6 +3852,26 @@ target_is_non_stop_p (void) && target_always_non_stop_p ())); } +/* See target.h. */ + +bool +exists_non_stop_target () +{ + if (target_is_non_stop_p ()) + return true; + + scoped_restore_current_thread restore_thread; + + for (inferior *inf : all_inferiors ()) + { + switch_to_inferior_no_thread (inf); + if (target_is_non_stop_p ()) + return true; + } + + return false; +} + /* Controls if targets can report that they always run in non-stop mode. This is just for maintainers to use when debugging gdb. */ enum auto_boolean target_non_stop_enabled = AUTO_BOOLEAN_AUTO; @@ -3984,11 +3968,11 @@ set_write_memory_permission (const char *args, int from_tty, update_observer_mode (); } +void _initialize_target (); + void -initialize_targets (void) +_initialize_target () { - push_target (&the_dummy_target); - the_debug_target = new debug_target (); add_info ("target", info_target_command, targ_desc);