aboutsummaryrefslogtreecommitdiff
path: root/gdb/amd-dbgapi-target.c
diff options
context:
space:
mode:
authorSimon Marchi <simon.marchi@efficios.com>2023-04-03 14:52:08 -0400
committerSimon Marchi <simon.marchi@efficios.com>2023-04-17 13:47:13 -0400
commit5f6d638d3cb8273dac5c5bc1b541066dc41c7bb1 (patch)
tree8c139b27f9940b98c063c1c03d54accdcd4f029d /gdb/amd-dbgapi-target.c
parent9145fd43029d2ed2a352ccf93f76b6f5b6dbb94d (diff)
downloadgdb-5f6d638d3cb8273dac5c5bc1b541066dc41c7bb1.zip
gdb-5f6d638d3cb8273dac5c5bc1b541066dc41c7bb1.tar.gz
gdb-5f6d638d3cb8273dac5c5bc1b541066dc41c7bb1.tar.bz2
gdb/amdgpu: add follow fork and exec support
Prior to this patch, it's not possible for GDB to debug GPU code in fork children or after an exec. The amd-dbgapi target attaches to processes when an inferior appears due to a "run" or "attach" command, but not after a fork or exec. This patch adds support for that, such that it's possible to for an inferior to fork and for GDB to debug the GPU code in the child. To achieve that, use the inferior_forked and inferior_execd observers. In the case of fork, we have nothing to do if `child_inf` is nullptr, meaning that GDB won't debug the child. We also don't attach if the inferior has vforked. We are already attached to the parent's address space, which is shared with the child, so trying to attach would cause problems. And anyway, the inferior can't do anything other than exec or exit, it certainly won't start GPU kernels before exec'ing. In the case of exec, we detach from the exec'ing inferior and attach to the following inferior. This works regardless of whether they are the same or not. If they are the same, meaning the execution continues in the existing inferior, we need to do a detach/attach anyway, as amd-dbgapi needs to be aware of the new address space created by the exec. Note that we use observers and not target_ops::follow_{fork,exec} here. When the amd-dbgapi target is compiled in, it will attach (in the amd_dbgapi_process_attach sense, not the ptrace sense) to native inferiors when they appear, but won't push itself on the inferior's target stack just yet. It only pushes itself if the inferior initializes the ROCm runtime. So, if a non-GPU-using inferior calls fork, an amd_dbgapi_target::follow_fork method would not get called. Same for exec. A previous version of the code had the amd-dbgapi target pushed all the time, in which case we could use the target methods. But we prefer having the target pushed only when necessary, it's less intrusive when doing native debugging that doesn't involve the GPU. Change-Id: I5819c151c371120da8bab2fa9cbfa8769ba1d6f9 Reviewed-By: Pedro Alves <pedro@palves.net>
Diffstat (limited to 'gdb/amd-dbgapi-target.c')
-rw-r--r--gdb/amd-dbgapi-target.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/gdb/amd-dbgapi-target.c b/gdb/amd-dbgapi-target.c
index f1ef37d..d188663 100644
--- a/gdb/amd-dbgapi-target.c
+++ b/gdb/amd-dbgapi-target.c
@@ -1343,6 +1343,17 @@ attach_amd_dbgapi (inferior *inf)
return;
}
+ /* dbgapi can't attach to a vfork child (a process born from a vfork that
+ hasn't exec'ed yet) while we are still attached to the parent. It would
+ not be useful for us to attach to vfork children anyway, because vfork
+ children are very restricted in what they can do (see vfork(2)) and aren't
+ going to launch some GPU programs that we need to debug. To avoid this
+ problem, we don't push the amd-dbgapi target / attach dbgapi in vfork
+ children. If a vfork child execs, we'll try enabling the amd-dbgapi target
+ through the inferior_execd observer. */
+ if (inf->vfork_parent != nullptr)
+ return;
+
auto *info = get_amd_dbgapi_inferior_info (inf);
/* Are we already attached? */
@@ -1655,6 +1666,32 @@ amd_dbgapi_target_inferior_created (inferior *inf)
attach_amd_dbgapi (inf);
}
+/* inferior_execd observer. */
+
+static void
+amd_dbgapi_inferior_execd (inferior *exec_inf, inferior *follow_inf)
+{
+ /* The inferior has EXEC'd and the process image has changed. The dbgapi is
+ attached to the old process image, so we need to detach and re-attach to
+ the new process image. */
+ detach_amd_dbgapi (exec_inf);
+ attach_amd_dbgapi (follow_inf);
+}
+
+/* inferior_forked observer. */
+
+static void
+amd_dbgapi_inferior_forked (inferior *parent_inf, inferior *child_inf,
+ target_waitkind fork_kind)
+{
+ if (child_inf != nullptr && fork_kind != TARGET_WAITKIND_VFORKED)
+ {
+ scoped_restore_current_thread restore_thread;
+ switch_to_thread (*child_inf->threads ().begin ());
+ attach_amd_dbgapi (child_inf);
+ }
+}
+
/* inferior_exit observer.
This covers normal exits, but also detached inferiors (including detached
@@ -1924,6 +1961,8 @@ _initialize_amd_dbgapi_target ()
gdb::observers::inferior_created.attach
(amd_dbgapi_target_inferior_created,
amd_dbgapi_target_inferior_created_observer_token, "amd-dbgapi");
+ gdb::observers::inferior_execd.attach (amd_dbgapi_inferior_execd, "amd-dbgapi");
+ gdb::observers::inferior_forked.attach (amd_dbgapi_inferior_forked, "amd-dbgapi");
gdb::observers::inferior_exit.attach (amd_dbgapi_inferior_exited, "amd-dbgapi");
gdb::observers::inferior_pre_detach.attach (amd_dbgapi_inferior_pre_detach, "amd-dbgapi");