From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 0F429383A0EB for ; Wed, 7 Dec 2022 13:51:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 0F429383A0EB Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1670421102; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=XCQyqRHq5bGCmIXLXlr3PmosAKTqndmTuRkNPFjrHGs=; b=bFQpOFQL5cSltix24w1qRxupjOThL2zhozmCnVth0P/oEKVAl3vrIoaHjicj2oZoKBQ6aD LHPqxHJulB1YQ3cXjznbZkiaTYM+u32zhQbAM381qGEmB+XrLJ7bGuDktwT+KpZ1Mfh/70 oEo18/rq1WutIsQjW1FRD0Xkt3fu0a8= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-569-__6F5svsN-WZFCAHLiPD-g-1; Wed, 07 Dec 2022 08:51:41 -0500 X-MC-Unique: __6F5svsN-WZFCAHLiPD-g-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 420F8802804 for ; Wed, 7 Dec 2022 13:51:41 +0000 (UTC) Received: from fedora.redhat.com (ovpn-194-124.brq.redhat.com [10.40.194.124]) by smtp.corp.redhat.com (Postfix) with ESMTPS id BEE042166B29; Wed, 7 Dec 2022 13:51:40 +0000 (UTC) From: Bruno Larsen To: gdb-patches@sourceware.org Cc: Bruno Larsen Subject: [PATCH] gdb: add 'maintenance print record-instruction' command Date: Wed, 7 Dec 2022 14:50:00 +0100 Message-Id: <20221207135000.1344331-1-blarsen@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,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 List-Id: While chasing some reverse debugging bugs, I found myself wondering what was recorded by GDB to undo and redo a certain instruction. This commit implements a simple way of printing that information. --- gdb/NEWS | 6 ++++ gdb/doc/gdb.texinfo | 8 +++++ gdb/record-full.c | 81 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) diff --git a/gdb/NEWS b/gdb/NEWS index c4ccfcc9e32..d6ce6bf86a0 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -103,6 +103,12 @@ * New commands +maintenance print record-instruction [ N ] + Print the recorded information for a given instruction. If N is not given + prints how GDB would undo the last instruction executed. If N is negative, + prints how GDB would undo the N-th previous instruction, and if N is + positive, it prints how GDB will redo the N-th following instruction. + maintenance set ignore-prologue-end-flag on|off maintenance show ignore-prologue-end-flag This setting, which is off by default, controls whether GDB ignores the diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 5b566669975..807af351e79 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -40531,6 +40531,14 @@ that symbol is described. The type chain produced by this command is a recursive definition of the data type as stored in @value{GDBN}'s data structures, including its flags and contained types. +@kindex maint print record-instruction +@item maint print record-instruction +@itemx maint print record-instruction @var{N} +@cindex print how GDB recorded a given instruction. If N is not positive +number, it prints the values stored by the inferior before the N-th previous +instruction was exectued. If N is positive, print the values after the N-th +following instruction is executed. If N is not given, 0 is assumed. + @kindex maint selftest @cindex self tests @item maint selftest @r{[}-verbose@r{]} @r{[}@var{filter}@r{]} diff --git a/gdb/record-full.c b/gdb/record-full.c index 48b92281fe6..47cdf75eea4 100644 --- a/gdb/record-full.c +++ b/gdb/record-full.c @@ -2764,6 +2764,79 @@ set_record_full_insn_max_num (const char *args, int from_tty, } } +/* Implement the 'maintenance print record-instruction' command. */ + +static void +maintenance_print_record_instruction (const char *args, int from_tty) +{ + struct record_full_entry* to_print = record_full_list; + + if (args != nullptr) + { + int offset = value_as_long (parse_and_eval (args)); + if (offset > 0) + { + /* Move forward OFFSET instructions. We know we found the + end of an instruction when to_print->type is 0. */ + while (to_print->next && offset > 0) + { + to_print = to_print->next; + if (!to_print->type) + offset --; + } + if (offset != 0) + error (_("Not enough recorded history")); + } + else + { + while (to_print->prev && offset < 0) + { + to_print = to_print->prev; + if (!to_print->type) + offset++; + } + if (offset != 0) + error (_("Not enough recorded history")); + } + } + gdb_assert (to_print != nullptr); + + /* Go back to the start of the instruction. */ + while (to_print->prev && to_print->prev->type) + to_print = to_print->prev; + + while (to_print->type) + { + switch (to_print->type) + { + case record_full_reg: + { + gdb_byte* b = record_full_get_loc (to_print); + gdb_printf ("Register %%%s changed:", + gdbarch_register_name (target_gdbarch (), + to_print->u.reg.num)); + for (int i = 0; i < to_print->u.reg.len; i++) + gdb_printf (" %02x",b[i]); + gdb_printf ("\n"); + break; + } + case record_full_mem: + { + gdb_byte* b = record_full_get_loc (to_print); + gdb_printf ("%d bytes of memory at address %s changed from:", + to_print->u.mem.len, + print_core_address (target_gdbarch (), + to_print->u.mem.addr)); + for (int i = 0; i < to_print->u.mem.len; i++) + gdb_printf (" %02x",b[i]); + gdb_printf ("\n"); + break; + } + } + to_print = to_print->next; + } +} + void _initialize_record_full (); void _initialize_record_full () @@ -2868,4 +2941,12 @@ When ON, query if PREC cannot record memory change of next instruction."), c = add_alias_cmd ("memory-query", record_full_memory_query_cmds.show, no_class, 1,&show_record_cmdlist); deprecate_cmd (c, "show record full memory-query"); + + add_cmd ("record-instruction", class_maintenance, + maintenance_print_record_instruction, + _("\ +Print a recorded instruction.\nIf no argument is provided, print the last \ +instruction recorded.\nIf a negative argument is given, prints how the nth \ +previous instruction will be undone.\nIf a positive argument is given, prints \ +how the nth following instruction will be redone."), &maintenanceprintlist); } -- 2.38.1