From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id CQ0eMWdMB2pflz0AWB0awg (envelope-from ) for ; Fri, 15 May 2026 12:40:07 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=bE2K/8y+; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id BBCB11E0B1; Fri, 15 May 2026 12:40:07 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id BD42B1E067 for ; Fri, 15 May 2026 12:40:04 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3BC3440A00FF for ; Fri, 15 May 2026 16:40:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3BC3440A00FF Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=bE2K/8y+ Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id CE81340A00CB for ; Fri, 15 May 2026 16:39:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CE81340A00CB Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org CE81340A00CB Authentication-Results: sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1778863141; cv=none; b=Fx15Fbhq0eD2A3Hlo0Yc4xinDmDjoA9FwiaVIg3F2uY9vXoWZk6w9cq3uCMRI478tN1/avuvHjPadgQTeUAsKg7dvIPePEFVEQaMITJXRwWWYbw2Zm3guB2HdpMlc1pJ0PXeoQVLxOkFkli7qijzmRR8fpt6CurPe+R3PRObGLw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1778863141; c=relaxed/simple; bh=qy+Mmi0vg2WSgE6wLtSBmH8AzCx/qXOEEVkEWoaumA0=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=PAcd8L6Hk1jset7L8OKaL/f5qFFvRJSUdOOF7RBitnkXC4a7CIqMX0FkranbBspVqV0oye8iELBxwP+teaHTfW+FbZjQukC/aRR/ifcgg4tmLW4ndVcoVf09F7gSHl01umGuYC03tbMvWMbAR1SfFQJttz+c0tAYgem4WsX2sVI= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=bE2K/8y+ DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CE81340A00CB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778863141; 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: in-reply-to:in-reply-to:references:references; bh=d+0rfIIOSXFWfe/ioeJcNwIFk/QHxAEXM/fjqKXorGU=; b=bE2K/8y+qFZaJMAoZ9fqIei6/ArFgu5xTcop+aA9ilWadLoZqAymzFbWORtxgLU9N/btvP cTgXrva6VU9a42H2i2Sl+3fOw1QJzrtZYRBZuPFNHGkx3OtHP8Iz9Sq/0Vz8Oo45c5/Wrw AHh9KN1fzmDav7uzyXvFFVInf+ikGeI= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-446-TAmwzNPGOFOCmSHERVcE7g-1; Fri, 15 May 2026 12:38:59 -0400 X-MC-Unique: TAmwzNPGOFOCmSHERVcE7g-1 X-Mimecast-MFC-AGG-ID: TAmwzNPGOFOCmSHERVcE7g_1778863139 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E3D8D1800371; Fri, 15 May 2026 16:38:58 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.96.134.23]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8D1B31955F2D; Fri, 15 May 2026 16:38:56 +0000 (UTC) From: Guinevere Larsen To: gdb-patches@sourceware.org Cc: Guinevere Larsen , Thiago Jung Bauermann Subject: [PATCH v3 3/7] gdb/record: c++ify internal structures of record-full.c Date: Fri, 15 May 2026 13:37:00 -0300 Message-ID: <20260515163706.3355686-4-guinevere@redhat.com> In-Reply-To: <20260515163706.3355686-1-guinevere@redhat.com> References: <20260515163706.3355686-1-guinevere@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: fYNgxDJxBO6q94G3b1Fc-SqqRX-oHoAub7eAK5TPwgE_1778863139 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org This commit adds a constructor, destructor, and some methods to the structures record_full_entry, record_full_reg_entry and record_full_mem_entry. This is a move to disentangle the internal representation of the data and how record-full manipulates it for replaying. Along with this change, record_full_entry is changed to use an std::variant, since it was basically doing that already, but now we have the stdlibc++ error checking to make sure we're only accessing elements we're allowed to. Reviewed-by: Thiago Jung Bauermann --- gdb/record-full.c | 601 +++++++++++++++++++++++++--------------------- 1 file changed, 321 insertions(+), 280 deletions(-) diff --git a/gdb/record-full.c b/gdb/record-full.c index e4dd07dc300..24e94eaf5da 100644 --- a/gdb/record-full.c +++ b/gdb/record-full.c @@ -51,6 +51,7 @@ #include #include #include +#include /* This module implements "target record-full", also known as "process record and replay". This target sits on top of a "normal" target @@ -93,12 +94,113 @@ struct record_full_mem_entry int len; /* Set this flag if target memory for this entry can no longer be accessed. */ - int mem_entry_not_accessible; + bool mem_entry_accessible; union { gdb_byte *ptr; gdb_byte buf[sizeof (gdb_byte *)]; } u; + + record_full_mem_entry () : addr (0), len (0) { } + + record_full_mem_entry (CORE_ADDR mem_addr, int mem_len) + { + addr = mem_addr; + len = mem_len; + if (len > sizeof (u.buf)) + u.ptr = new gdb_byte[len]; + mem_entry_accessible = true; + } + + record_full_mem_entry (record_full_mem_entry &&other) + { + addr = other.addr; + len = other.len; + memcpy (u.buf, other.u.buf, sizeof (u.buf)); + mem_entry_accessible = other.mem_entry_accessible; + /* With len == 0, OTHER is guaranteed to not try to free the + memory when it is destructed. */ + other.len = 0; + } + + ~record_full_mem_entry () + { + if (len > sizeof (u.buf)) + delete[] u.ptr; + } + + record_full_mem_entry &operator= (record_full_mem_entry &&other) + { + addr = other.addr; + len = other.len; + memcpy (u.buf, other.u.buf, sizeof (u.buf)); + mem_entry_accessible = other.mem_entry_accessible; + /* With len == 0, OTHER is guaranteed to not try to free the + memory when it is destructed. */ + other.len = 0; + return *this; + } + + DISABLE_COPY_AND_ASSIGN (record_full_mem_entry); + + gdb_byte *get_loc () + { + if (len > sizeof (u.buf)) + return u.ptr; + else + return u.buf; + } + + bool execute (gdbarch *gdbarch) + { + /* Nothing to do if the memory is flagged not_accessible. */ + if (!mem_entry_accessible) + return false; + + gdb::byte_vector buf (len); + + if (record_debug > 1) + gdb_printf (gdb_stdlog, + "Process record: record_full_mem %s to " + "inferior addr = %s len = %d.\n", + host_address_to_string (this), + paddress (gdbarch, addr), + len); + + if (record_read_memory (gdbarch, addr, buf.data (), len)) + mem_entry_accessible = false; + else + { + if (target_write_memory (addr, + get_loc (), + len)) + { + mem_entry_accessible = false; + if (record_debug) + warning (_("Process record: error writing memory at " + "addr = %s len = %d."), + paddress (gdbarch, addr), + len); + } + else + { + memcpy (get_loc (), buf.data (), len); + + /* We've changed memory --- check if a hardware + watchpoint should trap. Note that this + presently assumes the target beneath supports + continuable watchpoints. On non-continuable + watchpoints target, we'll want to check this + _before_ actually doing the memory change, and + not doing the change at all if the watchpoint + traps. */ + if (hardware_watchpoint_inserted_in_range + (current_inferior ()->aspace.get (), addr, len)) + return true; + } + } + return false; + } }; struct record_full_reg_entry @@ -110,6 +212,70 @@ struct record_full_reg_entry gdb_byte *ptr; gdb_byte buf[2 * sizeof (gdb_byte *)]; } u; + + record_full_reg_entry () : num (0), len (0) { } + + record_full_reg_entry (gdbarch *gdbarch, int regnum) + { + num = regnum; + len = register_size (gdbarch, regnum); + if (len > sizeof (u.buf)) + u.ptr = new gdb_byte[len]; + } + + record_full_reg_entry (record_full_reg_entry &&other) + { + num = other.num; + len = other.len; + memcpy (u.buf, other.u.buf, sizeof (u.buf)); + /* With len == 0, OTHER is guaranteed to not try to free the + memory when it is destructed. */ + other.len = 0; + } + + ~record_full_reg_entry () + { + if (len > sizeof (u.buf)) + delete[] u.ptr; + } + + record_full_reg_entry &operator=(record_full_reg_entry &&other) + { + num = other.num; + len = other.len; + memcpy (u.buf, other.u.buf, sizeof (u.buf)); + /* With len == 0, OTHER is guaranteed to not try to free the + memory when it is destructed. */ + other.len = 0; + return *this; + } + + DISABLE_COPY_AND_ASSIGN (record_full_reg_entry); + + gdb_byte *get_loc () + { + if (len > sizeof (u.buf)) + return u.ptr; + else + return u.buf; + } + + bool execute (regcache *regcache) + { + gdb::byte_vector buf (len); + + if (record_debug > 1) + gdb_printf (gdb_stdlog, + "Process record: record_full_reg %s to " + "inferior num = %d.\n", + host_address_to_string (this), + num); + + regcache->cooked_read (num, buf); + regcache->cooked_write (num, get_loc ()); + memcpy (get_loc (), buf.data (), len); + return false; + } }; enum record_full_type @@ -118,16 +284,88 @@ enum record_full_type record_full_mem }; -struct record_full_entry +class record_full_entry { - enum record_full_type type; - union + std::variant entry; + +public: + record_full_entry () : entry (record_full_reg_entry ()) {} + + /* Constructor for a register entry. Type is here to make it + easier to recognize it in the constructor calls, it isn't + actually important. */ + record_full_entry (record_full_type reg_type, gdbarch *gdbarch, + int regnum) + : entry(record_full_reg_entry (gdbarch, regnum)) { - /* reg */ - struct record_full_reg_entry reg; - /* mem */ - struct record_full_mem_entry mem; - } u; + gdb_assert (reg_type == record_full_reg); + } + + record_full_entry (record_full_type mem_type, CORE_ADDR addr, int len) + : entry(record_full_mem_entry (addr, len)) + { + gdb_assert (mem_type == record_full_mem); + } + + record_full_entry (record_full_entry &&other) + : entry (std::move (other.entry)) + { + } + + DISABLE_COPY_AND_ASSIGN (record_full_entry); + + record_full_reg_entry& reg () + { + gdb_assert (type () == record_full_reg); + return std::get (entry); + } + + record_full_mem_entry& mem () + { + gdb_assert (type () == record_full_mem); + return std::get (entry); + } + + record_full_type type () + { + switch (entry.index ()) + { + case 0: + return record_full_reg; + case 1: + return record_full_mem; + } + gdb_assert_not_reached ("Impossible variant index"); + } + + /* Get the pointer to the data stored by this entry. */ + gdb_byte *get_loc () + { + switch (type ()) + { + case record_full_reg: + return reg ().get_loc (); + case record_full_mem: + return mem ().get_loc (); + } + gdb_assert_not_reached ("Impossible entry type"); + } + + /* Execute this entry, swapping the appropriate values from memory or + register and the recorded ones. Returns TRUE if the execution was + stopped by a watchpoint. */ + + bool execute (regcache *regcache) + { + switch (type ()) + { + case record_full_reg: + return reg ().execute (regcache); + case record_full_mem: + return mem ().execute (regcache->arch ()); + } + return false; + } }; /* This is the main structure that comprises the execution log. @@ -384,91 +622,12 @@ static struct cmd_list_element *record_full_cmdlist; static void record_full_goto_insn (size_t target_insn, enum exec_direction_kind dir); -/* Initialization and cleanup functions for record_full_reg and - record_full_mem entries. */ - -/* Init a record_full_reg record entry. */ - -static inline record_full_entry -record_full_reg_init (struct regcache *regcache, int regnum) -{ - record_full_entry rec; - struct gdbarch *gdbarch = regcache->arch (); - - rec.type = record_full_reg; - rec.u.reg.num = regnum; - rec.u.reg.len = register_size (gdbarch, regnum); - if (rec.u.reg.len > sizeof (rec.u.reg.u.buf)) - rec.u.reg.u.ptr = (gdb_byte *) xmalloc (rec.u.reg.len); - - return rec; -} - -/* Cleanup a record_full_reg record entry. */ - -static inline void -record_full_reg_cleanup (record_full_entry rec) -{ - gdb_assert (rec.type == record_full_reg); - if (rec.u.reg.len > sizeof (rec.u.reg.u.buf)) - xfree (rec.u.reg.u.ptr); -} - -/* Init a record_full_mem record entry. */ - -static inline record_full_entry -record_full_mem_init (CORE_ADDR addr, int len) -{ - record_full_entry rec; - - rec.type = record_full_mem; - rec.u.mem.addr = addr; - rec.u.mem.len = len; - if (rec.u.mem.len > sizeof (rec.u.mem.u.buf)) - rec.u.mem.u.ptr = (gdb_byte *) xmalloc (len); - rec.u.mem.mem_entry_not_accessible = 0; - - return rec; -} - -/* Cleanup a record_full_mem record entry. */ - -static inline void -record_full_mem_cleanup (record_full_entry rec) -{ - gdb_assert (rec.type == record_full_mem); - if (rec.u.mem.len > sizeof (rec.u.mem.u.buf)) - xfree (rec.u.mem.u.ptr); -} - -/* Free one record entry, any type. */ - -static inline void -record_full_entry_cleanup (record_full_entry rec) -{ - - switch (rec.type) { - case record_full_reg: - record_full_reg_cleanup (rec); - break; - case record_full_mem: - record_full_mem_cleanup (rec); - break; - } -} - static void record_full_reset_history () { record_full_insn_count = 0; record_full_next_insn = 0; - for (auto &insn : record_full_list) - { - for (auto &entry : insn.effects) - record_full_entry_cleanup (entry); - } - record_full_list.clear (); } @@ -476,11 +635,7 @@ static void record_full_list_release_following (int index) { for (int i = record_full_list.size () - 1; i > index; i--) - { - for (auto &entry : record_full_list[i].effects) - record_full_entry_cleanup (entry); - record_full_list.pop_back (); - } + record_full_list.pop_back (); /* Set the next instruction to be past the end of the log so we start recording if the user moves forward again. */ record_full_next_insn = index; @@ -509,9 +664,6 @@ record_full_list_release_first (void) if (record_full_list.empty ()) return; - for (auto &entry : record_full_list[0].effects) - record_full_entry_cleanup (entry); - record_full_list.pop_front (); --record_full_next_insn; } @@ -521,28 +673,7 @@ record_full_list_release_first (void) static void record_full_arch_list_add (record_full_entry &rec) { - record_full_incomplete_instruction.effects.push_back (rec); -} - -/* Return the value storage location of a record entry. */ -static inline gdb_byte * -record_full_get_loc (struct record_full_entry *rec) -{ - switch (rec->type) { - case record_full_mem: - if (rec->u.mem.len > sizeof (rec->u.mem.u.buf)) - return rec->u.mem.u.ptr; - else - return rec->u.mem.u.buf; - case record_full_reg: - if (rec->u.reg.len > sizeof (rec->u.reg.u.buf)) - return rec->u.reg.u.ptr; - else - return rec->u.reg.u.buf; - default: - gdb_assert_not_reached ("unexpected record_full_entry type"); - return NULL; - } + record_full_incomplete_instruction.effects.push_back (std::move (rec)); } /* Record the value of a register NUM to record_full_arch_list. */ @@ -550,7 +681,7 @@ record_full_get_loc (struct record_full_entry *rec) int record_full_arch_list_add_reg (struct regcache *regcache, int regnum) { - record_full_entry rec; + record_full_entry rec (record_full_reg, regcache->arch (), regnum); if (record_debug > 1) gdb_printf (gdb_stdlog, @@ -558,9 +689,7 @@ record_full_arch_list_add_reg (struct regcache *regcache, int regnum) "record list.\n", regnum); - rec = record_full_reg_init (regcache, regnum); - - regcache->cooked_read (regnum, record_full_get_loc (&rec)); + regcache->cooked_read (regnum, rec.get_loc ()); record_full_arch_list_add (rec); @@ -573,7 +702,7 @@ record_full_arch_list_add_reg (struct regcache *regcache, int regnum) int record_full_arch_list_add_mem (CORE_ADDR addr, int len) { - record_full_entry rec; + record_full_entry rec (record_full_mem, addr, len); if (record_debug > 1) gdb_printf (gdb_stdlog, @@ -584,14 +713,9 @@ record_full_arch_list_add_mem (CORE_ADDR addr, int len) if (!addr) /* FIXME: Why? Some arch must permit it... */ return 0; - rec = record_full_mem_init (addr, len); - if (record_read_memory (current_inferior ()->arch (), addr, - record_full_get_loc (&rec), len)) - { - record_full_mem_cleanup (rec); - return -1; - } + rec.get_loc (), len)) + return -1; record_full_arch_list_add (rec); @@ -719,98 +843,14 @@ record_full_gdb_operation_disable_set (void) static enum target_stop_reason record_full_stop_reason = TARGET_STOPPED_BY_NO_REASON; -/* Execute one instruction from the record log. Each instruction in - the log will be represented by an arbitrary sequence of register - entries and memory entries, followed by an 'end' entry. */ - -static inline void -record_full_exec_entry (regcache *regcache, - gdbarch *gdbarch, - record_full_entry *entry) -{ - switch (entry->type) - { - case record_full_reg: /* reg */ - { - gdb::byte_vector reg (entry->u.reg.len); - - if (record_debug > 1) - gdb_printf (gdb_stdlog, - "Process record: record_full_reg %s to " - "inferior num = %d.\n", - host_address_to_string (entry), - entry->u.reg.num); - - regcache->cooked_read (entry->u.reg.num, reg.data ()); - regcache->cooked_write (entry->u.reg.num, record_full_get_loc (entry)); - memcpy (record_full_get_loc (entry), reg.data (), entry->u.reg.len); - } - break; - - case record_full_mem: /* mem */ - { - /* Nothing to do if the entry is flagged not_accessible. */ - if (!entry->u.mem.mem_entry_not_accessible) - { - gdb::byte_vector mem (entry->u.mem.len); - - if (record_debug > 1) - gdb_printf (gdb_stdlog, - "Process record: record_full_mem %s to " - "inferior addr = %s len = %d.\n", - host_address_to_string (entry), - paddress (gdbarch, entry->u.mem.addr), - entry->u.mem.len); - - if (record_read_memory (gdbarch, - entry->u.mem.addr, mem.data (), - entry->u.mem.len)) - entry->u.mem.mem_entry_not_accessible = 1; - else - { - if (target_write_memory (entry->u.mem.addr, - record_full_get_loc (entry), - entry->u.mem.len)) - { - entry->u.mem.mem_entry_not_accessible = 1; - if (record_debug) - warning (_("Process record: error writing memory at " - "addr = %s len = %d."), - paddress (gdbarch, entry->u.mem.addr), - entry->u.mem.len); - } - else - { - memcpy (record_full_get_loc (entry), mem.data (), - entry->u.mem.len); - - /* We've changed memory --- check if a hardware - watchpoint should trap. Note that this - presently assumes the target beneath supports - continuable watchpoints. On non-continuable - watchpoints target, we'll want to check this - _before_ actually doing the memory change, and - not doing the change at all if the watchpoint - traps. */ - if (hardware_watchpoint_inserted_in_range - (current_inferior ()->aspace.get (), - entry->u.mem.addr, entry->u.mem.len)) - record_full_stop_reason = TARGET_STOPPED_BY_WATCHPOINT; - } - } - } - } - break; - } -} - static inline void record_full_exec_insn (regcache *regcache, gdbarch *gdbarch, record_full_instruction &insn) { for (auto &entry : insn.effects) - record_full_exec_entry (regcache, gdbarch, &entry); + if (entry.execute (regcache)) + record_full_stop_reason = TARGET_STOPPED_BY_WATCHPOINT; } static void record_full_restore (struct bfd &cbfd); @@ -2185,21 +2225,19 @@ record_full_read_entry_from_bfd (bfd *cbfd, asection *osec, int *bfd_offset) bfdcore_read (cbfd, osec, ®num, sizeof (regnum), bfd_offset); regnum = netorder32 (regnum); - record_full_entry rec; - - rec = record_full_reg_init (cache, regnum); + record_full_entry rec (record_full_reg, cache->arch (), regnum); /* Get val. */ - bfdcore_read (cbfd, osec, record_full_get_loc (&rec), - rec.u.reg.len, bfd_offset); + bfdcore_read (cbfd, osec, rec.get_loc (), + rec.reg ().len, bfd_offset); if (record_debug) gdb_printf (gdb_stdlog, " Reading register %d (1 " "plus %lu plus %d bytes)\n", - rec.u.reg.num, + rec.reg ().num, (unsigned long) sizeof (regnum), - rec.u.reg.len); + rec.reg ().len); record_full_arch_list_add (rec); break; @@ -2216,19 +2254,17 @@ record_full_read_entry_from_bfd (bfd *cbfd, asection *osec, int *bfd_offset) bfd_offset); addr = netorder64 (addr); - record_full_entry rec; - rec = record_full_mem_init (addr, len); + record_full_entry rec (record_full_mem, addr, len); /* Get val. */ - bfdcore_read (cbfd, osec, record_full_get_loc (&rec), len, - bfd_offset); + bfdcore_read (cbfd, osec, rec.get_loc (), len, bfd_offset); if (record_debug) gdb_printf (gdb_stdlog, " Reading memory %s (1 plus " "%lu plus %lu plus %d bytes)\n", paddress (get_current_arch (), - rec.u.mem.addr), + rec.mem ().addr), (unsigned long) sizeof (addr), (unsigned long) sizeof (len), len); @@ -2380,52 +2416,56 @@ record_full_write_entry_to_bfd (record_full_entry &entry, uint32_t regnum, len; uint64_t addr; - type = entry.type; + type = entry.type (); bfdcore_write (obfd.get (), osec, &type, sizeof (type), bfd_offset); - switch (entry.type) + switch (type) { case record_full_reg: /* reg */ - if (record_debug) - gdb_printf (gdb_stdlog, - " Writing register %d (1 " - "plus %lu plus %d bytes)\n", - entry.u.reg.num, - (unsigned long) sizeof (regnum), - entry.u.reg.len); - - /* Write regnum. */ - regnum = netorder32 (entry.u.reg.num); - bfdcore_write (obfd.get (), osec, ®num, sizeof (regnum), bfd_offset); - - /* Write regval. */ - bfdcore_write (obfd.get (), osec, record_full_get_loc (&entry), - entry.u.reg.len, bfd_offset); - break; + { + auto ® = entry.reg (); + if (record_debug) + gdb_printf (gdb_stdlog, + " Writing register %d (1 " + "plus %lu plus %d bytes)\n", + reg.num, + (unsigned long) sizeof (regnum), + reg.len); + + /* Write regnum. */ + regnum = netorder32 (reg.num); + bfdcore_write (obfd.get (), osec, ®num, sizeof (regnum), bfd_offset); + + /* Write regval. */ + bfdcore_write (obfd.get (), osec, entry.get_loc (), reg.len, bfd_offset); + break; + } case record_full_mem: /* mem */ - if (record_debug) - gdb_printf (gdb_stdlog, - " Writing memory %s (1 plus " - "%lu plus %lu plus %d bytes)\n", - paddress (gdbarch, - entry.u.mem.addr), - (unsigned long) sizeof (addr), - (unsigned long) sizeof (len), - entry.u.mem.len); - - /* Write memlen. */ - len = netorder32 (entry.u.mem.len); - bfdcore_write (obfd.get (), osec, &len, sizeof (len), bfd_offset); - - /* Write memaddr. */ - addr = netorder64 (entry.u.mem.addr); - bfdcore_write (obfd.get (), osec, &addr, sizeof (addr), bfd_offset); - - /* Write memval. */ - bfdcore_write (obfd.get (), osec, record_full_get_loc (&entry), - entry.u.mem.len, bfd_offset); - break; + { + auto &mem = entry.mem (); + if (record_debug) + gdb_printf (gdb_stdlog, + " Writing memory %s (1 plus " + "%lu plus %lu plus %d bytes)\n", + paddress (gdbarch, mem.addr), + (unsigned long) sizeof (addr), + (unsigned long) sizeof (len), + mem.len); + + /* Write memlen. */ + len = netorder32 (mem.len); + bfdcore_write (obfd.get (), osec, &len, sizeof (len), bfd_offset); + + /* Write memaddr. */ + addr = netorder64 (mem.addr); + bfdcore_write (obfd.get (), osec, &addr, sizeof (addr), bfd_offset); + + /* Write memval. */ + bfdcore_write (obfd.get (), osec, entry.get_loc (), mem.len, + bfd_offset); + break; + } } } @@ -2473,13 +2513,13 @@ record_full_base_target::save_record (const char *recfilename) /* Number of effects of an instruction. */ save_size += sizeof (uint32_t) + sizeof (uint8_t) + sizeof (uint32_t); for (auto &entry : record_full_list[i].effects) - switch (entry.type) + switch (entry.type ()) { case record_full_reg: - save_size += 1 + 4 + entry.u.reg.len; + save_size += 1 + 4 + entry.reg ().len; break; case record_full_mem: - save_size += 1 + 4 + 8 + entry.u.mem.len; + save_size += 1 + 4 + 8 + entry.mem ().len; break; } } @@ -2612,18 +2652,18 @@ maintenance_print_record_instruction (const char *args, int from_tty) gdbarch *arch = current_inferior ()->arch (); - for (auto entry : to_print->effects) + for (auto &entry : to_print->effects) { - switch (entry.type) + switch (entry.type ()) { case record_full_reg: { - type *regtype = gdbarch_register_type (arch, entry.u.reg.num); + type *regtype = gdbarch_register_type (arch, entry.reg ().num); value *val = value_from_contents (regtype, - record_full_get_loc (&entry)); + entry.get_loc ()); gdb_printf ("Register %s changed: ", - gdbarch_register_name (arch, entry.u.reg.num)); + gdbarch_register_name (arch, entry.reg ().num)); struct value_print_options opts; get_user_print_options (&opts); opts.raw = true; @@ -2633,11 +2673,12 @@ maintenance_print_record_instruction (const char *args, int from_tty) } case record_full_mem: { - gdb_byte *b = record_full_get_loc (&entry); + record_full_mem_entry& mem = entry.mem (); + gdb_byte *b = entry.get_loc (); gdb_printf ("%d bytes of memory at address %s changed from:", - entry.u.mem.len, - print_core_address (arch, entry.u.mem.addr)); - for (int i = 0; i < entry.u.mem.len; i++) + mem.len, + print_core_address (arch, mem.addr)); + for (int i = 0; i < mem.len; i++) gdb_printf (" %02x", b[i]); gdb_printf ("\n"); break; -- 2.54.0