From patchwork Tue Mar 21 15:46:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Willgerodt, Felix" X-Patchwork-Id: 66693 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 2120C385086D for ; Tue, 21 Mar 2023 15:47:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2120C385086D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1679413626; bh=h8hGqGBkCMNRR5hyuZnyuaoeJyI7567kTG+nGRWXzrg=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=tnfxq6ikFPRvpEVYjRcvWykyCYcoRXwqspskuzoxWD3RSkyqG5K/74rHKEAB/8g2+ PDXbC5o19JAioHOaRFrJN6LlY/x79QqEO15Kt1fcj6UXzWwFSUYIxQZ24JJvY4vfgU pPM9jWuqJxD5rbXXGTrRJeLnTqdEhyh8CpJmovj0= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by sourceware.org (Postfix) with ESMTPS id C27FE3858004 for ; Tue, 21 Mar 2023 15:46:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C27FE3858004 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="366709315" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="366709315" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:46:40 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="792149344" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="792149344" Received: from mulfelix.iul.intel.com (HELO localhost) ([172.28.49.163]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:46:39 -0700 To: gdb-patches@sourceware.org Cc: Felix Willgerodt Subject: [PATCH v8 01/10] btrace: Introduce auxiliary instructions. Date: Tue, 21 Mar 2023 16:46:17 +0100 Message-Id: <20230321154626.448816-2-felix.willgerodt@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230321154626.448816-1-felix.willgerodt@intel.com> References: <20230321154626.448816-1-felix.willgerodt@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP 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.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Felix Willgerodt via Gdb-patches From: "Willgerodt, Felix" Reply-To: Felix Willgerodt Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Auxiliary instructions are pseudo instructions pointing to auxiliary data. This auxiliary data can be printed in all commands displaying (record function-call-history, record instruction-history) or stepping through (stepi etc.) the execution history, which will be introduced in the next commits. This patch is in preparation for the new ptwrite feature, which is based on auxiliary instructions. --- gdb/btrace.c | 2 ++ gdb/btrace.h | 24 +++++++++++++++++++++--- gdb/doc/gdb.texinfo | 3 +++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/gdb/btrace.c b/gdb/btrace.c index 38d3882c154..b0afc1735f8 100644 --- a/gdb/btrace.c +++ b/gdb/btrace.c @@ -1823,6 +1823,8 @@ btrace_clear_history (struct btrace_thread_info *btinfo) btinfo->insn_history = NULL; btinfo->call_history = NULL; btinfo->replay = NULL; + + btinfo->aux_data.clear (); } /* Clear the branch trace maintenance histories in BTINFO. */ diff --git a/gdb/btrace.h b/gdb/btrace.h index 0ec84113217..dd80d3e6806 100644 --- a/gdb/btrace.h +++ b/gdb/btrace.h @@ -52,7 +52,10 @@ enum btrace_insn_class BTRACE_INSN_RETURN, /* The instruction is an unconditional jump. */ - BTRACE_INSN_JUMP + BTRACE_INSN_JUMP, + + /* The instruction is a pseudo instruction containing auxiliary data. */ + BTRACE_INSN_AUX }; /* Instruction flags. */ @@ -68,8 +71,19 @@ DEF_ENUM_FLAGS_TYPE (enum btrace_insn_flag, btrace_insn_flags); This represents a single instruction in a branch trace. */ struct btrace_insn { - /* The address of this instruction. */ - CORE_ADDR pc; + union + { + /* The address of this instruction. Applies to btrace_insn with + iclass == BTRACE_INSN_OTHER or + iclass == BTRACE_INSN_CALL or + iclass == BTRACE_INSN_RETURN or + iclass == BTRACE_INSN_JUMP. */ + CORE_ADDR pc; + + /* Index into btrace_info::aux_data. Applies to btrace_insn with + iclass == BTRACE_INSN_AUX. */ + uint64_t aux_data_index; + }; /* The size of this instruction in bytes. */ gdb_byte size; @@ -330,6 +344,10 @@ struct btrace_thread_info function segment i will be at index (i - 1). */ std::vector functions; + /* Optional auxiliary information that is printed in all commands + displaying or stepping through the execution history. */ + std::vector aux_data; + /* The function level offset. When added to each function's LEVEL, this normalizes the function levels such that the smallest level becomes zero. */ diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 6c811b8be2e..d1690c07a99 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -7639,6 +7639,9 @@ Moxie, PowerPC, PowerPC64, S/390, and x86 (i386/amd64) running GNU/Linux. Process record and replay can be used both when native debugging, and when remote debugging via @code{gdbserver}. +When recording an inferior, @value{GDBN} may print auxiliary information +during stepping commands and commands displaying the execution history. + For architecture environments that support process record and replay, @value{GDBN} provides the following commands: From patchwork Tue Mar 21 15:46:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Willgerodt, Felix" X-Patchwork-Id: 66694 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 8D114385040C for ; Tue, 21 Mar 2023 15:47:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8D114385040C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1679413633; bh=KmjQMgUlipjbt0VsXgpxCwvx6WaXHHIL/asODkBxoZ0=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=qYoE1DD0oZBgZXXEyUv7EjI69/QHvQY9k+TuKSNeeg7znWlidewqNGW6ejAwcN2X8 plYnKZwDj9si5aRAU1vhzEf3MURJFIonar+D8p2d/rfod0S5lN/cbUMMaERXYtIy2S 7K9pfPaTtzE1kEBc6Glg14QiRHQ+b3W9qdbDSAJg= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by sourceware.org (Postfix) with ESMTPS id 8CC7C38582B0 for ; Tue, 21 Mar 2023 15:46:47 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8CC7C38582B0 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="366709378" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="366709378" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:46:47 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="792149356" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="792149356" Received: from mulfelix.iul.intel.com (HELO localhost) ([172.28.49.163]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:46:46 -0700 To: gdb-patches@sourceware.org Cc: Felix Willgerodt Subject: [PATCH v8 02/10] btrace: Enable auxiliary instructions in record instruction-history. Date: Tue, 21 Mar 2023 16:46:18 +0100 Message-Id: <20230321154626.448816-3-felix.willgerodt@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230321154626.448816-1-felix.willgerodt@intel.com> References: <20230321154626.448816-1-felix.willgerodt@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP 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.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Felix Willgerodt via Gdb-patches From: "Willgerodt, Felix" Reply-To: Felix Willgerodt Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Print the auxiliary data when a btrace_insn of type BTRACE_INSN_AUX is encountered in the instruction-history. Printing is active by default, it can be silenced with the /a modifier. This patch is in preparation for the new ptwrite feature, which is based on auxiliary instructions. --- gdb/disasm-flags.h | 1 + gdb/doc/gdb.texinfo | 3 +++ gdb/record-btrace.c | 14 ++++++++++++++ gdb/record.c | 5 +++++ 4 files changed, 23 insertions(+) diff --git a/gdb/disasm-flags.h b/gdb/disasm-flags.h index e2e8a7a82e5..08b2d506493 100644 --- a/gdb/disasm-flags.h +++ b/gdb/disasm-flags.h @@ -34,6 +34,7 @@ enum gdb_disassembly_flag : unsigned DISASSEMBLY_SOURCE = (0x1 << 5), DISASSEMBLY_SPECULATIVE = (0x1 << 6), DISASSEMBLY_RAW_BYTES = (0x1 << 7), + DISASSEMBLY_OMIT_AUX_INSN = (0x1 << 8), }; DEF_ENUM_FLAGS_TYPE (enum gdb_disassembly_flag, gdb_disassembly_flags); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index d1690c07a99..a3ca25577c4 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -8057,6 +8057,9 @@ To better align the printed instructions when the trace contains instructions from more than one function, the function name may be omitted by specifying the @code{/f} modifier. +Printing auxiliary information is enabled by default and can be +omitted with the @code{/a} modifier. + Speculatively executed instructions are prefixed with @samp{?}. This feature is not available for all recording formats. diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index 2d88e4d20bf..e69004b35b5 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -826,6 +826,20 @@ btrace_insn_history (struct ui_out *uiout, btrace_ui_out_decode_error (uiout, btrace_insn_get_error (&it), conf->format); } + else if (insn->iclass == BTRACE_INSN_AUX) + { + if ((flags & DISASSEMBLY_OMIT_AUX_INSN) != 0) + continue; + + uiout->field_fmt ("insn-number", "%u", btrace_insn_number (&it)); + uiout->text ("\t"); + uiout->spaces (3); + uiout->text ("["); + uiout->field_fmt ("aux-data", "%s", + it.btinfo->aux_data.at + (insn->aux_data_index).c_str ()); + uiout->text ("]\n"); + } else { struct disasm_insn dinsn; diff --git a/gdb/record.c b/gdb/record.c index f7c95153537..c7397858717 100644 --- a/gdb/record.c +++ b/gdb/record.c @@ -486,6 +486,9 @@ get_insn_history_modifiers (const char **arg) switch (*args) { + case 'a': + modifiers |= DISASSEMBLY_OMIT_AUX_INSN; + break; case 'm': case 's': modifiers |= DISASSEMBLY_SOURCE; @@ -856,6 +859,8 @@ With a /m or /s modifier, source lines are included (if available).\n\ With a /r modifier, raw instructions in hex are included.\n\ With a /f modifier, function names are omitted.\n\ With a /p modifier, current position markers are omitted.\n\ +With a /a modifier, omits output of auxiliary data, which is enabled \ +by default.\n\ With no argument, disassembles ten more instructions after the previous \ disassembly.\n\ \"record instruction-history -\" disassembles ten instructions before a \ From patchwork Tue Mar 21 15:46:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Willgerodt, Felix" X-Patchwork-Id: 66696 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 697023858031 for ; Tue, 21 Mar 2023 15:47:38 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 697023858031 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1679413658; bh=3UIGutvNd93jw6MUMtn9B0oZWPA9eWkbLw0BqjPRdzc=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=RRfkNWlf4GBbwhKNh6tDnH2Jt8gdLdzwazF0+09GaNoZylvoY+uT1TyiSwOrQ3sjd h9BBo28UlCRqDBVzn5uayxaNDkO8F9GnYt00GlV0wK5bk1NXtry8DCRkuq5bVooOXM CVPOnbEXvuDhJ6X2OBUKx/yNKa56sHzswXwFcpqk= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by sourceware.org (Postfix) with ESMTPS id B2ECE385559F for ; Tue, 21 Mar 2023 15:46:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B2ECE385559F X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="366709432" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="366709432" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:46:53 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="792149393" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="792149393" Received: from mulfelix.iul.intel.com (HELO localhost) ([172.28.49.163]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:46:52 -0700 To: gdb-patches@sourceware.org Cc: Felix Willgerodt Subject: [PATCH v8 03/10] btrace: Enable auxiliary instructions in record function-call-history. Date: Tue, 21 Mar 2023 16:46:19 +0100 Message-Id: <20230321154626.448816-4-felix.willgerodt@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230321154626.448816-1-felix.willgerodt@intel.com> References: <20230321154626.448816-1-felix.willgerodt@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP 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.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Felix Willgerodt via Gdb-patches From: "Willgerodt, Felix" Reply-To: Felix Willgerodt Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Print the auxiliary data when a btrace_insn of type BTRACE_INSN_AUX is encountered in the function-call-history. Printing is active by default, it can be silenced with the /a modifier. This patch is in preparation for the new ptwrite feature, which is based on auxiliary instructions. --- gdb/btrace.h | 6 +++++- gdb/doc/gdb.texinfo | 5 +++-- gdb/record-btrace.c | 21 +++++++++++++++++++++ gdb/record.c | 5 +++++ gdb/record.h | 5 ++++- 5 files changed, 38 insertions(+), 4 deletions(-) diff --git a/gdb/btrace.h b/gdb/btrace.h index dd80d3e6806..f6a8274bb16 100644 --- a/gdb/btrace.h +++ b/gdb/btrace.h @@ -105,7 +105,11 @@ enum btrace_function_flag /* The 'up' link points to a tail call. This obviously only makes sense if bfun_up_links_to_ret is clear. */ - BFUN_UP_LINKS_TO_TAILCALL = (1 << 1) + BFUN_UP_LINKS_TO_TAILCALL = (1 << 1), + + /* Indicates that at least one auxiliary instruction is in the current + function segment. */ + BFUN_CONTAINS_AUX = (1 << 2) }; DEF_ENUM_FLAGS_TYPE (enum btrace_function_flag, btrace_function_flags); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index a3ca25577c4..2d8cf143262 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -8113,8 +8113,9 @@ that function, the source lines for this instruction sequence (if the @code{/l} modifier is specified), and the instructions numbers that form the sequence (if the @code{/i} modifier is specified). The function names are indented to reflect the call stack depth if the @code{/c} modifier is -specified. The @code{/l}, @code{/i}, and @code{/c} modifiers can be given -together. +specified. Printing auxiliary information is enabled by default and can be +omitted with the @code{/a} modifier. The @code{/l}, @code{/i}, @code{/a}, +and @code{/c} modifiers can be given together. @smallexample (@value{GDBP}) @b{list 1, 10} diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index e69004b35b5..9ec7eb1b415 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -1158,6 +1158,23 @@ btrace_get_bfun_name (const struct btrace_function *bfun) return "??"; } +static void +btrace_print_aux_insn (struct ui_out *uiout, + const struct btrace_function *bfun, + const struct btrace_thread_info *btinfo) +{ + for (const btrace_insn &insn : bfun->insn) + { + if (insn.iclass == BTRACE_INSN_AUX) + { + uiout->text ("\t\t["); + uiout->field_fmt ("aux-data", "%s", + btinfo->aux_data.at (insn.aux_data_index).c_str ()); + uiout->text ("]\n"); + } + } +} + /* Disassemble a section of the recorded function trace. */ static void @@ -1233,6 +1250,10 @@ btrace_call_history (struct ui_out *uiout, } uiout->text ("\n"); + + if (((flags & RECORD_DONT_PRINT_AUX) == 0) + && ((bfun->flags & BFUN_CONTAINS_AUX) != 0)) + btrace_print_aux_insn(uiout, bfun, btinfo); } } diff --git a/gdb/record.c b/gdb/record.c index c7397858717..2c25dd3dfe1 100644 --- a/gdb/record.c +++ b/gdb/record.c @@ -639,6 +639,9 @@ get_call_history_modifiers (const char **arg) case 'c': modifiers |= RECORD_PRINT_INDENT_CALLS; break; + case 'a': + modifiers |= RECORD_DONT_PRINT_AUX; + break; default: error (_("Invalid modifier: %c."), *args); } @@ -883,6 +886,8 @@ Without modifiers, it prints the function name.\n\ With a /l modifier, the source file and line number range is included.\n\ With a /i modifier, the instruction number range is included.\n\ With a /c modifier, the output is indented based on the call stack depth.\n\ +With a /a modifier, omits output of auxiliary data, which is enabled \ +by default.\n\ With no argument, prints ten more lines after the previous ten-line print.\n\ \"record function-call-history -\" prints ten lines before a previous ten-line \ print.\n\ diff --git a/gdb/record.h b/gdb/record.h index 166b5349988..ec06aaa7909 100644 --- a/gdb/record.h +++ b/gdb/record.h @@ -62,7 +62,10 @@ enum record_print_flag RECORD_PRINT_INSN_RANGE = (1 << 1), /* Indent based on call stack depth (if applicable). */ - RECORD_PRINT_INDENT_CALLS = (1 << 2) + RECORD_PRINT_INDENT_CALLS = (1 << 2), + + /* Deactivate printing auxiliary data (if applicable). */ + RECORD_DONT_PRINT_AUX = (1 << 3) }; DEF_ENUM_FLAGS_TYPE (enum record_print_flag, record_print_flags); From patchwork Tue Mar 21 15:46:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Willgerodt, Felix" X-Patchwork-Id: 66695 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 2145C384F011 for ; Tue, 21 Mar 2023 15:47:27 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2145C384F011 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1679413647; bh=i/Ffsp4XOd+Ib6Dj6dJhCgb18GbG87veXP4u1yKa/Hg=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=pWFfk46A5a5p0J8V1BsiUZ5IXs4m3kfXlnsMMQIS4vsLPruKR2h+YEJcEB+glsras M+wGRV/7eieBLvOPTdivG4NDBzVPwD61D83BegaWyu3dcbI0MVTdImdprzjIn9smdl SrwM3Ez6vhY7JRM7NIGbrxittQemqrzBY79YJmwU= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by sourceware.org (Postfix) with ESMTPS id 787BD385F012 for ; Tue, 21 Mar 2023 15:47:00 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 787BD385F012 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="366709501" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="366709501" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:00 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="792149415" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="792149415" Received: from mulfelix.iul.intel.com (HELO localhost) ([172.28.49.163]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:46:59 -0700 To: gdb-patches@sourceware.org Cc: Felix Willgerodt Subject: [PATCH v8 04/10] btrace: Handle stepping and goto for auxiliary instructions. Date: Tue, 21 Mar 2023 16:46:20 +0100 Message-Id: <20230321154626.448816-5-felix.willgerodt@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230321154626.448816-1-felix.willgerodt@intel.com> References: <20230321154626.448816-1-felix.willgerodt@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP 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.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Felix Willgerodt via Gdb-patches From: "Willgerodt, Felix" Reply-To: Felix Willgerodt Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Print the auxiliary data when stepping. Don't allow to goto an auxiliary instruction. This patch is in preparation for the new ptwrite feature, which is based on auxiliary instructions. --- gdb/record-btrace.c | 67 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index 9ec7eb1b415..22687e889ec 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -2378,9 +2378,13 @@ record_btrace_single_step_forward (struct thread_info *tp) return btrace_step_stopped (); /* Skip gaps during replay. If we end up at a gap (at the end of the trace), - jump back to the instruction at which we started. */ + jump back to the instruction at which we started. If we're stepping a + BTRACE_INSN_AUX instruction, print the auxiliary data and skip the + instruction. */ + start = *replay; - do + + for (;;) { unsigned int steps; @@ -2388,12 +2392,27 @@ record_btrace_single_step_forward (struct thread_info *tp) of the execution history. */ steps = btrace_insn_next (replay, 1); if (steps == 0) + { + *replay = start; + return btrace_step_no_history (); + } + + const struct btrace_insn *insn = btrace_insn_get (replay); + if (insn == nullptr) + continue; + + /* If we're stepping a BTRACE_INSN_AUX instruction, print the auxiliary + data and skip the instruction. */ + if (insn->iclass == BTRACE_INSN_AUX) { - *replay = start; - return btrace_step_no_history (); + gdb_printf ("[%s]\n", + btinfo->aux_data.at (insn->aux_data_index).c_str ()); + continue; } + + /* We have an instruction, we are done. */ + break; } - while (btrace_insn_get (replay) == NULL); /* Determine the end of the instruction trace. */ btrace_insn_end (&end, btinfo); @@ -2424,9 +2443,12 @@ record_btrace_single_step_backward (struct thread_info *tp) /* If we can't step any further, we reached the end of the history. Skip gaps during replay. If we end up at a gap (at the beginning of - the trace), jump back to the instruction at which we started. */ + the trace), jump back to the instruction at which we started. + If we're stepping a BTRACE_INSN_AUX instruction, print the auxiliary + data and skip the instruction. */ start = *replay; - do + + for (;;) { unsigned int steps; @@ -2436,8 +2458,22 @@ record_btrace_single_step_backward (struct thread_info *tp) *replay = start; return btrace_step_no_history (); } + + const struct btrace_insn *insn = btrace_insn_get (replay); + if (insn == nullptr) + continue; + + /* Check if we're stepping a BTRACE_INSN_AUX instruction and skip it. */ + if (insn->iclass == BTRACE_INSN_AUX) + { + gdb_printf ("[%s]\n", + btinfo->aux_data.at (insn->aux_data_index).c_str ()); + continue; + } + + /* We have an instruction, we are done. */ + break; } - while (btrace_insn_get (replay) == NULL); /* Check if we're stepping a breakpoint. @@ -2859,25 +2895,30 @@ record_btrace_target::goto_record_end () /* The goto_record method of target record-btrace. */ void -record_btrace_target::goto_record (ULONGEST insn) +record_btrace_target::goto_record (ULONGEST insn_number) { struct thread_info *tp; struct btrace_insn_iterator it; unsigned int number; int found; - number = insn; + number = insn_number; /* Check for wrap-arounds. */ - if (number != insn) + if (number != insn_number) error (_("Instruction number out of range.")); tp = require_btrace_thread (); found = btrace_find_insn_by_number (&it, &tp->btrace, number); - /* Check if the instruction could not be found or is a gap. */ - if (found == 0 || btrace_insn_get (&it) == NULL) + /* Check if the instruction could not be found or is a gap or an + auxilliary instruction. */ + if (found == 0) + error (_("No such instruction.")); + + const struct btrace_insn *insn = btrace_insn_get (&it); + if ((insn == NULL) || (insn->iclass == BTRACE_INSN_AUX)) error (_("No such instruction.")); record_btrace_set_replay (tp, &it); From patchwork Tue Mar 21 15:46:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Willgerodt, Felix" X-Patchwork-Id: 66698 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 54459384D156 for ; Tue, 21 Mar 2023 15:48:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 54459384D156 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1679413683; bh=GB6gW75nXyU4HCp8fREZCu3FV7Ywudc7e0zaU8yTo6A=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=g9xoO/GnYpgVtkz7xbrgo3zIsoOlTfZEuwSDlkd4l4h+ZXLScW14oHYs4q4hB0yYh Ep43KQGe7eQc4m6X7ZMa/7/9SlNNHCvk3CzysfZGg/zKNIqhTA6Xqao/25S0/9/bEC 1HN0RQ8ADNiHFKoB6X1DpwM8ih8lRsRXAvJeuzw0= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by sourceware.org (Postfix) with ESMTPS id 139933858421 for ; Tue, 21 Mar 2023 15:47:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 139933858421 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="340517727" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="340517727" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:07 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="681530266" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="681530266" Received: from mulfelix.iul.intel.com (HELO localhost) ([172.28.49.163]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:06 -0700 To: gdb-patches@sourceware.org Cc: Felix Willgerodt Subject: [PATCH v8 05/10] python: Introduce gdb.RecordAuxiliary class. Date: Tue, 21 Mar 2023 16:46:21 +0100 Message-Id: <20230321154626.448816-6-felix.willgerodt@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230321154626.448816-1-felix.willgerodt@intel.com> References: <20230321154626.448816-1-felix.willgerodt@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP 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.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Felix Willgerodt via Gdb-patches From: "Willgerodt, Felix" Reply-To: Felix Willgerodt Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Auxiliary instructions are no real instructions and get their own object class, similar to gaps. gdb.Record.instruction_history is now possibly a list of gdb.RecordInstruction, gdb.RecordGap or gdb.RecordAuxiliary objects. This patch is in preparation for the new ptwrite feature, which is based on auxiliary instructions. --- gdb/doc/python.texi | 13 +++++++ gdb/python/py-record-btrace.c | 35 +++++++++++------ gdb/python/py-record.c | 73 ++++++++++++++++++++++++++++++++++- gdb/python/py-record.h | 3 ++ 4 files changed, 111 insertions(+), 13 deletions(-) diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 54d5660543a..31243b8ec47 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -3914,6 +3914,19 @@ the current recording method. A human readable string with the reason for the gap. @end defvar +Some @value{GDBN} features write auxiliary information into the execution +history. This information is represented by a @code{gdb.RecordAuxiliary} object +in the instruction list. It has the following attributes: + +@defvar RecordAuxiliary.number +An integer identifying this auxiliary. @code{number} corresponds to the numbers +seen in @code{record instruction-history} (@pxref{Process Record and Replay}). +@end defvar + +@defvar RecordAuxiliary.data +A string representation of the auxiliary data. +@end defvar + A @code{gdb.RecordFunctionSegment} object has the following attributes: @defvar RecordFunctionSegment.number diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c index 4af86672d26..16925eadd7a 100644 --- a/gdb/python/py-record-btrace.c +++ b/gdb/python/py-record-btrace.c @@ -45,7 +45,8 @@ struct btpy_list_object { /* Stride size. */ Py_ssize_t step; - /* Either &BTPY_CALL_TYPE or &RECPY_INSN_TYPE. */ + /* Either &recpy_func_type, &recpy_insn_type, &recpy_aux_type or + &recpy_gap_type. */ PyTypeObject* element_type; }; @@ -141,10 +142,11 @@ btrace_func_from_recpy_func (const PyObject * const pyobject) } /* Looks at the recorded item with the number NUMBER and create a - gdb.RecordInstruction or gdb.RecordGap object for it accordingly. */ + gdb.RecordInstruction, gdb.RecordGap or gdb.RecordAuxiliary object + for it accordingly. */ static PyObject * -btpy_insn_or_gap_new (thread_info *tinfo, Py_ssize_t number) +btpy_item_new (thread_info *tinfo, Py_ssize_t number) { btrace_insn_iterator iter; int err_code; @@ -163,6 +165,14 @@ btpy_insn_or_gap_new (thread_info *tinfo, Py_ssize_t number) return recpy_gap_new (err_code, err_string, number); } + const struct btrace_insn *insn = btrace_insn_get (&iter); + gdb_assert (insn != nullptr); + + if (insn->iclass == BTRACE_INSN_AUX) + return recpy_aux_new + (iter.btinfo->aux_data.at (insn->aux_data_index).c_str (), number); + + return recpy_insn_new (tinfo, RECORD_METHOD_BTRACE, number); } @@ -441,8 +451,10 @@ btpy_list_length (PyObject *self) } /* Implementation of - BtraceList.__getitem__ (self, key) -> BtraceInstruction and - BtraceList.__getitem__ (self, key) -> BtraceFunctionCall. */ + BtraceList.__getitem__ (self, key) -> BtraceInstruction, + BtraceList.__getitem__ (self, key) -> BtraceFunctionCall, + BtraceList.__getitem__ (self, key) -> BtraceAuxilliary and + BtraceList.__getitem__ (self, key) -> BtraceGap. */ static PyObject * btpy_list_item (PyObject *self, Py_ssize_t index) @@ -456,10 +468,10 @@ btpy_list_item (PyObject *self, Py_ssize_t index) number = obj->first + (obj->step * index); - if (obj->element_type == &recpy_insn_type) - return recpy_insn_new (obj->thread, RECORD_METHOD_BTRACE, number); - else + if (obj->element_type == &recpy_func_type) return recpy_func_new (obj->thread, RECORD_METHOD_BTRACE, number); + else + return btpy_item_new (obj->thread, number); } /* Implementation of BtraceList.__getitem__ (self, slice) -> BtraceList. */ @@ -646,8 +658,7 @@ recpy_bt_replay_position (PyObject *self, void *closure) if (tinfo->btrace.replay == NULL) Py_RETURN_NONE; - return btpy_insn_or_gap_new (tinfo, - btrace_insn_number (tinfo->btrace.replay)); + return btpy_item_new (tinfo, btrace_insn_number (tinfo->btrace.replay)); } /* Implementation of @@ -669,7 +680,7 @@ recpy_bt_begin (PyObject *self, void *closure) Py_RETURN_NONE; btrace_insn_begin (&iterator, &tinfo->btrace); - return btpy_insn_or_gap_new (tinfo, btrace_insn_number (&iterator)); + return btpy_item_new (tinfo, btrace_insn_number (&iterator)); } /* Implementation of @@ -691,7 +702,7 @@ recpy_bt_end (PyObject *self, void *closure) Py_RETURN_NONE; btrace_insn_end (&iterator, &tinfo->btrace); - return btpy_insn_or_gap_new (tinfo, btrace_insn_number (&iterator)); + return btpy_item_new (tinfo, btrace_insn_number (&iterator)); } /* Implementation of diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c index 1e40f2cded0..1afa0f25275 100644 --- a/gdb/python/py-record.c +++ b/gdb/python/py-record.c @@ -49,6 +49,12 @@ static PyTypeObject recpy_gap_type = { PyVarObject_HEAD_INIT (NULL, 0) }; +/* Python RecordAuxiliary type. */ + +PyTypeObject recpy_aux_type = { + PyVarObject_HEAD_INIT (nullptr, 0) +}; + /* Python RecordGap object. */ struct recpy_gap_object { @@ -64,6 +70,18 @@ struct recpy_gap_object Py_ssize_t number; }; +/* Python RecordAuxiliary object. */ +typedef struct +{ + PyObject_HEAD + + /* Auxiliary data. */ + const char *data; + + /* Element number. */ + Py_ssize_t number; +} recpy_aux_object; + /* Implementation of record.method. */ static PyObject * @@ -477,6 +495,43 @@ recpy_gap_reason_string (PyObject *self, void *closure) return PyUnicode_FromString (obj->reason_string); } +/* Create a new gdb.Auxiliary object. */ + +PyObject * +recpy_aux_new (const char *data, Py_ssize_t number) +{ + recpy_aux_object * const obj = PyObject_New (recpy_aux_object, + &recpy_aux_type); + + if (obj == nullptr) + return nullptr; + + obj->data = data; + obj->number = number; + + return (PyObject *) obj; +} + +/* Implementation of Auxiliary.number [int]. */ + +static PyObject * +recpy_aux_number (PyObject *self, void *closure) +{ + const recpy_aux_object * const obj = (const recpy_aux_object *) self; + + return gdb_py_object_from_longest (obj->number).release (); +} + +/* Implementation of Auxiliary.data [str]. */ + +static PyObject * +recpy_aux_data (PyObject *self, void *closure) +{ + const recpy_aux_object * const obj = (const recpy_aux_object *) self; + + return PyUnicode_FromString (obj->data); +} + /* Record method list. */ static PyMethodDef recpy_record_methods[] = { @@ -542,6 +597,14 @@ static gdb_PyGetSetDef recpy_gap_getset[] = { { NULL } }; +/* RecordAuxiliary member list. */ + +static gdb_PyGetSetDef recpy_aux_getset[] = { + { "number", recpy_aux_number, nullptr, "element number", nullptr}, + { "data", recpy_aux_data, nullptr, "data", nullptr}, + { nullptr } +}; + /* Sets up the record API in the gdb module. */ int @@ -581,10 +644,18 @@ gdbpy_initialize_record (void) recpy_gap_type.tp_doc = "GDB recorded gap object"; recpy_gap_type.tp_getset = recpy_gap_getset; + recpy_aux_type.tp_new = PyType_GenericNew; + recpy_aux_type.tp_flags = Py_TPFLAGS_DEFAULT; + recpy_aux_type.tp_basicsize = sizeof (recpy_aux_object); + recpy_aux_type.tp_name = "gdb.RecordAuxiliary"; + recpy_aux_type.tp_doc = "GDB recorded auxiliary object"; + recpy_aux_type.tp_getset = recpy_aux_getset; + if (PyType_Ready (&recpy_record_type) < 0 || PyType_Ready (&recpy_insn_type) < 0 || PyType_Ready (&recpy_func_type) < 0 - || PyType_Ready (&recpy_gap_type) < 0) + || PyType_Ready (&recpy_gap_type) < 0 + || PyType_Ready (&recpy_aux_type) < 0) return -1; else return 0; diff --git a/gdb/python/py-record.h b/gdb/python/py-record.h index 6eec71e06e7..75bf6fae935 100644 --- a/gdb/python/py-record.h +++ b/gdb/python/py-record.h @@ -71,4 +71,7 @@ extern PyObject *recpy_func_new (thread_info *thread, enum record_method method, extern PyObject *recpy_gap_new (int reason_code, const char *reason_string, Py_ssize_t number); +/* Create a new gdb.RecordGap object. */ +extern PyObject *recpy_aux_new (const char *data, Py_ssize_t number); + #endif /* PYTHON_PY_RECORD_H */ From patchwork Tue Mar 21 15:46:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Willgerodt, Felix" X-Patchwork-Id: 66699 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 4F38E3850429 for ; Tue, 21 Mar 2023 15:48:09 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4F38E3850429 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1679413689; bh=m+1XbP2fdSvC+chfpLJrb1Dv7Wp6xXWQo83UbsGGXwg=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=MzyRR1NW1Q5oPtcWR19vobLue4Ook7e0jwgcphTDjDRdkbt2+1T+163OXBjHa8GyR gWbp8i0Jfor8oGMqG+xfFBmO2qmf50uXgkV+bE7FHEr1Z0Zq8ND7byP9FY2/LyY/z8 mwcL2IQ2HQiHG5O+XtpW1eX/GxOT6wpiZk6rOfZU= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by sourceware.org (Postfix) with ESMTPS id 9D6FF3850439 for ; Tue, 21 Mar 2023 15:47:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9D6FF3850439 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="340517780" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="340517780" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:13 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="681530298" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="681530298" Received: from mulfelix.iul.intel.com (HELO localhost) ([172.28.49.163]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:12 -0700 To: gdb-patches@sourceware.org Cc: Felix Willgerodt Subject: [PATCH v8 06/10] python: Add clear() to gdb.Record. Date: Tue, 21 Mar 2023 16:46:22 +0100 Message-Id: <20230321154626.448816-7-felix.willgerodt@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230321154626.448816-1-felix.willgerodt@intel.com> References: <20230321154626.448816-1-felix.willgerodt@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP 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.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Felix Willgerodt via Gdb-patches From: "Willgerodt, Felix" Reply-To: Felix Willgerodt Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" This function allows to clear the trace data from python, forcing to re-decode the trace for successive commands. --- gdb/doc/python.texi | 5 +++++ gdb/python/py-record-btrace.c | 13 +++++++++++++ gdb/python/py-record-btrace.h | 3 +++ gdb/python/py-record.c | 16 ++++++++++++++++ gdb/testsuite/gdb.python/py-record-btrace.exp | 6 +++++- 5 files changed, 42 insertions(+), 1 deletion(-) diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 31243b8ec47..e1ab3b20eda 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -3858,6 +3858,11 @@ A @code{gdb.Record} object has the following methods: Move the replay position to the given @var{instruction}. @end defun +@defun Record.clear () +Clear the trace data of the current recording. This forces re-decoding of the +trace for successive commands. +@end defun + The common @code{gdb.Instruction} class that recording method specific instruction objects inherit from, has the following attributes: diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c index 16925eadd7a..4922154fc1b 100644 --- a/gdb/python/py-record-btrace.c +++ b/gdb/python/py-record-btrace.c @@ -802,6 +802,19 @@ recpy_bt_goto (PyObject *self, PyObject *args) Py_RETURN_NONE; } +/* Implementation of BtraceRecord.clear (self) -> None. */ + +PyObject * +recpy_bt_clear (PyObject *self, PyObject *args) +{ + const recpy_record_object * const record = (recpy_record_object *) self; + thread_info *const tinfo = record->thread; + + btrace_clear (tinfo); + + Py_RETURN_NONE; +} + /* BtraceList methods. */ static PyMethodDef btpy_list_methods[] = diff --git a/gdb/python/py-record-btrace.h b/gdb/python/py-record-btrace.h index 0af8153b715..f297772f946 100644 --- a/gdb/python/py-record-btrace.h +++ b/gdb/python/py-record-btrace.h @@ -31,6 +31,9 @@ extern PyObject *recpy_bt_format (PyObject *self, void *closure); /* Implementation of record.goto (instruction) -> None. */ extern PyObject *recpy_bt_goto (PyObject *self, PyObject *value); +/* Implementation of BtraceRecord.clear (self) -> None. */ +extern PyObject *recpy_bt_clear (PyObject *self, PyObject *args); + /* Implementation of record.instruction_history [list]. */ extern PyObject *recpy_bt_instruction_history (PyObject *self, void *closure); diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c index 1afa0f25275..d5bc1c7b2aa 100644 --- a/gdb/python/py-record.c +++ b/gdb/python/py-record.c @@ -127,6 +127,19 @@ recpy_goto (PyObject *self, PyObject *value) return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); } +/* Implementation of record.clear () -> None. */ + +static PyObject * +recpy_clear (PyObject *self, PyObject *value) +{ + const recpy_record_object * const obj = (recpy_record_object *) self; + + if (obj->method == RECORD_METHOD_BTRACE) + return recpy_bt_clear (self, value); + + return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); +} + /* Implementation of record.replay_position [instruction] */ static PyObject * @@ -538,6 +551,9 @@ static PyMethodDef recpy_record_methods[] = { { "goto", recpy_goto, METH_VARARGS, "goto (instruction|function_call) -> None.\n\ Rewind to given location."}, + { "clear", recpy_clear, METH_VARARGS, + "clear () -> None.\n\ +Clears the trace."}, { NULL } }; diff --git a/gdb/testsuite/gdb.python/py-record-btrace.exp b/gdb/testsuite/gdb.python/py-record-btrace.exp index bd397d3c974..1f0539466af 100644 --- a/gdb/testsuite/gdb.python/py-record-btrace.exp +++ b/gdb/testsuite/gdb.python/py-record-btrace.exp @@ -143,7 +143,11 @@ with_test_prefix "instruction " { gdb_test "python print(repr(i.data))" "" gdb_test "python print(i.decoded)" ".*" gdb_test "python print(i.size)" "$decimal" - gdb_test "python print(i.is_speculative)" "False" + gdb_test "python print(i.is_speculative)" "False" + gdb_test_no_output "python r.clear()" + gdb_test "python insn = r.instruction_history" + gdb_test_no_output "python i = insn\[0\]" + gdb_test "python print(i.size)" "$decimal" } with_test_prefix "function call" { From patchwork Tue Mar 21 15:46:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Willgerodt, Felix" X-Patchwork-Id: 66697 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 43AA7385B52B for ; Tue, 21 Mar 2023 15:48:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 43AA7385B52B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1679413681; bh=l+I+tUog5Rn8OSysbbCb/ufImFsgf+4NlERj7JNA1DM=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=jIT6yewtqzleABMv+h2igsJ+Bd0mf260nUiYXmlEsY7PMKIeQSNT67v5XjfTs9Nev sg8tbYRoUdL0+FQQ0uwBWYi3PbAnIEgefL8mTu1AUIBsKhycRP7wD0A4tOZpsg0k8M xJ5sZmmWR/VAjd4ASZOsgMRL3vnEdfJ1p/HQZtqc= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by sourceware.org (Postfix) with ESMTPS id 7096B385040F for ; Tue, 21 Mar 2023 15:47:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7096B385040F X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="340517803" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="340517803" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:21 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="681530339" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="681530339" Received: from mulfelix.iul.intel.com (HELO localhost) ([172.28.49.163]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:20 -0700 To: gdb-patches@sourceware.org Cc: Felix Willgerodt Subject: [PATCH v8 07/10] btrace, gdbserver: Add ptwrite to btrace_config_pt. Date: Tue, 21 Mar 2023 16:46:23 +0100 Message-Id: <20230321154626.448816-8-felix.willgerodt@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230321154626.448816-1-felix.willgerodt@intel.com> References: <20230321154626.448816-1-felix.willgerodt@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP 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.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Felix Willgerodt via Gdb-patches From: "Willgerodt, Felix" Reply-To: Felix Willgerodt Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" This enables gdb and gdbserver to communicate about ptwrite support. If ptwrite support would be enabled unconditionally, GDBs with older libipt versions would break. --- gdb/btrace.c | 8 +++++++- gdb/doc/gdb.texinfo | 21 +++++++++++++++++++++ gdb/features/btrace-conf.dtd | 1 + gdb/remote.c | 33 +++++++++++++++++++++++++++++++++ gdbserver/linux-low.cc | 3 +++ gdbserver/server.cc | 18 ++++++++++++++++++ gdbsupport/btrace-common.h | 6 ++++++ 7 files changed, 89 insertions(+), 1 deletion(-) diff --git a/gdb/btrace.c b/gdb/btrace.c index b0afc1735f8..f2fc4786e21 100644 --- a/gdb/btrace.c +++ b/gdb/btrace.c @@ -2273,7 +2273,7 @@ parse_xml_btrace_conf_pt (struct gdb_xml_parser *parser, std::vector &attributes) { struct btrace_config *conf; - struct gdb_xml_value *size; + struct gdb_xml_value *size, *ptwrite; conf = (struct btrace_config *) user_data; conf->format = BTRACE_FORMAT_PT; @@ -2282,10 +2282,16 @@ parse_xml_btrace_conf_pt (struct gdb_xml_parser *parser, size = xml_find_attribute (attributes, "size"); if (size != NULL) conf->pt.size = (unsigned int) *(ULONGEST *) size->value.get (); + + ptwrite = xml_find_attribute (attributes, "ptwrite"); + if (ptwrite != nullptr) + conf->pt.ptwrite = (bool) *(ULONGEST *) ptwrite->value.get (); } static const struct gdb_xml_attribute btrace_conf_pt_attributes[] = { { "size", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL }, + { "ptwrite", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_enum, + gdb_xml_enums_boolean }, { NULL, GDB_XML_AF_NONE, NULL, NULL } }; diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 2d8cf143262..cd2313cdb6a 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -43779,6 +43779,11 @@ These are the currently defined stub features and their properties: @tab @samp{-} @tab Yes +@item @samp{Qbtrace-conf:pt:ptwrite} +@tab Yes +@tab @samp{-} +@tab Yes + @item @samp{QNonStop} @tab No @tab @samp{-} @@ -44090,6 +44095,9 @@ The remote stub understands the @samp{Qbtrace-conf:bts:size} packet. @item Qbtrace-conf:pt:size The remote stub understands the @samp{Qbtrace-conf:pt:size} packet. +@item Qbtrace-conf:pt:ptwrite +The remote stub understands the @samp{Qbtrace-conf:pt:ptwrite} packet. + @item swbreak The remote stub reports the @samp{swbreak} stop reason for memory breakpoints. @@ -44597,6 +44605,18 @@ The ring buffer size has been set. A badly formed request or an error was encountered. @end table +@item Qbtrace-conf:pt:ptwrite=@var{(yes|no)} +Indicate support for @code{PTWRITE} packets. This allows for backwards +compatibility. + +Reply: +@table @samp +@item OK +The ptwrite config parameter has been set. +@item E.errtext +A badly formed request or an error was encountered. +@end table + @end table @node Architecture-Specific Protocol Details @@ -47245,6 +47265,7 @@ The formal DTD for the branch trace configuration format is given below: + @end smallexample @include agentexpr.texi diff --git a/gdb/features/btrace-conf.dtd b/gdb/features/btrace-conf.dtd index 3fbe3a4dc32..7aeaa4695e1 100644 --- a/gdb/features/btrace-conf.dtd +++ b/gdb/features/btrace-conf.dtd @@ -12,3 +12,4 @@ + diff --git a/gdb/remote.c b/gdb/remote.c index 526df313ea7..d0b96f2f2f6 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -286,6 +286,9 @@ enum { /* Support for the Qbtrace-conf:pt:size packet. */ PACKET_Qbtrace_conf_pt_size, + /* Support for the Qbtrace-conf:pt:ptwrite packet. */ + PACKET_Qbtrace_conf_pt_ptwrite, + /* Support for exec events. */ PACKET_exec_event_feature, @@ -5599,6 +5602,8 @@ static const struct protocol_feature remote_protocol_features[] = { PACKET_exec_event_feature }, { "Qbtrace-conf:pt:size", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_conf_pt_size }, + { "Qbtrace-conf:pt:ptwrite", PACKET_DISABLE, remote_supported_packet, + PACKET_Qbtrace_conf_pt_ptwrite }, { "vContSupported", PACKET_DISABLE, remote_supported_packet, PACKET_vContSupported }, { "QThreadEvents", PACKET_DISABLE, remote_supported_packet, PACKET_QThreadEvents }, { "no-resumed", PACKET_DISABLE, remote_supported_packet, PACKET_no_resumed }, @@ -14213,6 +14218,31 @@ remote_target::btrace_sync_conf (const btrace_config *conf) rs->btrace_config.pt.size = conf->pt.size; } + + if ((m_features.packet_support (PACKET_Qbtrace_conf_pt_ptwrite) + == PACKET_ENABLE) + && conf->pt.ptwrite != rs->btrace_config.pt.ptwrite) + { + pos = buf; + const char *ptw = conf->pt.ptwrite ? "yes" : "no"; + const char *name + = packets_descriptions[PACKET_Qbtrace_conf_pt_ptwrite].name; + pos += xsnprintf (pos, endbuf - pos, "%s=\"%s\"", name, ptw); + + putpkt (buf); + getpkt (&rs->buf, 0); + + if (m_features.packet_ok (buf, PACKET_Qbtrace_conf_pt_ptwrite) + == PACKET_ERROR) + { + if (buf[0] == 'E' && buf[1] == '.') + error (_("Failed to sync ptwrite config: %s"), buf + 2); + else + error (_("Failed to sync ptwrite config.")); + } + + rs->btrace_config.pt.ptwrite = conf->pt.ptwrite; + } } /* Read TP's btrace configuration from the target and store it into CONF. */ @@ -15392,6 +15422,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (PACKET_Qbtrace_conf_pt_size, "Qbtrace-conf:pt:size", "btrace-conf-pt-size", 0); + add_packet_config_cmd (PACKET_Qbtrace_conf_pt_ptwrite, "Qbtrace-conf:pt:ptwrite", + "btrace-conf-pt-ptwrite", 0); + add_packet_config_cmd (PACKET_vContSupported, "vContSupported", "verbose-resume-supported", 0); diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc index e6a39202a98..12ba2314308 100644 --- a/gdbserver/linux-low.cc +++ b/gdbserver/linux-low.cc @@ -6876,6 +6876,9 @@ linux_process_target::read_btrace_conf (const btrace_target_info *tinfo, string_xml_appendf (*buffer, "pt.size); string_xml_appendf (*buffer, "/>\n"); + string_xml_appendf (*buffer, " ptwrite=\"%s\"", + conf->pt.ptwrite ? "yes" : "no"); + string_xml_appendf (*buffer, "/>\n"); break; } } diff --git a/gdbserver/server.cc b/gdbserver/server.cc index 949849b63a2..4e62c1a4ced 100644 --- a/gdbserver/server.cc +++ b/gdbserver/server.cc @@ -547,6 +547,23 @@ handle_btrace_conf_general_set (char *own_buf) current_btrace_conf.pt.size = (unsigned int) size; } + else if (strncmp (op, "pt:ptwrite=", strlen ("pt:ptwrite=")) == 0) + { + bool ptwrite; + + op += strlen ("pt:ptwrite="); + if (strncmp (op, "\"yes\"", strlen ("\"yes\"")) == 0) + ptwrite = true; + else if (strncmp (op, "\"no\"", strlen ("\"no\"")) == 0) + ptwrite = false; + else + { + strcpy (own_buf, "E.Bad ptwrite value."); + return -1; + } + + current_btrace_conf.pt.ptwrite = ptwrite; + } else { strcpy (own_buf, "E.Bad Qbtrace configuration option."); @@ -2146,6 +2163,7 @@ supported_btrace_packets (char *buf) strcat (buf, ";Qbtrace-conf:bts:size+"); strcat (buf, ";Qbtrace:pt+"); strcat (buf, ";Qbtrace-conf:pt:size+"); + strcat (buf, ";Qbtrace-conf:pt:ptwrite+"); strcat (buf, ";Qbtrace:off+"); strcat (buf, ";qXfer:btrace:read+"); strcat (buf, ";qXfer:btrace-conf:read+"); diff --git a/gdbsupport/btrace-common.h b/gdbsupport/btrace-common.h index e287c93a6c1..03cc60648e9 100644 --- a/gdbsupport/btrace-common.h +++ b/gdbsupport/btrace-common.h @@ -117,6 +117,12 @@ struct btrace_config_pt This is unsigned int and not size_t since it is registered as control variable for "set record btrace pt buffer-size". */ unsigned int size; + + /* Configuration bit for ptwrite packets. + + If both gdb and gdbserver support this, gdb will try to enable ptwrite + packets when tracing is started. */ + bool ptwrite; }; /* A branch tracing configuration. From patchwork Tue Mar 21 15:46:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Willgerodt, Felix" X-Patchwork-Id: 66700 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 AAA8F385735E for ; Tue, 21 Mar 2023 15:48:33 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AAA8F385735E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1679413713; bh=SMwfxTcc8zH5IHrMcpzUN6qdES3GwCv/6fM6OQyyCY4=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=XsGfxABx+s1fFy+iZZhWY1zezff14v7nJqCk10T6MrJoQRm9BmpHN1vep+CsxLcp0 PDd4OngMfScxAok1s3QV+aAU9If2wvygEJeEyfhUKhRxLCce2aml+5jFBCO8YDF1yA jIBmpSU2luCNpQ55yWdsHtrAA0CjsYQiSHU2N4O8= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by sourceware.org (Postfix) with ESMTPS id 58D873858D3C for ; Tue, 21 Mar 2023 15:47:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 58D873858D3C X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="340517838" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="340517838" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:28 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="681530395" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="681530395" Received: from mulfelix.iul.intel.com (HELO localhost) ([172.28.49.163]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:27 -0700 To: gdb-patches@sourceware.org Cc: Felix Willgerodt Subject: [PATCH v8 08/10] btrace, linux: Enable ptwrite packets. Date: Tue, 21 Mar 2023 16:46:24 +0100 Message-Id: <20230321154626.448816-9-felix.willgerodt@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230321154626.448816-1-felix.willgerodt@intel.com> References: <20230321154626.448816-1-felix.willgerodt@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP 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.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Felix Willgerodt via Gdb-patches From: "Willgerodt, Felix" Reply-To: Felix Willgerodt Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Enable ptwrite in the PT config, if it is supported by the kernel. --- gdb/nat/linux-btrace.c | 29 +++++++++++++++++++++++++++++ gdb/record-btrace.c | 5 +++++ 2 files changed, 34 insertions(+) diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c index c5b3f1c93cf..e320eaa12ce 100644 --- a/gdb/nat/linux-btrace.c +++ b/gdb/nat/linux-btrace.c @@ -417,6 +417,29 @@ cpu_supports_bts (void) } } +/* Check whether the linux target supports Intel Processor Trace PTWRITE. */ + +static bool +linux_supports_ptwrite () +{ + static const char filename[] + = "/sys/bus/event_source/devices/intel_pt/caps/ptwrite"; + gdb_file_up file = gdb_fopen_cloexec (filename, "r"); + + if (file.get () == nullptr) + return false; + + int status, found = fscanf (file.get (), "%d", &status); + + if (found != 1) + { + warning (_("Failed to determine ptwrite support from %s."), filename); + return false; + } + + return status == 1; +} + /* The perf_event_open syscall failed. Try to print a helpful error message. */ @@ -626,6 +649,12 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf) pt->attr.exclude_hv = 1; pt->attr.exclude_idle = 1; + if (conf->ptwrite && linux_supports_ptwrite ()) + { + pt->attr.config |= 0x1000; + tinfo->conf.pt.ptwrite = conf->ptwrite; + } + errno = 0; scoped_fd fd (syscall (SYS_perf_event_open, &pt->attr, pid, -1, -1, 0)); if (fd.get () < 0) diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index 22687e889ec..0b36ce5fdf6 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -3291,4 +3291,9 @@ to see the actual buffer size."), NULL, show_record_pt_buffer_size_value, record_btrace_conf.bts.size = 64 * 1024; record_btrace_conf.pt.size = 16 * 1024; +#if (LIBIPT_VERSION >= 0x200) + record_btrace_conf.pt.ptwrite = true; +#else + record_btrace_conf.pt.ptwrite = false; +#endif } From patchwork Tue Mar 21 15:46:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Willgerodt, Felix" X-Patchwork-Id: 66701 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 A0C32384F02E for ; Tue, 21 Mar 2023 15:48:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A0C32384F02E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1679413717; bh=jR8ePuMZB44WhoXUGVBebykM0WywZQLxpwbYd7ORdT4=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=cTj7VDXplvMYbixTmDw2sQRNtPbOUTq506KjKl3xNVG/qSoqGjNoBzciqNOtZMuWf ipnXTvuaMK9LxF21hRKtR2tERAYKV1jV8Ixmn7Z2ej2eQS3OddLWOK/SrfyNjd/r3O DJ9v/XlJea7tIBy2ldAastrO8j5790bj97XDydIA= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by sourceware.org (Postfix) with ESMTPS id 1EFA0384D170 for ; Tue, 21 Mar 2023 15:47:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1EFA0384D170 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="340517868" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="340517868" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="681530424" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="681530424" Received: from mulfelix.iul.intel.com (HELO localhost) ([172.28.49.163]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:33 -0700 To: gdb-patches@sourceware.org Cc: Felix Willgerodt Subject: [PATCH v8 09/10] btrace, python: Enable ptwrite filter registration. Date: Tue, 21 Mar 2023 16:46:25 +0100 Message-Id: <20230321154626.448816-10-felix.willgerodt@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230321154626.448816-1-felix.willgerodt@intel.com> References: <20230321154626.448816-1-felix.willgerodt@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP 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.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Felix Willgerodt via Gdb-patches From: "Willgerodt, Felix" Reply-To: Felix Willgerodt Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" With this patch a default ptwrite filter is registered upon start of GDB. It prints the plain ptwrite payload as hex. The default filter can be overwritten by registering a custom filter in python or by registering "None", for no output at all. Registering a filter function creates per thread copies to allow unique internal states per thread. --- gdb/btrace.c | 4 ++ gdb/btrace.h | 8 ++++ gdb/data-directory/Makefile.in | 1 + gdb/extension-priv.h | 5 ++ gdb/extension.c | 13 +++++ gdb/extension.h | 3 ++ gdb/guile/guile.c | 1 + gdb/python/lib/gdb/ptwrite.py | 80 +++++++++++++++++++++++++++++++ gdb/python/py-record-btrace.c | 88 ++++++++++++++++++++++++++++++++++ gdb/python/py-record-btrace.h | 8 ++++ gdb/python/python-internal.h | 3 ++ gdb/python/python.c | 2 + 12 files changed, 216 insertions(+) create mode 100644 gdb/python/lib/gdb/ptwrite.py diff --git a/gdb/btrace.c b/gdb/btrace.c index f2fc4786e21..37dd0b666d8 100644 --- a/gdb/btrace.c +++ b/gdb/btrace.c @@ -34,6 +34,7 @@ #include "gdbsupport/rsp-low.h" #include "gdbcmd.h" #include "cli/cli-utils.h" +#include "extension.h" #include "gdbarch.h" /* For maintenance commands. */ @@ -1317,6 +1318,9 @@ ftrace_add_pt (struct btrace_thread_info *btinfo, uint64_t offset; int status; + /* Register the ptwrite filter. */ + apply_ext_lang_ptwrite_filter (btinfo); + for (;;) { struct pt_insn insn; diff --git a/gdb/btrace.h b/gdb/btrace.h index f6a8274bb16..912cb16056a 100644 --- a/gdb/btrace.h +++ b/gdb/btrace.h @@ -352,6 +352,14 @@ struct btrace_thread_info displaying or stepping through the execution history. */ std::vector aux_data; + /* Function pointer to the ptwrite callback. Returns the string returned + by the ptwrite filter function. */ + std::string (*ptw_callback_fun) (const uint64_t payload, const uint64_t ip, + const void *ptw_context) = nullptr; + + /* Context for the ptw_callback_fun. */ + void *ptw_context = nullptr; + /* The function level offset. When added to each function's LEVEL, this normalizes the function levels such that the smallest level becomes zero. */ diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in index ff1340c44c0..6ba880c3b6b 100644 --- a/gdb/data-directory/Makefile.in +++ b/gdb/data-directory/Makefile.in @@ -75,6 +75,7 @@ PYTHON_FILE_LIST = \ gdb/frames.py \ gdb/printing.py \ gdb/prompt.py \ + gdb/ptwrite.py \ gdb/styling.py \ gdb/types.py \ gdb/unwinder.py \ diff --git a/gdb/extension-priv.h b/gdb/extension-priv.h index 23a9f646d12..75112afd3ab 100644 --- a/gdb/extension-priv.h +++ b/gdb/extension-priv.h @@ -183,6 +183,11 @@ struct extension_language_ops enum ext_lang_frame_args args_type, struct ui_out *out, int frame_low, int frame_high); + /* Used for registering the ptwrite filter to the current thread. */ + void (*apply_ptwrite_filter) + (const struct extension_language_defn *extlang, + struct btrace_thread_info *btinfo); + /* Update values held by the extension language when OBJFILE is discarded. New global types must be created for every such value, which must then be updated to use the new types. diff --git a/gdb/extension.c b/gdb/extension.c index 4ac6e0b6732..8b32c7e1f13 100644 --- a/gdb/extension.c +++ b/gdb/extension.c @@ -551,6 +551,19 @@ apply_ext_lang_frame_filter (frame_info_ptr frame, return EXT_LANG_BT_NO_FILTERS; } +/* Used for registering the ptwrite filter to the current thread. */ + +void +apply_ext_lang_ptwrite_filter (btrace_thread_info *btinfo) +{ + for (const struct extension_language_defn *extlang : extension_languages) + { + if (extlang->ops != nullptr + && extlang->ops->apply_ptwrite_filter != nullptr) + extlang->ops->apply_ptwrite_filter (extlang, btinfo); + } +} + /* Update values held by the extension language when OBJFILE is discarded. New global types must be created for every such value, which must then be updated to use the new types. diff --git a/gdb/extension.h b/gdb/extension.h index ab83f9c6a28..639093945e4 100644 --- a/gdb/extension.h +++ b/gdb/extension.h @@ -295,6 +295,9 @@ extern enum ext_lang_bt_status apply_ext_lang_frame_filter enum ext_lang_frame_args args_type, struct ui_out *out, int frame_low, int frame_high); +extern void apply_ext_lang_ptwrite_filter + (struct btrace_thread_info *btinfo); + extern void preserve_ext_lang_values (struct objfile *, htab_t copied_types); extern const struct extension_language_defn *get_breakpoint_cond_ext_lang diff --git a/gdb/guile/guile.c b/gdb/guile/guile.c index 887b7fa5dc8..e9b0d4127d5 100644 --- a/gdb/guile/guile.c +++ b/gdb/guile/guile.c @@ -124,6 +124,7 @@ static const struct extension_language_ops guile_extension_ops = gdbscm_apply_val_pretty_printer, NULL, /* gdbscm_apply_frame_filter, */ + NULL, /* gdbscm_load_ptwrite_filter, */ gdbscm_preserve_values, diff --git a/gdb/python/lib/gdb/ptwrite.py b/gdb/python/lib/gdb/ptwrite.py new file mode 100644 index 00000000000..0f5b0473023 --- /dev/null +++ b/gdb/python/lib/gdb/ptwrite.py @@ -0,0 +1,80 @@ +# Ptwrite utilities. +# Copyright (C) 2022 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 . + +"""Utilities for working with ptwrite filters.""" + +from copy import deepcopy +import gdb + + +def default_filter(payload, ip): + """Default filter that is active upon starting GDB.""" + return "{:x}".format(payload) + + +# This dict contains the per thread copies of the filter function and the +# global template filter, from which the copies are created. +_ptwrite_filter = {"global": default_filter} + + +def ptwrite_exit_handler(event): + """Exit handler to prune _ptwrite_filter on inferior exit.""" + for key in list(_ptwrite_filter.keys()): + if key.startswith(f"{event.inferior.pid}."): + del _ptwrite_filter[key] + + +gdb.events.exited.connect(ptwrite_exit_handler) + + +def _clear_traces(thread_list): + """Helper function to clear the trace of all threads in THREAD_LIST.""" + current_thread = gdb.selected_thread() + recording = gdb.current_recording() + + if recording is not None: + for thread in thread_list: + thread.switch() + recording.clear() + + current_thread.switch() + + +def register_filter(filter_): + """Register the ptwrite filter function.""" + if filter_ is not None and not callable(filter_): + raise TypeError("The filter must be callable or 'None'.") + + # Clear the traces of all threads to force re-decoding with + # the new filter. + thread_list = gdb.selected_inferior().threads() + _clear_traces(thread_list) + + _ptwrite_filter.clear() + _ptwrite_filter["global"] = filter_ + + +def get_filter(): + """Returns the filters of the current thread.""" + # The key is of this format to enable an per-inferior cleanup when an + # inferior exits. + key = f"{gdb.selected_inferior().pid}.{gdb.selected_thread().ptid[1]}" + + # Create a new filter for new threads. + if key not in _ptwrite_filter.keys(): + _ptwrite_filter[key] = deepcopy(_ptwrite_filter["global"]) + + return _ptwrite_filter[key] diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c index 4922154fc1b..100a9ee8578 100644 --- a/gdb/python/py-record-btrace.c +++ b/gdb/python/py-record-btrace.c @@ -763,6 +763,94 @@ recpy_bt_function_call_history (PyObject *self, void *closure) return btpy_list_new (tinfo, first, last, 1, &recpy_func_type); } +/* Helper function that calls PTW_FILTER with PAYLOAD and IP as arguments. + Returns the string that will be printed. */ +std::string +recpy_call_filter (const uint64_t payload, const uint64_t ip, + const void *ptw_filter) +{ + std::string result; + + if ((PyObject *) ptw_filter == nullptr) + error (_("No valid ptwrite filter.")); + if ((PyObject *) ptw_filter == Py_None) + return result; + + gdbpy_enter enter_py; + + gdbpy_ref<> py_payload (PyLong_FromUnsignedLongLong (payload)); + gdbpy_ref<> py_ip (PyLong_FromUnsignedLongLong (ip)); + + if (ip == 0) + py_ip = gdbpy_ref<>::new_reference (Py_None); + + gdbpy_ref<> py_result (PyObject_CallFunctionObjArgs ((PyObject *) ptw_filter, + py_payload.get (), + py_ip.get (), + nullptr)); + + if (PyErr_Occurred ()) + { + gdbpy_print_stack (); + gdbpy_error (_("Couldn't call the ptwrite filter.")); + } + + /* Py_None is valid and results in no output. */ + if (py_result == Py_None) + return result; + + result = gdbpy_obj_to_string (py_result.get ()).get (); + + if (PyErr_Occurred ()) + { + gdbpy_print_stack (); + gdbpy_error (_("The ptwrite filter didn't return a string.")); + } + + return result; +} + +/* Helper function returning the current ptwrite filter. */ + +PyObject * +get_ptwrite_filter () +{ + gdbpy_ref<> module (PyImport_ImportModule ("gdb.ptwrite")); + + if (PyErr_Occurred ()) + { + gdbpy_print_stack (); + return nullptr; + } + + /* We need to keep the reference count. */ + gdbpy_ref<> ptw_filter (PyObject_CallMethod (module.get (), "get_filter", + nullptr)); + + if (PyErr_Occurred ()) + { + gdbpy_print_stack (); + gdbpy_error (_("Couldn't get the ptwrite filter.")); + } + + return ptw_filter.get(); +} + +/* Used for registering the default ptwrite filter to the current thread. A + pointer to this function is stored in the python extension interface. */ + +void +gdbpy_load_ptwrite_filter (const struct extension_language_defn *extlang, + struct btrace_thread_info *btinfo) +{ + gdb_assert (btinfo != nullptr); + + gdbpy_enter enter_py; + + btinfo->ptw_callback_fun = &recpy_call_filter; + btinfo->ptw_context= get_ptwrite_filter (); +} + /* Implementation of BtraceRecord.goto (self, BtraceInstruction) -> None. */ PyObject * diff --git a/gdb/python/py-record-btrace.h b/gdb/python/py-record-btrace.h index f297772f946..12750b3b1c3 100644 --- a/gdb/python/py-record-btrace.h +++ b/gdb/python/py-record-btrace.h @@ -91,4 +91,12 @@ extern PyObject *recpy_bt_func_prev (PyObject *self, void *closure); /* Implementation of RecordFunctionSegment.next [RecordFunctionSegment]. */ extern PyObject *recpy_bt_func_next (PyObject *self, void *closure); +/* Helper function returning the current ptwrite filter. */ +extern PyObject *get_ptwrite_filter (); + +/* Helper function to call the ptwrite filter. */ +extern std::string recpy_call_filter (const uint64_t payload, + const uint64_t ip, + const void *ptw_filter); + #endif /* PYTHON_PY_RECORD_BTRACE_H */ diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 258f5c42537..c21232c07dc 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -376,6 +376,9 @@ extern enum ext_lang_rc gdbpy_apply_val_pretty_printer struct ui_file *stream, int recurse, const struct value_print_options *options, const struct language_defn *language); +extern void gdbpy_load_ptwrite_filter + (const struct extension_language_defn *extlang, + struct btrace_thread_info *btinfo); extern enum ext_lang_bt_status gdbpy_apply_frame_filter (const struct extension_language_defn *, frame_info_ptr frame, frame_filter_flags flags, diff --git a/gdb/python/python.c b/gdb/python/python.c index b295ff88743..9a167ae9026 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -151,6 +151,8 @@ static const struct extension_language_ops python_extension_ops = gdbpy_apply_frame_filter, + gdbpy_load_ptwrite_filter, + gdbpy_preserve_values, gdbpy_breakpoint_has_cond, From patchwork Tue Mar 21 15:46:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Willgerodt, Felix" X-Patchwork-Id: 66702 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 1CA2E385480C for ; Tue, 21 Mar 2023 15:49:07 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1CA2E385480C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1679413747; bh=j3tGQ0KxBnEDr030ZPk3SyScRtpMVZxHHZt2BQQXimU=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=DlWX3pi3YPt/HbERX3ZXZ7NzDz8omvb4Ffyh6kiPJZzkVmMKvxF+y+9DmHeFQqQxE ftZ42IVLNbdqpjrNEh92w25mzHKytHOS4euoDvrHsf7ruYP22azfT3cbmaME2iK8T+ 37f/IagJ8D3YD0IF16VysIaAyN10gu6H1tjkYte4= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by sourceware.org (Postfix) with ESMTPS id CE0A4384D172 for ; Tue, 21 Mar 2023 15:47:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CE0A4384D172 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="319367378" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="319367378" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:41 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="770694124" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="770694124" Received: from mulfelix.iul.intel.com (HELO localhost) ([172.28.49.163]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:40 -0700 To: gdb-patches@sourceware.org Cc: Felix Willgerodt Subject: [PATCH v8 10/10] btrace: Extend ptwrite event decoding. Date: Tue, 21 Mar 2023 16:46:26 +0100 Message-Id: <20230321154626.448816-11-felix.willgerodt@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230321154626.448816-1-felix.willgerodt@intel.com> References: <20230321154626.448816-1-felix.willgerodt@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, SPF_HELO_NONE, SPF_NONE, TXREP 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.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Felix Willgerodt via Gdb-patches From: "Willgerodt, Felix" Reply-To: Felix Willgerodt Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Call the ptwrite filter function whenever a ptwrite event is decoded. The returned string is written to the aux_data string table and a corresponding auxiliary instruction is appended to the function segment. --- gdb/NEWS | 7 + gdb/btrace.c | 54 +++ gdb/config.in | 3 + gdb/configure | 11 + gdb/doc/python.texi | 150 ++++++ gdb/testsuite/gdb.btrace/i386-ptwrite.S | 550 ++++++++++++++++++++++ gdb/testsuite/gdb.btrace/ptwrite.c | 39 ++ gdb/testsuite/gdb.btrace/ptwrite.exp | 200 ++++++++ gdb/testsuite/gdb.btrace/x86_64-ptwrite.S | 544 +++++++++++++++++++++ gdb/testsuite/lib/gdb.exp | 72 +++ gdbsupport/common.m4 | 2 + gdbsupport/config.in | 3 + gdbsupport/configure | 11 + 13 files changed, 1646 insertions(+) create mode 100644 gdb/testsuite/gdb.btrace/i386-ptwrite.S create mode 100644 gdb/testsuite/gdb.btrace/ptwrite.c create mode 100644 gdb/testsuite/gdb.btrace/ptwrite.exp create mode 100644 gdb/testsuite/gdb.btrace/x86_64-ptwrite.S diff --git a/gdb/NEWS b/gdb/NEWS index cc262f1f8a6..5dd05867f2a 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -106,6 +106,13 @@ show always-read-ctf *** Changes in GDB 13 +* GDB now supports printing of ptwrite payloads from the Intel Processor + Trace during 'record instruction-history', 'record function-call-history' + and all stepping commands. The payload is also accessible in Python as a + RecordAuxiliary object. Printing is customizable via a ptwrite filter + function in Python. By default, the raw ptwrite payload is printed for + each ptwrite that is encountered. + * MI version 1 is deprecated, and will be removed in GDB 14. * GDB now supports dumping memory tag data for AArch64 MTE. It also supports diff --git a/gdb/btrace.c b/gdb/btrace.c index 37dd0b666d8..db0d0e291d9 100644 --- a/gdb/btrace.c +++ b/gdb/btrace.c @@ -1253,6 +1253,54 @@ handle_pt_insn_events (struct btrace_thread_info *btinfo, bfun->insn_offset - 1, offset); break; +#if defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) + case ptev_ptwrite: + { + uint64_t ip = 0; + std::string ptw_string; + btrace_insn_flags flags = 0; + + /* Lookup the ip if available. */ + if (event.ip_suppressed == 0) + ip = event.variant.ptwrite.ip; + + if (btinfo->ptw_callback_fun != nullptr) + ptw_string + = btinfo->ptw_callback_fun (event.variant.ptwrite.payload, + ip, btinfo->ptw_context); + + if (ptw_string.empty ()) + break; + + btinfo->aux_data.emplace_back (ptw_string); + + if (!btinfo->functions.empty () + && !btinfo->functions.back ().insn.empty ()) + flags = btinfo->functions.back ().insn.back ().flags; + + /* Update insn list with ptw payload insn. */ + struct btrace_insn ptw_insn; + ptw_insn.aux_data_index = btinfo->aux_data.size () - 1; + ptw_insn.size = 0; + ptw_insn.iclass = BTRACE_INSN_AUX; + ptw_insn.flags = flags; + + if (ip != 0) + bfun = ftrace_update_function (btinfo, ip); + else + { + if (btinfo->functions.empty ()) + bfun = ftrace_new_function (btinfo, NULL, NULL); + else + bfun = &btinfo->functions.back (); + } + + bfun->flags |= BFUN_CONTAINS_AUX; + ftrace_update_insns (bfun, ptw_insn); + + break; + } +#endif /* defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) */ } } #endif /* defined (HAVE_PT_INSN_EVENT) */ @@ -2981,6 +3029,12 @@ pt_print_packet (const struct pt_packet *packet) case ppt_mnt: gdb_printf (("mnt %" PRIx64 ""), packet->payload.mnt.payload); break; + +#if defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) + case ppt_ptw: + gdb_printf (("ptw %" PRIx64 ""), packet->payload.ptw.payload); + break; +#endif /* defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) */ } } diff --git a/gdb/config.in b/gdb/config.in index a7da88b92d7..9e6e59d73c3 100644 --- a/gdb/config.in +++ b/gdb/config.in @@ -460,6 +460,9 @@ /* Define to 1 if `pl_tdname' is a member of `struct ptrace_lwpinfo'. */ #undef HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME +/* Define to 1 if `variant.ptwrite' is a member of `struct pt_event'. */ +#undef HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE + /* Define to 1 if `enabled' is a member of `struct pt_insn'. */ #undef HAVE_STRUCT_PT_INSN_ENABLED diff --git a/gdb/configure b/gdb/configure index 5bb2a0795e5..778e69f74b9 100755 --- a/gdb/configure +++ b/gdb/configure @@ -25770,6 +25770,17 @@ cat >>confdefs.h <<_ACEOF _ACEOF +fi + + ac_fn_c_check_member "$LINENO" "struct pt_event" "variant.ptwrite" "ac_cv_member_struct_pt_event_variant_ptwrite" "#include +" +if test "x$ac_cv_member_struct_pt_event_variant_ptwrite" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE 1 +_ACEOF + + fi LIBS=$save_LIBS diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index e1ab3b20eda..e0772a7242e 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -7145,6 +7145,7 @@ registering objfile-specific pretty-printers and frame-filters. * gdb.printing:: Building and registering pretty-printers. * gdb.types:: Utilities for working with types. * gdb.prompt:: Utilities for prompt value substitution. +* gdb.ptwrite:: Utilities for PTWRITE filter registration. @end menu @node gdb.printing @@ -7335,3 +7336,152 @@ substitute_prompt ("frame: \f, args: \p@{print frame-arguments@}") "frame: main, args: scalars" @end smallexample @end table + +@node gdb.ptwrite +@subsubsection gdb.ptwrite +@cindex gdb.ptwrite + +This module provides additional functionality for recording programs that +make use of the @code{PTWRITE} instruction. @code{PTWRITE} is a x86 +instruction that allows to write values into the Intel Processor Trace +(@pxref{Process Record and Replay}). +The @value{NGCC} built-in functions for it are: +@smallexample +void __builtin_ia32_ptwrite32 (unsigned); +void __builtin_ia32_ptwrite64 (unsigned long long); +@end smallexample + +If an inferior uses the instruction, @value{GDBN} by default inserts the +raw payload value as auxiliary information into the execution history. +Auxiliary information is by default printed during +@code{record instruction-history}, @code{record function-call-history}, +and all stepping commands, and is accessible in Python as a +@code{RecordAuxiliary} object. + +@exdent Sample program: +@smallexample +@group +void +ptwrite64 (unsigned long long value) +@{ + __builtin_ia32_ptwrite64 (value); +@} +@end group + +@group +int +main (void) +@{ + ptwrite64 (0x42); + return 0; /* break here. */ +@} +@end group +@end smallexample + + +@exdent @value{GDBN} output after recording the sample program in pt format: +@smallexample +@group +(gdb) record instruction-history 12,14 +12 0x0040074c : ptwrite %rbx +13 [42] +14 0x00400751 : mov -0x8(%rbp),%rbx +(gdb) record function-call-history +1 main +2 ptwrite64 + [42] +3 main +@end group +@end smallexample + +The @code{gdb.ptwrite} module allows customizing the default output of +@code{PTWRITE} auxiliary information. A custom Python function can be +registered via @code{gdb.ptwrite.register_filter} as the @code{PTWRITE} +filter function. This function will be called with the @code{PTWRITE} +payload and PC as arguments during trace decoding. + +@findex gdb.ptwrite.register_filter +@defun register_filter (@var{filter}) +Used to register the @code{PTWRITE} filter. The filter can be any callable +object that accepts two arguments, the payload and PC. It can return +a string, which will be printed by @value{GDBN} during the aforementioned +commands, or @code{None}, resulting in no output. @code{None} can also be +registered to deactivate printing. +@end defun + +@findex gdb.ptwrite.get_filter +@defun get_filter () +Return the currently active @code{PTWRITE} filter function. +@end defun + +@findex gdb.ptwrite.default_filter +@defun default_filter (@var{payload}, @var{ip}) +The filter function active by default. It prints the payload in hexadecimal +format. +@end defun + +@value{GDBN} creates a new copy of the filter function for each thread to +allow for independent internal states. There is no support for registering +different filters for different threads. The filter can however +distinguish between multiple threads with the help of +@code{gdb.selected_thread().global_num} (@pxref{Threads In Python}) or +similar. For example: + +@smallexample +@group +(gdb) python-interactive +>>> class my_filter(): +... def __init__(self): +... self.var = 0 +... def __call__(self, payload, ip): +... if gdb.selected_thread().global_num == 1: +... self.var += 1 +... return f"counter: @{self.var@}, ip: @{ip:#x@}" +... else: +... return None +... +>>> import gdb.ptwrite +>>> gdb.ptwrite.register_filter(my_filter()) +>>> +@end group + +@group +(gdb) record function-call-history 59,64 +59 pthread_create@@GLIBC_2.2.5 +60 job() +61 task(void*) +62 ptwrite64(unsigned long) + [counter: 1, ip: 0x401156] +63 task(void*) +64 ptwrite32(unsigned int) + [counter: 2, ip: 0x40116c] +@end group + +@group +(gdb) info threads +* 1 Thread 0x7ffff7fd8740 (LWP 25796) "ptw_threads" task () + at bin/ptwrite/ptw_threads.c:45 + 2 Thread 0x7ffff6eb8700 (LWP 25797) "ptw_threads" task () + at bin/ptwrite/ptw_threads.c:45 +@end group + +@group +(gdb) thread 2 +[Switching to thread 2 (Thread 0x7ffff6eb8700 (LWP 25797))] +#0 task (arg=0x0) at ptwrite_threads.c:45 +45 return NULL; +@end group + +@group +(gdb) record function-call-history 10,14 +10 start_thread +11 task(void*) +12 ptwrite64(unsigned long) +13 task(void*) +14 ptwrite32(unsigned int) +@end group +@end smallexample + +This @value{GDBN} feature is dependent on hardware and operating system +support and requires the Intel Processor Trace decoder library in version +2.0.0 or newer. diff --git a/gdb/testsuite/gdb.btrace/i386-ptwrite.S b/gdb/testsuite/gdb.btrace/i386-ptwrite.S new file mode 100644 index 00000000000..ae6372ab991 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/i386-ptwrite.S @@ -0,0 +1,550 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2022 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 . + + + This file has been generated using gcc version 10.3.1 20210422 + (Red Hat 10.3.1-1): + gcc -S -dA -g -m32 -mptwrite ptwrite.c -o i386-ptwrite.S. */ + + + .file "ptwrite.c" + .text +.Ltext0: + .globl ptwrite1 + .type ptwrite1, @function +ptwrite1: +.LFB4021: + .file 1 "ptwrite.c" + # ptwrite.c:22:1 + .loc 1 22 1 + .cfi_startproc +# BLOCK 2 seq:0 +# PRED: ENTRY (FALLTHRU) + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset 5, -8 + movl %esp, %ebp + .cfi_def_cfa_register 5 + subl $16, %esp + # ptwrite.c:23:3 + .loc 1 23 3 + movl 8(%ebp), %eax + movl %eax, -4(%ebp) +.LBB6: +.LBB7: + .file 2 "/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h" + # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:307:3 + .loc 2 307 3 + movl -4(%ebp), %eax + ptwrite %eax + # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:308:1 + .loc 2 308 1 + nop +.LBE7: +.LBE6: + # ptwrite.c:24:1 + .loc 1 24 1 + nop + leave + .cfi_restore 5 + .cfi_def_cfa 4, 4 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE4021: + .size ptwrite1, .-ptwrite1 + .globl ptwrite2 + .type ptwrite2, @function +ptwrite2: +.LFB4022: + # ptwrite.c:28:1 + .loc 1 28 1 + .cfi_startproc +# BLOCK 2 seq:0 +# PRED: ENTRY (FALLTHRU) + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset 5, -8 + movl %esp, %ebp + .cfi_def_cfa_register 5 + subl $16, %esp + # ptwrite.c:29:3 + .loc 1 29 3 + movl 8(%ebp), %eax + movl %eax, -4(%ebp) +.LBB8: +.LBB9: + # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:307:3 + .loc 2 307 3 + movl -4(%ebp), %eax + ptwrite %eax + # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:308:1 + .loc 2 308 1 + nop +.LBE9: +.LBE8: + # ptwrite.c:30:1 + .loc 1 30 1 + nop + leave + .cfi_restore 5 + .cfi_def_cfa 4, 4 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE4022: + .size ptwrite2, .-ptwrite2 + .globl main + .type main, @function +main: +.LFB4023: + # ptwrite.c:34:1 + .loc 1 34 1 + .cfi_startproc +# BLOCK 2 seq:0 +# PRED: ENTRY (FALLTHRU) + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset 5, -8 + movl %esp, %ebp + .cfi_def_cfa_register 5 + # ptwrite.c:35:3 + .loc 1 35 3 + pushl $66 + call ptwrite1 + addl $4, %esp + # ptwrite.c:36:3 + .loc 1 36 3 + pushl $67 + call ptwrite2 + addl $4, %esp + # ptwrite.c:38:10 + .loc 1 38 10 + movl $0, %eax + # ptwrite.c:39:1 + .loc 1 39 1 + leave + .cfi_restore 5 + .cfi_def_cfa 4, 4 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE4023: + .size main, .-main +.Letext0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .long 0x129 # Length of Compilation Unit Info + .value 0x4 # DWARF version number + .long .Ldebug_abbrev0 # Offset Into Abbrev. Section + .byte 0x4 # Pointer Size (in bytes) + .uleb128 0x1 # (DIE (0xb) DW_TAG_compile_unit) + .long .LASF15 # DW_AT_producer: "GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -m32 -mptwrite -mtune=generic -march=i686 -g" + .byte 0xc # DW_AT_language + .long .LASF16 # DW_AT_name: "ptwrite.c" + .long .LASF17 # DW_AT_comp_dir: "gdb/gdb/testsuite/gdb.btrace" + .long .Ltext0 # DW_AT_low_pc + .long .Letext0-.Ltext0 # DW_AT_high_pc + .long .Ldebug_line0 # DW_AT_stmt_list + .uleb128 0x2 # (DIE (0x25) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .ascii "int\0" # DW_AT_name + .uleb128 0x3 # (DIE (0x2c) DW_TAG_base_type) + .byte 0x2 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .long .LASF0 # DW_AT_name: "short int" + .uleb128 0x3 # (DIE (0x33) DW_TAG_base_type) + .byte 0x1 # DW_AT_byte_size + .byte 0x6 # DW_AT_encoding + .long .LASF1 # DW_AT_name: "char" + .uleb128 0x3 # (DIE (0x3a) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .long .LASF2 # DW_AT_name: "long long int" + .uleb128 0x3 # (DIE (0x41) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x4 # DW_AT_encoding + .long .LASF3 # DW_AT_name: "float" + .uleb128 0x3 # (DIE (0x48) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF4 # DW_AT_name: "unsigned int" + .uleb128 0x3 # (DIE (0x4f) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .long .LASF5 # DW_AT_name: "long int" + .uleb128 0x3 # (DIE (0x56) DW_TAG_base_type) + .byte 0x1 # DW_AT_byte_size + .byte 0x8 # DW_AT_encoding + .long .LASF6 # DW_AT_name: "unsigned char" + .uleb128 0x3 # (DIE (0x5d) DW_TAG_base_type) + .byte 0x2 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF7 # DW_AT_name: "short unsigned int" + .uleb128 0x3 # (DIE (0x64) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF8 # DW_AT_name: "long unsigned int" + .uleb128 0x3 # (DIE (0x6b) DW_TAG_base_type) + .byte 0x1 # DW_AT_byte_size + .byte 0x6 # DW_AT_encoding + .long .LASF9 # DW_AT_name: "signed char" + .uleb128 0x3 # (DIE (0x72) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF10 # DW_AT_name: "long long unsigned int" + .uleb128 0x3 # (DIE (0x79) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x4 # DW_AT_encoding + .long .LASF11 # DW_AT_name: "double" + .uleb128 0x4 # (DIE (0x80) DW_TAG_subprogram) + # DW_AT_external + .long .LASF18 # DW_AT_name: "main" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x21 # DW_AT_decl_line + .byte 0x1 # DW_AT_decl_column + # DW_AT_prototyped + .long 0x25 # DW_AT_type + .long .LFB4023 # DW_AT_low_pc + .long .LFE4023-.LFB4023 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_tail_call_sites + .uleb128 0x5 # (DIE (0x96) DW_TAG_subprogram) + # DW_AT_external + .long .LASF12 # DW_AT_name: "ptwrite2" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x1b # DW_AT_decl_line + .byte 0x1 # DW_AT_decl_column + # DW_AT_prototyped + .long .LFB4022 # DW_AT_low_pc + .long .LFE4022-.LFB4022 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_call_sites + .long 0xd5 # DW_AT_sibling + .uleb128 0x6 # (DIE (0xac) DW_TAG_formal_parameter) + .long .LASF14 # DW_AT_name: "value" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x1b # DW_AT_decl_line + .byte 0xf # DW_AT_decl_column + .long 0x25 # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 0 + .uleb128 0x7 # (DIE (0xbb) DW_TAG_inlined_subroutine) + .long 0x114 # DW_AT_abstract_origin + .long .LBB8 # DW_AT_low_pc + .long .LBE8-.LBB8 # DW_AT_high_pc + .byte 0x1 # DW_AT_call_file (ptwrite.c) + .byte 0x1d # DW_AT_call_line + .byte 0x3 # DW_AT_call_column + .uleb128 0x8 # (DIE (0xcb) DW_TAG_formal_parameter) + .long 0x11e # DW_AT_abstract_origin + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -12 + .byte 0 # end of children of DIE 0xbb + .byte 0 # end of children of DIE 0x96 + .uleb128 0x5 # (DIE (0xd5) DW_TAG_subprogram) + # DW_AT_external + .long .LASF13 # DW_AT_name: "ptwrite1" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x15 # DW_AT_decl_line + .byte 0x1 # DW_AT_decl_column + # DW_AT_prototyped + .long .LFB4021 # DW_AT_low_pc + .long .LFE4021-.LFB4021 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_call_sites + .long 0x114 # DW_AT_sibling + .uleb128 0x6 # (DIE (0xeb) DW_TAG_formal_parameter) + .long .LASF14 # DW_AT_name: "value" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x15 # DW_AT_decl_line + .byte 0xf # DW_AT_decl_column + .long 0x25 # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 0 + .uleb128 0x7 # (DIE (0xfa) DW_TAG_inlined_subroutine) + .long 0x114 # DW_AT_abstract_origin + .long .LBB6 # DW_AT_low_pc + .long .LBE6-.LBB6 # DW_AT_high_pc + .byte 0x1 # DW_AT_call_file (ptwrite.c) + .byte 0x17 # DW_AT_call_line + .byte 0x3 # DW_AT_call_column + .uleb128 0x8 # (DIE (0x10a) DW_TAG_formal_parameter) + .long 0x11e # DW_AT_abstract_origin + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -12 + .byte 0 # end of children of DIE 0xfa + .byte 0 # end of children of DIE 0xd5 + .uleb128 0x9 # (DIE (0x114) DW_TAG_subprogram) + # DW_AT_external + .long .LASF19 # DW_AT_name: "_ptwrite32" + .byte 0x2 # DW_AT_decl_file (/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h) + .value 0x131 # DW_AT_decl_line + .byte 0x1 # DW_AT_decl_column + # DW_AT_prototyped + .byte 0x3 # DW_AT_inline + # DW_AT_artificial + .uleb128 0xa # (DIE (0x11e) DW_TAG_formal_parameter) + .ascii "__B\0" # DW_AT_name + .byte 0x2 # DW_AT_decl_file (/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h) + .value 0x131 # DW_AT_decl_line + .byte 0x16 # DW_AT_decl_column + .long 0x48 # DW_AT_type + .byte 0 # end of children of DIE 0x114 + .byte 0 # end of children of DIE 0xb + .section .debug_abbrev,"",@progbits +.Ldebug_abbrev0: + .uleb128 0x1 # (abbrev code) + .uleb128 0x11 # (TAG: DW_TAG_compile_unit) + .byte 0x1 # DW_children_yes + .uleb128 0x25 # (DW_AT_producer) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x13 # (DW_AT_language) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x1b # (DW_AT_comp_dir) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x6 # (DW_FORM_data4) + .uleb128 0x10 # (DW_AT_stmt_list) + .uleb128 0x17 # (DW_FORM_sec_offset) + .byte 0 + .byte 0 + .uleb128 0x2 # (abbrev code) + .uleb128 0x24 # (TAG: DW_TAG_base_type) + .byte 0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3e # (DW_AT_encoding) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .byte 0 + .byte 0 + .uleb128 0x3 # (abbrev code) + .uleb128 0x24 # (TAG: DW_TAG_base_type) + .byte 0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3e # (DW_AT_encoding) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .byte 0 + .byte 0 + .uleb128 0x4 # (abbrev code) + .uleb128 0x2e # (TAG: DW_TAG_subprogram) + .byte 0 # DW_children_no + .uleb128 0x3f # (DW_AT_external) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x39 # (DW_AT_decl_column) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x27 # (DW_AT_prototyped) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x6 # (DW_FORM_data4) + .uleb128 0x40 # (DW_AT_frame_base) + .uleb128 0x18 # (DW_FORM_exprloc) + .uleb128 0x2116 # (DW_AT_GNU_all_tail_call_sites) + .uleb128 0x19 # (DW_FORM_flag_present) + .byte 0 + .byte 0 + .uleb128 0x5 # (abbrev code) + .uleb128 0x2e # (TAG: DW_TAG_subprogram) + .byte 0x1 # DW_children_yes + .uleb128 0x3f # (DW_AT_external) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x39 # (DW_AT_decl_column) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x27 # (DW_AT_prototyped) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x6 # (DW_FORM_data4) + .uleb128 0x40 # (DW_AT_frame_base) + .uleb128 0x18 # (DW_FORM_exprloc) + .uleb128 0x2117 # (DW_AT_GNU_all_call_sites) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x1 # (DW_AT_sibling) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x6 # (abbrev code) + .uleb128 0x5 # (TAG: DW_TAG_formal_parameter) + .byte 0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x39 # (DW_AT_decl_column) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x2 # (DW_AT_location) + .uleb128 0x18 # (DW_FORM_exprloc) + .byte 0 + .byte 0 + .uleb128 0x7 # (abbrev code) + .uleb128 0x1d # (TAG: DW_TAG_inlined_subroutine) + .byte 0x1 # DW_children_yes + .uleb128 0x31 # (DW_AT_abstract_origin) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x6 # (DW_FORM_data4) + .uleb128 0x58 # (DW_AT_call_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x59 # (DW_AT_call_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x57 # (DW_AT_call_column) + .uleb128 0xb # (DW_FORM_data1) + .byte 0 + .byte 0 + .uleb128 0x8 # (abbrev code) + .uleb128 0x5 # (TAG: DW_TAG_formal_parameter) + .byte 0 # DW_children_no + .uleb128 0x31 # (DW_AT_abstract_origin) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x2 # (DW_AT_location) + .uleb128 0x18 # (DW_FORM_exprloc) + .byte 0 + .byte 0 + .uleb128 0x9 # (abbrev code) + .uleb128 0x2e # (TAG: DW_TAG_subprogram) + .byte 0x1 # DW_children_yes + .uleb128 0x3f # (DW_AT_external) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0x5 # (DW_FORM_data2) + .uleb128 0x39 # (DW_AT_decl_column) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x27 # (DW_AT_prototyped) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x20 # (DW_AT_inline) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x34 # (DW_AT_artificial) + .uleb128 0x19 # (DW_FORM_flag_present) + .byte 0 + .byte 0 + .uleb128 0xa # (abbrev code) + .uleb128 0x5 # (TAG: DW_TAG_formal_parameter) + .byte 0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0x5 # (DW_FORM_data2) + .uleb128 0x39 # (DW_AT_decl_column) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .byte 0 + .section .debug_aranges,"",@progbits + .long 0x1c # Length of Address Ranges Info + .value 0x2 # DWARF aranges version + .long .Ldebug_info0 # Offset of Compilation Unit Info + .byte 0x4 # Size of Address + .byte 0 # Size of Segment Descriptor + .value 0 # Pad to 8 byte boundary + .value 0 + .long .Ltext0 # Address + .long .Letext0-.Ltext0 # Length + .long 0 + .long 0 + .section .debug_line,"",@progbits +.Ldebug_line0: + .section .debug_str,"MS",@progbits,1 +.LASF2: + .string "long long int" +.LASF14: + .string "value" +.LASF19: + .string "_ptwrite32" +.LASF4: + .string "unsigned int" +.LASF17: + .string "gdb/gdb/testsuite/gdb.btrace" +.LASF18: + .string "main" +.LASF16: + .string "ptwrite.c" +.LASF8: + .string "long unsigned int" +.LASF10: + .string "long long unsigned int" +.LASF13: + .string "ptwrite1" +.LASF12: + .string "ptwrite2" +.LASF6: + .string "unsigned char" +.LASF1: + .string "char" +.LASF5: + .string "long int" +.LASF15: + .string "GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -m32 -mptwrite -mtune=generic -march=i686 -g" +.LASF11: + .string "double" +.LASF7: + .string "short unsigned int" +.LASF9: + .string "signed char" +.LASF3: + .string "float" +.LASF0: + .string "short int" + .ident "GCC: (GNU) 10.3.1 20210422 (Red Hat 10.3.1-1)" + .section .note.GNU-stack,"",@progbits diff --git a/gdb/testsuite/gdb.btrace/ptwrite.c b/gdb/testsuite/gdb.btrace/ptwrite.c new file mode 100644 index 00000000000..c85b656919b --- /dev/null +++ b/gdb/testsuite/gdb.btrace/ptwrite.c @@ -0,0 +1,39 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2021 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 . */ + +#include + +void +ptwrite1 (int value) +{ + _ptwrite32 (value); +} + +void +ptwrite2 (int value) +{ + _ptwrite32 (value); +} + +int +main (void) +{ + ptwrite1 (0x42); + ptwrite2 (0x43); + + return 0; +} diff --git a/gdb/testsuite/gdb.btrace/ptwrite.exp b/gdb/testsuite/gdb.btrace/ptwrite.exp new file mode 100644 index 00000000000..734b99ea0ea --- /dev/null +++ b/gdb/testsuite/gdb.btrace/ptwrite.exp @@ -0,0 +1,200 @@ +# This testcase is part of GDB, the GNU debugger. +# +# Copyright 2021 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 . + +load_lib gdb-python.exp + +require allow_btrace_ptw_tests allow_python_tests + +set opts {} + +if [info exists COMPILE] { + # make check RUNTESTFLAGS="gdb.btrace/ptwrite.exp COMPILE=1" + standard_testfile ptwrite.c + lappend opts debug additional_flags=-mptwrite +} elseif {[istarget "i?86-*-*"] || [istarget "x86_64-*-*"]} { + if {[is_amd64_regs_target]} { + standard_testfile x86_64-ptwrite.S + } else { + standard_testfile i386-ptwrite.S + } +} else { + unsupported "target architecture not supported" + return -1 +} + +if [prepare_for_testing "failed to prepare" $testfile $srcfile $opts] { + return -1 +} + +if { ![runto_main] } { + untested "failed to run to main" + return -1 +} + +### 1. Default testrun + +# Setup recording +gdb_test_no_output "set record instruction-history-size unlimited" +gdb_test_no_output "record btrace pt" +gdb_test "next" ".*" "next" +gdb_test "next" ".*" "next 2" + +with_test_prefix "Default" { + # Test record instruction-history + gdb_test "record instruction-history 1" [multi_line \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[42\\\]" \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[43\\\].*" \ + ] + + gdb_test "record instruction-history /a 1" [multi_line \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+.*" \ + ] + + # Test function call history + gdb_test "record function-call-history 1,4" [multi_line \ + "1\tmain" \ + "2\tptwrite1" \ + "\t\t\\\[42\\\]" \ + "3\tmain" \ + "4\tptwrite2" \ + "\t\t\\\[43\\\]" \ + ] + + gdb_test "record function-call-history /a 1,4" [multi_line \ + "1\tmain" \ + "2\tptwrite1" \ + "3\tmain" \ + "4\tptwrite2" \ + ] +} + +# Test payload printing during stepping +with_test_prefix "Stepping" { + gdb_test "record goto 10" "No such instruction\." + gdb_test "record goto 9" ".*ptwrite.* at .*" + gdb_test "stepi" ".*\\\[42\\\].*" + gdb_test "reverse-stepi" ".*\\\[42\\\].*" + gdb_test "continue" [multi_line \ + ".*\\\[42\\\]" \ + "\\\[43\\\].*" \ + ] + gdb_test "reverse-continue" [multi_line \ + ".*\\\[43\\\]" \ + "\\\[42\\\].*" \ + ] +} + +# Test auxiliary type in python +gdb_test_multiline "auxiliary type in python" \ + "python" "" \ + "h = gdb.current_recording().instruction_history" "" \ + "for insn in h:" "" \ + " if hasattr(insn, 'decoded'):" "" \ + " print(insn.decoded.decode())" "" \ + " elif hasattr(insn, 'data'):" "" \ + " print(insn.data)" "" \ + "end" \ + [multi_line \ + ".*mov -0x4\\\(%(e|r)bp\\\),%(e|r)ax" \ + "ptwrite %eax" \ + "42" \ + "nop.*" \ + "mov -0x4\\\(%(e|r)bp\\\),%(e|r)ax" \ + "ptwrite %eax" \ + "43" \ + "nop.*" + ] + + +### 2. Test filter registration +### 2.1 Custom filter +with_test_prefix "Custom" { + gdb_test_multiline "register filter in python" \ + "python" "" \ + "def my_filter(payload, ip):" "" \ + " if payload == 66:" "" \ + " return \"payload: {0}, ip: {1:#x}\".format(payload, ip)" "" \ + " else:" "" \ + " return None" "" \ + "import gdb.ptwrite" "" \ + "gdb.ptwrite.register_filter(my_filter)" "" \ + "end" "" + + gdb_test "record instruction-history 1" [multi_line \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[payload: 66, ip: $hex\\\]" \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t $hex :.*" \ + ] +} + +### 2.2 None as filter +with_test_prefix "None" { + gdb_test_multiline "register filter in python" \ + "python" "" \ + "import gdb.ptwrite" "" \ + "gdb.ptwrite.register_filter(None)" "" \ + "end" "" + + gdb_test "record instruction-history 1" [multi_line \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t $hex :.*" \ + "\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t $hex :.*" \ + ] +} + +### 2.3 Lambdas as filter +with_test_prefix "Lambdas" { + gdb_test_multiline "register filter in python" \ + "python" "" \ + "import gdb.ptwrite" "" \ + "gdb.ptwrite.register_filter(lambda payload, ip: \"{}\".format(payload + 2))" "" \ + "end" "" + + gdb_test "record instruction-history 1" [multi_line \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[68\\\]" \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[69\\\].*" \ + ] "Lambdas: record instruction-history 1" +} + +### 2.4 Functors as filter +with_test_prefix "Functors" { + gdb_test_multiline "register filter in python" \ + "python" "" \ + "import gdb.ptwrite" "" \ + "class foobar(object):" "" \ + " def __init__(self):" "" \ + " self.variable = 0" "" \ + " def __call__(self, payload, ip):" "" \ + " self.variable += 1" "" \ + " return \"{}, {}\".format(self.variable, payload)" "" \ + "gdb.ptwrite.register_filter(foobar())" "" \ + "end" "" + + gdb_test "record instruction-history 1" [multi_line \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[1, 66\\\]" \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[2, 67\\\].*" \ + ] "Functors: record instruction-history 1" +} diff --git a/gdb/testsuite/gdb.btrace/x86_64-ptwrite.S b/gdb/testsuite/gdb.btrace/x86_64-ptwrite.S new file mode 100644 index 00000000000..6fe64013399 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/x86_64-ptwrite.S @@ -0,0 +1,544 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2022 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 . + + + This file has been generated using gcc version 10.3.1 20210422 + (Red Hat 10.3.1-1): + gcc -S -dA -g -mptwrite ptwrite.c -o x86_64-ptwrite.S. */ + + .file "ptwrite.c" + .text +.Ltext0: + .globl ptwrite1 + .type ptwrite1, @function +ptwrite1: +.LFB4096: + .file 1 "ptwrite.c" + # ptwrite.c:22:1 + .loc 1 22 1 + .cfi_startproc +# BLOCK 2 seq:0 +# PRED: ENTRY (FALLTHRU) + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + movl %edi, -20(%rbp) + # ptwrite.c:23:3 + .loc 1 23 3 + movl -20(%rbp), %eax + movl %eax, -4(%rbp) +.LBB6: +.LBB7: + .file 2 "/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h" + # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:307:3 + .loc 2 307 3 + movl -4(%rbp), %eax + ptwrite %eax + # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:308:1 + .loc 2 308 1 + nop +.LBE7: +.LBE6: + # ptwrite.c:24:1 + .loc 1 24 1 + nop + popq %rbp + .cfi_def_cfa 7, 8 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE4096: + .size ptwrite1, .-ptwrite1 + .globl ptwrite2 + .type ptwrite2, @function +ptwrite2: +.LFB4097: + # ptwrite.c:28:1 + .loc 1 28 1 + .cfi_startproc +# BLOCK 2 seq:0 +# PRED: ENTRY (FALLTHRU) + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + movl %edi, -20(%rbp) + # ptwrite.c:29:3 + .loc 1 29 3 + movl -20(%rbp), %eax + movl %eax, -4(%rbp) +.LBB8: +.LBB9: + # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:307:3 + .loc 2 307 3 + movl -4(%rbp), %eax + ptwrite %eax + # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:308:1 + .loc 2 308 1 + nop +.LBE9: +.LBE8: + # ptwrite.c:30:1 + .loc 1 30 1 + nop + popq %rbp + .cfi_def_cfa 7, 8 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE4097: + .size ptwrite2, .-ptwrite2 + .globl main + .type main, @function +main: +.LFB4098: + # ptwrite.c:34:1 + .loc 1 34 1 + .cfi_startproc +# BLOCK 2 seq:0 +# PRED: ENTRY (FALLTHRU) + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + # ptwrite.c:35:3 + .loc 1 35 3 + movl $66, %edi + call ptwrite1 + # ptwrite.c:36:3 + .loc 1 36 3 + movl $67, %edi + call ptwrite2 + # ptwrite.c:38:10 + .loc 1 38 10 + movl $0, %eax + # ptwrite.c:39:1 + .loc 1 39 1 + popq %rbp + .cfi_def_cfa 7, 8 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE4098: + .size main, .-main +.Letext0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .long 0x159 # Length of Compilation Unit Info + .value 0x4 # DWARF version number + .long .Ldebug_abbrev0 # Offset Into Abbrev. Section + .byte 0x8 # Pointer Size (in bytes) + .uleb128 0x1 # (DIE (0xb) DW_TAG_compile_unit) + .long .LASF15 # DW_AT_producer: "GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -mptwrite -mtune=generic -march=x86-64 -g" + .byte 0xc # DW_AT_language + .long .LASF16 # DW_AT_name: "ptwrite.c" + .long .LASF17 # DW_AT_comp_dir: "gdb/gdb/testsuite/gdb.btrace" + .quad .Ltext0 # DW_AT_low_pc + .quad .Letext0-.Ltext0 # DW_AT_high_pc + .long .Ldebug_line0 # DW_AT_stmt_list + .uleb128 0x2 # (DIE (0x2d) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .ascii "int\0" # DW_AT_name + .uleb128 0x3 # (DIE (0x34) DW_TAG_base_type) + .byte 0x2 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .long .LASF0 # DW_AT_name: "short int" + .uleb128 0x3 # (DIE (0x3b) DW_TAG_base_type) + .byte 0x1 # DW_AT_byte_size + .byte 0x6 # DW_AT_encoding + .long .LASF1 # DW_AT_name: "char" + .uleb128 0x3 # (DIE (0x42) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .long .LASF2 # DW_AT_name: "long long int" + .uleb128 0x3 # (DIE (0x49) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x4 # DW_AT_encoding + .long .LASF3 # DW_AT_name: "float" + .uleb128 0x3 # (DIE (0x50) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF4 # DW_AT_name: "long unsigned int" + .uleb128 0x3 # (DIE (0x57) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .long .LASF5 # DW_AT_name: "long int" + .uleb128 0x3 # (DIE (0x5e) DW_TAG_base_type) + .byte 0x1 # DW_AT_byte_size + .byte 0x8 # DW_AT_encoding + .long .LASF6 # DW_AT_name: "unsigned char" + .uleb128 0x3 # (DIE (0x65) DW_TAG_base_type) + .byte 0x2 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF7 # DW_AT_name: "short unsigned int" + .uleb128 0x3 # (DIE (0x6c) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF8 # DW_AT_name: "unsigned int" + .uleb128 0x3 # (DIE (0x73) DW_TAG_base_type) + .byte 0x1 # DW_AT_byte_size + .byte 0x6 # DW_AT_encoding + .long .LASF9 # DW_AT_name: "signed char" + .uleb128 0x3 # (DIE (0x7a) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF10 # DW_AT_name: "long long unsigned int" + .uleb128 0x3 # (DIE (0x81) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x4 # DW_AT_encoding + .long .LASF11 # DW_AT_name: "double" + .uleb128 0x4 # (DIE (0x88) DW_TAG_subprogram) + # DW_AT_external + .long .LASF18 # DW_AT_name: "main" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x21 # DW_AT_decl_line + .byte 0x1 # DW_AT_decl_column + # DW_AT_prototyped + .long 0x2d # DW_AT_type + .quad .LFB4098 # DW_AT_low_pc + .quad .LFE4098-.LFB4098 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_tail_call_sites + .uleb128 0x5 # (DIE (0xa6) DW_TAG_subprogram) + # DW_AT_external + .long .LASF12 # DW_AT_name: "ptwrite2" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x1b # DW_AT_decl_line + .byte 0x1 # DW_AT_decl_column + # DW_AT_prototyped + .quad .LFB4097 # DW_AT_low_pc + .quad .LFE4097-.LFB4097 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_call_sites + .long 0xf5 # DW_AT_sibling + .uleb128 0x6 # (DIE (0xc4) DW_TAG_formal_parameter) + .long .LASF14 # DW_AT_name: "value" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x1b # DW_AT_decl_line + .byte 0xf # DW_AT_decl_column + .long 0x2d # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -36 + .uleb128 0x7 # (DIE (0xd3) DW_TAG_inlined_subroutine) + .long 0x144 # DW_AT_abstract_origin + .quad .LBB8 # DW_AT_low_pc + .quad .LBE8-.LBB8 # DW_AT_high_pc + .byte 0x1 # DW_AT_call_file (ptwrite.c) + .byte 0x1d # DW_AT_call_line + .byte 0x3 # DW_AT_call_column + .uleb128 0x8 # (DIE (0xeb) DW_TAG_formal_parameter) + .long 0x14e # DW_AT_abstract_origin + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -20 + .byte 0 # end of children of DIE 0xd3 + .byte 0 # end of children of DIE 0xa6 + .uleb128 0x5 # (DIE (0xf5) DW_TAG_subprogram) + # DW_AT_external + .long .LASF13 # DW_AT_name: "ptwrite1" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x15 # DW_AT_decl_line + .byte 0x1 # DW_AT_decl_column + # DW_AT_prototyped + .quad .LFB4096 # DW_AT_low_pc + .quad .LFE4096-.LFB4096 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_call_sites + .long 0x144 # DW_AT_sibling + .uleb128 0x6 # (DIE (0x113) DW_TAG_formal_parameter) + .long .LASF14 # DW_AT_name: "value" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x15 # DW_AT_decl_line + .byte 0xf # DW_AT_decl_column + .long 0x2d # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -36 + .uleb128 0x7 # (DIE (0x122) DW_TAG_inlined_subroutine) + .long 0x144 # DW_AT_abstract_origin + .quad .LBB6 # DW_AT_low_pc + .quad .LBE6-.LBB6 # DW_AT_high_pc + .byte 0x1 # DW_AT_call_file (ptwrite.c) + .byte 0x17 # DW_AT_call_line + .byte 0x3 # DW_AT_call_column + .uleb128 0x8 # (DIE (0x13a) DW_TAG_formal_parameter) + .long 0x14e # DW_AT_abstract_origin + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -20 + .byte 0 # end of children of DIE 0x122 + .byte 0 # end of children of DIE 0xf5 + .uleb128 0x9 # (DIE (0x144) DW_TAG_subprogram) + # DW_AT_external + .long .LASF19 # DW_AT_name: "_ptwrite32" + .byte 0x2 # DW_AT_decl_file (/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h) + .value 0x131 # DW_AT_decl_line + .byte 0x1 # DW_AT_decl_column + # DW_AT_prototyped + .byte 0x3 # DW_AT_inline + # DW_AT_artificial + .uleb128 0xa # (DIE (0x14e) DW_TAG_formal_parameter) + .ascii "__B\0" # DW_AT_name + .byte 0x2 # DW_AT_decl_file (/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h) + .value 0x131 # DW_AT_decl_line + .byte 0x16 # DW_AT_decl_column + .long 0x6c # DW_AT_type + .byte 0 # end of children of DIE 0x144 + .byte 0 # end of children of DIE 0xb + .section .debug_abbrev,"",@progbits +.Ldebug_abbrev0: + .uleb128 0x1 # (abbrev code) + .uleb128 0x11 # (TAG: DW_TAG_compile_unit) + .byte 0x1 # DW_children_yes + .uleb128 0x25 # (DW_AT_producer) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x13 # (DW_AT_language) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x1b # (DW_AT_comp_dir) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x7 # (DW_FORM_data8) + .uleb128 0x10 # (DW_AT_stmt_list) + .uleb128 0x17 # (DW_FORM_sec_offset) + .byte 0 + .byte 0 + .uleb128 0x2 # (abbrev code) + .uleb128 0x24 # (TAG: DW_TAG_base_type) + .byte 0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3e # (DW_AT_encoding) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .byte 0 + .byte 0 + .uleb128 0x3 # (abbrev code) + .uleb128 0x24 # (TAG: DW_TAG_base_type) + .byte 0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3e # (DW_AT_encoding) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .byte 0 + .byte 0 + .uleb128 0x4 # (abbrev code) + .uleb128 0x2e # (TAG: DW_TAG_subprogram) + .byte 0 # DW_children_no + .uleb128 0x3f # (DW_AT_external) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x39 # (DW_AT_decl_column) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x27 # (DW_AT_prototyped) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x7 # (DW_FORM_data8) + .uleb128 0x40 # (DW_AT_frame_base) + .uleb128 0x18 # (DW_FORM_exprloc) + .uleb128 0x2116 # (DW_AT_GNU_all_tail_call_sites) + .uleb128 0x19 # (DW_FORM_flag_present) + .byte 0 + .byte 0 + .uleb128 0x5 # (abbrev code) + .uleb128 0x2e # (TAG: DW_TAG_subprogram) + .byte 0x1 # DW_children_yes + .uleb128 0x3f # (DW_AT_external) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x39 # (DW_AT_decl_column) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x27 # (DW_AT_prototyped) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x7 # (DW_FORM_data8) + .uleb128 0x40 # (DW_AT_frame_base) + .uleb128 0x18 # (DW_FORM_exprloc) + .uleb128 0x2117 # (DW_AT_GNU_all_call_sites) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x1 # (DW_AT_sibling) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x6 # (abbrev code) + .uleb128 0x5 # (TAG: DW_TAG_formal_parameter) + .byte 0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x39 # (DW_AT_decl_column) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x2 # (DW_AT_location) + .uleb128 0x18 # (DW_FORM_exprloc) + .byte 0 + .byte 0 + .uleb128 0x7 # (abbrev code) + .uleb128 0x1d # (TAG: DW_TAG_inlined_subroutine) + .byte 0x1 # DW_children_yes + .uleb128 0x31 # (DW_AT_abstract_origin) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x7 # (DW_FORM_data8) + .uleb128 0x58 # (DW_AT_call_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x59 # (DW_AT_call_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x57 # (DW_AT_call_column) + .uleb128 0xb # (DW_FORM_data1) + .byte 0 + .byte 0 + .uleb128 0x8 # (abbrev code) + .uleb128 0x5 # (TAG: DW_TAG_formal_parameter) + .byte 0 # DW_children_no + .uleb128 0x31 # (DW_AT_abstract_origin) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x2 # (DW_AT_location) + .uleb128 0x18 # (DW_FORM_exprloc) + .byte 0 + .byte 0 + .uleb128 0x9 # (abbrev code) + .uleb128 0x2e # (TAG: DW_TAG_subprogram) + .byte 0x1 # DW_children_yes + .uleb128 0x3f # (DW_AT_external) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0x5 # (DW_FORM_data2) + .uleb128 0x39 # (DW_AT_decl_column) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x27 # (DW_AT_prototyped) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x20 # (DW_AT_inline) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x34 # (DW_AT_artificial) + .uleb128 0x19 # (DW_FORM_flag_present) + .byte 0 + .byte 0 + .uleb128 0xa # (abbrev code) + .uleb128 0x5 # (TAG: DW_TAG_formal_parameter) + .byte 0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0x5 # (DW_FORM_data2) + .uleb128 0x39 # (DW_AT_decl_column) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .byte 0 + .section .debug_aranges,"",@progbits + .long 0x2c # Length of Address Ranges Info + .value 0x2 # DWARF aranges version + .long .Ldebug_info0 # Offset of Compilation Unit Info + .byte 0x8 # Size of Address + .byte 0 # Size of Segment Descriptor + .value 0 # Pad to 16 byte boundary + .value 0 + .quad .Ltext0 # Address + .quad .Letext0-.Ltext0 # Length + .quad 0 + .quad 0 + .section .debug_line,"",@progbits +.Ldebug_line0: + .section .debug_str,"MS",@progbits,1 +.LASF2: + .string "long long int" +.LASF14: + .string "value" +.LASF19: + .string "_ptwrite32" +.LASF8: + .string "unsigned int" +.LASF17: + .string "gdb/gdb/testsuite/gdb.btrace" +.LASF18: + .string "main" +.LASF16: + .string "ptwrite.c" +.LASF4: + .string "long unsigned int" +.LASF10: + .string "long long unsigned int" +.LASF15: + .string "GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -mptwrite -mtune=generic -march=x86-64 -g" +.LASF13: + .string "ptwrite1" +.LASF12: + .string "ptwrite2" +.LASF6: + .string "unsigned char" +.LASF1: + .string "char" +.LASF5: + .string "long int" +.LASF11: + .string "double" +.LASF7: + .string "short unsigned int" +.LASF9: + .string "signed char" +.LASF3: + .string "float" +.LASF0: + .string "short int" + .ident "GCC: (GNU) 10.3.1 20210422 (Red Hat 10.3.1-1)" + .section .note.GNU-stack,"",@progbits diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 0a0ae697d1e..bced47eda99 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -3939,6 +3939,78 @@ gdb_caching_proc allow_btrace_pt_tests {} { return $allow_btrace_pt_tests } +# Run a test on the target to see if it supports ptwrite instructions and +# if GDB can decode ptwrite events. Return 1 if so, 0 if it does not. + +gdb_caching_proc allow_btrace_ptw_tests {} { + global srcdir subdir gdb_prompt inferior_exited_re decimal + + require allow_btrace_pt_tests + set me "allow_btrace_ptw_tests" + + set src { + int + main () + { + asm volatile ("PTWRITE %0;" : : "b"(0x42)); + return 0; + } + } + + if {![gdb_simple_compile $me $src executable]} { + return 1 + } + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load "$obj" + if ![runto_main] { + return 1 + } + + gdb_test_no_output "record btrace pt" "$me: record btrace pt" + + set allow_btrace_ptw_tests 2 + gdb_test_multiple "next" "$me: next" { + -re -wrap ".*Illegal instruction.*" { + verbose -log "$me: ptwrite instruction support not detected." + set allow_btrace_ptw_tests 0 + } + -re -wrap ".*$inferior_exited_re normally.*" { + verbose -log "$me: ptwrite support not detected." + set allow_btrace_ptw_tests 0 + } + -re -wrap "$decimal.*(at|in|return 0).*" { + set allow_btrace_ptw_tests 1 + } + } + + if { $allow_btrace_ptw_tests == 1 } { + # Show the func-call-history to get the packet trace. + gdb_test "record function-call-history" ".*" + + gdb_test_multiple "maintenance btrace packet-history 0,1000" \ + "$me: check decoding support" { + -re "ptw" { + verbose -log "$me: ptwrite decoding support detected." + set allow_btrace_ptw_tests 1 + } + -re ".*${gdb_prompt} $" { + verbose -log "$me: ptwrite decoding support not detected." + set allow_btrace_ptw_tests 0 + } + } + } + + gdb_exit + remote_file build delete $obj + + verbose "$me: returning $allow_btrace_ptw_tests" 2 + return $allow_btrace_ptw_tests +} + + # Run a test on the target to see if it supports Aarch64 SVE hardware. # Return 1 if so, 0 if it does not. Note this causes a restart of GDB. diff --git a/gdbsupport/common.m4 b/gdbsupport/common.m4 index 3909ec81ccb..1ad2395e80f 100644 --- a/gdbsupport/common.m4 +++ b/gdbsupport/common.m4 @@ -190,6 +190,8 @@ AC_DEFUN([GDB_AC_COMMON], [ AC_CHECK_FUNCS(pt_insn_event) AC_CHECK_MEMBERS([struct pt_insn.enabled, struct pt_insn.resynced], [], [], [#include ]) + AC_CHECK_MEMBERS([struct pt_event.variant.ptwrite], [], [], + [#include ]) LIBS=$save_LIBS fi fi diff --git a/gdbsupport/config.in b/gdbsupport/config.in index 2cdc1fbde61..8ce8e23bc24 100644 --- a/gdbsupport/config.in +++ b/gdbsupport/config.in @@ -238,6 +238,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H +/* Define to 1 if `variant.ptwrite' is a member of `struct pt_event'. */ +#undef HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE + /* Define to 1 if `enabled' is a member of `struct pt_insn'. */ #undef HAVE_STRUCT_PT_INSN_ENABLED diff --git a/gdbsupport/configure b/gdbsupport/configure index 9433ac41468..7a10c96bd75 100755 --- a/gdbsupport/configure +++ b/gdbsupport/configure @@ -9625,6 +9625,17 @@ cat >>confdefs.h <<_ACEOF _ACEOF +fi + + ac_fn_c_check_member "$LINENO" "struct pt_event" "variant.ptwrite" "ac_cv_member_struct_pt_event_variant_ptwrite" "#include +" +if test "x$ac_cv_member_struct_pt_event_variant_ptwrite" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE 1 +_ACEOF + + fi LIBS=$save_LIBS