From patchwork Wed Feb 14 21:58:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?R=C3=A9mi_Bernon?= X-Patchwork-Id: 85750 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D63B9386180C for ; Wed, 14 Feb 2024 22:04:17 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail.codeweavers.com (mail.codeweavers.com [4.36.192.163]) by sourceware.org (Postfix) with ESMTPS id E8DA23857716 for ; Wed, 14 Feb 2024 22:03:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E8DA23857716 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=codeweavers.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=codeweavers.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E8DA23857716 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=4.36.192.163 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1707948237; cv=none; b=lbVU2sT3WS0Py68DgIdf5drEEaaSTfvHYYCVplzzp2uqqcSSxd/z5czE9SwoTV6u0EIALkbOOvoCQcydVdIbzRItntQm0SRqFK11YPX9QXjDYJ4a+sdarFa++kQ+GQ3R8RFdkU7PtahsXezFwUjNWUyV5uiIm+ozuYl2z0SL9HM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1707948237; c=relaxed/simple; bh=Fm2jPm8QZvL1RZzKOPnOyS1oYAlpOfXtz/eCyOxtmJ8=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=v+Gttg5UgutrYS9hUmWLigNiYRR25r1l4K9wkL5BlvSTvAt7dYkGbb8b6l+RaTcQmiIUDmsIYIAgiKUeRp/OclHOlMlXpC4Y42PEtdU3RHZivXoN0YCRBK5rKELt5qzCA30cJ4AqG25cpAhZHWYkxiiTy6P0QV9K4xNQ4HuUzbc= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=codeweavers.com; s=s1; h=Message-ID:Date:Subject:Cc:To:From:Sender; bh=REXeDI1erakimUQMzdWgPXBJQPiTrkfoMzhPaSMemv8=; b=JwSoYYi/wNPIsAne6bjl90a3PQ 9J2UprVULJdQWwHWd+7aieBtIq2npaLbgu0bYjIf6ZZ70RXMORNpn7Xs2BLAdtKYVtkNDqAnMCyQy 2VdO4ru7Fr5nJm3uYmqC/1JUX9sahetkrEh9pCStwvGgqtja+H3j8krgJPCnYTB+jjdQ98JpUbvI2 8vOmR8q8/YC/h5awqsCFEoGe0WSrsEZKT2vcsh7cHVzTxpnJiYn0XVtxMgfe0Oyn8qGeoTUQXY5FV 0QdNO/2WfzpfMiU4EE/BWFQ814AAyCdF7w3HtsYZu7rjULJjZzZPDyEX0MPB+z1Rrfw62DfE0YS7N mz86rKZA==; Received: from cw141ip122.vpn.codeweavers.com ([10.69.141.122] helo=fractal7.codeweavers.com) by mail.codeweavers.com with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1raNM3-00GXzu-2r; Wed, 14 Feb 2024 16:03:49 -0600 From: =?utf-8?q?R=C3=A9mi_Bernon?= To: gdb-patches@sourceware.org Cc: =?utf-8?q?R=C3=A9mi_Bernon?= Subject: [PATCH] gdb/python: Allow SIGTRAMP_FRAME python unwinders to be created. Date: Wed, 14 Feb 2024 22:58:52 +0100 Message-ID: <20240214215916.2655301-1-rbernon@codeweavers.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 X-Spam-Status: No, score=-13.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org 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; } }