public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: "Rémi Bernon" <rbernon@codeweavers.com>
To: gdb-patches@sourceware.org
Cc: "Rémi Bernon" <rbernon@codeweavers.com>
Subject: [PATCH] gdb/python: Allow SIGTRAMP_FRAME python unwinders to be created.
Date: Wed, 14 Feb 2024 22:58:52 +0100	[thread overview]
Message-ID: <20240214215916.2655301-1-rbernon@codeweavers.com> (raw)

Wine now executes Win32 code on a separate stack for its Unix code. It
switches from one stack to another on through specific functions, and
without any custom unwinders, debugging Wine in Gdb will only let you
see the frames of either the Win32 side, or the Unix side.

The Win32 and Unix call stacks are actually interleaved, with Unix code
sometimes calling back into Win32. Using a custom Python frame unwinder
we can provide Gdb with the information it needs to join both toghether
and show a complete interleaved call stack. However, Gdb will often stop
unwinding as it will see the frames from one stack as inner the frames
from the other stack.

This allows to write custom unwinders to produce SIGTRAMP_FRAME typed
frames, which bypasses this restriction and will show the Win32 / Unix
gate as a signal frame.
---
 gdb/python/lib/gdb/__init__.py |  8 ++++----
 gdb/python/lib/gdb/unwinder.py |  7 ++++++-
 gdb/python/py-unwind.c         | 16 +++++++++++++++-
 3 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py
index b3124369fe8..d9226440cbc 100644
--- a/gdb/python/lib/gdb/__init__.py
+++ b/gdb/python/lib/gdb/__init__.py
@@ -86,7 +86,7 @@ frame_filters = {}
 frame_unwinders = []
 
 
-def _execute_unwinders(pending_frame):
+def _execute_unwinders(pending_frame, frame_type):
     """Internal function called from GDB to execute all unwinders.
 
     Runs each currently enabled unwinder until it finds the one that
@@ -105,19 +105,19 @@ def _execute_unwinders(pending_frame):
     """
     for objfile in objfiles():
         for unwinder in objfile.frame_unwinders:
-            if unwinder.enabled:
+            if unwinder.enabled and unwinder.frame_type == frame_type:
                 unwind_info = unwinder(pending_frame)
                 if unwind_info is not None:
                     return (unwind_info, unwinder.name)
 
     for unwinder in current_progspace().frame_unwinders:
-        if unwinder.enabled:
+        if unwinder.enabled and unwinder.frame_type == frame_type:
             unwind_info = unwinder(pending_frame)
             if unwind_info is not None:
                 return (unwind_info, unwinder.name)
 
     for unwinder in frame_unwinders:
-        if unwinder.enabled:
+        if unwinder.enabled and unwinder.frame_type == frame_type:
             unwind_info = unwinder(pending_frame)
             if unwind_info is not None:
                 return (unwind_info, unwinder.name)
diff --git a/gdb/python/lib/gdb/unwinder.py b/gdb/python/lib/gdb/unwinder.py
index 140b84d3374..7e23a662a32 100644
--- a/gdb/python/lib/gdb/unwinder.py
+++ b/gdb/python/lib/gdb/unwinder.py
@@ -29,7 +29,7 @@ class Unwinder(object):
         enabled: A boolean indicating whether the unwinder is enabled.
     """
 
-    def __init__(self, name):
+    def __init__(self, name, frame_type=gdb.NORMAL_FRAME):
         """Constructor.
 
         Args:
@@ -39,9 +39,14 @@ class Unwinder(object):
         if not isinstance(name, str):
             raise TypeError("incorrect type for name: %s" % type(name))
 
+        self._frame_type = frame_type
         self._name = name
         self._enabled = True
 
+    @property
+    def frame_type(self):
+        return self._frame_type
+
     @property
     def name(self):
         return self._name
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index 1856e41e2a1..2d36c43d342 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -844,7 +844,8 @@ pyuw_sniffer (const struct frame_unwind *self, frame_info_ptr this_frame,
   /* A (gdb.UnwindInfo, str) tuple, or None.  */
   gdbpy_ref<> pyo_execute_ret
     (PyObject_CallFunctionObjArgs (pyo_execute.get (),
-				   pyo_pending_frame.get (), NULL));
+				   pyo_pending_frame.get (),
+				   PyLong_FromLong(self->type), NULL));
   if (pyo_execute_ret == nullptr)
     {
       /* If the unwinder is cancelled due to a Ctrl-C, then propagate
@@ -965,6 +966,19 @@ pyuw_on_new_gdbarch (struct gdbarch *newarch)
       unwinder->sniffer = pyuw_sniffer;
       unwinder->dealloc_cache = pyuw_dealloc_cache;
       frame_unwind_prepend_unwinder (newarch, unwinder);
+
+      struct frame_unwind *unwinder_signals
+	  = GDBARCH_OBSTACK_ZALLOC (newarch, struct frame_unwind);
+
+      unwinder_signals->name = "python-sigtramp";
+      unwinder_signals->type = SIGTRAMP_FRAME;
+      unwinder_signals->stop_reason = default_frame_unwind_stop_reason;
+      unwinder_signals->this_id = pyuw_this_id;
+      unwinder_signals->prev_register = pyuw_prev_register;
+      unwinder_signals->unwind_data = (const struct frame_data *) newarch;
+      unwinder_signals->sniffer = pyuw_sniffer;
+      unwinder_signals->dealloc_cache = pyuw_dealloc_cache;
+      frame_unwind_prepend_unwinder (newarch, unwinder_signals);
       data->unwinder_registered = 1;
     }
 }
-- 
2.43.0


             reply	other threads:[~2024-02-14 22:03 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-14 21:58 Rémi Bernon [this message]
2024-02-21 16:41 ` [PING][PATCH] " Rémi Bernon
2024-02-29  8:17 ` Rémi Bernon
2024-03-14 13:00 ` [PATCH] " Guinevere Larsen
2024-03-19 15:58   ` Rémi Bernon
2024-03-20 14:13 ` Andrew Burgess

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240214215916.2655301-1-rbernon@codeweavers.com \
    --to=rbernon@codeweavers.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).