mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-06 12:09:26 +08:00
294c36eb6a
On "exec", some targets need to unpush themselves from the inferior, and do some bookkeeping, like forgetting the data associated to the exec'ing inferior. One such example is the thread-db target. It does so in a special case in thread_db_target::wait, just before returning the TARGET_WAITKIND_EXECD event to its caller. We have another such case in the context of rocm-gdb [1], where the "rocm" target is pushed on top of the linux-nat target. When an exec happens, we want to unpush the rocm target from the exec'ing inferior to close some file descriptors that refer to the pre-exec address space and forget about that inferior. We then want to push the target on the inferior in which execution continues, to open the file descriptors for the post-exec address space. I think that a good way to address this cleanly is to do all this in the target_ops::follow_exec implementations. Make the process_stratum_target::follow_exec implementation have the default behavior of pushing itself to the new inferior's target stack (if execution continues in a new inferior) and add the initial thread. remote_target::follow_exec is an example of process target that wants to do a bit more than the default behavior. So it calls process_stratum_target::follow_exec first and does the extra work second. linux-thread-db (a non-process target) implements follow_exec to do some bookeeping (forget about that process' data), before handing down the event down to the process target (which hits process_stratum_target::follow_exec). gdb/ChangeLog: * target.h (struct target_ops) <follow_exec>: Add ptid_t parameter. (target_follow_exec): Likewise. * target.c (target_follow_exec): Add ptid_t parameter. * infrun.c (follow_exec): Adjust call to target_follow_exec, don't push target nor create thread. * linux-thread-db.c (class thread_db_target) <follow_exec>: New. (thread_db_target::wait): Just return on TARGET_WAITKIND_EXECD. (thread_db_target::follow_exec): New. * remote.c (class remote_target) <follow_exec>: Add ptid_t parameter. (remote_target::follow_exec): Call process_stratum_target::follow_exec. * target-delegates.c: Re-generate. Change-Id: I3f96d0ba3ea0dde6540b7e1b4d5cdb01635088c8
131 lines
3.5 KiB
C
131 lines
3.5 KiB
C
/* Abstract base class inherited by all process_stratum targets
|
|
|
|
Copyright (C) 2018-2021 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 "process-stratum-target.h"
|
|
#include "inferior.h"
|
|
|
|
process_stratum_target::~process_stratum_target ()
|
|
{
|
|
}
|
|
|
|
struct address_space *
|
|
process_stratum_target::thread_address_space (ptid_t ptid)
|
|
{
|
|
/* Fall-back to the "main" address space of the inferior. */
|
|
inferior *inf = find_inferior_ptid (this, ptid);
|
|
|
|
if (inf == NULL || inf->aspace == NULL)
|
|
internal_error (__FILE__, __LINE__,
|
|
_("Can't determine the current "
|
|
"address space of thread %s\n"),
|
|
target_pid_to_str (ptid).c_str ());
|
|
|
|
return inf->aspace;
|
|
}
|
|
|
|
struct gdbarch *
|
|
process_stratum_target::thread_architecture (ptid_t ptid)
|
|
{
|
|
inferior *inf = find_inferior_ptid (this, ptid);
|
|
gdb_assert (inf != NULL);
|
|
return inf->gdbarch;
|
|
}
|
|
|
|
bool
|
|
process_stratum_target::has_all_memory ()
|
|
{
|
|
/* If no inferior selected, then we can't read memory here. */
|
|
return inferior_ptid != null_ptid;
|
|
}
|
|
|
|
bool
|
|
process_stratum_target::has_memory ()
|
|
{
|
|
/* If no inferior selected, then we can't read memory here. */
|
|
return inferior_ptid != null_ptid;
|
|
}
|
|
|
|
bool
|
|
process_stratum_target::has_stack ()
|
|
{
|
|
/* If no inferior selected, there's no stack. */
|
|
return inferior_ptid != null_ptid;
|
|
}
|
|
|
|
bool
|
|
process_stratum_target::has_registers ()
|
|
{
|
|
/* Can't read registers from no inferior. */
|
|
return inferior_ptid != null_ptid;
|
|
}
|
|
|
|
bool
|
|
process_stratum_target::has_execution (inferior *inf)
|
|
{
|
|
/* If there's a process running already, we can't make it run
|
|
through hoops. */
|
|
return inf->pid != 0;
|
|
}
|
|
|
|
void
|
|
process_stratum_target::follow_exec (inferior *follow_inf, ptid_t ptid,
|
|
const char *execd_pathname)
|
|
{
|
|
inferior *orig_inf = current_inferior ();
|
|
|
|
if (orig_inf != follow_inf)
|
|
{
|
|
/* Execution continues in a new inferior, push the original inferior's
|
|
process target on the new inferior's target stack. The process target
|
|
may decide to unpush itself from the original inferior's target stack
|
|
after that, at its discretion. */
|
|
follow_inf->push_target (orig_inf->process_target ());
|
|
thread_info *t = add_thread (follow_inf->process_target (), ptid);
|
|
|
|
/* Leave the new inferior / thread as the current inferior / thread. */
|
|
switch_to_thread (t);
|
|
}
|
|
}
|
|
|
|
/* See process-stratum-target.h. */
|
|
|
|
std::set<process_stratum_target *>
|
|
all_non_exited_process_targets ()
|
|
{
|
|
/* Inferiors may share targets. To eliminate duplicates, use a set. */
|
|
std::set<process_stratum_target *> targets;
|
|
for (inferior *inf : all_non_exited_inferiors ())
|
|
targets.insert (inf->process_target ());
|
|
|
|
return targets;
|
|
}
|
|
|
|
/* See process-stratum-target.h. */
|
|
|
|
void
|
|
switch_to_target_no_thread (process_stratum_target *target)
|
|
{
|
|
for (inferior *inf : all_inferiors (target))
|
|
{
|
|
switch_to_inferior_no_thread (inf);
|
|
break;
|
|
}
|
|
}
|