|
@@ -0,0 +1,114 @@
|
|
|
+From a80fc99e8f2e1c5ac1620a8c6c26d65daa98204e Mon Sep 17 00:00:00 2001
|
|
|
+From: Brian Gianforcaro <b.gianfo@gmail.com>
|
|
|
+Date: Sun, 20 Feb 2022 00:32:51 -0800
|
|
|
+Subject: [PATCH 5/6] serenity: Implement custom wait override for the
|
|
|
+ serenity_nat_target
|
|
|
+
|
|
|
+While troubleshooting why gdb wasn't working when attempting to debug
|
|
|
+serenity programs I noticed two things:
|
|
|
+
|
|
|
+ - The contract of serenity's `waitpid(..)` appears to be slightly
|
|
|
+ different than the generic ptrace target expects. We need to make
|
|
|
+ sure we pass `WSTOPPED`, and it can return different errno values
|
|
|
+ that we would want to re-try on.
|
|
|
+
|
|
|
+- The contract of serenity's `ptrace(..)` implementation appears to
|
|
|
+ diverge as well, as we are expected to call `PT_ATTACH` before we
|
|
|
+ call `PT_CONTINUE`, otherwise `ptrace(..)` will just error out.
|
|
|
+
|
|
|
+Allow gdb to understand these differences, I've overloaded the
|
|
|
+serenity_nat_target::wait(..) method and added the logic there.
|
|
|
+---
|
|
|
+ gdb/serenity-nat.c | 62 +++++++++++++++++++++++++++++++++++++++++++++-
|
|
|
+ gdb/serenity-nat.h | 4 +++
|
|
|
+ 2 files changed, 65 insertions(+), 1 deletion(-)
|
|
|
+
|
|
|
+diff --git a/gdb/serenity-nat.c b/gdb/serenity-nat.c
|
|
|
+index ff740d4..b1d39d4 100644
|
|
|
+--- a/gdb/serenity-nat.c
|
|
|
++++ b/gdb/serenity-nat.c
|
|
|
+@@ -10,4 +10,64 @@
|
|
|
+ #include "gdbsupport/gdb_wait.h"
|
|
|
+
|
|
|
+ #include "inf-child.h"
|
|
|
+-#include "serenity-nat.h"
|
|
|
+\ No newline at end of file
|
|
|
++#include "serenity-nat.h"
|
|
|
++
|
|
|
++ptid_t serenity_nat_target::wait (ptid_t ptid, struct target_waitstatus* ourstatus, target_wait_flags)
|
|
|
++{
|
|
|
++ int pid;
|
|
|
++ int status, save_errno;
|
|
|
++
|
|
|
++ do
|
|
|
++ {
|
|
|
++ set_sigint_trap ();
|
|
|
++
|
|
|
++ do
|
|
|
++ {
|
|
|
++ errno = 0;
|
|
|
++ pid = waitpid (ptid.pid (), &status, WSTOPPED);
|
|
|
++ if (errno != 0)
|
|
|
++ {
|
|
|
++ save_errno = errno;
|
|
|
++ perror_with_name (("waitpid"));
|
|
|
++ }
|
|
|
++ }
|
|
|
++ while (pid == -1 && (save_errno == EINTR || save_errno == EAGAIN));
|
|
|
++
|
|
|
++ clear_sigint_trap ();
|
|
|
++
|
|
|
++ if (pid == -1)
|
|
|
++ {
|
|
|
++ fprintf_unfiltered (gdb_stderr,
|
|
|
++ _("Child process unexpectedly missing: %s.\n"),
|
|
|
++ safe_strerror (save_errno));
|
|
|
++
|
|
|
++ /* Claim it exited with unknown signal. */
|
|
|
++ ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
|
|
|
++ ourstatus->value.sig = GDB_SIGNAL_UNKNOWN;
|
|
|
++ return inferior_ptid;
|
|
|
++ }
|
|
|
++
|
|
|
++ /* Ignore terminated detached child processes. */
|
|
|
++ if (!WIFSTOPPED (status) && find_inferior_pid (this, pid) == nullptr)
|
|
|
++ pid = -1;
|
|
|
++ }
|
|
|
++ while (pid == -1);
|
|
|
++
|
|
|
++ store_waitstatus (ourstatus, status);
|
|
|
++
|
|
|
++ /* Serenity requires us to PT_ATTACH before we PT_CONTINUE, however GDB doesn't
|
|
|
++ * provide a hook for us to do that before we issue the PT_CONTINUE, so we are
|
|
|
++ * forced to do it here.
|
|
|
++ */
|
|
|
++ if (!m_attach_before_continue_called) {
|
|
|
++ errno = 0;
|
|
|
++ ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0);
|
|
|
++ if (errno != 0) {
|
|
|
++ save_errno = errno;
|
|
|
++ printf_unfiltered (_("PT_ATTACH failed: %d - %s \n"), save_errno, safe_strerror (save_errno));
|
|
|
++ }
|
|
|
++ m_attach_before_continue_called = true;
|
|
|
++ }
|
|
|
++
|
|
|
++ return ptid_t (pid);
|
|
|
++}
|
|
|
+diff --git a/gdb/serenity-nat.h b/gdb/serenity-nat.h
|
|
|
+index dcd24ce..9ae3b87 100644
|
|
|
+--- a/gdb/serenity-nat.h
|
|
|
++++ b/gdb/serenity-nat.h
|
|
|
+@@ -11,6 +11,10 @@
|
|
|
+
|
|
|
+ class serenity_nat_target : public inf_ptrace_target
|
|
|
+ {
|
|
|
++ ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
|
|
|
++
|
|
|
++private:
|
|
|
++ bool m_attach_before_continue_called { false };
|
|
|
+ };
|
|
|
+
|
|
|
+ #endif /* serenity-nat.h */
|
|
|
+--
|
|
|
+2.32.0
|
|
|
+
|