binutils-gdb/gdb/testsuite/gdb.rocm/fork-exec-gpu-to-non-gpu-execer.cpp
Simon Marchi 5f6d638d3c 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>
2023-04-17 13:47:13 -04:00

56 lines
1.3 KiB
C++

/* This testcase is part of GDB, the GNU debugger.
Copyright 2021-2023 Free Software Foundation, Inc.
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 <hip/hip_runtime.h>
#include <unistd.h>
__global__ static void
kernel1 ()
{}
__device__ static void
break_here_execer ()
{
}
__global__ static void
kernel2 ()
{
break_here_execer ();
}
int
main ()
{
/* Launch a first kernel to make sure the runtime is active by the time we
call fork. */
kernel1<<<1, 1>>> ();
/* fork + exec while the runtime is active. */
if (FORK () == 0)
{
int ret = execl (EXECEE, EXECEE, NULL);
perror ("exec");
abort ();
}
kernel2<<<1, 1>>> ();
hipDeviceSynchronize ();
return 0;
}