a068643d69
Currently the target pid_to_str method returns a const char *, so many implementations have a static buffer that they update. This patch changes these methods to return a std::string instead. I think this is cleaner and avoids possible gotchas when calling pid_to_str on different ptids in a single statement. (Though no such calls exist currently.) This also updates various helper functions, and the gdbarch pid_to_str methods. I also made a best effort to fix all the callers, but I can't build some of the *-nat.c files. Tested by the buildbot. gdb/ChangeLog 2019-03-13 Tom Tromey <tromey@adacore.com> * i386-gnu-nat.c (i386_gnu_nat_target::fetch_registers) (i386_gnu_nat_target::store_registers): Update. * target-debug.h (target_debug_print_std_string): New macro. * x86-linux-nat.c (x86_linux_nat_target::enable_btrace): Update. * windows-tdep.c (display_one_tib): Update. * tui/tui-stack.c (tui_make_status_line): Update. * top.c (print_inferior_quit_action): Update. * thread.c (thr_try_catch_cmd): Update. (add_thread_with_info): Update. (thread_target_id_str): Update. (thr_try_catch_cmd): Update. (thread_command): Update. (thread_find_command): Update. * record-btrace.c (record_btrace_target::info_record) (record_btrace_resume_thread, record_btrace_target::resume) (record_btrace_cancel_resume, record_btrace_step_thread) (record_btrace_target::wait, record_btrace_target::wait) (record_btrace_target::wait, record_btrace_target::stop): Update. * progspace.c (print_program_space): Update. * process-stratum-target.c (process_stratum_target::thread_address_space): Update. * linux-fork.c (linux_fork_mourn_inferior) (detach_checkpoint_command, info_checkpoints_command) (linux_fork_context): Update. (linux_fork_detach): Update. (class scoped_switch_fork_info): Update. (delete_checkpoint_command): Update. * infrun.c (follow_fork_inferior): Update. (follow_fork_inferior): Update. (proceed_after_vfork_done): Update. (handle_vfork_child_exec_or_exit): Update. (follow_exec): Update. (displaced_step_prepare_throw): Update. (displaced_step_restore): Update. (start_step_over): Update. (resume_1): Update. (clear_proceed_status_thread): Update. (proceed): Update. (print_target_wait_results): Update. (do_target_wait): Update. (context_switch): Update. (stop_all_threads): Update. (restart_threads): Update. (finish_step_over): Update. (handle_signal_stop): Update. (switch_back_to_stepped_thread): Update. (keep_going_pass_signal): Update. (print_exited_reason): Update. (normal_stop): Update. * inferior.c (inferior_pid_to_str): Change return type. (print_selected_inferior): Update. (add_inferior): Update. (detach_inferior): Update. * dummy-frame.c (fprint_dummy_frames): Update. * dcache.c (dcache_info_1): Update. * btrace.c (btrace_enable, btrace_disable, btrace_teardown) (btrace_fetch, btrace_clear): Update. * linux-tdep.c (linux_core_pid_to_str): Change return type. * i386-cygwin-tdep.c (i386_windows_core_pid_to_str): Change return type. * fbsd-tdep.c (fbsd_core_pid_to_str): Change return type. * sol2-tdep.h (sol2_core_pid_to_str): Change return type. * sol2-tdep.c (sol2_core_pid_to_str): Change return type. * gdbarch.c, gdbarch.h: Rebuild. * gdbarch.sh (core_pid_to_str): Change return type. * windows-nat.c (struct windows_nat_target) <pid_to_str>: Change return type. (windows_nat_target::pid_to_str): Change return type. (windows_delete_thread): Update. (windows_nat_target::attach): Update. (windows_nat_target::files_info): Update. * target-delegates.c: Rebuild. * sol-thread.c (class sol_thread_target) <pid_to_str>: Change return type. (sol_thread_target::pid_to_str): Change return type. * remote.c (class remote_target) <pid_to_str>: Change return type. (remote_target::pid_to_str): Change return type. (extended_remote_target::attach, remote_target::remote_stop_ns) (remote_target::remote_notif_remove_queued_reply) (remote_target::push_stop_reply, remote_target::disable_btrace): Update. (extended_remote_target::attach): Update. * remote-sim.c (struct gdbsim_target) <pid_to_str>: Change return type. (gdbsim_target::pid_to_str): Change return type. * ravenscar-thread.c (struct ravenscar_thread_target) <pid_to_str>: Change return type. (ravenscar_thread_target::pid_to_str): Change return type. * procfs.c (class procfs_target) <pid_to_str>: Change return type. (procfs_target::pid_to_str): Change return type. (procfs_target::attach): Update. (procfs_target::detach): Update. (procfs_target::fetch_registers): Update. (procfs_target::store_registers): Update. (procfs_target::wait): Update. (procfs_target::files_info): Update. * obsd-nat.c (obsd_nat_target::pid_to_str): Change return type. * nto-procfs.c (struct nto_procfs_target) <pid_to_str>: Change return type. (nto_procfs_target::pid_to_str): Change return type. (nto_procfs_target::files_info, nto_procfs_target::attach): Update. * linux-thread-db.c (class thread_db_target) <pid_to_str>: Change return type. * linux-nat.c (linux_nat_target::pid_to_str): Change return type. (exit_lwp): Update. (attach_proc_task_lwp_callback, get_detach_signal) (detach_one_lwp, resume_lwp, linux_nat_target::resume) (linux_nat_target::resume, wait_lwp, stop_callback) (maybe_clear_ignore_sigint, stop_wait_callback, status_callback) (save_stop_reason, select_event_lwp, linux_nat_filter_event) (linux_nat_wait_1, resume_stopped_resumed_lwps) (linux_nat_target::wait, linux_nat_stop_lwp): Update. * inf-ptrace.c (inf_ptrace_target::pid_to_str): Change return type. (inf_ptrace_target::attach): Update. (inf_ptrace_target::files_info): Update. * go32-nat.c (struct go32_nat_target) <pid_to_str>: Change return type. (go32_nat_target::pid_to_str): Change return type. * gnu-nat.c (gnu_nat_target::pid_to_str): Change return type. (gnu_nat_target::wait): Update. (gnu_nat_target::wait): Update. (gnu_nat_target::resume): Update. * fbsd-nat.c (fbsd_nat_target::pid_to_str): Change return type. (fbsd_nat_target::wait): Update. * darwin-nat.c (darwin_nat_target::pid_to_str): Change return type. (darwin_nat_target::attach): Update. * corelow.c (class core_target) <pid_to_str>: Change return type. (core_target::pid_to_str): Change return type. * target.c (normal_pid_to_str): Change return type. (default_pid_to_str): Likewise. (target_pid_to_str): Change return type. (target_translate_tls_address): Update. (target_announce_detach): Update. * bsd-uthread.c (struct bsd_uthread_target) <pid_to_str>: Change return type. (bsd_uthread_target::pid_to_str): Change return type. * bsd-kvm.c (class bsd_kvm_target) <pid_to_str>: Change return type. (bsd_kvm_target::pid_to_str): Change return type. * aix-thread.c (class aix_thread_target) <pid_to_str>: Change return type. (aix_thread_target::pid_to_str): Change return type. * target.h (struct target_ops) <pid_to_str>: Change return type. (target_pid_to_str, normal_pid_to_str): Likewise. * obsd-nat.h (class obsd_nat_target) <pid_to_str>: Change return type. * linux-nat.h (class linux_nat_target) <pid_to_str>: Change return type. * inf-ptrace.h (struct inf_ptrace_target) <pid_to_str>: Change return type. * gnu-nat.h (struct gnu_nat_target) <pid_to_str>: Change return type. * fbsd-nat.h (class fbsd_nat_target) <pid_to_str>: Change return type. * darwin-nat.h (class darwin_nat_target) <pid_to_str>: Change return type.
427 lines
11 KiB
C
427 lines
11 KiB
C
/* Program and address space management, for GDB, the GNU debugger.
|
||
|
||
Copyright (C) 2009-2019 Free Software Foundation, Inc.
|
||
|
||
This file is part of GDB.
|
||
|
||
This program is free software; you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation; either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||
|
||
#include "defs.h"
|
||
#include "gdbcmd.h"
|
||
#include "objfiles.h"
|
||
#include "arch-utils.h"
|
||
#include "gdbcore.h"
|
||
#include "solib.h"
|
||
#include "gdbthread.h"
|
||
#include "inferior.h"
|
||
|
||
/* The last program space number assigned. */
|
||
int last_program_space_num = 0;
|
||
|
||
/* The head of the program spaces list. */
|
||
struct program_space *program_spaces;
|
||
|
||
/* Pointer to the current program space. */
|
||
struct program_space *current_program_space;
|
||
|
||
/* The last address space number assigned. */
|
||
static int highest_address_space_num;
|
||
|
||
|
||
|
||
/* Keep a registry of per-program_space data-pointers required by other GDB
|
||
modules. */
|
||
|
||
DEFINE_REGISTRY (program_space, REGISTRY_ACCESS_FIELD)
|
||
|
||
/* Keep a registry of per-address_space data-pointers required by other GDB
|
||
modules. */
|
||
|
||
DEFINE_REGISTRY (address_space, REGISTRY_ACCESS_FIELD)
|
||
|
||
|
||
|
||
/* Create a new address space object, and add it to the list. */
|
||
|
||
struct address_space *
|
||
new_address_space (void)
|
||
{
|
||
struct address_space *aspace;
|
||
|
||
aspace = XCNEW (struct address_space);
|
||
aspace->num = ++highest_address_space_num;
|
||
address_space_alloc_data (aspace);
|
||
|
||
return aspace;
|
||
}
|
||
|
||
/* Maybe create a new address space object, and add it to the list, or
|
||
return a pointer to an existing address space, in case inferiors
|
||
share an address space on this target system. */
|
||
|
||
struct address_space *
|
||
maybe_new_address_space (void)
|
||
{
|
||
int shared_aspace = gdbarch_has_shared_address_space (target_gdbarch ());
|
||
|
||
if (shared_aspace)
|
||
{
|
||
/* Just return the first in the list. */
|
||
return program_spaces->aspace;
|
||
}
|
||
|
||
return new_address_space ();
|
||
}
|
||
|
||
static void
|
||
free_address_space (struct address_space *aspace)
|
||
{
|
||
address_space_free_data (aspace);
|
||
xfree (aspace);
|
||
}
|
||
|
||
int
|
||
address_space_num (struct address_space *aspace)
|
||
{
|
||
return aspace->num;
|
||
}
|
||
|
||
/* Start counting over from scratch. */
|
||
|
||
static void
|
||
init_address_spaces (void)
|
||
{
|
||
highest_address_space_num = 0;
|
||
}
|
||
|
||
|
||
|
||
/* Adds a new empty program space to the program space list, and binds
|
||
it to ASPACE. Returns the pointer to the new object. */
|
||
|
||
program_space::program_space (address_space *aspace_)
|
||
: num (++last_program_space_num), aspace (aspace_)
|
||
{
|
||
program_space_alloc_data (this);
|
||
|
||
if (program_spaces == NULL)
|
||
program_spaces = this;
|
||
else
|
||
{
|
||
struct program_space *last;
|
||
|
||
for (last = program_spaces; last->next != NULL; last = last->next)
|
||
;
|
||
last->next = this;
|
||
}
|
||
}
|
||
|
||
/* Releases program space PSPACE, and all its contents (shared
|
||
libraries, objfiles, and any other references to the PSPACE in
|
||
other modules). It is an internal error to call this when PSPACE
|
||
is the current program space, since there should always be a
|
||
program space. */
|
||
|
||
program_space::~program_space ()
|
||
{
|
||
gdb_assert (this != current_program_space);
|
||
|
||
scoped_restore_current_program_space restore_pspace;
|
||
|
||
set_current_program_space (this);
|
||
|
||
breakpoint_program_space_exit (this);
|
||
no_shared_libraries (NULL, 0);
|
||
exec_close ();
|
||
free_all_objfiles ();
|
||
if (!gdbarch_has_shared_address_space (target_gdbarch ()))
|
||
free_address_space (this->aspace);
|
||
clear_section_table (&this->target_sections);
|
||
clear_program_space_solib_cache (this);
|
||
/* Discard any data modules have associated with the PSPACE. */
|
||
program_space_free_data (this);
|
||
}
|
||
|
||
/* Copies program space SRC to DEST. Copies the main executable file,
|
||
and the main symbol file. Returns DEST. */
|
||
|
||
struct program_space *
|
||
clone_program_space (struct program_space *dest, struct program_space *src)
|
||
{
|
||
scoped_restore_current_program_space restore_pspace;
|
||
|
||
set_current_program_space (dest);
|
||
|
||
if (src->pspace_exec_filename != NULL)
|
||
exec_file_attach (src->pspace_exec_filename, 0);
|
||
|
||
if (src->symfile_object_file != NULL)
|
||
symbol_file_add_main (objfile_name (src->symfile_object_file),
|
||
SYMFILE_DEFER_BP_RESET);
|
||
|
||
return dest;
|
||
}
|
||
|
||
/* Sets PSPACE as the current program space. It is the caller's
|
||
responsibility to make sure that the currently selected
|
||
inferior/thread matches the selected program space. */
|
||
|
||
void
|
||
set_current_program_space (struct program_space *pspace)
|
||
{
|
||
if (current_program_space == pspace)
|
||
return;
|
||
|
||
gdb_assert (pspace != NULL);
|
||
|
||
current_program_space = pspace;
|
||
|
||
/* Different symbols change our view of the frame chain. */
|
||
reinit_frame_cache ();
|
||
}
|
||
|
||
/* Returns true iff there's no inferior bound to PSPACE. */
|
||
|
||
int
|
||
program_space_empty_p (struct program_space *pspace)
|
||
{
|
||
if (find_inferior_for_program_space (pspace) != NULL)
|
||
return 0;
|
||
|
||
return 1;
|
||
}
|
||
|
||
/* Remove a program space from the program spaces list and release it. It is
|
||
an error to call this function while PSPACE is the current program space. */
|
||
|
||
void
|
||
delete_program_space (struct program_space *pspace)
|
||
{
|
||
struct program_space *ss, **ss_link;
|
||
gdb_assert (pspace != NULL);
|
||
gdb_assert (pspace != current_program_space);
|
||
|
||
ss = program_spaces;
|
||
ss_link = &program_spaces;
|
||
while (ss != NULL)
|
||
{
|
||
if (ss == pspace)
|
||
{
|
||
*ss_link = ss->next;
|
||
break;
|
||
}
|
||
|
||
ss_link = &ss->next;
|
||
ss = *ss_link;
|
||
}
|
||
|
||
delete pspace;
|
||
}
|
||
|
||
/* Prints the list of program spaces and their details on UIOUT. If
|
||
REQUESTED is not -1, it's the ID of the pspace that should be
|
||
printed. Otherwise, all spaces are printed. */
|
||
|
||
static void
|
||
print_program_space (struct ui_out *uiout, int requested)
|
||
{
|
||
struct program_space *pspace;
|
||
int count = 0;
|
||
|
||
/* Compute number of pspaces we will print. */
|
||
ALL_PSPACES (pspace)
|
||
{
|
||
if (requested != -1 && pspace->num != requested)
|
||
continue;
|
||
|
||
++count;
|
||
}
|
||
|
||
/* There should always be at least one. */
|
||
gdb_assert (count > 0);
|
||
|
||
ui_out_emit_table table_emitter (uiout, 3, count, "pspaces");
|
||
uiout->table_header (1, ui_left, "current", "");
|
||
uiout->table_header (4, ui_left, "id", "Id");
|
||
uiout->table_header (17, ui_left, "exec", "Executable");
|
||
uiout->table_body ();
|
||
|
||
ALL_PSPACES (pspace)
|
||
{
|
||
struct inferior *inf;
|
||
int printed_header;
|
||
|
||
if (requested != -1 && requested != pspace->num)
|
||
continue;
|
||
|
||
ui_out_emit_tuple tuple_emitter (uiout, NULL);
|
||
|
||
if (pspace == current_program_space)
|
||
uiout->field_string ("current", "*");
|
||
else
|
||
uiout->field_skip ("current");
|
||
|
||
uiout->field_int ("id", pspace->num);
|
||
|
||
if (pspace->pspace_exec_filename)
|
||
uiout->field_string ("exec", pspace->pspace_exec_filename);
|
||
else
|
||
uiout->field_skip ("exec");
|
||
|
||
/* Print extra info that doesn't really fit in tabular form.
|
||
Currently, we print the list of inferiors bound to a pspace.
|
||
There can be more than one inferior bound to the same pspace,
|
||
e.g., both parent/child inferiors in a vfork, or, on targets
|
||
that share pspaces between inferiors. */
|
||
printed_header = 0;
|
||
for (inf = inferior_list; inf; inf = inf->next)
|
||
if (inf->pspace == pspace)
|
||
{
|
||
if (!printed_header)
|
||
{
|
||
printed_header = 1;
|
||
printf_filtered ("\n\tBound inferiors: ID %d (%s)",
|
||
inf->num,
|
||
target_pid_to_str (ptid_t (inf->pid)).c_str ());
|
||
}
|
||
else
|
||
printf_filtered (", ID %d (%s)",
|
||
inf->num,
|
||
target_pid_to_str (ptid_t (inf->pid)).c_str ());
|
||
}
|
||
|
||
uiout->text ("\n");
|
||
}
|
||
}
|
||
|
||
/* Boolean test for an already-known program space id. */
|
||
|
||
static int
|
||
valid_program_space_id (int num)
|
||
{
|
||
struct program_space *pspace;
|
||
|
||
ALL_PSPACES (pspace)
|
||
if (pspace->num == num)
|
||
return 1;
|
||
|
||
return 0;
|
||
}
|
||
|
||
/* If ARGS is NULL or empty, print information about all program
|
||
spaces. Otherwise, ARGS is a text representation of a LONG
|
||
indicating which the program space to print information about. */
|
||
|
||
static void
|
||
maintenance_info_program_spaces_command (const char *args, int from_tty)
|
||
{
|
||
int requested = -1;
|
||
|
||
if (args && *args)
|
||
{
|
||
requested = parse_and_eval_long (args);
|
||
if (!valid_program_space_id (requested))
|
||
error (_("program space ID %d not known."), requested);
|
||
}
|
||
|
||
print_program_space (current_uiout, requested);
|
||
}
|
||
|
||
/* Simply returns the count of program spaces. */
|
||
|
||
int
|
||
number_of_program_spaces (void)
|
||
{
|
||
struct program_space *pspace;
|
||
int count = 0;
|
||
|
||
ALL_PSPACES (pspace)
|
||
count++;
|
||
|
||
return count;
|
||
}
|
||
|
||
/* Update all program spaces matching to address spaces. The user may
|
||
have created several program spaces, and loaded executables into
|
||
them before connecting to the target interface that will create the
|
||
inferiors. All that happens before GDB has a chance to know if the
|
||
inferiors will share an address space or not. Call this after
|
||
having connected to the target interface and having fetched the
|
||
target description, to fixup the program/address spaces mappings.
|
||
|
||
It is assumed that there are no bound inferiors yet, otherwise,
|
||
they'd be left with stale referenced to released aspaces. */
|
||
|
||
void
|
||
update_address_spaces (void)
|
||
{
|
||
int shared_aspace = gdbarch_has_shared_address_space (target_gdbarch ());
|
||
struct program_space *pspace;
|
||
struct inferior *inf;
|
||
|
||
init_address_spaces ();
|
||
|
||
if (shared_aspace)
|
||
{
|
||
struct address_space *aspace = new_address_space ();
|
||
|
||
free_address_space (current_program_space->aspace);
|
||
ALL_PSPACES (pspace)
|
||
pspace->aspace = aspace;
|
||
}
|
||
else
|
||
ALL_PSPACES (pspace)
|
||
{
|
||
free_address_space (pspace->aspace);
|
||
pspace->aspace = new_address_space ();
|
||
}
|
||
|
||
for (inf = inferior_list; inf; inf = inf->next)
|
||
if (gdbarch_has_global_solist (target_gdbarch ()))
|
||
inf->aspace = maybe_new_address_space ();
|
||
else
|
||
inf->aspace = inf->pspace->aspace;
|
||
}
|
||
|
||
|
||
|
||
/* See progspace.h. */
|
||
|
||
void
|
||
clear_program_space_solib_cache (struct program_space *pspace)
|
||
{
|
||
pspace->added_solibs.clear ();
|
||
pspace->deleted_solibs.clear ();
|
||
}
|
||
|
||
|
||
|
||
void
|
||
initialize_progspace (void)
|
||
{
|
||
add_cmd ("program-spaces", class_maintenance,
|
||
maintenance_info_program_spaces_command,
|
||
_("Info about currently known program spaces."),
|
||
&maintenanceinfolist);
|
||
|
||
/* There's always one program space. Note that this function isn't
|
||
an automatic _initialize_foo function, since other
|
||
_initialize_foo routines may need to install their per-pspace
|
||
data keys. We can only allocate a progspace when all those
|
||
modules have done that. Do this before
|
||
initialize_current_architecture, because that accesses exec_bfd,
|
||
which in turn dereferences current_program_space. */
|
||
current_program_space = new program_space (new_address_space ());
|
||
}
|