From patchwork Fri Dec 1 16:27:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81136 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 D3AFE386183D for ; Fri, 1 Dec 2023 16:28:24 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 37927385AC36 for ; Fri, 1 Dec 2023 16:27:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 37927385AC36 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 37927385AC36 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448076; cv=none; b=nikux9iWrX0LL9KlIlTE/2Bl35nLgIVOWxd+MFIPF4LU/XsORCZUHTEYqQO9Z+gOlKlvXtoGr2x8XlvL56CArNC+sd43o1nHjKjw6Shl24auZm7SRHi4M/jmZbMR96HnQR92bKQQIovd6zmW2Mwf0/bwEW7dRb5NTTbHNLgY0qY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448076; c=relaxed/simple; bh=zRLgixRRcctv/Oi4VLFAPEQKIoo56gvBSGX3WZE3vxw=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=nNPSnFHgsvWUN1/6cw+LWB3BJ5h9HN5O7PV7mNLEQPHfyTH0gak/Q3xfwzLLvK06fd/fcPwK/gGGtSx6nekjXdpSL1RoFatAfcE+tB864qBmz02UpR+86LIvgcWImVeMIjiUAp8Kap0ZWs8R9msoagjWscDO9x+PCzEPGTDrrAc= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 590C51E0BB; Fri, 1 Dec 2023 11:27:53 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 01/24] gdb: don't handle i386 k registers as pseudo registers Date: Fri, 1 Dec 2023 11:27:14 -0500 Message-ID: <20231201162751.741751-2-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org I think that i386 k registers are raw registers, and therefore shouldn't be handled in the various functions handling pseudo registers. What tipped me off is the code in i386_pseudo_register_read_into_value: else if (i386_k_regnum_p (gdbarch, regnum)) { regnum -= tdep->k0_regnum; /* Extract (always little endian). */ status = regcache->raw_read (tdep->k0_regnum + regnum, raw_buf); We take regnum (the pseudo register number we want to read), subtract k0_regnum, add k0_regnum, and pass the result to raw_read. So we would end up calling raw_read with the same regnum as the function received which is supposedly a pseudo register number. Other hints are: - The command `maint print raw-registers` shows the k registers. - Printing $k0 doesn't cause i386_pseudo_register_read_into_value to be called. - There's code in i387-tdep.c to save/restore the k registers. Remove handling of the k registers from: - i386_pseudo_register_read_into_value - i386_pseudo_register_write - i386_ax_pseudo_register_collect Change-Id: Ic97956ed59af6099fef6d36a0b61464172694562 Reviewed-by: John Baldwin --- gdb/i386-tdep.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index e00c3bd9d568..f356995520fe 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -3464,17 +3464,6 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch, memcpy (buf + size, &upper, size); } } - else if (i386_k_regnum_p (gdbarch, regnum)) - { - regnum -= tdep->k0_regnum; - - /* Extract (always little endian). */ - status = regcache->raw_read (tdep->k0_regnum + regnum, raw_buf); - if (status != REG_VALID) - result_value->mark_bytes_unavailable (0, 8); - else - memcpy (buf, raw_buf, 8); - } else if (i386_zmm_regnum_p (gdbarch, regnum)) { regnum -= tdep->zmm0_regnum; @@ -3656,12 +3645,6 @@ i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, regcache->raw_write (I387_BND0R_REGNUM (tdep) + regnum, raw_buf); } - else if (i386_k_regnum_p (gdbarch, regnum)) - { - regnum -= tdep->k0_regnum; - - regcache->raw_write (tdep->k0_regnum + regnum, buf); - } else if (i386_zmm_regnum_p (gdbarch, regnum)) { regnum -= tdep->zmm0_regnum; @@ -3758,12 +3741,6 @@ i386_ax_pseudo_register_collect (struct gdbarch *gdbarch, ax_reg_mask (ax, I387_BND0R_REGNUM (tdep) + regnum); return 0; } - else if (i386_k_regnum_p (gdbarch, regnum)) - { - regnum -= tdep->k0_regnum; - ax_reg_mask (ax, tdep->k0_regnum + regnum); - return 0; - } else if (i386_zmm_regnum_p (gdbarch, regnum)) { regnum -= tdep->zmm0_regnum; From patchwork Fri Dec 1 16:27:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81137 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 D70E33860002 for ; Fri, 1 Dec 2023 16:28:32 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id A596E3856DD4 for ; Fri, 1 Dec 2023 16:27:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A596E3856DD4 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A596E3856DD4 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448077; cv=none; b=D7dOaZc+inAsbwBZ8yKQPuYQ/6VuhMJvQ21BwI9vM7MBlxN5AloVYjeyn59XKRi2gAumgGgeyRQKnJRVTVk0Jshhf6IWvRadq1UkdK9jnV+p4Vg8Ryg+Wl0AAPwGF9Ifw4Z9tYNOJlrRbizq9YoIExefwM0uCZuBUyPXRp951Z4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448077; c=relaxed/simple; bh=4aq1iGf6v+dIt5l6l8HFkQIQ7m3ORp1ahIk7iJbHHmo=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=VnX4bJDkYep594zP+bBmAd3YUJhjk3MbLFTLXZDc452EOEV3wgfOcsFGTGpz4z0RaXmUivY2W31TEw09t7Y2OnMu5Dju8Ii6CrD56WQVUAeqqoKPE25Ibhfg8C7JBMXEBEx2FslgDeZxtn09v71gUguRiM8ZY6fr/vCRXhIAun0= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id BCF721E0C0; Fri, 1 Dec 2023 11:27:53 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 02/24] gdb: use reg_buffer_common throughout gdbsupport/common-regcache.h Date: Fri, 1 Dec 2023 11:27:15 -0500 Message-ID: <20231201162751.741751-3-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org New in v3: - remove unrelated whitespace change - formatting fixes - use regcache local var instead of self->regcache Right now, gdbsupport/common-regcache.h contains two abstractons for a regcache. An opaque type `regcache` (gdb and gdbserver both have their own regcache that is the concrete version of this) and an abstract base class `reg_buffer_common`, that is the base of regcaches on both sides. These abstractions allow code to be written for both gdb and gdbserver, for instance in the gdb/arch sub-directory. However, having two different abstractions is impractical. If some common code has a regcache, and wants to use an operation defined on reg_buffer_common, it can't. It would be better to have just one. Change all instances of `regcache *` in gdbsupport/common-regcache.h to be `reg_buffer_common *`, then fix fallouts. Implementations in gdb and gdbserver now need to down-cast (using gdb::checked_static_cast) from reg_buffer_common to their concrete regcache type. Some of them could be avoided by changing free functions (like regcache_register_size) to be virtual methods on reg_buffer_common. I tried it, it seems to work, but I did not include it in this series to avoid adding unnecessary changes. Change-Id: Ia5503adb6b5509a0f4604bd2a68b4642cc5283fd Reviewed-by: John Baldwin --- gdb/arch/arm-get-next-pcs.c | 8 ++++---- gdb/arch/arm-get-next-pcs.h | 5 +++-- gdb/arch/arm.c | 2 +- gdb/arch/arm.h | 4 ++-- gdb/arm-linux-tdep.c | 11 ++++++----- gdb/arm-tdep.c | 5 +++-- gdb/nat/aarch64-hw-point.c | 3 +-- gdb/nat/linux-btrace.c | 3 +-- gdb/regcache.c | 17 ++++++++++------- gdbserver/linux-arm-low.cc | 4 +++- gdbserver/regcache.cc | 17 +++++++++++------ gdbsupport/common-regcache.cc | 2 +- gdbsupport/common-regcache.h | 17 ++++++++++------- 13 files changed, 56 insertions(+), 42 deletions(-) diff --git a/gdb/arch/arm-get-next-pcs.c b/gdb/arch/arm-get-next-pcs.c index dcbb5a5e2e69..528753aff2f7 100644 --- a/gdb/arch/arm-get-next-pcs.c +++ b/gdb/arch/arm-get-next-pcs.c @@ -32,7 +32,7 @@ arm_get_next_pcs_ctor (struct arm_get_next_pcs *self, int byte_order, int byte_order_for_code, int has_thumb2_breakpoint, - struct regcache *regcache) + reg_buffer_common *regcache) { self->ops = ops; self->byte_order = byte_order; @@ -268,12 +268,12 @@ thumb_get_next_pcs_raw (struct arm_get_next_pcs *self) { int byte_order = self->byte_order; int byte_order_for_code = self->byte_order_for_code; + reg_buffer_common *regcache = self->regcache; CORE_ADDR pc = regcache_read_pc (self->regcache); unsigned long pc_val = ((unsigned long) pc) + 4; /* PC after prefetch */ unsigned short inst1; CORE_ADDR nextpc = pc + 2; /* Default is next instruction. */ ULONGEST status, itstate; - struct regcache *regcache = self->regcache; std::vector next_pcs; nextpc = MAKE_THUMB_ADDR (nextpc); @@ -653,8 +653,8 @@ arm_get_next_pcs_raw (struct arm_get_next_pcs *self) unsigned long this_instr = 0; unsigned long status; CORE_ADDR nextpc; - struct regcache *regcache = self->regcache; - CORE_ADDR pc = regcache_read_pc (self->regcache); + reg_buffer_common *regcache = self->regcache; + CORE_ADDR pc = regcache_read_pc (regcache); std::vector next_pcs; pc_val = (unsigned long) pc; diff --git a/gdb/arch/arm-get-next-pcs.h b/gdb/arch/arm-get-next-pcs.h index e6bb8d832286..ec347f01b4fd 100644 --- a/gdb/arch/arm-get-next-pcs.h +++ b/gdb/arch/arm-get-next-pcs.h @@ -24,6 +24,7 @@ /* Forward declaration. */ struct arm_get_next_pcs; +struct reg_buffer_common; /* get_next_pcs operations. */ struct arm_get_next_pcs_ops @@ -50,7 +51,7 @@ struct arm_get_next_pcs not. */ int has_thumb2_breakpoint; /* Registry cache. */ - struct regcache *regcache; + reg_buffer_common *regcache; }; /* Initialize arm_get_next_pcs. */ @@ -59,7 +60,7 @@ void arm_get_next_pcs_ctor (struct arm_get_next_pcs *self, int byte_order, int byte_order_for_code, int has_thumb2_breakpoint, - struct regcache *regcache); + reg_buffer_common *regcache); /* Find the next possible PCs after the current instruction executes. */ std::vector arm_get_next_pcs (struct arm_get_next_pcs *self); diff --git a/gdb/arch/arm.c b/gdb/arch/arm.c index 6fc4c0e11cd6..5c41b26483bb 100644 --- a/gdb/arch/arm.c +++ b/gdb/arch/arm.c @@ -322,7 +322,7 @@ thumb2_instruction_changes_pc (unsigned short inst1, unsigned short inst2) /* See arm.h. */ unsigned long -shifted_reg_val (struct regcache *regcache, unsigned long inst, +shifted_reg_val (reg_buffer_common *regcache, unsigned long inst, int carry, unsigned long pc_val, unsigned long status_reg) { unsigned long res, shift; diff --git a/gdb/arch/arm.h b/gdb/arch/arm.h index c64a15600de3..b6c316191877 100644 --- a/gdb/arch/arm.h +++ b/gdb/arch/arm.h @@ -188,7 +188,7 @@ enum system_register_address : CORE_ADDR ((CORE_ADDR) (((unsigned long) (addr)) + 8 + (sbits (instr, 0, 23) << 2))) /* Forward declaration. */ -struct regcache; +struct reg_buffer_common; /* Return the size in bytes of the complete Thumb instruction whose first halfword is INST1. */ @@ -213,7 +213,7 @@ int thumb_advance_itstate (unsigned int itstate); /* Decode shifted register value. */ -unsigned long shifted_reg_val (struct regcache *regcache, +unsigned long shifted_reg_val (reg_buffer_common *regcache, unsigned long inst, int carry, unsigned long pc_val, diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c index 8117d35a4d37..05538251612b 100644 --- a/gdb/arm-linux-tdep.c +++ b/gdb/arm-linux-tdep.c @@ -903,8 +903,10 @@ static CORE_ADDR arm_linux_get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self) { CORE_ADDR next_pc = 0; - CORE_ADDR pc = regcache_read_pc (self->regcache); - int is_thumb = arm_is_thumb (self->regcache); + regcache *regcache + = gdb::checked_static_cast (self->regcache); + CORE_ADDR pc = regcache_read_pc (regcache); + int is_thumb = arm_is_thumb (regcache); ULONGEST svc_number = 0; if (is_thumb) @@ -914,7 +916,7 @@ arm_linux_get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self) } else { - struct gdbarch *gdbarch = self->regcache->arch (); + struct gdbarch *gdbarch = regcache->arch (); enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch); unsigned long this_instr = @@ -937,8 +939,7 @@ arm_linux_get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self) { /* SIGRETURN or RT_SIGRETURN may affect the arm thumb mode, so update IS_THUMB. */ - next_pc = arm_linux_sigreturn_next_pc (self->regcache, svc_number, - &is_thumb); + next_pc = arm_linux_sigreturn_next_pc (regcache, svc_number, &is_thumb); } /* Addresses for calling Thumb functions have the bit 0 set. */ diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 23fecf7cf666..83fce2abd508 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -7255,7 +7255,8 @@ CORE_ADDR arm_get_next_pcs_addr_bits_remove (struct arm_get_next_pcs *self, CORE_ADDR val) { - return gdbarch_addr_bits_remove (self->regcache->arch (), val); + return gdbarch_addr_bits_remove + (gdb::checked_static_cast (self->regcache)->arch (), val); } /* Wrapper over syscall_next_pc for use in get_next_pcs. */ @@ -7271,7 +7272,7 @@ arm_get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self) int arm_get_next_pcs_is_thumb (struct arm_get_next_pcs *self) { - return arm_is_thumb (self->regcache); + return arm_is_thumb (gdb::checked_static_cast (self->regcache)); } /* single_step() is called just before we want to resume the inferior, diff --git a/gdb/nat/aarch64-hw-point.c b/gdb/nat/aarch64-hw-point.c index 6747e61e0265..8e9a532cd2a4 100644 --- a/gdb/nat/aarch64-hw-point.c +++ b/gdb/nat/aarch64-hw-point.c @@ -137,8 +137,7 @@ aarch64_point_is_aligned (ptid_t ptid, int is_watchpoint, CORE_ADDR addr, alignment = AARCH64_HWP_ALIGNMENT; else { - struct regcache *regcache - = get_thread_regcache_for_ptid (ptid); + reg_buffer_common *regcache = get_thread_regcache_for_ptid (ptid); /* Set alignment to 2 only if the current process is 32-bit, since thumb instruction can be 2-byte aligned. Otherwise, set diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c index 89bf28b5133f..c4f4cbd77115 100644 --- a/gdb/nat/linux-btrace.c +++ b/gdb/nat/linux-btrace.c @@ -284,13 +284,12 @@ perf_event_read_bts (btrace_target_info *tinfo, const uint8_t *begin, struct perf_event_sample sample; size_t read = 0; struct btrace_block block = { 0, 0 }; - struct regcache *regcache; gdb_assert (begin <= start); gdb_assert (start <= end); /* The first block ends at the current pc. */ - regcache = get_thread_regcache_for_ptid (tinfo->ptid); + reg_buffer_common *regcache = get_thread_regcache_for_ptid (tinfo->ptid); block.end = regcache_read_pc (regcache); /* The buffer may contain a partial record as its last entry (i.e. when the diff --git a/gdb/regcache.c b/gdb/regcache.c index e46a0b58f505..6c986b740dfd 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -180,9 +180,10 @@ register_size (struct gdbarch *gdbarch, int regnum) /* See gdbsupport/common-regcache.h. */ int -regcache_register_size (const struct regcache *regcache, int n) +regcache_register_size (const reg_buffer_common *regcache, int n) { - return register_size (regcache->arch (), n); + return register_size + (gdb::checked_static_cast (regcache)->arch (), n); } reg_buffer::reg_buffer (gdbarch *gdbarch, bool has_pseudo) @@ -417,7 +418,7 @@ get_thread_regcache (thread_info *thread) /* See gdbsupport/common-regcache.h. */ -struct regcache * +reg_buffer_common * get_thread_regcache_for_ptid (ptid_t ptid) { /* This function doesn't take a process_stratum_target parameter @@ -630,11 +631,12 @@ readable_regcache::raw_read (int regnum, T *val) } enum register_status -regcache_raw_read_unsigned (struct regcache *regcache, int regnum, +regcache_raw_read_unsigned (reg_buffer_common *regcache, int regnum, ULONGEST *val) { gdb_assert (regcache != NULL); - return regcache->raw_read (regnum, val); + return gdb::checked_static_cast (regcache)->raw_read + (regnum, val); } void @@ -1314,8 +1316,9 @@ reg_buffer::raw_compare (int regnum, const void *buf, int offset) const /* Special handling for register PC. */ CORE_ADDR -regcache_read_pc (struct regcache *regcache) +regcache_read_pc (reg_buffer_common *reg_buf) { + regcache *regcache = gdb::checked_static_cast (reg_buf); struct gdbarch *gdbarch = regcache->arch (); CORE_ADDR pc_val; @@ -1342,7 +1345,7 @@ regcache_read_pc (struct regcache *regcache) /* See gdbsupport/common-regcache.h. */ CORE_ADDR -regcache_read_pc_protected (regcache *regcache) +regcache_read_pc_protected (reg_buffer_common *regcache) { CORE_ADDR pc; try diff --git a/gdbserver/linux-arm-low.cc b/gdbserver/linux-arm-low.cc index 5975b44af0ae..0a6f3622695a 100644 --- a/gdbserver/linux-arm-low.cc +++ b/gdbserver/linux-arm-low.cc @@ -24,6 +24,7 @@ #include "linux-aarch32-low.h" #include "linux-aarch32-tdesc.h" #include "linux-arm-tdesc.h" +#include "gdbsupport/gdb-checked-static-cast.h" #include /* Don't include elf.h if linux/elf.h got included by gdb_proc_service.h. @@ -913,7 +914,8 @@ get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self) CORE_ADDR pc = regcache_read_pc (self->regcache); int is_thumb = arm_is_thumb_mode (); ULONGEST svc_number = 0; - struct regcache *regcache = self->regcache; + regcache *regcache + = gdb::checked_static_cast (self->regcache); if (is_thumb) { diff --git a/gdbserver/regcache.cc b/gdbserver/regcache.cc index 2e75a948a198..823ea1f015d3 100644 --- a/gdbserver/regcache.cc +++ b/gdbserver/regcache.cc @@ -21,6 +21,8 @@ #include "gdbthread.h" #include "tdesc.h" #include "gdbsupport/rsp-low.h" +#include "gdbsupport/gdb-checked-static-cast.h" + #ifndef IN_PROCESS_AGENT struct regcache * @@ -64,7 +66,7 @@ get_thread_regcache (struct thread_info *thread, int fetch) /* See gdbsupport/common-regcache.h. */ -struct regcache * +reg_buffer_common * get_thread_regcache_for_ptid (ptid_t ptid) { return get_thread_regcache (find_thread_ptid (ptid), 1); @@ -307,9 +309,10 @@ register_size (const struct target_desc *tdesc, int n) /* See gdbsupport/common-regcache.h. */ int -regcache_register_size (const struct regcache *regcache, int n) +regcache_register_size (const reg_buffer_common *regcache, int n) { - return register_size (regcache->tdesc, n); + return register_size + (gdb::checked_static_cast (regcache)->tdesc, n); } static unsigned char * @@ -437,10 +440,11 @@ regcache::raw_collect (int n, void *buf) const } enum register_status -regcache_raw_read_unsigned (struct regcache *regcache, int regnum, +regcache_raw_read_unsigned (reg_buffer_common *reg_buf, int regnum, ULONGEST *val) { int size; + regcache *regcache = gdb::checked_static_cast (reg_buf); gdb_assert (regcache != NULL); @@ -486,9 +490,10 @@ collect_register_by_name (struct regcache *regcache, /* Special handling for register PC. */ CORE_ADDR -regcache_read_pc (struct regcache *regcache) +regcache_read_pc (reg_buffer_common *regcache) { - return the_target->read_pc (regcache); + return the_target->read_pc + (gdb::checked_static_cast (regcache)); } void diff --git a/gdbsupport/common-regcache.cc b/gdbsupport/common-regcache.cc index 3515bedb3830..b6f02bac16e2 100644 --- a/gdbsupport/common-regcache.cc +++ b/gdbsupport/common-regcache.cc @@ -23,7 +23,7 @@ /* Return the register's value or throw if it's not available. */ ULONGEST -regcache_raw_get_unsigned (struct regcache *regcache, int regnum) +regcache_raw_get_unsigned (reg_buffer_common *regcache, int regnum) { ULONGEST value; enum register_status status; diff --git a/gdbsupport/common-regcache.h b/gdbsupport/common-regcache.h index e462f532407b..6d98ca8c92ed 100644 --- a/gdbsupport/common-regcache.h +++ b/gdbsupport/common-regcache.h @@ -20,6 +20,8 @@ #ifndef COMMON_COMMON_REGCACHE_H #define COMMON_COMMON_REGCACHE_H +struct reg_buffer_common; + /* This header is a stopgap until we have an independent regcache. */ enum register_status : signed char @@ -44,28 +46,29 @@ enum register_status : signed char thread specified by PTID. This function must be provided by the client. */ -extern struct regcache *get_thread_regcache_for_ptid (ptid_t ptid); +extern reg_buffer_common *get_thread_regcache_for_ptid (ptid_t ptid); /* Return the size of register numbered N in REGCACHE. This function must be provided by the client. */ -extern int regcache_register_size (const struct regcache *regcache, int n); +extern int regcache_register_size (const reg_buffer_common *regcache, int n); /* Read the PC register. This function must be provided by the client. */ -extern CORE_ADDR regcache_read_pc (struct regcache *regcache); +extern CORE_ADDR regcache_read_pc (reg_buffer_common *regcache); /* Read the PC register. If PC cannot be read, return 0. This is a wrapper around 'regcache_read_pc'. */ -extern CORE_ADDR regcache_read_pc_protected (regcache *regcache); +extern CORE_ADDR regcache_read_pc_protected (reg_buffer_common *regcache); /* Read a raw register into a unsigned integer. */ -extern enum register_status regcache_raw_read_unsigned - (struct regcache *regcache, int regnum, ULONGEST *val); +extern enum register_status +regcache_raw_read_unsigned (reg_buffer_common *regcache, int regnum, + ULONGEST *val); -ULONGEST regcache_raw_get_unsigned (struct regcache *regcache, int regnum); +ULONGEST regcache_raw_get_unsigned (reg_buffer_common *regcache, int regnum); struct reg_buffer_common { From patchwork Fri Dec 1 16:27:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81134 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 600963860C0B for ; Fri, 1 Dec 2023 16:28:09 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id B8EB5385AE43 for ; Fri, 1 Dec 2023 16:27:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B8EB5385AE43 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org B8EB5385AE43 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448076; cv=none; b=K3uugBRaTSdSr8a//LyEBHh81yxosc21oNQ7a2CqFMGoFLM0EQTEhKtdBI8Iz+gH5qocG+pVbWT+cSfDBva6Z2xqry4WbyyplLA0F6P2htAfBvr3i+nbeLfWM19WeJ6yo2s58cmdvpnC92+TEcNJQyhv766cJZpJ3KxSOUfu7xI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448076; c=relaxed/simple; bh=spuC8vhQgZpJBPyror/PrWsTQXfb4UhG+AgpuUkz7+g=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=NuqHLfO0jXsTah5rfMFt2+RcAKPxIlY6qN6oUUusJcoXzrlVycqsaGpKxfQMa4smcPt5AlZJny5o7Gf/W48HMn7/rckObgKP2m+ZwyOz7ynpB7kS7BgcrbcgAhDao6LrYQfeImPPQOD29IWxv8dKJavnJ80bLcMownjDyEpPKso= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 20D821E11B; Fri, 1 Dec 2023 11:27:54 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 03/24] gdb: make store_integer take an array_view Date: Fri, 1 Dec 2023 11:27:16 -0500 Message-ID: <20231201162751.741751-4-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org New in v3: - Fix type of store_unsigned_integer parameter, LONGEST -> ULONGEST Change store_integer, store_signed_integer and store_unsigned_integer to accept an array_view. Add some backwards compatibility overloads to avoid changing all callers at once. Change-Id: Ibb1381228ab1cb65fc7e2e4b92cf9ab1047cdc03 Reviewed-By: John Baldwin --- gdb/defs.h | 39 +++++++++++++++++++++++++++++++-------- gdb/findvar.c | 16 +++++++--------- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/gdb/defs.h b/gdb/defs.h index bcce4f4c3e43..e20143b8146a 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -495,21 +495,44 @@ extern CORE_ADDR extract_typed_address (const gdb_byte *buf, target-format integer at ADDR which is LEN bytes long. */ template> -extern void store_integer (gdb_byte *addr, int len, enum bfd_endian byte_order, - T val); +extern void store_integer (gdb::array_view dst, + bfd_endian byte_order, T val); + +template +static inline void +store_integer (gdb_byte *addr, int len, bfd_endian byte_order, T val) +{ + return store_integer (gdb::make_array_view (addr, len), byte_order, val); +} + +static inline void +store_signed_integer (gdb::array_view dst, bfd_endian byte_order, + LONGEST val) +{ + return store_integer (dst, byte_order, val); +} + +static inline void +store_signed_integer (gdb_byte *addr, int len, bfd_endian byte_order, + LONGEST val) +{ + return store_signed_integer (gdb::make_array_view (addr, len), byte_order, + val); +} static inline void -store_signed_integer (gdb_byte *addr, int len, - enum bfd_endian byte_order, LONGEST val) +store_unsigned_integer (gdb::array_view dst, bfd_endian byte_order, + ULONGEST val) { - return store_integer (addr, len, byte_order, val); + return store_integer (dst, byte_order, val); } static inline void -store_unsigned_integer (gdb_byte *addr, int len, - enum bfd_endian byte_order, ULONGEST val) +store_unsigned_integer (gdb_byte *addr, int len, bfd_endian byte_order, + ULONGEST val) { - return store_integer (addr, len, byte_order, val); + return store_unsigned_integer (gdb::make_array_view (addr, len), byte_order, + val); } extern void store_typed_address (gdb_byte *buf, struct type *type, diff --git a/gdb/findvar.c b/gdb/findvar.c index 952ec20c0b73..c7a681f8a890 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -159,12 +159,12 @@ extract_typed_address (const gdb_byte *buf, struct type *type) target-format integer at ADDR which is LEN bytes long. */ template void -store_integer (gdb_byte *addr, int len, enum bfd_endian byte_order, +store_integer (gdb::array_view dst, enum bfd_endian byte_order, T val) { gdb_byte *p; - gdb_byte *startaddr = addr; - gdb_byte *endaddr = startaddr + len; + gdb_byte *startaddr = dst.data (); + gdb_byte *endaddr = startaddr + dst.size (); /* Start at the least significant end of the integer, and work towards the most significant. */ @@ -187,13 +187,11 @@ store_integer (gdb_byte *addr, int len, enum bfd_endian byte_order, } /* Explicit instantiations. */ -template void store_integer (gdb_byte *addr, int len, - enum bfd_endian byte_order, - LONGEST val); +template void store_integer (gdb::array_view dst, + bfd_endian byte_order, LONGEST val); -template void store_integer (gdb_byte *addr, int len, - enum bfd_endian byte_order, - ULONGEST val); +template void store_integer (gdb::array_view dst, + bfd_endian byte_order, ULONGEST val); /* Store the address ADDR as a pointer of type TYPE at BUF, in target form. */ From patchwork Fri Dec 1 16:27:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81135 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 3663E385F025 for ; Fri, 1 Dec 2023 16:28:23 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 0AEB1385B534 for ; Fri, 1 Dec 2023 16:27:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0AEB1385B534 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 0AEB1385B534 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448076; cv=none; b=Hs9k8iBB+OXBJ0xHr5JDLeFdNUIFTTLXAVWbJQARxlsiM5ke8OIkS3jWYe+ncIXcbJmxxOPAnDzqKHoWJ4b3eOb2Zd+KK45ciP/UNRS8+lSzmgUM+6/+L5o5ckVq8PtZ1G3Dhn0W16prIFBeCcuSloe5C/STgF7iJ26P/qu8fkk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448076; c=relaxed/simple; bh=IJw8kRhdL2p+p3yR5meXNLNrmI5LZMPWx/EMtKyJK48=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=A4lmMCL38Scq6LcbfUHPyt/N/4Pdw0Dz/t2WydnlKAKTJqfSrKIWWKsD3Qp8VNs5KOEjaUImGezBSI/eQWaS9/lPShXnVWcoPg5f9La4UqZ90sueMjXYXuUXPzPNaDFJa5eUdhf4nT8HpyGLleATWqPVyLXfnYkkbsj/ZW666ak= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 55C0D1E11E; Fri, 1 Dec 2023 11:27:54 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 04/24] gdb: simplify conditions in regcache::{read, write, raw_collect, raw_supply}_part Date: Fri, 1 Dec 2023 11:27:17 -0500 Message-ID: <20231201162751.741751-5-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Make a few simplifications in these functions. 1. When checking if we need to do nothing, if the length is 0, we don't need to do anything, regardless of the value of offset. Remove the offset check. 2. When check if transferring the whole register, if the length is equal to the register size, then we transfer the whole register, no need to check the offset. Remove the offset check. 3. In the gdb_asserts, it is unnecessary to check for: offset <= reg_size given that right after we check for: len >= 0 && offset + len <= reg_size If `offset + len` is <= reg_size and len is >= 0, then necessarily offset is <= reg_size. Remove the `offset <= reg_size` check. Change-Id: I30a73acdc7bf432c45a07f5f177224d1cdc298e8 Reviewed-By: John Baldwin --- gdb/regcache.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/gdb/regcache.c b/gdb/regcache.c index 6c986b740dfd..7eb54d27b135 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -873,16 +873,16 @@ readable_regcache::read_part (int regnum, int offset, int len, int reg_size = register_size (arch (), regnum); gdb_assert (out != NULL); - gdb_assert (offset >= 0 && offset <= reg_size); + gdb_assert (offset >= 0); gdb_assert (len >= 0 && offset + len <= reg_size); - if (offset == 0 && len == 0) + if (len == 0) { /* Nothing to do. */ return REG_VALID; } - if (offset == 0 && len == reg_size) + if (len == reg_size) { /* Read the full register. */ return (is_raw) ? raw_read (regnum, out) : cooked_read (regnum, out); @@ -910,16 +910,16 @@ reg_buffer::raw_collect_part (int regnum, int offset, int len, int reg_size = register_size (arch (), regnum); gdb_assert (out != nullptr); - gdb_assert (offset >= 0 && offset <= reg_size); + gdb_assert (offset >= 0); gdb_assert (len >= 0 && offset + len <= reg_size); - if (offset == 0 && len == 0) + if (len == 0) { /* Nothing to do. */ return; } - if (offset == 0 && len == reg_size) + if (len == reg_size) { /* Collect the full register. */ return raw_collect (regnum, out); @@ -940,16 +940,16 @@ regcache::write_part (int regnum, int offset, int len, int reg_size = register_size (arch (), regnum); gdb_assert (in != NULL); - gdb_assert (offset >= 0 && offset <= reg_size); + gdb_assert (offset >= 0); gdb_assert (len >= 0 && offset + len <= reg_size); - if (offset == 0 && len == 0) + if (len == 0) { /* Nothing to do. */ return REG_VALID; } - if (offset == 0 && len == reg_size) + if (len == reg_size) { /* Write the full register. */ (is_raw) ? raw_write (regnum, in) : cooked_write (regnum, in); @@ -979,16 +979,16 @@ reg_buffer::raw_supply_part (int regnum, int offset, int len, int reg_size = register_size (arch (), regnum); gdb_assert (in != nullptr); - gdb_assert (offset >= 0 && offset <= reg_size); + gdb_assert (offset >= 0); gdb_assert (len >= 0 && offset + len <= reg_size); - if (offset == 0 && len == 0) + if (len == 0) { /* Nothing to do. */ return; } - if (offset == 0 && len == reg_size) + if (len == reg_size) { /* Supply the full register. */ return raw_supply (regnum, in); From patchwork Fri Dec 1 16:27:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81140 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 87F2F385E45D for ; Fri, 1 Dec 2023 16:28:56 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 99E92385B53E for ; Fri, 1 Dec 2023 16:27:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 99E92385B53E Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 99E92385B53E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448082; cv=none; b=fzj3NKjs1JQ21m/AqpwBMZ+nyRE0CoFhvkqblsZkqXlYDkm11n065+bVgY6MQNhNwnc5cYFAxx8izBkboam8o/787cPdDGSAhyCaC7y/YxykK+FAFIzWcSSEsmmtu0oRa1tD+C8s0UcNR6sAeG60gnSD6eidykBDIQEx/A04u8I= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448082; c=relaxed/simple; bh=uApraNbineIh2OAenFjbkWmZTwYY/nVYudg8YN/y5iw=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=WaIr5BFFlD1dKXM/YuoNOlOhTIcl035R1zGsn4iYjxtxMrklmRm3BSpZKBJdrebQGIggsBAvws+U4j+BsFgfok6ovlH29s4/eQWz5+yXY/iKu1dMcjOiQ8AkqZsKnH+MgzkdrMsoBPRrbSb5qA0tbr/GQhKg8TNOt8kvmo1rPj8= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id C5F111E1A7; Fri, 1 Dec 2023 11:27:54 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 05/24] gdb: change regcache interface to use array_view Date: Fri, 1 Dec 2023 11:27:18 -0500 Message-ID: <20231201162751.741751-6-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org New in v3: - fix regression in reg_buffer::raw_compare: the old code allows passing an offset equal to the register size, effectively comparing 0 bytes, the code in v2 does not. Add a selftest checking that this behavior works. - rename len to size in some functions New in v2: - remove dummy float parameters Change most of regcache (and base classes) to use array_view when possible, instead of raw pointers. By propagating the use of array_view further, it enables having some runtime checks to make sure the what we read from or write to regcaches has the expected length (such as the one in the `copy(array_view, array_view)` function. It also integrates well when connecting with other APIs already using gdb::array_view. Add some overloads of the methods using raw pointers to avoid having to change all call sites at once (which is both a lot of work and risky). I tried to do this change in small increments, but since many of these functions use each other, it ended up simpler to do it in one shot than having a lot of intermediary / transient changes. This change extends into gdbserver as well, because there is some part of the regcache interface that is shared. Changing the reg_buffer_common interface to use array_view caused some build failures in nat/aarch64-scalable-linux-ptrace.c. That file currently "takes advantage" of the fact that reg_buffer_common::{raw_supply,raw_collect} operates on `void *`, which IMO is dangerous. It uses raw_supply/raw_collect directly on uint64_t's, which I guess is fine because it is expected that native code will have the same endianness as the debugged process. To accomodate that, add some overloads of raw_collect and raw_supply that work on uint64_t. This file also uses raw_collect and raw_supply on `char` pointers. Change it to use `gdb_byte` pointers instead. Add overloads of raw_collect and raw_supply that work on `gdb_byte *` and make an array_view on the fly using the register's size. Those call sites could be converted to use array_view with not much work, in which case these overloads could be removed, but I didn't want to do it in this patch, to avoid starting to dig in arch-specific code. During development, I inadvertently changed reg_buffer::raw_compare's behavior to not accept an offset equal to the register size. This behavior (effectively comparing 0 bytes, returning true) change was caught by the AArch64 SME core tests. Add a selftest to make sure that this raw_compare behavior is preserved in the future. Change-Id: I9005f04114543ddff738949e12d85a31855304c2 Reviewed-By: John Baldwin --- gdb/frame.c | 4 +- gdb/nat/aarch64-scalable-linux-ptrace.c | 20 +- gdb/regcache.c | 493 ++++++++++++++---------- gdb/regcache.h | 110 ++++-- gdbserver/regcache.cc | 49 ++- gdbserver/regcache.h | 4 +- gdbsupport/common-regcache.h | 38 +- gdbsupport/rsp-low.cc | 8 + gdbsupport/rsp-low.h | 2 + 9 files changed, 457 insertions(+), 271 deletions(-) diff --git a/gdb/frame.c b/gdb/frame.c index 2a8a33b072d9..529453efa158 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1108,9 +1108,9 @@ get_frame_func (frame_info_ptr this_frame) std::unique_ptr frame_save_as_regcache (frame_info_ptr this_frame) { - auto cooked_read = [this_frame] (int regnum, gdb_byte *buf) + auto cooked_read = [this_frame] (int regnum, gdb::array_view buf) { - if (!deprecated_frame_register_read (this_frame, regnum, buf)) + if (!deprecated_frame_register_read (this_frame, regnum, buf.data ())) return REG_UNAVAILABLE; else return REG_VALID; diff --git a/gdb/nat/aarch64-scalable-linux-ptrace.c b/gdb/nat/aarch64-scalable-linux-ptrace.c index dc0e45fa91ee..b8fb317edaca 100644 --- a/gdb/nat/aarch64-scalable-linux-ptrace.c +++ b/gdb/nat/aarch64-scalable-linux-ptrace.c @@ -613,7 +613,7 @@ aarch64_sve_regs_copy_to_reg_buf (int tid, struct reg_buffer_common *reg_buf) { gdb::byte_vector sve_state = aarch64_fetch_sve_regset (tid); - char *base = (char *) sve_state.data (); + gdb_byte *base = sve_state.data (); struct user_sve_header *header = (struct user_sve_header *) sve_state.data (); @@ -684,8 +684,10 @@ aarch64_sve_regs_copy_to_reg_buf (int tid, struct reg_buffer_common *reg_buf) reg_buf->raw_supply (AARCH64_SVE_Z0_REGNUM + i, reg); } - reg_buf->raw_supply (AARCH64_FPSR_REGNUM, &fpsimd->fpsr); - reg_buf->raw_supply (AARCH64_FPCR_REGNUM, &fpsimd->fpcr); + reg_buf->raw_supply (AARCH64_FPSR_REGNUM, + (const gdb_byte *) &fpsimd->fpsr); + reg_buf->raw_supply (AARCH64_FPCR_REGNUM, + (const gdb_byte *) &fpsimd->fpcr); /* Clear the SVE only registers. */ memset (reg, 0, SVE_PT_SVE_ZREG_SIZE (vq)); @@ -720,7 +722,7 @@ aarch64_sve_regs_copy_from_reg_buf (int tid, gdb::byte_vector new_state (SVE_PT_SIZE (32, SVE_PT_REGS_SVE), 0); memcpy (new_state.data (), sve_state.data (), sve_state.size ()); header = (struct user_sve_header *) new_state.data (); - char *base = (char *) new_state.data (); + gdb_byte *base = new_state.data (); /* Sanity check the data in the header. */ if (!sve_vl_valid (header->vl) @@ -805,9 +807,11 @@ aarch64_sve_regs_copy_from_reg_buf (int tid, } if (REG_VALID == reg_buf->get_register_status (AARCH64_FPSR_REGNUM)) - reg_buf->raw_collect (AARCH64_FPSR_REGNUM, &fpsimd->fpsr); + reg_buf->raw_collect (AARCH64_FPSR_REGNUM, + (gdb_byte *) &fpsimd->fpsr); if (REG_VALID == reg_buf->get_register_status (AARCH64_FPCR_REGNUM)) - reg_buf->raw_collect (AARCH64_FPCR_REGNUM, &fpsimd->fpcr); + reg_buf->raw_collect (AARCH64_FPCR_REGNUM, + (gdb_byte *) &fpsimd->fpcr); /* At this point we have collected all the data from the register cache and we are ready to update the FPSIMD register content @@ -894,7 +898,7 @@ aarch64_za_regs_copy_to_reg_buf (int tid, struct reg_buffer_common *reg_buf, /* Sanity check. */ gdb_assert (!za_state.empty ()); - char *base = (char *) za_state.data (); + gdb_byte *base = za_state.data (); struct user_za_header *header = (struct user_za_header *) base; /* If we have ZA state, read it. Otherwise, make the contents of ZA @@ -1027,7 +1031,7 @@ aarch64_za_regs_copy_from_reg_buf (int tid, /* Fetch the current ZA state from the thread. */ gdb::byte_vector za_state = aarch64_fetch_za_regset (tid); - char *base = (char *) za_state.data (); + gdb_byte *base = za_state.data (); struct user_za_header *za_header = (struct user_za_header *) base; uint64_t svq = sve_vq_from_vl (za_header->vl); diff --git a/gdb/regcache.c b/gdb/regcache.c index 7eb54d27b135..19ba353a335c 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -220,10 +220,9 @@ regcache::regcache (inferior *inf_for_target_calls, gdbarch *gdbarch) readonly_detached_regcache::readonly_detached_regcache (regcache &src) : readonly_detached_regcache (src.arch (), - [&src] (int regnum, gdb_byte *buf) - { - return src.cooked_read (regnum, buf); - }) + [&src] (int regnum, + gdb::array_view buf) + { return src.cooked_read (regnum, buf); }) { } @@ -233,19 +232,38 @@ reg_buffer::arch () const return m_descr->gdbarch; } -/* Return a pointer to register REGNUM's buffer cache. */ +/* Helper for reg_buffer::register_buffer. */ -gdb_byte * +template +gdb::array_view reg_buffer::register_buffer (int regnum) const { - return m_registers.get () + m_descr->register_offset[regnum]; + assert_regnum (regnum); + ElemType *start = &m_registers[m_descr->register_offset[regnum]]; + int size = m_descr->sizeof_register[regnum]; + return gdb::array_view (start, size); +} + +/* See regcache.h. */ + +gdb::array_view +reg_buffer::register_buffer (int regnum) const +{ + return register_buffer (regnum); +} + +/* See regcache.h. */ + +gdb::array_view +reg_buffer::register_buffer (int regnum) +{ + return register_buffer (regnum); } void reg_buffer::save (register_read_ftype cooked_read) { struct gdbarch *gdbarch = m_descr->gdbarch; - int regnum; /* It should have pseudo registers. */ gdb_assert (m_has_pseudo); @@ -256,17 +274,17 @@ reg_buffer::save (register_read_ftype cooked_read) save_reggroup) and mark them as valid. The full [0 .. gdbarch_num_regs + gdbarch_num_pseudo_regs) range is checked since some architectures need to save/restore `cooked' registers that live in memory. */ - for (regnum = 0; regnum < m_descr->nr_cooked_registers; regnum++) + for (int regnum = 0; regnum < m_descr->nr_cooked_registers; regnum++) { if (gdbarch_register_reggroup_p (gdbarch, regnum, save_reggroup)) { - gdb_byte *dst_buf = register_buffer (regnum); - enum register_status status = cooked_read (regnum, dst_buf); + gdb::array_view dst_buf = register_buffer (regnum); + register_status status = cooked_read (regnum, dst_buf); gdb_assert (status != REG_UNKNOWN); if (status != REG_VALID) - memset (dst_buf, 0, register_size (gdbarch, regnum)); + memset (dst_buf.data (), 0, dst_buf.size ()); m_register_status[regnum] = status; } @@ -592,21 +610,30 @@ regcache::raw_update (int regnum) } } -enum register_status -readable_regcache::raw_read (int regnum, gdb_byte *buf) +register_status +readable_regcache::raw_read (int regnum, gdb::array_view dst) { - gdb_assert (buf != NULL); + assert_regnum (regnum); + gdb_assert (dst.size () == m_descr->sizeof_register[regnum]); + raw_update (regnum); if (m_register_status[regnum] != REG_VALID) - memset (buf, 0, m_descr->sizeof_register[regnum]); + memset (dst.data (), 0, dst.size ()); else - memcpy (buf, register_buffer (regnum), - m_descr->sizeof_register[regnum]); + copy (register_buffer (regnum), dst); return m_register_status[regnum]; } +register_status +readable_regcache::raw_read (int regnum, gdb_byte *dst) +{ + assert_regnum (regnum); + int size = m_descr->sizeof_register[regnum]; + return raw_read (regnum, gdb::make_array_view (dst, size)); +} + enum register_status regcache_raw_read_signed (struct regcache *regcache, int regnum, LONGEST *val) { @@ -619,14 +646,16 @@ enum register_status readable_regcache::raw_read (int regnum, T *val) { assert_regnum (regnum); - size_t len = m_descr->sizeof_register[regnum]; - gdb_byte *buf = (gdb_byte *) alloca (len); - register_status status = raw_read (regnum, buf); + size_t size = m_descr->sizeof_register[regnum]; + gdb_byte *buf = (gdb_byte *) alloca (size); + auto view = gdb::make_array_view (buf, size); + register_status status = raw_read (regnum, view); + if (status == REG_VALID) - *val = extract_integer ({buf, len}, - gdbarch_byte_order (m_descr->gdbarch)); + *val = extract_integer (view, gdbarch_byte_order (m_descr->gdbarch)); else *val = 0; + return status; } @@ -650,13 +679,13 @@ template void regcache::raw_write (int regnum, T val) { - gdb_byte *buf; - assert_regnum (regnum); - buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]); - store_integer (buf, m_descr->sizeof_register[regnum], - gdbarch_byte_order (m_descr->gdbarch), val); - raw_write (regnum, buf); + + int size = m_descr->sizeof_register[regnum]; + gdb_byte *buf = (gdb_byte *) alloca (size); + auto view = gdb::make_array_view (buf, size); + store_integer (view, gdbarch_byte_order (m_descr->gdbarch), val); + raw_write (regnum, view); } void @@ -680,47 +709,60 @@ regcache_raw_get_signed (struct regcache *regcache, int regnum) return value; } -enum register_status -readable_regcache::cooked_read (int regnum, gdb_byte *buf) +/* See regcache.h. */ + +register_status +readable_regcache::cooked_read (int regnum, gdb::array_view dst) { gdb_assert (regnum >= 0); gdb_assert (regnum < m_descr->nr_cooked_registers); + if (regnum < num_raw_registers ()) - return raw_read (regnum, buf); - else if (m_has_pseudo - && m_register_status[regnum] != REG_UNKNOWN) + return raw_read (regnum, dst); + + gdb_assert (dst.size () == m_descr->sizeof_register[regnum]); + + if (m_has_pseudo && m_register_status[regnum] != REG_UNKNOWN) { if (m_register_status[regnum] == REG_VALID) - memcpy (buf, register_buffer (regnum), - m_descr->sizeof_register[regnum]); + copy (register_buffer (regnum), dst); else - memset (buf, 0, m_descr->sizeof_register[regnum]); + memset (dst.data (), 0, dst.size ()); return m_register_status[regnum]; } else if (gdbarch_pseudo_register_read_value_p (m_descr->gdbarch)) { - struct value *computed; - enum register_status result = REG_VALID; - + register_status result = REG_VALID; scoped_value_mark mark; + value *computed + = gdbarch_pseudo_register_read_value (m_descr->gdbarch, this, regnum); - computed = gdbarch_pseudo_register_read_value (m_descr->gdbarch, - this, regnum); if (computed->entirely_available ()) - memcpy (buf, computed->contents_raw ().data (), - m_descr->sizeof_register[regnum]); + copy (computed->contents_raw (), dst); else { - memset (buf, 0, m_descr->sizeof_register[regnum]); + memset (dst.data (), 0, dst.size ()); result = REG_UNAVAILABLE; } return result; } else - return gdbarch_pseudo_register_read (m_descr->gdbarch, this, - regnum, buf); + return gdbarch_pseudo_register_read (m_descr->gdbarch, this, regnum, + dst.data ()); +} + +/* See regcache.h. */ + +register_status +readable_regcache::cooked_read (int regnum, gdb_byte *dst) +{ + gdb_assert (regnum >= 0); + gdb_assert (regnum < m_descr->nr_cooked_registers); + + int size = m_descr->sizeof_register[regnum]; + return cooked_read (regnum, gdb::make_array_view (dst, size)); } struct value * @@ -742,8 +784,7 @@ readable_regcache::cooked_read_value (int regnum) /* It is more efficient in general to do this delegation in this direction than in the other one, even though the value-based API is preferred. */ - if (cooked_read (regnum, - result->contents_raw ().data ()) == REG_UNAVAILABLE) + if (cooked_read (regnum, result->contents_raw ()) == REG_UNAVAILABLE) result->mark_bytes_unavailable (0, result->type ()->length ()); @@ -767,12 +808,12 @@ enum register_status readable_regcache::cooked_read (int regnum, T *val) { gdb_assert (regnum >= 0 && regnum < m_descr->nr_cooked_registers); - size_t len = m_descr->sizeof_register[regnum]; - gdb_byte *buf = (gdb_byte *) alloca (len); - register_status status = cooked_read (regnum, buf); + size_t size = m_descr->sizeof_register[regnum]; + gdb_byte *buf = (gdb_byte *) alloca (size); + auto view = gdb::make_array_view (buf, size); + register_status status = cooked_read (regnum, view); if (status == REG_VALID) - *val = extract_integer ({buf, len}, - gdbarch_byte_order (m_descr->gdbarch)); + *val = extract_integer (view, gdbarch_byte_order (m_descr->gdbarch)); else *val = 0; return status; @@ -798,13 +839,14 @@ template void regcache::cooked_write (int regnum, T val) { - gdb_byte *buf; + gdb_assert (regnum >= 0); + gdb_assert (regnum < m_descr->nr_cooked_registers); - gdb_assert (regnum >=0 && regnum < m_descr->nr_cooked_registers); - buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]); - store_integer (buf, m_descr->sizeof_register[regnum], - gdbarch_byte_order (m_descr->gdbarch), val); - cooked_write (regnum, buf); + int size = m_descr->sizeof_register[regnum]; + gdb_byte *buf = (gdb_byte *) alloca (size); + auto view = gdb::make_array_view (buf, size); + store_integer (view, gdbarch_byte_order (m_descr->gdbarch), val); + cooked_write (regnum, view); } void @@ -816,11 +858,10 @@ regcache_cooked_write_unsigned (struct regcache *regcache, int regnum, } void -regcache::raw_write (int regnum, const gdb_byte *buf) +regcache::raw_write (int regnum, gdb::array_view src) { - - gdb_assert (buf != NULL); assert_regnum (regnum); + gdb_assert (src.size () == m_descr->sizeof_register[regnum]); /* On the sparc, writing %g0 is a no-op, so we don't even want to change the registers array if something writes to this register. */ @@ -830,15 +871,15 @@ regcache::raw_write (int regnum, const gdb_byte *buf) /* If we have a valid copy of the register, and new value == old value, then don't bother doing the actual store. */ if (get_register_status (regnum) == REG_VALID - && (memcmp (register_buffer (regnum), buf, - m_descr->sizeof_register[regnum]) == 0)) + && (memcmp (register_buffer (regnum).data (), src.data (), src.size ()) + == 0)) return; std::optional maybe_restore_thread = maybe_switch_inferior (m_inf_for_target_calls); target_prepare_to_store (this); - raw_supply (regnum, buf); + raw_supply (regnum, src); /* Invalidate the register after it is written, in case of a failure. */ @@ -853,211 +894,248 @@ regcache::raw_write (int regnum, const gdb_byte *buf) } void -regcache::cooked_write (int regnum, const gdb_byte *buf) +regcache::raw_write (int regnum, const gdb_byte *src) +{ + assert_regnum (regnum); + + int size = m_descr->sizeof_register[regnum]; + raw_write (regnum, gdb::make_array_view (src, size)); +} + +/* See regcache.h. */ + +void +regcache::cooked_write (int regnum, gdb::array_view src) { gdb_assert (regnum >= 0); gdb_assert (regnum < m_descr->nr_cooked_registers); + if (regnum < num_raw_registers ()) - raw_write (regnum, buf); + raw_write (regnum, src); else - gdbarch_pseudo_register_write (m_descr->gdbarch, this, - regnum, buf); + gdbarch_pseudo_register_write (m_descr->gdbarch, this, regnum, + src.data ()); } /* See regcache.h. */ -enum register_status -readable_regcache::read_part (int regnum, int offset, int len, - gdb_byte *out, bool is_raw) +void +regcache::cooked_write (int regnum, const gdb_byte *src) +{ + gdb_assert (regnum >= 0); + gdb_assert (regnum < m_descr->nr_cooked_registers); + + int size = m_descr->sizeof_register[regnum]; + return cooked_write (regnum, gdb::make_array_view (src, size)); +} + +/* See regcache.h. */ + +register_status +readable_regcache::read_part (int regnum, int offset, + gdb::array_view dst, bool is_raw) { int reg_size = register_size (arch (), regnum); - gdb_assert (out != NULL); gdb_assert (offset >= 0); - gdb_assert (len >= 0 && offset + len <= reg_size); + gdb_assert (offset + dst.size () <= reg_size); - if (len == 0) + if (dst.size () == 0) { /* Nothing to do. */ return REG_VALID; } - if (len == reg_size) + if (dst.size () == reg_size) { /* Read the full register. */ - return (is_raw) ? raw_read (regnum, out) : cooked_read (regnum, out); + if (is_raw) + return raw_read (regnum, dst); + else + return cooked_read (regnum, dst); } - enum register_status status; - gdb_byte *reg = (gdb_byte *) alloca (reg_size); - /* Read full register to buffer. */ - status = (is_raw) ? raw_read (regnum, reg) : cooked_read (regnum, reg); + register_status status; + gdb_byte *reg_buf = (gdb_byte *) alloca (reg_size); + auto reg = gdb::make_array_view (reg_buf, reg_size); + + if (is_raw) + status = raw_read (regnum, reg); + else + status = cooked_read (regnum, reg); + if (status != REG_VALID) return status; /* Copy out. */ - memcpy (out, reg + offset, len); + copy (reg.slice (offset, dst.size ()), dst); return REG_VALID; } /* See regcache.h. */ void -reg_buffer::raw_collect_part (int regnum, int offset, int len, - gdb_byte *out) const +reg_buffer::raw_collect_part (int regnum, int offset, + gdb::array_view dst) const { int reg_size = register_size (arch (), regnum); - gdb_assert (out != nullptr); gdb_assert (offset >= 0); - gdb_assert (len >= 0 && offset + len <= reg_size); + gdb_assert (offset + dst.size () <= reg_size); - if (len == 0) + if (dst.size () == 0) { /* Nothing to do. */ return; } - if (len == reg_size) + if (dst.size () == reg_size) { /* Collect the full register. */ - return raw_collect (regnum, out); + return raw_collect (regnum, dst); } /* Read to buffer, then write out. */ - gdb_byte *reg = (gdb_byte *) alloca (reg_size); + gdb_byte *reg_buf = (gdb_byte *) alloca (reg_size); + auto reg = gdb::make_array_view (reg_buf, reg_size); raw_collect (regnum, reg); - memcpy (out, reg + offset, len); + copy (reg.slice (offset, dst.size ()), dst); } /* See regcache.h. */ -enum register_status -regcache::write_part (int regnum, int offset, int len, - const gdb_byte *in, bool is_raw) +register_status +regcache::write_part (int regnum, int offset, + gdb::array_view src, bool is_raw) { int reg_size = register_size (arch (), regnum); - gdb_assert (in != NULL); gdb_assert (offset >= 0); - gdb_assert (len >= 0 && offset + len <= reg_size); + gdb_assert (offset + src.size () <= reg_size); - if (len == 0) + if (src.size () == 0) { /* Nothing to do. */ return REG_VALID; } - if (len == reg_size) + if (src.size () == reg_size) { /* Write the full register. */ - (is_raw) ? raw_write (regnum, in) : cooked_write (regnum, in); + if (is_raw) + raw_write (regnum, src); + else + cooked_write (regnum, src); + return REG_VALID; } - enum register_status status; - gdb_byte *reg = (gdb_byte *) alloca (reg_size); - /* Read existing register to buffer. */ - status = (is_raw) ? raw_read (regnum, reg) : cooked_read (regnum, reg); + register_status status; + gdb_byte *reg_buf = (gdb_byte *) alloca (reg_size); + auto reg = gdb::make_array_view (reg_buf, reg_size); + + if (is_raw) + status = raw_read (regnum, reg); + else + status = cooked_read (regnum, reg); + if (status != REG_VALID) return status; /* Update buffer, then write back to regcache. */ - memcpy (reg + offset, in, len); - is_raw ? raw_write (regnum, reg) : cooked_write (regnum, reg); + copy (src, reg.slice (offset, src.size ())); + + if (is_raw) + raw_write (regnum, reg); + else + cooked_write (regnum, reg); + return REG_VALID; } /* See regcache.h. */ void -reg_buffer::raw_supply_part (int regnum, int offset, int len, - const gdb_byte *in) +reg_buffer::raw_supply_part (int regnum, int offset, + gdb::array_view src) { int reg_size = register_size (arch (), regnum); - gdb_assert (in != nullptr); gdb_assert (offset >= 0); - gdb_assert (len >= 0 && offset + len <= reg_size); + gdb_assert (offset + src.size () <= reg_size); - if (len == 0) + if (src.size () == 0) { /* Nothing to do. */ return; } - if (len == reg_size) + if (src.size () == reg_size) { /* Supply the full register. */ - return raw_supply (regnum, in); + return raw_supply (regnum, src); } - gdb_byte *reg = (gdb_byte *) alloca (reg_size); - /* Read existing value to buffer. */ + gdb_byte *reg_buf = (gdb_byte *) alloca (reg_size); + auto reg = gdb::make_array_view (reg_buf, reg_size); raw_collect (regnum, reg); /* Write to buffer, then write out. */ - memcpy (reg + offset, in, len); + copy (src, reg.slice (offset, src.size ())); raw_supply (regnum, reg); } -enum register_status -readable_regcache::raw_read_part (int regnum, int offset, int len, - gdb_byte *buf) +register_status +readable_regcache::raw_read_part (int regnum, int offset, + gdb::array_view dst) { assert_regnum (regnum); - return read_part (regnum, offset, len, buf, true); + return read_part (regnum, offset, dst, true); } /* See regcache.h. */ void -regcache::raw_write_part (int regnum, int offset, int len, - const gdb_byte *buf) +regcache::raw_write_part (int regnum, int offset, + gdb::array_view src) { assert_regnum (regnum); - write_part (regnum, offset, len, buf, true); + write_part (regnum, offset, src, true); } /* See regcache.h. */ -enum register_status -readable_regcache::cooked_read_part (int regnum, int offset, int len, - gdb_byte *buf) +register_status +readable_regcache::cooked_read_part (int regnum, int offset, + gdb::array_view dst) { gdb_assert (regnum >= 0 && regnum < m_descr->nr_cooked_registers); - return read_part (regnum, offset, len, buf, false); + return read_part (regnum, offset, dst, false); } /* See regcache.h. */ void -regcache::cooked_write_part (int regnum, int offset, int len, - const gdb_byte *buf) +regcache::cooked_write_part (int regnum, int offset, + gdb::array_view src) { gdb_assert (regnum >= 0 && regnum < m_descr->nr_cooked_registers); - write_part (regnum, offset, len, buf, false); + write_part (regnum, offset, src, false); } /* See gdbsupport/common-regcache.h. */ void -reg_buffer::raw_supply (int regnum, const void *buf) +reg_buffer::raw_supply (int regnum, gdb::array_view src) { - void *regbuf; - size_t size; + gdb::array_view dst = register_buffer (regnum); - assert_regnum (regnum); - - regbuf = register_buffer (regnum); - size = m_descr->sizeof_register[regnum]; - - if (buf) + if (src.data () != nullptr) { - memcpy (regbuf, buf, size); + copy (src, dst); m_register_status[regnum] = REG_VALID; } else @@ -1065,7 +1143,7 @@ reg_buffer::raw_supply (int regnum, const void *buf) /* This memset not strictly necessary, but better than garbage in case the register value manages to escape somewhere (due to a bug, no less). */ - memset (regbuf, 0, size); + memset (dst.data (), 0, dst.size ()); m_register_status[regnum] = REG_UNAVAILABLE; } } @@ -1073,19 +1151,24 @@ reg_buffer::raw_supply (int regnum, const void *buf) /* See regcache.h. */ void -reg_buffer::raw_supply_integer (int regnum, const gdb_byte *addr, - int addr_len, bool is_signed) +reg_buffer::raw_supply (int regnum, const void *src) { - enum bfd_endian byte_order = gdbarch_byte_order (m_descr->gdbarch); - gdb_byte *regbuf; - size_t regsize; - assert_regnum (regnum); - regbuf = register_buffer (regnum); - regsize = m_descr->sizeof_register[regnum]; + int size = m_descr->sizeof_register[regnum]; + raw_supply (regnum, gdb::make_array_view ((const gdb_byte *) src, size)); +} + +/* See regcache.h. */ - copy_integer_to_size (regbuf, regsize, addr, addr_len, is_signed, +void +reg_buffer::raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len, + bool is_signed) +{ + gdb::array_view dst = register_buffer (regnum); + bfd_endian byte_order = gdbarch_byte_order (m_descr->gdbarch); + + copy_integer_to_size (dst.data (), dst.size (), addr, addr_len, is_signed, byte_order); m_register_status[regnum] = REG_VALID; } @@ -1095,32 +1178,29 @@ reg_buffer::raw_supply_integer (int regnum, const gdb_byte *addr, void reg_buffer::raw_supply_zeroed (int regnum) { - void *regbuf; - size_t size; - - assert_regnum (regnum); - - regbuf = register_buffer (regnum); - size = m_descr->sizeof_register[regnum]; - - memset (regbuf, 0, size); + gdb::array_view dst = register_buffer (regnum); + memset (dst.data (), 0, dst.size ()); m_register_status[regnum] = REG_VALID; } /* See gdbsupport/common-regcache.h. */ void -reg_buffer::raw_collect (int regnum, void *buf) const +reg_buffer::raw_collect (int regnum, gdb::array_view dst) const { - const void *regbuf; - size_t size; + gdb::array_view src = register_buffer (regnum); + copy (src, dst); +} - gdb_assert (buf != NULL); +/* See regcache.h. */ + +void +reg_buffer::raw_collect (int regnum, void *dst) const +{ assert_regnum (regnum); - regbuf = register_buffer (regnum); - size = m_descr->sizeof_register[regnum]; - memcpy (buf, regbuf, size); + int size = m_descr->sizeof_register[regnum]; + return raw_collect (regnum, gdb::make_array_view ((gdb_byte *) dst, size)); } /* See regcache.h. */ @@ -1129,16 +1209,9 @@ void reg_buffer::raw_collect_integer (int regnum, gdb_byte *addr, int addr_len, bool is_signed) const { - enum bfd_endian byte_order = gdbarch_byte_order (m_descr->gdbarch); - const gdb_byte *regbuf; - size_t regsize; - - assert_regnum (regnum); - - regbuf = register_buffer (regnum); - regsize = m_descr->sizeof_register[regnum]; - - copy_integer_to_size (addr, addr_len, regbuf, regsize, is_signed, + gdb::array_view dst = register_buffer (regnum); + bfd_endian byte_order = gdbarch_byte_order (m_descr->gdbarch); + copy_integer_to_size (addr, addr_len, dst.data (), dst.size (), is_signed, byte_order); } @@ -1157,7 +1230,8 @@ regcache::transfer_regset_register (struct regcache *out_regcache, int regnum, if (out_buf != nullptr) { - raw_collect_part (regnum, 0, reg_size, out_buf + offs); + raw_collect_part (regnum, 0, + gdb::make_array_view (out_buf + offs, reg_size)); /* Ensure any additional space is cleared. */ if (slot_size > reg_size) @@ -1168,12 +1242,14 @@ regcache::transfer_regset_register (struct regcache *out_regcache, int regnum, /* Zero-extend the register value if the slot is smaller than the register. */ if (slot_size < register_size (gdbarch, regnum)) out_regcache->raw_supply_zeroed (regnum); - out_regcache->raw_supply_part (regnum, 0, reg_size, in_buf + offs); + out_regcache->raw_supply_part (regnum, 0, + gdb::make_array_view (in_buf + offs, + reg_size)); } else { /* Invalidate the register. */ - out_regcache->raw_supply (regnum, nullptr); + out_regcache->raw_supply (regnum, {}); } } @@ -1304,13 +1380,12 @@ bool reg_buffer::raw_compare (int regnum, const void *buf, int offset) const { gdb_assert (buf != NULL); - assert_regnum (regnum); - const char *regbuf = (const char *) register_buffer (regnum); - size_t size = m_descr->sizeof_register[regnum]; - gdb_assert (size >= offset); + gdb::array_view regbuf = register_buffer (regnum); + gdb_assert (offset <= regbuf.size ()); + regbuf = regbuf.slice (offset); - return (memcmp (buf, regbuf + offset, size - offset) == 0); + return memcmp (buf, regbuf.data (), regbuf.size ()) == 0; } /* Special handling for register PC. */ @@ -1399,17 +1474,15 @@ regcache::debug_print_register (const char *func, int regno) if (regno >= 0 && regno < gdbarch_num_regs (gdbarch)) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - int size = register_size (gdbarch, regno); - gdb_byte *buf = register_buffer (regno); + gdb::array_view buf = register_buffer (regno); gdb_printf (gdb_stdlog, " = "); - for (int i = 0; i < size; i++) - { - gdb_printf (gdb_stdlog, "%02x", buf[i]); - } - if (size <= sizeof (LONGEST)) + for (gdb_byte byte : buf) + gdb_printf (gdb_stdlog, "%02x", byte); + + if (buf.size () <= sizeof (LONGEST)) { - ULONGEST val = extract_unsigned_integer (buf, size, byte_order); + ULONGEST val = extract_unsigned_integer (buf, byte_order); gdb_printf (gdb_stdlog, " %s %s", core_addr_to_string_nz (val), plongest (val)); @@ -1758,6 +1831,23 @@ registers_changed_ptid_target_ptid_test () ptid_t (2, 2)) == 1); } +/* Test using reg_buffer::raw_compare with offset equal to the register size + (thus comparing 0 bytes). */ + +static void +reg_buffer_raw_compare_zero_len_test () +{ + regcache_test_data_up data = populate_regcaches_for_test (); + inferior &inf = data->test_ctx_1.mock_inferior; + const regcache *regcache + = get_thread_arch_regcache (&inf, ptid_t (1, 1), inf.arch ()); + + /* The buffer address is irrelevant since we end up comparing 0 bytes, we just + need to pass something. */ + gdb_byte buf; + SELF_CHECK (regcache->raw_compare (0, &buf, register_size (inf.arch (), 0))); +} + class target_ops_no_register : public test_target_ops { public: @@ -1869,7 +1959,7 @@ cooked_read_test (struct gdbarch *gdbarch) readwrite.set_ptid (mockctx.mock_ptid); gdb::byte_vector buf (register_size (gdbarch, nonzero_regnum)); - readwrite.raw_read (nonzero_regnum, buf.data ()); + readwrite.raw_read (nonzero_regnum, buf); /* raw_read calls target_fetch_registers. */ SELF_CHECK (mockctx.mock_target.fetch_registers_called > 0); @@ -1890,9 +1980,7 @@ cooked_read_test (struct gdbarch *gdbarch) gdb::byte_vector inner_buf (register_size (gdbarch, regnum)); - SELF_CHECK (REG_VALID == readwrite.cooked_read (regnum, - inner_buf.data ())); - + SELF_CHECK (REG_VALID == readwrite.cooked_read (regnum, inner_buf)); SELF_CHECK (mockctx.mock_target.fetch_registers_called == 0); SELF_CHECK (mockctx.mock_target.store_registers_called == 0); SELF_CHECK (mockctx.mock_target.xfer_partial_called == 0); @@ -1912,8 +2000,7 @@ cooked_read_test (struct gdbarch *gdbarch) continue; gdb::byte_vector inner_buf (register_size (gdbarch, regnum)); - enum register_status status = readonly.cooked_read (regnum, - inner_buf.data ()); + register_status status = readonly.cooked_read (regnum, inner_buf); if (regnum < gdbarch_num_regs (gdbarch)) { @@ -2003,8 +2090,8 @@ cooked_write_test (struct gdbarch *gdbarch) && regnum <= gdbarch_num_regs (gdbarch) + 4)) continue; - std::vector expected (register_size (gdbarch, regnum), 0); - std::vector buf (register_size (gdbarch, regnum), 0); + gdb::byte_vector expected (register_size (gdbarch, regnum), 0); + gdb::byte_vector buf (register_size (gdbarch, regnum), 0); const auto type = register_type (gdbarch, regnum); if (type->code () == TYPE_CODE_FLT @@ -2059,9 +2146,9 @@ cooked_write_test (struct gdbarch *gdbarch) SELF_CHECK (0); } - readwrite.cooked_write (regnum, expected.data ()); + readwrite.cooked_write (regnum, expected); - SELF_CHECK (readwrite.cooked_read (regnum, buf.data ()) == REG_VALID); + SELF_CHECK (readwrite.cooked_read (regnum, buf) == REG_VALID); SELF_CHECK (expected == buf); } } @@ -2154,6 +2241,8 @@ _initialize_regcache () selftests::registers_changed_ptid_target_pid_test); selftests::register_test ("registers_changed_ptid_target_ptid", selftests::registers_changed_ptid_target_ptid_test); + selftests::register_test ("reg_buffer_raw_compare_zero_len", + selftests::reg_buffer_raw_compare_zero_len_test); selftests::register_test_foreach_arch ("regcache::cooked_read_test", selftests::cooked_read_test); diff --git a/gdb/regcache.h b/gdb/regcache.h index 7922a5c5ae21..d90f74bfbb06 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -20,6 +20,7 @@ #ifndef REGCACHE_H #define REGCACHE_H +#include "gdbsupport/array-view.h" #include "gdbsupport/common-regcache.h" #include "gdbsupport/function-view.h" @@ -167,8 +168,8 @@ extern struct type *register_type (struct gdbarch *gdbarch, int regnum); extern int register_size (struct gdbarch *gdbarch, int regnum); -typedef gdb::function_view - register_read_ftype; +using register_read_ftype + = gdb::function_view)>; /* A (register_number, register_value) pair. */ @@ -194,7 +195,10 @@ class reg_buffer : public reg_buffer_common enum register_status get_register_status (int regnum) const override; /* See gdbsupport/common-regcache.h. */ - void raw_collect (int regnum, void *buf) const override; + void raw_collect (int regnum, gdb::array_view dst) const override; + + /* Deprecated overload of the above. */ + void raw_collect (int regnum, void *dst) const; /* Collect register REGNUM from REGCACHE. Store collected value as an integer at address ADDR, in target endian, with length ADDR_LEN and sign IS_SIGNED. @@ -204,17 +208,23 @@ class reg_buffer : public reg_buffer_common void raw_collect_integer (int regnum, gdb_byte *addr, int addr_len, bool is_signed) const; - /* Collect register REGNUM from REGCACHE, starting at OFFSET in register, - reading only LEN. */ - void raw_collect_part (int regnum, int offset, int len, gdb_byte *out) const; + /* Collect part of register REGNUM from this register buffer. Start at OFFSET + in register. The size is given by the size of DST. */ + void raw_collect_part (int regnum, int offset, + gdb::array_view dst) const; + + /* Deprecated overload of the above. */ + void raw_collect_part (int regnum, int offset, int len, gdb_byte *dst) const + { raw_collect_part (regnum, offset, gdb::make_array_view (dst, len)); } /* See gdbsupport/common-regcache.h. */ - void raw_supply (int regnum, const void *buf) override; + void raw_supply (int regnum, gdb::array_view src) override; + + /* Deprecated overload of the above. */ + void raw_supply (int regnum, const void *src); void raw_supply (int regnum, const reg_buffer &src) - { - raw_supply (regnum, src.register_buffer (regnum)); - } + { raw_supply (regnum, src.register_buffer (regnum)); } /* Supply register REGNUM to REGCACHE. Value to supply is an integer stored at address ADDR, in target endian, with length ADDR_LEN and sign IS_SIGNED. @@ -229,9 +239,11 @@ class reg_buffer : public reg_buffer_common unavailable). */ void raw_supply_zeroed (int regnum); - /* Supply register REGNUM to REGCACHE, starting at OFFSET in register, writing - only LEN, without editing the rest of the register. */ - void raw_supply_part (int regnum, int offset, int len, const gdb_byte *in); + /* Supply part of register REGNUM to this register buffer. Start at OFFSET in + the register. The size is given by the size of SRC. The rest of the + register left untouched. */ + void raw_supply_part (int regnum, int offset, + gdb::array_view src); void invalidate (int regnum); @@ -246,7 +258,11 @@ class reg_buffer : public reg_buffer_common int num_raw_registers () const; - gdb_byte *register_buffer (int regnum) const; + /* Return a view on register REGNUM's buffer cache. */ + template + gdb::array_view register_buffer (int regnum) const; + gdb::array_view register_buffer (int regnum) const; + gdb::array_view register_buffer (int regnum); /* Save a register cache. The set of registers saved into the regcache determined by the save_reggroup. COOKED_READ returns @@ -276,27 +292,41 @@ class readable_regcache : public reg_buffer /* Transfer a raw register [0..NUM_REGS) from core-gdb to this regcache, return its value in *BUF and return its availability status. */ + register_status raw_read (int regnum, gdb::array_view dst); + + /* Deprecated overload of the above. */ + register_status raw_read (int regnum, gdb_byte *dst); - enum register_status raw_read (int regnum, gdb_byte *buf); template> - enum register_status raw_read (int regnum, T *val); + register_status raw_read (int regnum, T *val); /* Partial transfer of raw registers. Return the status of the register. */ - enum register_status raw_read_part (int regnum, int offset, int len, - gdb_byte *buf); + register_status raw_read_part (int regnum, int offset, + gdb::array_view dst); + + /* Deprecated overload of the above. */ + register_status raw_read_part (int regnum, int offset, int len, + gdb_byte *dst) + { return raw_read_part (regnum, offset, gdb::make_array_view (dst, len)); } /* Make certain that the register REGNUM is up-to-date. */ virtual void raw_update (int regnum) = 0; /* Transfer a raw register [0..NUM_REGS+NUM_PSEUDO_REGS) from core-gdb to - this regcache, return its value in *BUF and return its availability status. */ - enum register_status cooked_read (int regnum, gdb_byte *buf); + this regcache, return its value in DST and return its availability status. */ + register_status cooked_read (int regnum, gdb::array_view dst); + register_status cooked_read (int regnum, gdb_byte *dst); + template> - enum register_status cooked_read (int regnum, T *val); + register_status cooked_read (int regnum, T *val); /* Partial transfer of a cooked register. */ - enum register_status cooked_read_part (int regnum, int offset, int len, - gdb_byte *buf); + register_status cooked_read_part (int regnum, int offset, + gdb::array_view dst); + + /* Deprecated overload of the above. */ + register_status cooked_read_part (int regnum, int offset, int len, gdb_byte *src) + { return cooked_read_part (regnum, offset, gdb::make_array_view (src, len)); } /* Read register REGNUM from the regcache and return a new value. This will call mark_value_bytes_unavailable as appropriate. */ @@ -306,8 +336,8 @@ class readable_regcache : public reg_buffer /* Perform a partial register transfer using a read, modify, write operation. Will fail if register is currently invalid. */ - enum register_status read_part (int regnum, int offset, int len, - gdb_byte *out, bool is_raw); + register_status read_part (int regnum, int offset, + gdb::array_view dst, bool is_raw); }; /* Buffer of registers, can be read and written. */ @@ -343,13 +373,19 @@ class regcache : public detached_regcache /* Update the value of raw register REGNUM (in the range [0..NUM_REGS)) and transfer its value to core-gdb. */ - void raw_write (int regnum, const gdb_byte *buf); + void raw_write (int regnum, gdb::array_view src); + + /* Deprecated overload of the above. */ + void raw_write (int regnum, const gdb_byte *src); template> void raw_write (int regnum, T val); /* Transfer of pseudo-registers. */ - void cooked_write (int regnum, const gdb_byte *buf); + void cooked_write (int regnum, gdb::array_view src); + + /* Deprecated overload of the above. */ + void cooked_write (int regnum, const gdb_byte *src); template> void cooked_write (int regnum, T val); @@ -358,12 +394,21 @@ class regcache : public detached_regcache /* Partial transfer of raw registers. Perform read, modify, write style operations. */ - void raw_write_part (int regnum, int offset, int len, const gdb_byte *buf); + void raw_write_part (int regnum, int offset, + gdb::array_view src); + + /* Deprecated overload of the above. */ + void raw_write_part (int regnum, int offset, int len, const gdb_byte *src) + { raw_write_part (regnum, offset, gdb::make_array_view (src, len)); } /* Partial transfer of a cooked register. Perform read, modify, write style operations. */ - void cooked_write_part (int regnum, int offset, int len, - const gdb_byte *buf); + void cooked_write_part (int regnum, int offset, + gdb::array_view src); + + /* Deprecated overload of the above. */ + void cooked_write_part (int regnum, int offset, int len, const gdb_byte *src) + { cooked_write_part (regnum, offset, gdb::make_array_view (src, len)); } /* Transfer a set of registers (as described by REGSET) between REGCACHE and BUF. If REGNUM == -1, transfer all registers @@ -430,8 +475,9 @@ class regcache : public detached_regcache /* Perform a partial register transfer using a read, modify, write operation. */ - enum register_status write_part (int regnum, int offset, int len, - const gdb_byte *in, bool is_raw); + register_status write_part (int regnum, int offset, + gdb::array_view src, + bool is_raw); /* The inferior to switch to, to make target calls. diff --git a/gdbserver/regcache.cc b/gdbserver/regcache.cc index 823ea1f015d3..c5d3670b4b56 100644 --- a/gdbserver/regcache.cc +++ b/gdbserver/regcache.cc @@ -315,27 +315,32 @@ regcache_register_size (const reg_buffer_common *regcache, int n) (gdb::checked_static_cast (regcache)->tdesc, n); } -static unsigned char * +static gdb::array_view register_data (const struct regcache *regcache, int n) { - return (regcache->registers - + find_register_by_number (regcache->tdesc, n).offset / 8); + const gdb::reg ® = find_register_by_number (regcache->tdesc, n); + return gdb::make_array_view (regcache->registers + reg.offset / 8, + reg.size / 8); } void -supply_register (struct regcache *regcache, int n, const void *buf) +supply_register (struct regcache *regcache, int n, const void *vbuf) { - return regcache->raw_supply (n, buf); + const gdb::reg ® = find_register_by_number (regcache->tdesc, n); + const gdb_byte *buf = static_cast (vbuf); + return regcache->raw_supply (n, gdb::make_array_view (buf, reg.size / 8)); } /* See gdbsupport/common-regcache.h. */ void -regcache::raw_supply (int n, const void *buf) +regcache::raw_supply (int n, gdb::array_view src) { - if (buf) + auto dst = register_data (this, n); + + if (src.data () != nullptr) { - memcpy (register_data (this, n), buf, register_size (tdesc, n)); + copy (src, dst); #ifndef IN_PROCESS_AGENT if (register_status != NULL) register_status[n] = REG_VALID; @@ -343,7 +348,7 @@ regcache::raw_supply (int n, const void *buf) } else { - memset (register_data (this, n), 0, register_size (tdesc, n)); + memset (dst.data (), 0, dst.size ()); #ifndef IN_PROCESS_AGENT if (register_status != NULL) register_status[n] = REG_UNAVAILABLE; @@ -356,8 +361,8 @@ regcache::raw_supply (int n, const void *buf) void supply_register_zeroed (struct regcache *regcache, int n) { - memset (register_data (regcache, n), 0, - register_size (regcache->tdesc, n)); + auto dst = register_data (regcache, n); + memset (dst.data (), 0, dst.size ()); #ifndef IN_PROCESS_AGENT if (regcache->register_status != NULL) regcache->register_status[n] = REG_VALID; @@ -426,17 +431,20 @@ supply_register_by_name (struct regcache *regcache, #endif void -collect_register (struct regcache *regcache, int n, void *buf) +collect_register (struct regcache *regcache, int n, void *vbuf) { - regcache->raw_collect (n, buf); + const gdb::reg ® = find_register_by_number (regcache->tdesc, n); + gdb_byte *buf = static_cast (vbuf); + regcache->raw_collect (n, gdb::make_array_view (buf, reg.size / 8)); } /* See gdbsupport/common-regcache.h. */ void -regcache::raw_collect (int n, void *buf) const +regcache::raw_collect (int n, gdb::array_view dst) const { - memcpy (buf, register_data (this, n), register_size (tdesc, n)); + auto src = register_data (this, n); + copy (src, dst); } enum register_status @@ -476,8 +484,7 @@ regcache_raw_get_unsigned_by_name (struct regcache *regcache, void collect_register_as_string (struct regcache *regcache, int n, char *buf) { - bin2hex (register_data (regcache, n), buf, - register_size (regcache->tdesc, n)); + bin2hex (register_data (regcache, n), buf); } void @@ -524,9 +531,9 @@ regcache::raw_compare (int regnum, const void *buf, int offset) const { gdb_assert (buf != NULL); - const unsigned char *regbuf = register_data (this, regnum); - int size = register_size (tdesc, regnum); - gdb_assert (size >= offset); + gdb::array_view regbuf = register_data (this, regnum); + gdb_assert (offset < regbuf.size ()); + regbuf = regbuf.slice (offset); - return (memcmp (buf, regbuf + offset, size - offset) == 0); + return memcmp (buf, regbuf.data (), regbuf.size ()) == 0; } diff --git a/gdbserver/regcache.h b/gdbserver/regcache.h index 4700c03f104e..02791a048fb0 100644 --- a/gdbserver/regcache.h +++ b/gdbserver/regcache.h @@ -50,10 +50,10 @@ struct regcache : public reg_buffer_common enum register_status get_register_status (int regnum) const override; /* See gdbsupport/common-regcache.h. */ - void raw_supply (int regnum, const void *buf) override; + void raw_supply (int regnum, gdb::array_view src) override; /* See gdbsupport/common-regcache.h. */ - void raw_collect (int regnum, void *buf) const override; + void raw_collect (int regnum, gdb::array_view dst) const override; /* See gdbsupport/common-regcache.h. */ bool raw_compare (int regnum, const void *buf, int offset) const override; diff --git a/gdbsupport/common-regcache.h b/gdbsupport/common-regcache.h index 6d98ca8c92ed..c40b92a83ee1 100644 --- a/gdbsupport/common-regcache.h +++ b/gdbsupport/common-regcache.h @@ -78,11 +78,41 @@ struct reg_buffer_common buffer. */ virtual register_status get_register_status (int regnum) const = 0; - /* Supply register REGNUM, whose contents are stored in BUF, to REGCACHE. */ - virtual void raw_supply (int regnum, const void *buf) = 0; + /* Supply register REGNUM, whose contents are stored in SRC, to this register + buffer. */ + virtual void raw_supply (int regnum, gdb::array_view src) + = 0; + + void raw_supply (int regnum, const uint64_t *src) + { + raw_supply (regnum, + gdb::make_array_view ((const gdb_byte *) src, sizeof (*src))); + } + + void raw_supply (int regnum, const gdb_byte *src) + { + raw_supply (regnum, + gdb::make_array_view (src, + regcache_register_size (this, regnum))); + } - /* Collect register REGNUM from REGCACHE and store its contents in BUF. */ - virtual void raw_collect (int regnum, void *buf) const = 0; + /* Collect register REGNUM from this register buffer and store its contents in + DST. */ + virtual void raw_collect (int regnum, gdb::array_view dst) const + = 0; + + void raw_collect (int regnum, uint64_t *dst) const + { + raw_collect (regnum, + gdb::make_array_view ((gdb_byte *) dst, sizeof (*dst))); + }; + + void raw_collect (int regnum, gdb_byte *dst) + { + raw_collect (regnum, + gdb::make_array_view (dst, + regcache_register_size (this, regnum))); + } /* Compare the contents of the register stored in the regcache (ignoring the first OFFSET bytes) to the contents of BUF (without any offset). Returns diff --git a/gdbsupport/rsp-low.cc b/gdbsupport/rsp-low.cc index 3d8c2002956e..632be265c00c 100644 --- a/gdbsupport/rsp-low.cc +++ b/gdbsupport/rsp-low.cc @@ -143,6 +143,14 @@ bin2hex (const gdb_byte *bin, char *hex, int count) /* See rsp-low.h. */ +int +bin2hex (gdb::array_view bin, char *hex) +{ + return bin2hex (bin.data (), hex, bin.size ()); +} + +/* See rsp-low.h. */ + std::string bin2hex (const gdb_byte *bin, int count) { diff --git a/gdbsupport/rsp-low.h b/gdbsupport/rsp-low.h index 327d5f3a0947..1fc2572a7f5c 100644 --- a/gdbsupport/rsp-low.h +++ b/gdbsupport/rsp-low.h @@ -54,6 +54,8 @@ extern std::string hex2str (const char *hex, int count); extern int bin2hex (const gdb_byte *bin, char *hex, int count); +extern int bin2hex (gdb::array_view bin, char *hex); + /* Overloaded version of bin2hex that returns a std::string. */ extern std::string bin2hex (const gdb_byte *bin, int count); From patchwork Fri Dec 1 16:27:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81138 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 0224C385E449 for ; Fri, 1 Dec 2023 16:28:35 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id A1802385C322 for ; Fri, 1 Dec 2023 16:27:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A1802385C322 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A1802385C322 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448078; cv=none; b=OysgYCyDTJOSEaMN+X+amNZpFOZ9k/PPZI837oNYUGBSJaJiWtYuu0Cg4xzjTgwABWY7vIdY4ytrei/qm0zcsXxKyrAIewoMTwAPS1rx5inyaAOaHwtUA3Lw2J/aKX2c2Qbl22EWdmAHWuWX2BnSnVxuPy58wnoBTYVGzYgfn/o= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448078; c=relaxed/simple; bh=wVPqzAmvuAtSNJir8Y7X9eB5HWLgPd0NVVOngu41xeI=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=xclH5gcNsndIky3JSPIebuMeUxEsV6oLZbs1QoFuAUvyHPTd+/U47VyipOUFn9BC3k5KPd7CwkngZVX5LDwf+5D2Gxj8Jwiv44MC+zCwaRbgAJNYSz0d+R0b5wA9YecUNS7LycgQ5W5dIYuMhW/LbDbBkSKG7NH+WeVYZ/N8KAc= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 103501E1A8; Fri, 1 Dec 2023 11:27:55 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin , Andrew Burgess Subject: [PATCH 06/24] gdb: fix bugs in {get,put}_frame_register_bytes Date: Fri, 1 Dec 2023 11:27:19 -0500 Message-ID: <20231201162751.741751-7-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org I found this only by inspection: the myaddr pointer in {get,put}_frame_register_bytes is reset to `buffer.data ()` at each iteration. This means that we will always use the bytes at the beginning of `buffer` to read or write to the registers, instead of progressing in `buffer`. Fix this by re-writing the functions to chip away the beginning of the buffer array_view as we progress in reading or writing the data. These bugs was introduced almost 3 years ago [1], and yet nobody complained. I'm wondering which architecture relies on that register "overflow" behavior (reading or writing multiple consecutive registers with one {get,put}_frame_register_bytes calls), and in which situation. I find these functions a bit dangerous, if a caller mis-calculates things, it could end up silently reading or writing to the next register, even if it's not the intent. If I could change it, I would prefer to have functions specifically made for that ({get,put}_frame_register_bytes_consecutive or something like that) and make {get,put}_frame_register_bytes only able to write within a single register (which I presume represents most of the use cases of the current {get,put}_frame_register_bytes). If a caller mis-calculates things and an overflow occurs while calling {get,put}_frame_register_bytes, it would hit an assert. The problem is knowing which callers rely on the overflow behavior and which don't. [1] https://gitlab.com/gnutools/binutils-gdb/-/commit/bdec2917b1e94c7198ba39919f45060067952f43 Change-Id: I43bd4a9f7fa8419d388a2b20bdc57d652688ddf8 Reviewed-By: John Baldwin Approved-By: Andrew Burgess --- gdb/frame.c | 63 +++++++++++++++++++---------------------------------- 1 file changed, 23 insertions(+), 40 deletions(-) diff --git a/gdb/frame.c b/gdb/frame.c index 529453efa158..08ce21705432 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1483,9 +1483,6 @@ get_frame_register_bytes (frame_info_ptr frame, int regnum, int *optimizedp, int *unavailablep) { struct gdbarch *gdbarch = get_frame_arch (frame); - int i; - int maxsize; - int numregs; /* Skip registers wholly inside of OFFSET. */ while (offset >= register_size (gdbarch, regnum)) @@ -1496,9 +1493,9 @@ get_frame_register_bytes (frame_info_ptr frame, int regnum, /* Ensure that we will not read beyond the end of the register file. This can only ever happen if the debug information is bad. */ - maxsize = -offset; - numregs = gdbarch_num_cooked_regs (gdbarch); - for (i = regnum; i < numregs; i++) + int maxsize = -offset; + int numregs = gdbarch_num_cooked_regs (gdbarch); + for (int i = regnum; i < numregs; i++) { int thissize = register_size (gdbarch, i); @@ -1507,20 +1504,15 @@ get_frame_register_bytes (frame_info_ptr frame, int regnum, maxsize += thissize; } - int len = buffer.size (); - if (len > maxsize) + if (buffer.size () > maxsize) error (_("Bad debug information detected: " - "Attempt to read %d bytes from registers."), len); + "Attempt to read %zu bytes from registers."), buffer.size ()); /* Copy the data. */ - while (len > 0) + while (!buffer.empty ()) { - int curr_len = register_size (gdbarch, regnum) - offset; - - if (curr_len > len) - curr_len = len; - - gdb_byte *myaddr = buffer.data (); + int curr_len = std::min (register_size (gdbarch, regnum) - offset, + buffer.size ()); if (curr_len == register_size (gdbarch, regnum)) { @@ -1528,8 +1520,8 @@ get_frame_register_bytes (frame_info_ptr frame, int regnum, CORE_ADDR addr; int realnum; - frame_register (frame, regnum, optimizedp, unavailablep, - &lval, &addr, &realnum, myaddr); + frame_register (frame, regnum, optimizedp, unavailablep, &lval, + &addr, &realnum, buffer.data ()); if (*optimizedp || *unavailablep) return false; } @@ -1548,13 +1540,12 @@ get_frame_register_bytes (frame_info_ptr frame, int regnum, return false; } - memcpy (myaddr, value->contents_all ().data () + offset, - curr_len); + copy (value->contents_all ().slice (offset, curr_len), + buffer.slice (0, curr_len)); release_value (value); } - myaddr += curr_len; - len -= curr_len; + buffer = buffer.slice (curr_len); offset = 0; regnum++; } @@ -1579,36 +1570,28 @@ put_frame_register_bytes (frame_info_ptr frame, int regnum, regnum++; } - int len = buffer.size (); /* Copy the data. */ - while (len > 0) + while (!buffer.empty ()) { - int curr_len = register_size (gdbarch, regnum) - offset; + int curr_len = std::min (register_size (gdbarch, regnum) - offset, + buffer.size ()); - if (curr_len > len) - curr_len = len; - - const gdb_byte *myaddr = buffer.data (); if (curr_len == register_size (gdbarch, regnum)) - { - put_frame_register (frame, regnum, myaddr); - } + put_frame_register (frame, regnum, buffer.data ()); else { - struct value *value + value *value = frame_unwind_register_value (frame_info_ptr (frame->next), regnum); - gdb_assert (value != NULL); + gdb_assert (value != nullptr); - memcpy ((char *) value->contents_writeable ().data () + offset, - myaddr, curr_len); - put_frame_register (frame, regnum, - value->contents_raw ().data ()); + copy (buffer.slice (0, curr_len), + value->contents_writeable ().slice (offset, curr_len)); + put_frame_register (frame, regnum, value->contents_raw ().data ()); release_value (value); } - myaddr += curr_len; - len -= curr_len; + buffer = buffer.slice (curr_len); offset = 0; regnum++; } From patchwork Fri Dec 1 16:27:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81139 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 0A0D3386183E for ; Fri, 1 Dec 2023 16:28:48 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 321BB385C6E9 for ; Fri, 1 Dec 2023 16:27:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 321BB385C6E9 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 321BB385C6E9 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448078; cv=none; b=VYwCWD/8MPEbWUeHgK/SCRt9zZFPpmJxcYMVHA1C36ePyOeau4eQy9PLLhbFOQCGzEtt43t4+27t/u68yxNExh4CdsOoQZlFQX6zK1j3Mwf6Y4MkG7d+9J0aDlI+Axbb6j2Iwe2wUdZ7kdw2W1plfSzi7zTjNl1N2mWH1IOVaAM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448078; c=relaxed/simple; bh=QdtO7zio5F9mkl/Bt0oSO6mrV7NRszAKmNs9tqTjGMg=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=JQHvxx1Ph+tNzy828h7bUqauCUpFE7h5paSM/LY226FJefD7EZv7Or1QKcHyeYNaMn3knE/D185aJAMQHdOhQuhYaB+b9K6gQAef3715+A/teZpTMn+jWXUDeM2j5Bcy46W1DIZmJ8O1dH+Fs60QfyVDRXUiGiY701ezz+M+v8k= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 42D411E1A9; Fri, 1 Dec 2023 11:27:55 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 07/24] gdb: make put_frame_register take an array_view Date: Fri, 1 Dec 2023 11:27:20 -0500 Message-ID: <20231201162751.741751-8-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Change put_frame_register to take an array_view instead of a raw pointer. Add an assertion to verify that the number of bytes we try to write matches the length of the register. Change-Id: Ib75a9c8a12b47e203097621643eaa2c1830591ae Reviewed-By: John Baldwin --- gdb/alpha-tdep.c | 12 ++++++------ gdb/frame.c | 11 +++++++---- gdb/frame.h | 2 +- gdb/i386-tdep.c | 3 ++- gdb/i387-tdep.c | 6 ++++-- gdb/ia64-tdep.c | 6 ++++-- gdb/m68k-tdep.c | 7 ++++--- gdb/mips-tdep.c | 5 +++-- gdb/rs6000-tdep.c | 7 ++++--- 9 files changed, 35 insertions(+), 24 deletions(-) diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c index 0d3a49550530..eaf2a7e97949 100644 --- a/gdb/alpha-tdep.c +++ b/gdb/alpha-tdep.c @@ -263,14 +263,14 @@ static void alpha_value_to_register (frame_info_ptr frame, int regnum, struct type *valtype, const gdb_byte *in) { - gdb_byte out[ALPHA_REGISTER_SIZE]; - + int reg_size = register_size (get_frame_arch (frame), regnum); gdb_assert (valtype->length () == 4); - gdb_assert (register_size (get_frame_arch (frame), regnum) - <= ALPHA_REGISTER_SIZE); - alpha_lds (get_frame_arch (frame), out, in); + gdb_assert (reg_size <= ALPHA_REGISTER_SIZE); - put_frame_register (frame, regnum, out); + gdb_byte out[ALPHA_REGISTER_SIZE]; + alpha_lds (get_frame_arch (frame), out, in); + auto out_view = gdb::make_array_view (out, reg_size); + put_frame_register (frame, regnum, out_view); } diff --git a/gdb/frame.c b/gdb/frame.c index 08ce21705432..9312d1b40168 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1424,7 +1424,7 @@ read_frame_register_unsigned (frame_info_ptr frame, int regnum, void put_frame_register (frame_info_ptr frame, int regnum, - const gdb_byte *buf) + gdb::array_view buf) { struct gdbarch *gdbarch = get_frame_arch (frame); int realnum; @@ -1432,6 +1432,9 @@ put_frame_register (frame_info_ptr frame, int regnum, int unavail; enum lval_type lval; CORE_ADDR addr; + int size = register_size (gdbarch, regnum); + + gdb_assert (buf.size () == size); frame_register (frame, regnum, &optim, &unavail, &lval, &addr, &realnum, NULL); @@ -1441,7 +1444,7 @@ put_frame_register (frame_info_ptr frame, int regnum, { case lval_memory: { - write_memory (addr, buf, register_size (gdbarch, regnum)); + write_memory (addr, buf.data (), size); break; } case lval_register: @@ -1577,7 +1580,7 @@ put_frame_register_bytes (frame_info_ptr frame, int regnum, buffer.size ()); if (curr_len == register_size (gdbarch, regnum)) - put_frame_register (frame, regnum, buffer.data ()); + put_frame_register (frame, regnum, buffer.slice (0, curr_len)); else { value *value @@ -1587,7 +1590,7 @@ put_frame_register_bytes (frame_info_ptr frame, int regnum, copy (buffer.slice (0, curr_len), value->contents_writeable ().slice (offset, curr_len)); - put_frame_register (frame, regnum, value->contents_raw ().data ()); + put_frame_register (frame, regnum, value->contents_raw ()); release_value (value); } diff --git a/gdb/frame.h b/gdb/frame.h index 19bf81766822..4117e169379a 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -731,7 +731,7 @@ extern bool read_frame_register_unsigned (frame_info_ptr frame, frame. Note: this call makes the frame's state undefined. The register and frame caches must be flushed. */ extern void put_frame_register (frame_info_ptr frame, int regnum, - const gdb_byte *buf); + gdb::array_view buf); /* Read LEN bytes from one or multiple registers starting with REGNUM in frame FRAME, starting at OFFSET, into BUF. If the register diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index f356995520fe..3afa902767e5 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -3917,7 +3917,8 @@ i386_value_to_register (frame_info_ptr frame, int regnum, gdb_assert (regnum != -1); gdb_assert (register_size (get_frame_arch (frame), regnum) == 4); - put_frame_register (frame, regnum, from); + auto from_view = gdb::make_array_view (from, 4); + put_frame_register (frame, regnum, from_view); regnum = i386_next_regnum (regnum); len -= 4; from += 4; diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c index b9c9e476e936..b39ca2adef55 100644 --- a/gdb/i387-tdep.c +++ b/gdb/i387-tdep.c @@ -397,8 +397,10 @@ i387_value_to_register (frame_info_ptr frame, int regnum, } /* Convert from TYPE. */ - target_float_convert (from, type, to, i387_ext_type (gdbarch)); - put_frame_register (frame, regnum, to); + struct type *to_type = i387_ext_type (gdbarch); + target_float_convert (from, type, to, to_type); + auto to_view = gdb::make_array_view (to, to_type->length ()); + put_frame_register (frame, regnum, to_view); } diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c index 6d537c4c8d36..f778c092537b 100644 --- a/gdb/ia64-tdep.c +++ b/gdb/ia64-tdep.c @@ -1245,8 +1245,10 @@ ia64_value_to_register (frame_info_ptr frame, int regnum, { struct gdbarch *gdbarch = get_frame_arch (frame); gdb_byte out[IA64_FP_REGISTER_SIZE]; - target_float_convert (in, valtype, out, ia64_ext_type (gdbarch)); - put_frame_register (frame, regnum, out); + type *to_type = ia64_ext_type (gdbarch); + target_float_convert (in, valtype, out, to_type); + auto out_view = gdb::make_array_view (out, to_type->length ()); + put_frame_register (frame, regnum, out_view); } diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c index 0b761d019f2a..2e8043af0e06 100644 --- a/gdb/m68k-tdep.c +++ b/gdb/m68k-tdep.c @@ -236,8 +236,8 @@ m68k_value_to_register (frame_info_ptr frame, int regnum, struct type *type, const gdb_byte *from) { gdb_byte to[M68K_MAX_REGISTER_SIZE]; - struct type *fpreg_type = register_type (get_frame_arch (frame), - M68K_FP0_REGNUM); + gdbarch *arch = get_frame_arch (frame); + struct type *fpreg_type = register_type (arch, M68K_FP0_REGNUM); /* We only support floating-point values. */ if (type->code () != TYPE_CODE_FLT) @@ -249,7 +249,8 @@ m68k_value_to_register (frame_info_ptr frame, int regnum, /* Convert from TYPE. */ target_float_convert (from, type, to, fpreg_type); - put_frame_register (frame, regnum, to); + auto to_view = gdb::make_array_view (to, fpreg_type->length ()); + put_frame_register (frame, regnum, to_view); } diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index c7157c19e7be..16edfdb0f1b8 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -990,8 +990,9 @@ mips_value_to_register (frame_info_ptr frame, int regnum, if (mips_convert_register_float_case_p (gdbarch, regnum, type)) { - put_frame_register (frame, regnum + 0, from + 4); - put_frame_register (frame, regnum + 1, from + 0); + auto from_view = gdb::make_array_view (from, 8); + put_frame_register (frame, regnum, from_view.slice (4)); + put_frame_register (frame, regnum + 1, from_view.slice (0, 4)); } else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type)) { diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 16f3da9c0117..cbbaf6d83a19 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -2741,9 +2741,10 @@ rs6000_value_to_register (frame_info_ptr frame, fpr to vsr. */ regnum = ieee_128_float_regnum_adjust (gdbarch, type, regnum); - target_float_convert (from, type, - to, builtin_type (gdbarch)->builtin_double); - put_frame_register (frame, regnum, to); + struct type *to_type = builtin_type (gdbarch)->builtin_double; + target_float_convert (from, type, to, to_type); + auto to_view = gdb::make_array_view (to, to_type->length ()); + put_frame_register (frame, regnum, to_view); } static struct value * From patchwork Fri Dec 1 16:27:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81143 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 6F73E3860002 for ; Fri, 1 Dec 2023 16:30:25 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 2BD84385B53E for ; Fri, 1 Dec 2023 16:29:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2BD84385B53E Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 2BD84385B53E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448200; cv=none; b=Ia/DW67jo92ifkcIFoMjpixAzvvWMLCuH1UQfgeQaV/KuAifZs/4EYzXpk7aAOj4JIGBC6JNZiz4hHIoiy59Z9q0yU5XHbnIeseolBFKrYACNIZyJ7S++JycLQwxtreIGuckVui7YgrG0eqrhij8DB1kcfx8cGB7BvJP89lBRQw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448200; c=relaxed/simple; bh=iaaVJJ08UHd1zVElD2L75RPGtKQipy7DhubyKnidLuM=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=YvIL4+pr3r4oejZjypyhfYP2TyjT6BGuYnaZvKeJp2ZPH8Yk+hynfc7l4xqoEVrcFbnMhdAak8yexqiVEqoSv9t8dG40MYFnuedAddWtWgW87QQioeO/dr6AQ8Ypaz6Hu+kXvYxplpRm5CsT0PaN5pO55Xeuk5aWw3rBdUbFFGU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 04CF01E091; Fri, 1 Dec 2023 11:29:56 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 08/24] gdb: change value_of_register and value_of_register_lazy to take the next frame Date: Fri, 1 Dec 2023 11:27:21 -0500 Message-ID: <20231201162751.741751-9-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Some functions related to the handling of registers in frames accept "this frame", for which we want to read or write the register values, while other functions accept "the next frame", which is the frame next to that. The later is needed because we sometimes need to read register values for a frame that does not exist yet (usually when trying to unwind that frame-to-be). value_of_register and value_of_register_lazy both take "this frame", even if what they ultimately want internally is "the next frame". This is annoying if you are in a spot that currently has "the next frame" and need to call one of these functions (which happens later in this series). You need to get the previous frame only for those functions to get the next frame again. This is more manipulations, more chances of mistake. I propose to change these functions (and a few more functions in the subsequent patches) to operate on "the next frame". Things become a bit less awkward when all these functions agree on which frame they take. So, in this patch, change value_of_register_lazy and value_of_register to take "the next frame" instead of "this frame". This adds a lot of get_next_frame_sentinel_okay, but if we convert the user registers API to also use "the next frame" instead of "this frame", it will get simple again. Change-Id: Iaa24815e648fbe5ae3c214c738758890a91819cd Reviewed-By: John Baldwin --- gdb/aarch64-tdep.c | 3 +-- gdb/arm-tdep.c | 4 ++-- gdb/eval.c | 3 ++- gdb/findvar.c | 34 ++++++++++++---------------------- gdb/frame-unwind.c | 3 ++- gdb/guile/scm-frame.c | 3 ++- gdb/infcmd.c | 6 +++--- gdb/loongarch-tdep.c | 3 ++- gdb/mi/mi-main.c | 3 ++- gdb/mips-tdep.c | 2 +- gdb/nds32-tdep.c | 5 +++-- gdb/python/py-frame.c | 3 ++- gdb/python/py-unwind.c | 4 ++-- gdb/riscv-tdep.c | 4 ++-- gdb/s12z-tdep.c | 2 +- gdb/std-regs.c | 11 +++++++---- gdb/value.h | 9 +++++++-- 17 files changed, 53 insertions(+), 49 deletions(-) diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 4a7ce68e85a9..b0aee191d71f 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -3449,9 +3449,8 @@ value_of_aarch64_user_reg (frame_info_ptr frame, const void *baton) { const int *reg_p = (const int *) baton; - return value_of_register (*reg_p, frame); + return value_of_register (*reg_p, get_next_frame_sentinel_okay (frame)); } - /* Implement the "software_single_step" gdbarch method, needed to single step through atomic sequences on AArch64. */ diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 83fce2abd508..1ee8bdf46159 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -9954,9 +9954,9 @@ static struct value * value_of_arm_user_reg (frame_info_ptr frame, const void *baton) { const int *reg_p = (const int *) baton; - return value_of_register (*reg_p, frame); + return value_of_register (*reg_p, get_next_frame_sentinel_okay (frame)); } - + static enum gdb_osabi arm_elf_osabi_sniffer (bfd *abfd) { diff --git a/gdb/eval.c b/gdb/eval.c index 8192aeba3640..e075cc3138d6 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -1134,7 +1134,8 @@ eval_op_register (struct type *expect_type, struct expression *exp, && regno < gdbarch_num_cooked_regs (exp->gdbarch)) val = value::zero (register_type (exp->gdbarch, regno), not_lval); else - val = value_of_register (regno, get_selected_frame (NULL)); + val = value_of_register + (regno, get_next_frame_sentinel_okay (get_selected_frame ())); if (val == NULL) error (_("Value of register %s not available."), name); else diff --git a/gdb/findvar.c b/gdb/findvar.c index c7a681f8a890..e5513d00dea4 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -243,42 +243,32 @@ copy_integer_to_size (gdb_byte *dest, int dest_size, const gdb_byte *source, } } -/* Return a `value' with the contents of (virtual or cooked) register - REGNUM as found in the specified FRAME. The register's type is - determined by register_type (). */ +/* See value.h. */ -struct value * -value_of_register (int regnum, frame_info_ptr frame) +value * +value_of_register (int regnum, frame_info_ptr next_frame) { - struct gdbarch *gdbarch = get_frame_arch (frame); - struct value *reg_val; + gdbarch *gdbarch = frame_unwind_arch (next_frame); /* User registers lie completely outside of the range of normal registers. Catch them early so that the target never sees them. */ if (regnum >= gdbarch_num_cooked_regs (gdbarch)) - return value_of_user_reg (regnum, frame); + return value_of_user_reg (regnum, get_prev_frame_always (next_frame)); - reg_val = value_of_register_lazy (frame, regnum); + value *reg_val = value_of_register_lazy (next_frame, regnum); reg_val->fetch_lazy (); return reg_val; } -/* Return a `value' with the contents of (virtual or cooked) register - REGNUM as found in the specified FRAME. The register's type is - determined by register_type (). The value is not fetched. */ +/* See value.h. */ -struct value * -value_of_register_lazy (frame_info_ptr frame, int regnum) +value * +value_of_register_lazy (frame_info_ptr next_frame, int regnum) { - struct gdbarch *gdbarch = get_frame_arch (frame); - struct value *reg_val; - frame_info_ptr next_frame; + gdbarch *gdbarch = frame_unwind_arch (next_frame); gdb_assert (regnum < gdbarch_num_cooked_regs (gdbarch)); - - gdb_assert (frame != NULL); - - next_frame = get_next_frame_sentinel_okay (frame); + gdb_assert (next_frame != nullptr); /* In some cases NEXT_FRAME may not have a valid frame-id yet. This can happen if we end up trying to unwind a register as part of the frame @@ -291,7 +281,7 @@ value_of_register_lazy (frame_info_ptr frame, int regnum) /* We should have a valid next frame. */ gdb_assert (frame_id_p (get_frame_id (next_frame))); - reg_val = value::allocate_lazy (register_type (gdbarch, regnum)); + value *reg_val = value::allocate_lazy (register_type (gdbarch, regnum)); reg_val->set_lval (lval_register); VALUE_REGNUM (reg_val) = regnum; VALUE_NEXT_FRAME_ID (reg_val) = get_frame_id (next_frame); diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c index 927b6256b0b3..89ae3d70b200 100644 --- a/gdb/frame-unwind.c +++ b/gdb/frame-unwind.c @@ -278,7 +278,8 @@ struct value * frame_unwind_got_register (frame_info_ptr frame, int regnum, int new_regnum) { - return value_of_register_lazy (frame, new_regnum); + return value_of_register_lazy (get_next_frame_sentinel_okay (frame), + new_regnum); } /* Return a value which indicates that FRAME saved REGNUM in memory at diff --git a/gdb/guile/scm-frame.c b/gdb/guile/scm-frame.c index 45863c587c1d..830acb8b53ed 100644 --- a/gdb/guile/scm-frame.c +++ b/gdb/guile/scm-frame.c @@ -835,7 +835,8 @@ gdbscm_frame_read_register (SCM self, SCM register_scm) register_str, strlen (register_str)); if (regnum >= 0) - value = value_of_register (regnum, frame); + value = value_of_register (regnum, + get_next_frame_sentinel_okay (frame)); } } catch (const gdb_exception &ex) diff --git a/gdb/infcmd.c b/gdb/infcmd.c index ec818bc6936f..20e5fde55ee1 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -2319,9 +2319,9 @@ default_print_registers_info (struct gdbarch *gdbarch, if (*(gdbarch_register_name (gdbarch, i)) == '\0') continue; - default_print_one_register_info (file, - gdbarch_register_name (gdbarch, i), - value_of_register (i, frame)); + default_print_one_register_info + (file, gdbarch_register_name (gdbarch, i), + value_of_register (i, get_next_frame_sentinel_okay (frame))); } } diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c index f7d08c60a582..12865b99e13f 100644 --- a/gdb/loongarch-tdep.c +++ b/gdb/loongarch-tdep.c @@ -392,7 +392,8 @@ loongarch_software_single_step (struct regcache *regcache) static struct value * value_of_loongarch_user_reg (frame_info_ptr frame, const void *baton) { - return value_of_register ((long long) baton, frame); + return value_of_register ((long long) baton, + get_next_frame_sentinel_okay (frame)); } /* Implement the frame_align gdbarch method. */ diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 487b0a920254..21f2c72cfb90 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -1101,7 +1101,8 @@ output_register (frame_info_ptr frame, int regnum, int format, int skip_unavailable) { struct ui_out *uiout = current_uiout; - struct value *val = value_of_register (regnum, frame); + value *val + = value_of_register (regnum, get_next_frame_sentinel_okay (frame)); struct value_print_options opts; if (skip_unavailable && !val->entirely_available ()) diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 16edfdb0f1b8..adaa091bda14 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -8074,7 +8074,7 @@ static struct value * value_of_mips_user_reg (frame_info_ptr frame, const void *baton) { const int *reg_p = (const int *) baton; - return value_of_register (*reg_p, frame); + return value_of_register (*reg_p, get_next_frame_sentinel_okay (frame)); } static struct gdbarch * diff --git a/gdb/nds32-tdep.c b/gdb/nds32-tdep.c index a81b5fd1fae1..7618a81fc256 100644 --- a/gdb/nds32-tdep.c +++ b/gdb/nds32-tdep.c @@ -267,9 +267,10 @@ static const struct static struct value * value_of_nds32_reg (frame_info_ptr frame, const void *baton) { - return value_of_register ((int) (intptr_t) baton, frame); + return value_of_register ((int) (intptr_t) baton, + get_next_frame_sentinel_okay (frame)); } - + /* Implement the "frame_align" gdbarch method. */ static CORE_ADDR diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c index 0a7e10f09ff2..f38bf5d8237f 100644 --- a/gdb/python/py-frame.c +++ b/gdb/python/py-frame.c @@ -260,7 +260,8 @@ frapy_read_register (PyObject *self, PyObject *args, PyObject *kw) return nullptr; gdb_assert (regnum >= 0); - struct value *val = value_of_register (regnum, frame); + value *val + = value_of_register (regnum, get_next_frame_sentinel_okay (frame)); if (val == NULL) PyErr_SetString (PyExc_ValueError, _("Can't read register.")); diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c index ee50c51b531d..f1162f22290f 100644 --- a/gdb/python/py-unwind.c +++ b/gdb/python/py-unwind.c @@ -467,8 +467,8 @@ pending_framepy_read_register (PyObject *self, PyObject *args, PyObject *kw) which maps to a real register. In the past, get_frame_register_value() was used here, which did not handle the user register case. */ - struct value *val = value_of_register (regnum, - pending_frame->frame_info); + value *val = value_of_register + (regnum, get_next_frame_sentinel_okay (pending_frame->frame_info)); if (val == NULL) PyErr_Format (PyExc_ValueError, "Cannot read register %d from frame.", diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index 2b4b9e2a02ac..8110a8deedbf 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -168,7 +168,7 @@ static struct value * value_of_riscv_user_reg (frame_info_ptr frame, const void *baton) { const int *reg_p = (const int *) baton; - return value_of_register (*reg_p, frame); + return value_of_register (*reg_p, get_next_frame_sentinel_okay (frame)); } /* Information about a register alias that needs to be set up for this @@ -1149,7 +1149,7 @@ riscv_print_one_register_info (struct gdbarch *gdbarch, try { - val = value_of_register (regnum, frame); + val = value_of_register (regnum, get_next_frame_sentinel_okay (frame)); regtype = val->type (); } catch (const gdb_exception_error &ex) diff --git a/gdb/s12z-tdep.c b/gdb/s12z-tdep.c index 4781eab083eb..42fd1fb1d6ca 100644 --- a/gdb/s12z-tdep.c +++ b/gdb/s12z-tdep.c @@ -494,7 +494,7 @@ s12z_print_ccw_info (struct gdbarch *gdbarch, frame_info_ptr frame, int reg) { - struct value *v = value_of_register (reg, frame); + value *v = value_of_register (reg, get_next_frame_sentinel_okay (frame)); const char *name = gdbarch_register_name (gdbarch, reg); uint32_t ccw = value_as_long (v); gdb_puts (name, file); diff --git a/gdb/std-regs.c b/gdb/std-regs.c index 54cf9018e426..221b15f1de9f 100644 --- a/gdb/std-regs.c +++ b/gdb/std-regs.c @@ -39,7 +39,7 @@ value_of_builtin_frame_fp_reg (frame_info_ptr frame, const void *baton) register can do so by adding "fp" to register name table (mind you, doing this is probably a dangerous thing). */ return value_of_register (gdbarch_deprecated_fp_regnum (gdbarch), - frame); + get_next_frame_sentinel_okay (frame)); else { struct type *data_ptr_type = builtin_type (gdbarch)->builtin_data_ptr; @@ -58,7 +58,8 @@ value_of_builtin_frame_pc_reg (frame_info_ptr frame, const void *baton) struct gdbarch *gdbarch = get_frame_arch (frame); if (gdbarch_pc_regnum (gdbarch) >= 0) - return value_of_register (gdbarch_pc_regnum (gdbarch), frame); + return value_of_register (gdbarch_pc_regnum (gdbarch), + get_next_frame_sentinel_okay (frame)); else { struct type *func_ptr_type = builtin_type (gdbarch)->builtin_func_ptr; @@ -77,7 +78,8 @@ value_of_builtin_frame_sp_reg (frame_info_ptr frame, const void *baton) struct gdbarch *gdbarch = get_frame_arch (frame); if (gdbarch_sp_regnum (gdbarch) >= 0) - return value_of_register (gdbarch_sp_regnum (gdbarch), frame); + return value_of_register (gdbarch_sp_regnum (gdbarch), + get_next_frame_sentinel_okay (frame)); error (_("Standard register ``$sp'' is not available for this target")); } @@ -87,7 +89,8 @@ value_of_builtin_frame_ps_reg (frame_info_ptr frame, const void *baton) struct gdbarch *gdbarch = get_frame_arch (frame); if (gdbarch_ps_regnum (gdbarch) >= 0) - return value_of_register (gdbarch_ps_regnum (gdbarch), frame); + return value_of_register (gdbarch_ps_regnum (gdbarch), + get_next_frame_sentinel_okay (frame)); error (_("Standard register ``$ps'' is not available for this target")); } diff --git a/gdb/value.h b/gdb/value.h index 6d91e8eee7a9..3f9b35b589bd 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -1123,9 +1123,14 @@ extern struct value *value_of_variable (struct symbol *var, extern struct value *address_of_variable (struct symbol *var, const struct block *b); -extern struct value *value_of_register (int regnum, frame_info_ptr frame); +/* Return a value with the contents of register REGNUM as found in the frame + previous to NEXT_FRAME. */ -struct value *value_of_register_lazy (frame_info_ptr frame, int regnum); +extern value *value_of_register (int regnum, frame_info_ptr next_frame); + +/* Same as the above, but the value is not fetched. */ + +extern value *value_of_register_lazy (frame_info_ptr next_frame, int regnum); /* Return the symbol's reading requirement. */ From patchwork Fri Dec 1 16:27:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81146 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 C2734385B534 for ; Fri, 1 Dec 2023 16:31:39 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 4C0FB385C407 for ; Fri, 1 Dec 2023 16:29:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4C0FB385C407 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 4C0FB385C407 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448198; cv=none; b=eKvRp7Cb/H+Yoiy73yZnrRn8BqDVy4a717O3CAt0OjOkf3cdyIDIusn9C7Dtu22a1EvdrrfRrhxPIkit6VJj/csGRCeNJztgcFLkyw8+UNebbhX7sv5loLJioc/YInCn5m80wiuH5OEtG5UpuHpslcGjZoB07Pl8ZYDqkNRiLR8= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448198; c=relaxed/simple; bh=Xg3GmfGeKhMmERKD5sLTZ+GHG4VKGc2zbMAVMWvCbFI=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=VUJj1CrTZGre78btMNspPIXaMjF23uHWurEQAGaJK4vDtqJ7XAjGzwgSJDWlBq5r1qCU46Z3NDtx8e/pZuEjzYVR2X0BFGfoK9gkuUEDygqmCbeMKPfzXpx17rdmYOucNH3KtqwPFrzAoVp4kcvW55dYQW69mcl5ZlGQrzsgF/0= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 7E2EB1E0BB; Fri, 1 Dec 2023 11:29:56 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 09/24] gdb: remove frame_register Date: Fri, 1 Dec 2023 11:27:22 -0500 Message-ID: <20231201162751.741751-10-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org I was going to change frame_register to take the "next frame", but I realized that doing so would make it a useless wrapper around frame_register_unwind. So, just remove frame_register and replace uses with frame_register_unwind. Change-Id: I185868bc69f8e098124775d0550d069220a4678a Reviewed-By: John Baldwin --- gdb/frame.c | 39 ++++++++------------------------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/gdb/frame.c b/gdb/frame.c index 9312d1b40168..61d6822ecc1a 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1214,31 +1214,6 @@ frame_register_unwind (frame_info_ptr next_frame, int regnum, release_value (value); } -/* Get the value of the register that belongs to this FRAME. This - function is a wrapper to the call sequence ``frame_register_unwind - (get_next_frame (FRAME))''. As per frame_register_unwind(), if - VALUEP is NULL, the registers value is not fetched/computed. */ - -static void -frame_register (frame_info_ptr frame, int regnum, - int *optimizedp, int *unavailablep, enum lval_type *lvalp, - CORE_ADDR *addrp, int *realnump, gdb_byte *bufferp) -{ - /* Require all but BUFFERP to be valid. A NULL BUFFERP indicates - that the value proper does not need to be fetched. */ - gdb_assert (optimizedp != NULL); - gdb_assert (lvalp != NULL); - gdb_assert (addrp != NULL); - gdb_assert (realnump != NULL); - /* gdb_assert (bufferp != NULL); */ - - /* Obtain the register value by unwinding the register from the next - (more inner frame). */ - gdb_assert (frame != NULL && frame->next != NULL); - frame_register_unwind (frame_info_ptr (frame->next), regnum, optimizedp, - unavailablep, lvalp, addrp, realnump, bufferp); -} - void frame_unwind_register (frame_info_ptr next_frame, int regnum, gdb_byte *buf) { @@ -1436,8 +1411,8 @@ put_frame_register (frame_info_ptr frame, int regnum, gdb_assert (buf.size () == size); - frame_register (frame, regnum, &optim, &unavail, - &lval, &addr, &realnum, NULL); + frame_register_unwind (get_next_frame_sentinel_okay (frame), regnum, &optim, + &unavail, &lval, &addr, &realnum, nullptr); if (optim) error (_("Attempt to assign to a register that was not saved.")); switch (lval) @@ -1473,8 +1448,9 @@ deprecated_frame_register_read (frame_info_ptr frame, int regnum, CORE_ADDR addr; int realnum; - frame_register (frame, regnum, &optimized, &unavailable, - &lval, &addr, &realnum, myaddr); + frame_register_unwind (get_next_frame_sentinel_okay (frame), regnum, + &optimized, &unavailable, &lval, &addr, &realnum, + myaddr); return !optimized && !unavailable; } @@ -1523,8 +1499,9 @@ get_frame_register_bytes (frame_info_ptr frame, int regnum, CORE_ADDR addr; int realnum; - frame_register (frame, regnum, optimizedp, unavailablep, &lval, - &addr, &realnum, buffer.data ()); + frame_register_unwind (get_next_frame_sentinel_okay (frame), regnum, + optimizedp, unavailablep, &lval, &addr, + &realnum, buffer.data ()); if (*optimizedp || *unavailablep) return false; } From patchwork Fri Dec 1 16:27:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81141 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 304F9386180D for ; Fri, 1 Dec 2023 16:30:15 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 31D8C385C322 for ; Fri, 1 Dec 2023 16:29:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 31D8C385C322 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 31D8C385C322 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448199; cv=none; b=XyQ0AEkoldwsZymA4UtPgqTfkksb3rotKM8cptlehZsi5CnW3GhESDtXm/krTPPzMJb6wh0PZTbE6O6bJCnY/TScUEWxWDhGnRyZL86vKmZpp67Z6lehUGNJOcjJCRVysC1MLGIckmz6HliuotQmPfPrWlbscnMutkavl6qAlpg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448199; c=relaxed/simple; bh=OEPc0yq5K2X/UI8XnXHLc9h6DFiFcBWvP8izOCUQDLU=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=p2L/mOStqA5oNY5Guuy+AsSCA9StVn3gOKpWUJjBsRJcnF/355qgq4SUTcISlgsl64hrupAFHjDN5e21zViKV2D72hJKhpiEn3Fc5LybJQosGCh7RJ5nA+gOqW/4HkhvxDNjtDZ97pOUaWWKM9uDlHUCjVbfiNC3hls0pIVHB5M= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id B70201E0C0; Fri, 1 Dec 2023 11:29:56 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 10/24] gdb: make put_frame_register take the next frame Date: Fri, 1 Dec 2023 11:27:23 -0500 Message-ID: <20231201162751.741751-11-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Similar to the previous patches, change put_frame_register to take the "next frame" instead of "this frame". Change-Id: I062fd4663b8f54f0fc7bbf39c860b7341363821b Reviewed-By: John Baldwin --- gdb/alpha-tdep.c | 3 ++- gdb/frame.c | 16 +++++++++------- gdb/frame.h | 8 ++++---- gdb/i386-tdep.c | 3 ++- gdb/i387-tdep.c | 2 +- gdb/ia64-tdep.c | 2 +- gdb/m68k-tdep.c | 2 +- gdb/mips-tdep.c | 5 +++-- gdb/rs6000-tdep.c | 2 +- 9 files changed, 24 insertions(+), 19 deletions(-) diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c index eaf2a7e97949..799441758103 100644 --- a/gdb/alpha-tdep.c +++ b/gdb/alpha-tdep.c @@ -269,8 +269,9 @@ alpha_value_to_register (frame_info_ptr frame, int regnum, gdb_byte out[ALPHA_REGISTER_SIZE]; alpha_lds (get_frame_arch (frame), out, in); + auto out_view = gdb::make_array_view (out, reg_size); - put_frame_register (frame, regnum, out_view); + put_frame_register (get_next_frame_sentinel_okay (frame), regnum, out_view); } diff --git a/gdb/frame.c b/gdb/frame.c index 61d6822ecc1a..44c4906e9cc1 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1398,10 +1398,10 @@ read_frame_register_unsigned (frame_info_ptr frame, int regnum, } void -put_frame_register (frame_info_ptr frame, int regnum, - gdb::array_view buf) +put_frame_register (frame_info_ptr next_frame, int regnum, + gdb::array_view buf) { - struct gdbarch *gdbarch = get_frame_arch (frame); + gdbarch *gdbarch = frame_unwind_arch (next_frame); int realnum; int optim; int unavail; @@ -1411,8 +1411,8 @@ put_frame_register (frame_info_ptr frame, int regnum, gdb_assert (buf.size () == size); - frame_register_unwind (get_next_frame_sentinel_okay (frame), regnum, &optim, - &unavail, &lval, &addr, &realnum, nullptr); + frame_register_unwind (next_frame, regnum, &optim, &unavail, &lval, &addr, + &realnum, nullptr); if (optim) error (_("Attempt to assign to a register that was not saved.")); switch (lval) @@ -1557,7 +1557,8 @@ put_frame_register_bytes (frame_info_ptr frame, int regnum, buffer.size ()); if (curr_len == register_size (gdbarch, regnum)) - put_frame_register (frame, regnum, buffer.slice (0, curr_len)); + put_frame_register (get_next_frame_sentinel_okay (frame), regnum, + buffer.slice (0, curr_len)); else { value *value @@ -1567,7 +1568,8 @@ put_frame_register_bytes (frame_info_ptr frame, int regnum, copy (buffer.slice (0, curr_len), value->contents_writeable ().slice (offset, curr_len)); - put_frame_register (frame, regnum, value->contents_raw ()); + put_frame_register (get_next_frame_sentinel_okay (frame), regnum, + value->contents_raw ()); release_value (value); } diff --git a/gdb/frame.h b/gdb/frame.h index 4117e169379a..1d870d619ca5 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -727,10 +727,10 @@ extern ULONGEST get_frame_register_unsigned (frame_info_ptr frame, extern bool read_frame_register_unsigned (frame_info_ptr frame, int regnum, ULONGEST *val); -/* The reverse. Store a register value relative to the specified - frame. Note: this call makes the frame's state undefined. The - register and frame caches must be flushed. */ -extern void put_frame_register (frame_info_ptr frame, int regnum, +/* The reverse. Store a register value relative to NEXT_FRAME's previous frame. + Note: this call makes the frame's state undefined. The register and frame + caches must be flushed. */ +extern void put_frame_register (frame_info_ptr next_frame, int regnum, gdb::array_view buf); /* Read LEN bytes from one or multiple registers starting with REGNUM diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 3afa902767e5..f188f83de6f3 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -3918,7 +3918,8 @@ i386_value_to_register (frame_info_ptr frame, int regnum, gdb_assert (register_size (get_frame_arch (frame), regnum) == 4); auto from_view = gdb::make_array_view (from, 4); - put_frame_register (frame, regnum, from_view); + put_frame_register (get_next_frame_sentinel_okay (frame), regnum, + from_view); regnum = i386_next_regnum (regnum); len -= 4; from += 4; diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c index b39ca2adef55..77dc5a008d5f 100644 --- a/gdb/i387-tdep.c +++ b/gdb/i387-tdep.c @@ -400,7 +400,7 @@ i387_value_to_register (frame_info_ptr frame, int regnum, struct type *to_type = i387_ext_type (gdbarch); target_float_convert (from, type, to, to_type); auto to_view = gdb::make_array_view (to, to_type->length ()); - put_frame_register (frame, regnum, to_view); + put_frame_register (get_next_frame_sentinel_okay (frame), regnum, to_view); } diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c index f778c092537b..3bede2644c03 100644 --- a/gdb/ia64-tdep.c +++ b/gdb/ia64-tdep.c @@ -1248,7 +1248,7 @@ ia64_value_to_register (frame_info_ptr frame, int regnum, type *to_type = ia64_ext_type (gdbarch); target_float_convert (in, valtype, out, to_type); auto out_view = gdb::make_array_view (out, to_type->length ()); - put_frame_register (frame, regnum, out_view); + put_frame_register (get_next_frame_sentinel_okay (frame), regnum, out_view); } diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c index 2e8043af0e06..8bbfa4bd0b10 100644 --- a/gdb/m68k-tdep.c +++ b/gdb/m68k-tdep.c @@ -250,7 +250,7 @@ m68k_value_to_register (frame_info_ptr frame, int regnum, /* Convert from TYPE. */ target_float_convert (from, type, to, fpreg_type); auto to_view = gdb::make_array_view (to, fpreg_type->length ()); - put_frame_register (frame, regnum, to_view); + put_frame_register (get_next_frame_sentinel_okay (frame), regnum, to_view); } diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index adaa091bda14..dbdf8a668b8f 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -991,8 +991,9 @@ mips_value_to_register (frame_info_ptr frame, int regnum, if (mips_convert_register_float_case_p (gdbarch, regnum, type)) { auto from_view = gdb::make_array_view (from, 8); - put_frame_register (frame, regnum, from_view.slice (4)); - put_frame_register (frame, regnum + 1, from_view.slice (0, 4)); + frame_info_ptr next_frame = get_next_frame_sentinel_okay (frame); + put_frame_register (next_frame, regnum, from_view.slice (4)); + put_frame_register (next_frame, regnum + 1, from_view.slice (0, 4)); } else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type)) { diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index cbbaf6d83a19..c43039302bc3 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -2744,7 +2744,7 @@ rs6000_value_to_register (frame_info_ptr frame, struct type *to_type = builtin_type (gdbarch)->builtin_double; target_float_convert (from, type, to, to_type); auto to_view = gdb::make_array_view (to, to_type->length ()); - put_frame_register (frame, regnum, to_view); + put_frame_register (get_next_frame_sentinel_okay (frame), regnum, to_view); } static struct value * From patchwork Fri Dec 1 16:27:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81142 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 0AD00386185E for ; Fri, 1 Dec 2023 16:30:20 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 752A0385C416 for ; Fri, 1 Dec 2023 16:29:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 752A0385C416 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 752A0385C416 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448199; cv=none; b=EGwC8up5kwIjHq1Gy7nq70aeiu3E2cq7BmEwH5EyqVwQd+RejY5heBS6yEwAXCoB/E7Sd/ULmUiAqhdvDMgD74gllGNNUiZAngY8pserKxXkS1tAws6gORTo8IplSFfworWY8Imp8TVPm2SagHKkzDk7B7shZzMLkkIkLBO5zMU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448199; c=relaxed/simple; bh=+7td15jb4Akq9DFlKzXnSVVSd8jpbBYPMmsnP5aKFfA=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=PFS027gO9ZiGDwJYtLdVnYQG80XxS54gxpdTd//eVwIrzqic9UNi5EvXn1Wl3LVmi5UCycDk1cj5oYFwTYhOfAOzDmte9LtwffA9mqIt3qLBazbsyDwJb+3H+a0HrVDoHySIJUg7dNc66QD+YcWQN8CUkzLonL2Vbbp9rj3ZviA= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id E1C2A1E11B; Fri, 1 Dec 2023 11:29:56 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 11/24] gdb: make put_frame_register_bytes take the next frame Date: Fri, 1 Dec 2023 11:27:24 -0500 Message-ID: <20231201162751.741751-12-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Similar to the previous patches, change put_frame_register_bytes to take the "next frame" instead of "this frame". Change-Id: I27bcb26573686d99b231230823cff8db6405a788 Reviewed-By: John Baldwin --- gdb/dwarf2/expr.c | 6 +++--- gdb/frame.c | 14 +++++--------- gdb/frame.h | 4 ++-- gdb/mips-tdep.c | 11 ++++++----- gdb/valops.c | 32 +++++++++++++++----------------- 5 files changed, 31 insertions(+), 36 deletions(-) diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c index b21016eb38bb..7fc7b3abf5ca 100644 --- a/gdb/dwarf2/expr.c +++ b/gdb/dwarf2/expr.c @@ -272,9 +272,9 @@ rw_pieced_value (value *v, value *from, bool check_optimized) copy_bitwise (buffer.data (), bits_to_skip % 8, from_contents, offset, this_size_bits, bits_big_endian); - put_frame_register_bytes (frame, gdb_regnum, - bits_to_skip / 8, - buffer); + put_frame_register_bytes + (get_next_frame_sentinel_okay (frame), gdb_regnum, + bits_to_skip / 8, buffer); } } break; diff --git a/gdb/frame.c b/gdb/frame.c index 44c4906e9cc1..982aaa6d6753 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1537,11 +1537,11 @@ get_frame_register_bytes (frame_info_ptr frame, int regnum, } void -put_frame_register_bytes (frame_info_ptr frame, int regnum, +put_frame_register_bytes (frame_info_ptr next_frame, int regnum, CORE_ADDR offset, gdb::array_view buffer) { - struct gdbarch *gdbarch = get_frame_arch (frame); + gdbarch *gdbarch = frame_unwind_arch (next_frame); /* Skip registers wholly inside of OFFSET. */ while (offset >= register_size (gdbarch, regnum)) @@ -1557,19 +1557,15 @@ put_frame_register_bytes (frame_info_ptr frame, int regnum, buffer.size ()); if (curr_len == register_size (gdbarch, regnum)) - put_frame_register (get_next_frame_sentinel_okay (frame), regnum, - buffer.slice (0, curr_len)); + put_frame_register (next_frame, regnum, buffer.slice (0, curr_len)); else { - value *value - = frame_unwind_register_value (frame_info_ptr (frame->next), - regnum); + value *value = frame_unwind_register_value (next_frame, regnum); gdb_assert (value != nullptr); copy (buffer.slice (0, curr_len), value->contents_writeable ().slice (offset, curr_len)); - put_frame_register (get_next_frame_sentinel_okay (frame), regnum, - value->contents_raw ()); + put_frame_register (next_frame, regnum, value->contents_raw ()); release_value (value); } diff --git a/gdb/frame.h b/gdb/frame.h index 1d870d619ca5..5ce3a1b285aa 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -743,8 +743,8 @@ extern bool get_frame_register_bytes (frame_info_ptr frame, int regnum, int *optimizedp, int *unavailablep); /* Write bytes from BUFFER to one or multiple registers starting with REGNUM - in frame FRAME, starting at OFFSET. */ -extern void put_frame_register_bytes (frame_info_ptr frame, int regnum, + in NEXT_FRAME's previous frame, starting at OFFSET. */ +extern void put_frame_register_bytes (frame_info_ptr next_frame, int regnum, CORE_ADDR offset, gdb::array_view buffer); diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index dbdf8a668b8f..9c0cfede492a 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -999,7 +999,8 @@ mips_value_to_register (frame_info_ptr frame, int regnum, { gdb_byte fill[8]; size_t len = type->length (); - + frame_info_ptr next_frame = get_next_frame_sentinel_okay (frame); + /* Sign extend values, irrespective of type, that are stored to a 64-bit general purpose register. (32-bit unsigned values are stored as signed quantities within a 64-bit register. @@ -1012,8 +1013,8 @@ mips_value_to_register (frame_info_ptr frame, int regnum, store_signed_integer (fill, 8, BFD_ENDIAN_BIG, -1); else store_signed_integer (fill, 8, BFD_ENDIAN_BIG, 0); - put_frame_register_bytes (frame, regnum, 0, {fill, 8 - len}); - put_frame_register_bytes (frame, regnum, 8 - len, {from, len}); + put_frame_register_bytes (next_frame, regnum, 0, {fill, 8 - len}); + put_frame_register_bytes (next_frame, regnum, 8 - len, {from, len}); } else { @@ -1021,8 +1022,8 @@ mips_value_to_register (frame_info_ptr frame, int regnum, store_signed_integer (fill, 8, BFD_ENDIAN_LITTLE, -1); else store_signed_integer (fill, 8, BFD_ENDIAN_LITTLE, 0); - put_frame_register_bytes (frame, regnum, 0, {from, len}); - put_frame_register_bytes (frame, regnum, len, {fill, 8 - len}); + put_frame_register_bytes (next_frame, regnum, 0, {from, len}); + put_frame_register_bytes (next_frame, regnum, len, {fill, 8 - len}); } } else diff --git a/gdb/valops.c b/gdb/valops.c index 6521580a1e83..8e1849837cf1 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -1191,10 +1191,6 @@ value_assign (struct value *toval, struct value *fromval) case lval_register: { - frame_info_ptr frame; - struct gdbarch *gdbarch; - int value_reg; - /* Figure out which frame this register value is in. The value holds the frame_id for the next frame, that is the frame this register value was unwound from. @@ -1202,15 +1198,14 @@ value_assign (struct value *toval, struct value *fromval) Below we will call put_frame_register_bytes which requires that we pass it the actual frame in which the register value is valid, i.e. not the next frame. */ - frame = frame_find_by_id (VALUE_NEXT_FRAME_ID (toval)); - frame = get_prev_frame_always (frame); + frame_info_ptr next_frame = frame_find_by_id (VALUE_NEXT_FRAME_ID (toval)); - value_reg = VALUE_REGNUM (toval); + int value_reg = VALUE_REGNUM (toval); - if (!frame) + if (next_frame == nullptr) error (_("Value being assigned to is no longer active.")); - gdbarch = get_frame_arch (frame); + gdbarch *gdbarch = frame_unwind_arch (next_frame); if (toval->bitsize ()) { @@ -1230,9 +1225,10 @@ value_assign (struct value *toval, struct value *fromval) "don't fit in a %d bit word."), (int) sizeof (LONGEST) * HOST_CHAR_BIT); - if (!get_frame_register_bytes (frame, value_reg, offset, - {buffer, changed_len}, - &optim, &unavail)) + if (!get_frame_register_bytes (get_prev_frame_always (next_frame), + value_reg, offset, + { buffer, changed_len }, &optim, + &unavail)) { if (optim) throw_error (OPTIMIZED_OUT_ERROR, @@ -1245,8 +1241,8 @@ value_assign (struct value *toval, struct value *fromval) modify_field (type, buffer, value_as_long (fromval), toval->bitpos (), toval->bitsize ()); - put_frame_register_bytes (frame, value_reg, offset, - {buffer, changed_len}); + put_frame_register_bytes (next_frame, value_reg, offset, + { buffer, changed_len }); } else { @@ -1256,17 +1252,19 @@ value_assign (struct value *toval, struct value *fromval) /* If TOVAL is a special machine register requiring conversion of program values to a special raw format. */ - gdbarch_value_to_register (gdbarch, frame, + gdbarch_value_to_register (gdbarch, + get_prev_frame_always (next_frame), VALUE_REGNUM (toval), type, fromval->contents ().data ()); } else - put_frame_register_bytes (frame, value_reg, + put_frame_register_bytes (next_frame, value_reg, toval->offset (), fromval->contents ()); } - gdb::observers::register_changed.notify (frame, value_reg); + gdb::observers::register_changed.notify + (get_prev_frame_always (next_frame), value_reg); break; } From patchwork Fri Dec 1 16:27:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81147 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 6DCD8386180D for ; Fri, 1 Dec 2023 16:31:54 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id E4A27385C6DE for ; Fri, 1 Dec 2023 16:29:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E4A27385C6DE Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E4A27385C6DE Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448200; cv=none; b=nASmeXpPfvFm5A5GMGCgbjqVLGnW/uw3/zoNttnO5xnqpWaYTeRgm6OdBXk/Ti6wzzsYL7p6Km2nfw7n1PX+tGiczYQoJcYVpqshiAu//cFhuFOphOFH2eYUYM3x3B3kuxg2eBygTuGVhd1hYGIpzgGEX0FWwhZVmQfgGJz5ckQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448200; c=relaxed/simple; bh=v3Hy35HSXC9RZUfatLFJmMpuvB8l7zneABMgAFOlGbI=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=Rj9c2167kAX8sBOVas9lYHJO6R915L6vKWXhtFUBKGSDH5ew3WiKm70s1ZbKBoKnMMbawYXSAMzgxKbdkqBy6/90lZFIUny7GWUgOw6X1QoLiFtjOMtgn/v2SCivIQ58ROI7Zmep7Fo7zlhXUV1EDC4n54yJdkOHroBy7d2BPoA= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 1EF681E11E; Fri, 1 Dec 2023 11:29:57 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 12/24] gdb: make get_frame_register_bytes take the next frame Date: Fri, 1 Dec 2023 11:27:25 -0500 Message-ID: <20231201162751.741751-13-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Similar to the previous patches, change get_frame_register_bytes to take the "next frame" instead of "this frame". Change-Id: Ie8f35042bfa6e93565fcefaee71b6b3903f0fe9f Reviewed-By: John Baldwin --- gdb/dwarf2/expr.c | 22 +++++++++++----------- gdb/frame.c | 16 ++++++---------- gdb/frame.h | 10 +++++----- gdb/i386-tdep.c | 8 ++++---- gdb/i387-tdep.c | 10 +++++----- gdb/ia64-tdep.c | 9 ++++----- gdb/m68k-tdep.c | 10 +++++----- gdb/mips-tdep.c | 7 ++++--- gdb/rs6000-tdep.c | 10 +++++----- gdb/valops.c | 3 +-- 10 files changed, 50 insertions(+), 55 deletions(-) diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c index 7fc7b3abf5ca..c71bbb594131 100644 --- a/gdb/dwarf2/expr.c +++ b/gdb/dwarf2/expr.c @@ -204,8 +204,9 @@ rw_pieced_value (value *v, value *from, bool check_optimized) { case DWARF_VALUE_REGISTER: { - frame_info_ptr frame = frame_find_by_id (c->frame_id); - gdbarch *arch = get_frame_arch (frame); + frame_info_ptr next_frame + = get_next_frame_sentinel_okay (frame_find_by_id (c->frame_id)); + gdbarch *arch = frame_unwind_arch (next_frame); int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, p->v.regno); ULONGEST reg_bits = 8 * register_size (arch, gdb_regnum); int optim, unavail; @@ -225,9 +226,9 @@ rw_pieced_value (value *v, value *from, bool check_optimized) if (from == nullptr) { /* Read mode. */ - if (!get_frame_register_bytes (frame, gdb_regnum, - bits_to_skip / 8, - buffer, &optim, &unavail)) + if (!get_frame_register_bytes (next_frame, gdb_regnum, + bits_to_skip / 8, buffer, + &optim, &unavail)) { if (optim) { @@ -254,9 +255,9 @@ rw_pieced_value (value *v, value *from, bool check_optimized) { /* Data is copied non-byte-aligned into the register. Need some bits from original register value. */ - get_frame_register_bytes (frame, gdb_regnum, - bits_to_skip / 8, - buffer, &optim, &unavail); + get_frame_register_bytes (next_frame, gdb_regnum, + bits_to_skip / 8, buffer, &optim, + &unavail); if (optim) throw_error (OPTIMIZED_OUT_ERROR, _("Can't do read-modify-write to " @@ -272,9 +273,8 @@ rw_pieced_value (value *v, value *from, bool check_optimized) copy_bitwise (buffer.data (), bits_to_skip % 8, from_contents, offset, this_size_bits, bits_big_endian); - put_frame_register_bytes - (get_next_frame_sentinel_okay (frame), gdb_regnum, - bits_to_skip / 8, buffer); + put_frame_register_bytes (next_frame, gdb_regnum, + bits_to_skip / 8, buffer); } } break; diff --git a/gdb/frame.c b/gdb/frame.c index 982aaa6d6753..d260e8c28f3f 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1456,12 +1456,11 @@ deprecated_frame_register_read (frame_info_ptr frame, int regnum, } bool -get_frame_register_bytes (frame_info_ptr frame, int regnum, - CORE_ADDR offset, - gdb::array_view buffer, +get_frame_register_bytes (frame_info_ptr next_frame, int regnum, + CORE_ADDR offset, gdb::array_view buffer, int *optimizedp, int *unavailablep) { - struct gdbarch *gdbarch = get_frame_arch (frame); + gdbarch *gdbarch = frame_unwind_arch (next_frame); /* Skip registers wholly inside of OFFSET. */ while (offset >= register_size (gdbarch, regnum)) @@ -1499,17 +1498,14 @@ get_frame_register_bytes (frame_info_ptr frame, int regnum, CORE_ADDR addr; int realnum; - frame_register_unwind (get_next_frame_sentinel_okay (frame), regnum, - optimizedp, unavailablep, &lval, &addr, - &realnum, buffer.data ()); + frame_register_unwind (next_frame, regnum, optimizedp, unavailablep, + &lval, &addr, &realnum, buffer.data ()); if (*optimizedp || *unavailablep) return false; } else { - struct value *value - = frame_unwind_register_value (frame_info_ptr (frame->next), - regnum); + value *value = frame_unwind_register_value (next_frame, regnum); gdb_assert (value != NULL); *optimizedp = value->optimized_out (); *unavailablep = !value->entirely_available (); diff --git a/gdb/frame.h b/gdb/frame.h index 5ce3a1b285aa..62f53ece9eaa 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -733,11 +733,11 @@ extern bool read_frame_register_unsigned (frame_info_ptr frame, extern void put_frame_register (frame_info_ptr next_frame, int regnum, gdb::array_view buf); -/* Read LEN bytes from one or multiple registers starting with REGNUM - in frame FRAME, starting at OFFSET, into BUF. If the register - contents are optimized out or unavailable, set *OPTIMIZEDP, - *UNAVAILABLEP accordingly. */ -extern bool get_frame_register_bytes (frame_info_ptr frame, int regnum, +/* Read LEN bytes from one or multiple registers starting with REGNUM in + NEXT_FRAME's previous frame, starting at OFFSET, into BUF. If the register + contents are optimized out or unavailable, set *OPTIMIZEDP, *UNAVAILABLEP + accordingly. */ +extern bool get_frame_register_bytes (frame_info_ptr next_frame, int regnum, CORE_ADDR offset, gdb::array_view buffer, int *optimizedp, int *unavailablep); diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index f188f83de6f3..59d77d1d574d 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -3877,10 +3877,10 @@ i386_register_to_value (frame_info_ptr frame, int regnum, gdb_assert (regnum != -1); gdb_assert (register_size (gdbarch, regnum) == 4); - if (!get_frame_register_bytes (frame, regnum, 0, - gdb::make_array_view (to, - register_size (gdbarch, - regnum)), + auto to_view + = gdb::make_array_view (to, register_size (gdbarch, regnum)); + frame_info_ptr next_frame = get_next_frame_sentinel_okay (frame); + if (!get_frame_register_bytes (next_frame, regnum, 0, to_view, optimizedp, unavailablep)) return 0; diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c index 77dc5a008d5f..ffd8303746e5 100644 --- a/gdb/i387-tdep.c +++ b/gdb/i387-tdep.c @@ -364,11 +364,11 @@ i387_register_to_value (frame_info_ptr frame, int regnum, } /* Convert to TYPE. */ - if (!get_frame_register_bytes (frame, regnum, 0, - gdb::make_array_view (from, - register_size (gdbarch, - regnum)), - optimizedp, unavailablep)) + auto from_view + = gdb::make_array_view (from, register_size (gdbarch, regnum)); + frame_info_ptr next_frame = get_next_frame_sentinel_okay (frame); + if (!get_frame_register_bytes (next_frame, regnum, 0, from_view, optimizedp, + unavailablep)) return 0; target_float_convert (from, i387_ext_type (gdbarch), to, type); diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c index 3bede2644c03..b009b46ef6df 100644 --- a/gdb/ia64-tdep.c +++ b/gdb/ia64-tdep.c @@ -1227,11 +1227,10 @@ ia64_register_to_value (frame_info_ptr frame, int regnum, gdb_byte in[IA64_FP_REGISTER_SIZE]; /* Convert to TYPE. */ - if (!get_frame_register_bytes (frame, regnum, 0, - gdb::make_array_view (in, - register_size (gdbarch, - regnum)), - optimizedp, unavailablep)) + auto in_view = gdb::make_array_view (in, register_size (gdbarch, regnum)); + frame_info_ptr next_frame = get_next_frame_sentinel_okay (frame); + if (!get_frame_register_bytes (next_frame, regnum, 0, in_view, optimizedp, + unavailablep)) return 0; target_float_convert (in, ia64_ext_type (gdbarch), out, valtype); diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c index 8bbfa4bd0b10..f9c734cf3808 100644 --- a/gdb/m68k-tdep.c +++ b/gdb/m68k-tdep.c @@ -216,11 +216,11 @@ m68k_register_to_value (frame_info_ptr frame, int regnum, gdb_assert (type->code () == TYPE_CODE_FLT); /* Convert to TYPE. */ - if (!get_frame_register_bytes (frame, regnum, 0, - gdb::make_array_view (from, - register_size (gdbarch, - regnum)), - optimizedp, unavailablep)) + auto from_view + = gdb::make_array_view (from, register_size (gdbarch, regnum)); + frame_info_ptr next_frame = get_next_frame_sentinel_okay (frame); + if (!get_frame_register_bytes (next_frame, regnum, 0, from_view, optimizedp, + unavailablep)) return 0; target_float_convert (from, fpreg_type, to, type); diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 9c0cfede492a..fc3193ea27a5 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -947,17 +947,18 @@ mips_register_to_value (frame_info_ptr frame, int regnum, int *optimizedp, int *unavailablep) { struct gdbarch *gdbarch = get_frame_arch (frame); + frame_info_ptr next_frame = get_next_frame_sentinel_okay (frame); if (mips_convert_register_float_case_p (gdbarch, regnum, type)) { get_frame_register (frame, regnum + 0, to + 4); get_frame_register (frame, regnum + 1, to + 0); - if (!get_frame_register_bytes (frame, regnum + 0, 0, {to + 4, 4}, + if (!get_frame_register_bytes (next_frame, regnum + 0, 0, { to + 4, 4 }, optimizedp, unavailablep)) return 0; - if (!get_frame_register_bytes (frame, regnum + 1, 0, {to + 0, 4}, + if (!get_frame_register_bytes (next_frame, regnum + 1, 0, { to + 0, 4 }, optimizedp, unavailablep)) return 0; *optimizedp = *unavailablep = 0; @@ -969,7 +970,7 @@ mips_register_to_value (frame_info_ptr frame, int regnum, CORE_ADDR offset; offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 8 - len : 0; - if (!get_frame_register_bytes (frame, regnum, offset, {to, len}, + if (!get_frame_register_bytes (next_frame, regnum, offset, { to, len }, optimizedp, unavailablep)) return 0; diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index c43039302bc3..643997e5bd7d 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -2713,11 +2713,11 @@ rs6000_register_to_value (frame_info_ptr frame, fpr to vsr. */ regnum = ieee_128_float_regnum_adjust (gdbarch, type, regnum); - if (!get_frame_register_bytes (frame, regnum, 0, - gdb::make_array_view (from, - register_size (gdbarch, - regnum)), - optimizedp, unavailablep)) + auto from_view + = gdb::make_array_view (from, register_size (gdbarch, regnum)); + frame_info_ptr next_frame = get_next_frame_sentinel_okay (frame); + if (!get_frame_register_bytes (frame, regnum, 0, from_view, optimizedp, + unavailablep)) return 0; target_float_convert (from, builtin_type (gdbarch)->builtin_double, diff --git a/gdb/valops.c b/gdb/valops.c index 8e1849837cf1..dbf7a7552b10 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -1225,8 +1225,7 @@ value_assign (struct value *toval, struct value *fromval) "don't fit in a %d bit word."), (int) sizeof (LONGEST) * HOST_CHAR_BIT); - if (!get_frame_register_bytes (get_prev_frame_always (next_frame), - value_reg, offset, + if (!get_frame_register_bytes (next_frame, value_reg, offset, { buffer, changed_len }, &optim, &unavail)) { From patchwork Fri Dec 1 16:27:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81144 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 1947E3860002 for ; Fri, 1 Dec 2023 16:30:43 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 7502B3858C2C for ; Fri, 1 Dec 2023 16:29:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7502B3858C2C Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 7502B3858C2C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448200; cv=none; b=f9JZdC9IV2vh6jBVBrLQMf8hqlIoCrpH3Q+eU9BJ1mrj7WISOmwvVojt5n7Q76tQYPTMVsnFF5dT6UCLo9T4D5rnBGT2x2CyFy3ztDDjW7jZr4dYxPoy42yRnFvOaZQfs7LFKUSlCIGvSYDhY3PN02WhFR6SRDC4HCam2HdiGpw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448200; c=relaxed/simple; bh=CuDKpQj3haWbgVxRBZuY8UXK6M28nxrW0IoCdGOXX0o=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=t7uR/kxWPVBe5SZImVyGfvCEbd35mBKZU6Sh0eUXWb9HoXQhSYtwGM564dB0vsQuBOQ5z4JQGoXQFv78yGpXl0kjUm+OjLfxw+oq/U3/OSpphRvAwublQ477hYQBGYDZUXleQX+XrV4gAmIBSnqWNtDP+ua0tzbELx+I3CN7DgM= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 4A42D1E1A7; Fri, 1 Dec 2023 11:29:57 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 13/24] gdb: add value::allocate_register Date: Fri, 1 Dec 2023 11:27:26 -0500 Message-ID: <20231201162751.741751-14-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Add value::allocate_register, to facilitate allocating a value representing a register in a given frame (or rather, in the given frame's previous frame). It will be used in a subsequent patch. I changed one relatively obvious spot that could use it, to at least exercise the code path. Change-Id: Icd4960f5e471a74b657bb3596c88d89679ef3772 Reviewed-By: John Baldwin --- gdb/regcache.c | 7 ++----- gdb/value.c | 15 +++++++++++++++ gdb/value.h | 7 +++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/gdb/regcache.c b/gdb/regcache.c index 19ba353a335c..9b3fd4f060c7 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -775,11 +775,8 @@ readable_regcache::cooked_read_value (int regnum) || (m_has_pseudo && m_register_status[regnum] != REG_UNKNOWN) || !gdbarch_pseudo_register_read_value_p (m_descr->gdbarch)) { - struct value *result; - - result = value::allocate (register_type (m_descr->gdbarch, regnum)); - result->set_lval (lval_register); - VALUE_REGNUM (result) = regnum; + value *result = value::allocate_register + (get_next_frame_sentinel_okay (get_current_frame ()), regnum); /* It is more efficient in general to do this delegation in this direction than in the other one, even though the value-based diff --git a/gdb/value.c b/gdb/value.c index 1a3985582ba5..99af27b98700 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -959,6 +959,21 @@ value::allocate (struct type *type) return allocate (type, true); } +/* See value.h */ + +struct value * +value::allocate_register (frame_info_ptr next_frame, int regnum) +{ + value *result + = value::allocate (register_type (frame_unwind_arch (next_frame), regnum)); + + result->set_lval (lval_register); + VALUE_REGNUM (result) = regnum; + VALUE_NEXT_FRAME_ID (result) = get_frame_id (next_frame); + + return result; +} + /* Allocate a value that has the correct length for COUNT repetitions of type TYPE. */ diff --git a/gdb/value.h b/gdb/value.h index 3f9b35b589bd..2f3b41e26ea4 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -159,6 +159,13 @@ struct value /* Allocate a value and its contents for type TYPE. */ static struct value *allocate (struct type *type); + /* Allocate a non-lazy value representing register RENUM in the frame previous + to NEXT_FRAME. The type of the value is found using `register_type`. + + The caller is responsible for filling the value's contents. */ + static struct value *allocate_register (frame_info_ptr next_frame, + int regnum); + /* Create a computed lvalue, with type TYPE, function pointers FUNCS, and closure CLOSURE. */ static struct value *allocate_computed (struct type *type, From patchwork Fri Dec 1 16:27:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81152 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 16939384DEF1 for ; Fri, 1 Dec 2023 16:32:33 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 8EA24385C6F3 for ; Fri, 1 Dec 2023 16:29:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8EA24385C6F3 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 8EA24385C6F3 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448204; cv=none; b=XKuij8vUCkwKFq2oknxGz3dqPZNu64qZeZRjywEW5vEDhxmyMIc0ZhJ6TNlmJffrHq5lsllDvuUNMo6E79q5TDSHcsmdvmhDJWhzM1rJc8/LZsZR89lgzxAFcJn6j1GFwyoIOwoXBtu0heUswJKiCrEMNe7ezMzU1yJkbiUlUJg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448204; c=relaxed/simple; bh=2qMLRXHu00rAOkb6jE3PQe9b25ZfEgm3lmvuBTWxkBs=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=NyCIhNFHPOzoGaOE/wF2dX0sV42OfpfhO3tJRzF97TUx1ZELCbIdWnc/FoE2Zi5DYLV/tMk03mtw0ubwlOyAht3R1gFZyCsUr+gqfJXvAPMKDiNhGUdzrDZrN95Xdvz97IDNUDMK9CFFhqDxi1w5fpGFYiEgnkd6Lp4FBxtG5Ds= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 869651E1A8; Fri, 1 Dec 2023 11:29:57 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 14/24] gdb: read pseudo register through frame Date: Fri, 1 Dec 2023 11:27:27 -0500 Message-ID: <20231201162751.741751-15-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Change gdbarch_pseudo_register_read_value to take a frame instead of a regcache. The frame (and formerly the regcache) is used to read raw registers needed to make up the pseudo register value. The problem with using the regcache is that it always provides raw register values for the current frame (frame 0). Let's say the user wants to read the ebx register on amd64. ebx is a pseudo register, obtained by reading the bottom half (bottom 4 bytes) of the rbx register, which is a raw register. If the currently selected frame is frame 0, it works fine: (gdb) frame 0 #0 break_here_asm () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:36 36 in /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S (gdb) p/x $ebx $1 = 0x24252627 (gdb) p/x $rbx $2 = 0x2021222324252627 But if the user is looking at another frame, and the raw register behind the pseudo register has been saved at some point in the call stack, then we get a wrong answer: (gdb) frame 1 #1 0x000055555555517d in caller () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:56 56 in /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S (gdb) p/x $ebx $3 = 0x24252627 (gdb) p/x $rbx $4 = 0x1011121314151617 Here, the value of ebx was computed using the value of rbx in frame 0 (through the regcache), it should have been computed using the value of rbx in frame 1. In other to make this work properly, make the following changes: - Make dwarf2_frame_prev_register return nullptr if it doesn't know how to unwind a register and that register is a pseudo register. Previously, it returned `frame_unwind_got_register`, meaning, in our example, "the value of ebx in frame 1 is the same as the value of ebx in frame 0", which is obviously false. Return nullptr as a way to say "I don't know". - In frame_unwind_register_value, when prev_register (for instance dwarf2_frame_prev_register) returns nullptr, and we are trying to read a pseudo register, try to get the register value through gdbarch_pseudo_register_read_value or gdbarch_pseudo_register_read. If using gdbarch_pseudo_register_read, the behavior is known to be broken. Implementations should be migrated to use gdbarch_pseudo_register_read_value to fix that. - Change gdbarch_pseudo_register_read_value to take a frame_info instead of a regcache, update implementations (aarch64, amd64, i386). In i386-tdep.c, I made a copy of i386_mmx_regnum_to_fp_regnum that uses a frame instead of a regcache. The version using the regcache is still used by i386_pseudo_register_write. It will get removed in a subsequent patch. - Add some helpers in value.{c,h} to implement the common cases of pseudo registers: taking part of a raw register and concatenating multiple raw registers. - Update readable_regcache::{cooked_read,cooked_read_value} to pass the current frame to gdbarch_pseudo_register_read_value. Passing the current frame will give the same behavior as before: for frame 0, raw registers will be read from the current thread's regcache. Notes: - I do not plan on changing gdbarch_pseudo_register_read to receive a frame instead of a regcache. That method is considered deprecated. Instead, we should be working on migrating implementations to use gdbarch_pseudo_register_read_value instead. - In frame_unwind_register_value, we still ask the unwinder to try to unwind pseudo register values. It's apparently possible for the debug info to provide information about [1] pseudo registers, so we want to try that first, before falling back to computing them ourselves. [1] https://inbox.sourceware.org/gdb-patches/20180528174715.A954AD804AD@oc3748833570.ibm.com/ Change-Id: Id6ef1c64e19090a183dec050e4034d8c2394e7ca Reviewed-by: John Baldwin --- gdb/aarch64-tdep.c | 148 +++++++++++-------------- gdb/amd64-tdep.c | 43 ++------ gdb/dwarf2/frame.c | 5 +- gdb/frame.c | 36 +++++- gdb/gdbarch-gen.h | 4 +- gdb/gdbarch.c | 4 +- gdb/gdbarch_components.py | 2 +- gdb/i386-tdep.c | 224 ++++++++++++++------------------------ gdb/i386-tdep.h | 7 +- gdb/regcache.c | 38 +++++-- gdb/value.c | 70 ++++++++++++ gdb/value.h | 26 +++++ 12 files changed, 322 insertions(+), 285 deletions(-) diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index b0aee191d71f..d901b69ce11d 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -3104,25 +3104,14 @@ aarch64_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum, /* Helper for aarch64_pseudo_read_value. */ -static struct value * -aarch64_pseudo_read_value_1 (struct gdbarch *gdbarch, - readable_regcache *regcache, int regnum_offset, - int regsize, struct value *result_value) +static value * +aarch64_pseudo_read_value_1 (frame_info_ptr next_frame, + const int pseudo_reg_num, int raw_regnum_offset) { - unsigned v_regnum = AARCH64_V0_REGNUM + regnum_offset; - - /* Enough space for a full vector register. */ - gdb_byte reg_buf[register_size (gdbarch, AARCH64_V0_REGNUM)]; - static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM); + unsigned v_regnum = AARCH64_V0_REGNUM + raw_regnum_offset; - if (regcache->raw_read (v_regnum, reg_buf) != REG_VALID) - result_value->mark_bytes_unavailable (0, - result_value->type ()->length ()); - else - memcpy (result_value->contents_raw ().data (), reg_buf, regsize); - - return result_value; - } + return pseudo_from_raw_part (next_frame, pseudo_reg_num, v_regnum, 0); +} /* Helper function for reading/writing ZA pseudo-registers. Given REGNUM, a ZA pseudo-register number, return, in OFFSETS, the information on positioning @@ -3205,54 +3194,47 @@ aarch64_za_offsets_from_regnum (struct gdbarch *gdbarch, int regnum, /* Given REGNUM, a SME pseudo-register number, return its value in RESULT. */ -static struct value * -aarch64_sme_pseudo_register_read (struct gdbarch *gdbarch, - readable_regcache *regcache, int regnum, - struct value *result) +static value * +aarch64_sme_pseudo_register_read (gdbarch *gdbarch, frame_info_ptr next_frame, + const int pseudo_reg_num) { aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); gdb_assert (tdep->has_sme ()); gdb_assert (tdep->sme_svq > 0); - gdb_assert (tdep->sme_pseudo_base <= regnum); - gdb_assert (regnum < tdep->sme_pseudo_base + tdep->sme_pseudo_count); + gdb_assert (tdep->sme_pseudo_base <= pseudo_reg_num); + gdb_assert (pseudo_reg_num < tdep->sme_pseudo_base + tdep->sme_pseudo_count); /* Fetch the offsets that we need in order to read from the correct blocks of ZA. */ struct za_offsets offsets; - aarch64_za_offsets_from_regnum (gdbarch, regnum, offsets); + aarch64_za_offsets_from_regnum (gdbarch, pseudo_reg_num, offsets); /* Fetch the contents of ZA. */ - size_t svl = sve_vl_from_vq (tdep->sme_svq); - gdb::byte_vector za (std::pow (svl, 2)); - regcache->raw_read (tdep->sme_za_regnum, za.data ()); + value *za_value = value_of_register (tdep->sme_za_regnum, next_frame); + value *result = value::allocate_register (next_frame, pseudo_reg_num); /* Copy the requested data. */ for (int chunks = 0; chunks < offsets.chunks; chunks++) { - const gdb_byte *source - = za.data () + offsets.starting_offset + chunks * offsets.stride_size; - gdb_byte *destination - = result->contents_raw ().data () + chunks * offsets.chunk_size; - - memcpy (destination, source, offsets.chunk_size); + int src_offset = offsets.starting_offset + chunks * offsets.stride_size; + int dst_offset = chunks * offsets.chunk_size; + za_value->contents_copy (result, dst_offset, src_offset, + offsets.chunk_size); } + return result; } /* Implement the "pseudo_register_read_value" gdbarch method. */ -static struct value * -aarch64_pseudo_read_value (struct gdbarch *gdbarch, readable_regcache *regcache, - int regnum) +static value * +aarch64_pseudo_read_value (gdbarch *gdbarch, frame_info_ptr next_frame, + const int pseudo_reg_num) { aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - struct value *result_value = value::allocate (register_type (gdbarch, regnum)); - result_value->set_lval (lval_register); - VALUE_REGNUM (result_value) = regnum; - - if (is_w_pseudo_register (gdbarch, regnum)) + if (is_w_pseudo_register (gdbarch, pseudo_reg_num)) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); /* Default offset for little endian. */ @@ -3262,53 +3244,49 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch, readable_regcache *regcache, offset = 4; /* Find the correct X register to extract the data from. */ - int x_regnum = AARCH64_X0_REGNUM + (regnum - tdep->w_pseudo_base); - gdb_byte data[4]; + int x_regnum + = AARCH64_X0_REGNUM + (pseudo_reg_num - tdep->w_pseudo_base); /* Read the bottom 4 bytes of X. */ - if (regcache->raw_read_part (x_regnum, offset, 4, data) != REG_VALID) - result_value->mark_bytes_unavailable (0, 4); - else - memcpy (result_value->contents_raw ().data (), data, 4); - - return result_value; + return pseudo_from_raw_part (next_frame, pseudo_reg_num, x_regnum, + offset); } - else if (is_sme_pseudo_register (gdbarch, regnum)) - return aarch64_sme_pseudo_register_read (gdbarch, regcache, regnum, - result_value); - - regnum -= gdbarch_num_regs (gdbarch); - - if (regnum >= AARCH64_Q0_REGNUM && regnum < AARCH64_Q0_REGNUM + 32) - return aarch64_pseudo_read_value_1 (gdbarch, regcache, - regnum - AARCH64_Q0_REGNUM, - Q_REGISTER_SIZE, result_value); - - if (regnum >= AARCH64_D0_REGNUM && regnum < AARCH64_D0_REGNUM + 32) - return aarch64_pseudo_read_value_1 (gdbarch, regcache, - regnum - AARCH64_D0_REGNUM, - D_REGISTER_SIZE, result_value); - - if (regnum >= AARCH64_S0_REGNUM && regnum < AARCH64_S0_REGNUM + 32) - return aarch64_pseudo_read_value_1 (gdbarch, regcache, - regnum - AARCH64_S0_REGNUM, - S_REGISTER_SIZE, result_value); - - if (regnum >= AARCH64_H0_REGNUM && regnum < AARCH64_H0_REGNUM + 32) - return aarch64_pseudo_read_value_1 (gdbarch, regcache, - regnum - AARCH64_H0_REGNUM, - H_REGISTER_SIZE, result_value); - - if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32) - return aarch64_pseudo_read_value_1 (gdbarch, regcache, - regnum - AARCH64_B0_REGNUM, - B_REGISTER_SIZE, result_value); - - if (tdep->has_sve () && regnum >= AARCH64_SVE_V0_REGNUM - && regnum < AARCH64_SVE_V0_REGNUM + 32) - return aarch64_pseudo_read_value_1 (gdbarch, regcache, - regnum - AARCH64_SVE_V0_REGNUM, - V_REGISTER_SIZE, result_value); + else if (is_sme_pseudo_register (gdbarch, pseudo_reg_num)) + return aarch64_sme_pseudo_register_read (gdbarch, next_frame, + pseudo_reg_num); + + /* Offset in the "pseudo-register space". */ + int pseudo_offset = pseudo_reg_num - gdbarch_num_regs (gdbarch); + + if (pseudo_offset >= AARCH64_Q0_REGNUM + && pseudo_offset < AARCH64_Q0_REGNUM + 32) + return aarch64_pseudo_read_value_1 (next_frame, pseudo_reg_num, + pseudo_offset - AARCH64_Q0_REGNUM); + + if (pseudo_offset >= AARCH64_D0_REGNUM + && pseudo_offset < AARCH64_D0_REGNUM + 32) + return aarch64_pseudo_read_value_1 (next_frame, pseudo_reg_num, + pseudo_offset - AARCH64_D0_REGNUM); + + if (pseudo_offset >= AARCH64_S0_REGNUM + && pseudo_offset < AARCH64_S0_REGNUM + 32) + return aarch64_pseudo_read_value_1 (next_frame, pseudo_reg_num, + pseudo_offset - AARCH64_S0_REGNUM); + + if (pseudo_offset >= AARCH64_H0_REGNUM + && pseudo_offset < AARCH64_H0_REGNUM + 32) + return aarch64_pseudo_read_value_1 (next_frame, pseudo_reg_num, + pseudo_offset - AARCH64_H0_REGNUM); + + if (pseudo_offset >= AARCH64_B0_REGNUM + && pseudo_offset < AARCH64_B0_REGNUM + 32) + return aarch64_pseudo_read_value_1 (next_frame, pseudo_reg_num, + pseudo_offset - AARCH64_B0_REGNUM); + + if (tdep->has_sve () && pseudo_offset >= AARCH64_SVE_V0_REGNUM + && pseudo_offset < AARCH64_SVE_V0_REGNUM + 32) + return aarch64_pseudo_read_value_1 (next_frame, pseudo_reg_num, + pseudo_offset - AARCH64_SVE_V0_REGNUM); gdb_assert_not_reached ("regnum out of bound"); } diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index e6feee677b3d..955a6860631d 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -348,18 +348,12 @@ amd64_pseudo_register_name (struct gdbarch *gdbarch, int regnum) return i386_pseudo_register_name (gdbarch, regnum); } -static struct value * -amd64_pseudo_register_read_value (struct gdbarch *gdbarch, - readable_regcache *regcache, +static value * +amd64_pseudo_register_read_value (gdbarch *gdbarch, frame_info_ptr next_frame, int regnum) { i386_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - value *result_value = value::allocate (register_type (gdbarch, regnum)); - result_value->set_lval (lval_register); - VALUE_REGNUM (result_value) = regnum; - gdb_byte *buf = result_value->contents_raw ().data (); - if (i386_byte_regnum_p (gdbarch, regnum)) { int gpnum = regnum - tdep->al_regnum; @@ -368,44 +362,21 @@ amd64_pseudo_register_read_value (struct gdbarch *gdbarch, if (gpnum >= AMD64_NUM_LOWER_BYTE_REGS) { gpnum -= AMD64_NUM_LOWER_BYTE_REGS; - gdb_byte raw_buf[register_size (gdbarch, gpnum)]; /* Special handling for AH, BH, CH, DH. */ - register_status status = regcache->raw_read (gpnum, raw_buf); - if (status == REG_VALID) - memcpy (buf, raw_buf + 1, 1); - else - result_value->mark_bytes_unavailable (0, - result_value->type ()->length ()); + return pseudo_from_raw_part (next_frame, regnum, gpnum, 1); } else - { - gdb_byte raw_buf[register_size (gdbarch, gpnum)]; - register_status status = regcache->raw_read (gpnum, raw_buf); - if (status == REG_VALID) - memcpy (buf, raw_buf, 1); - else - result_value->mark_bytes_unavailable (0, - result_value->type ()->length ()); - } + return pseudo_from_raw_part (next_frame, regnum, gpnum, 0); } else if (i386_dword_regnum_p (gdbarch, regnum)) { int gpnum = regnum - tdep->eax_regnum; - gdb_byte raw_buf[register_size (gdbarch, gpnum)]; - /* Extract (always little endian). */ - register_status status = regcache->raw_read (gpnum, raw_buf); - if (status == REG_VALID) - memcpy (buf, raw_buf, 4); - else - result_value->mark_bytes_unavailable (0, - result_value->type ()->length ()); + + return pseudo_from_raw_part (next_frame, regnum, gpnum, 0); } else - i386_pseudo_register_read_into_value (gdbarch, regcache, regnum, - result_value); - - return result_value; + return i386_pseudo_register_read_value (gdbarch, next_frame, regnum); } static void diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c index d72dd0ad971d..d3d1ecdf1f5b 100644 --- a/gdb/dwarf2/frame.c +++ b/gdb/dwarf2/frame.c @@ -1220,7 +1220,10 @@ dwarf2_frame_prev_register (frame_info_ptr this_frame, void **this_cache, "undefined"). Code above issues a complaint about this. Here just fudge the books, assume GCC, and that the value is more inner on the stack. */ - return frame_unwind_got_register (this_frame, regnum, regnum); + if (regnum < gdbarch_num_regs (gdbarch)) + return frame_unwind_got_register (this_frame, regnum, regnum); + else + return nullptr; case DWARF2_FRAME_REG_SAME_VALUE: return frame_unwind_got_register (this_frame, regnum, regnum); diff --git a/gdb/frame.c b/gdb/frame.c index d260e8c28f3f..a9cad1dca8fb 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1257,9 +1257,39 @@ frame_unwind_register_value (frame_info_ptr next_frame, int regnum) frame_unwind_find_by_frame (next_frame, &next_frame->prologue_cache); /* Ask this frame to unwind its register. */ - value *value = next_frame->unwind->prev_register (next_frame, - &next_frame->prologue_cache, - regnum); + value *value + = next_frame->unwind->prev_register (next_frame, + &next_frame->prologue_cache, regnum); + if (value == nullptr) + { + if (gdbarch_pseudo_register_read_value_p (gdbarch)) + { + /* This is a pseudo register, we don't know how how what raw registers + this pseudo register is made of. Ask the gdbarch to read the + value, it will itself ask the next frame to unwind the values of + the raw registers it needs to compose the value of the pseudo + register. */ + value = gdbarch_pseudo_register_read_value + (gdbarch, next_frame, regnum); + } + else if (gdbarch_pseudo_register_read_p (gdbarch)) + { + value = value::allocate_register (next_frame, regnum); + + /* Passing the current regcache is known to be broken, the pseudo + register value will be constructed using the current raw registers, + rather than reading them using NEXT_FRAME. Architectures should be + migrated to gdbarch_pseudo_register_read_value. */ + register_status status = gdbarch_pseudo_register_read + (gdbarch, get_thread_regcache (inferior_thread ()), regnum, + value->contents_writeable ().data ()); + if (status == REG_UNAVAILABLE) + value->mark_bytes_unavailable (0, value->type ()->length ()); + } + else + error (_("Can't unwind value of register %d (%s)"), regnum, + user_reg_map_regnum_to_name (gdbarch, regnum)); + } if (frame_debug) { diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h index 9f468bd1f618..c70bfc97634a 100644 --- a/gdb/gdbarch-gen.h +++ b/gdb/gdbarch-gen.h @@ -196,8 +196,8 @@ extern void set_gdbarch_pseudo_register_read (struct gdbarch *gdbarch, gdbarch_p extern bool gdbarch_pseudo_register_read_value_p (struct gdbarch *gdbarch); -typedef struct value * (gdbarch_pseudo_register_read_value_ftype) (struct gdbarch *gdbarch, readable_regcache *regcache, int cookednum); -extern struct value * gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, readable_regcache *regcache, int cookednum); +typedef struct value * (gdbarch_pseudo_register_read_value_ftype) (struct gdbarch *gdbarch, frame_info_ptr next_frame, int cookednum); +extern struct value * gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, frame_info_ptr next_frame, int cookednum); extern void set_gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value); extern bool gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch); diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index ea6e4c647b10..06ff52576bdf 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -1886,13 +1886,13 @@ gdbarch_pseudo_register_read_value_p (struct gdbarch *gdbarch) } struct value * -gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, readable_regcache *regcache, int cookednum) +gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, frame_info_ptr next_frame, int cookednum) { gdb_assert (gdbarch != NULL); gdb_assert (gdbarch->pseudo_register_read_value != NULL); if (gdbarch_debug >= 2) gdb_printf (gdb_stdlog, "gdbarch_pseudo_register_read_value called\n"); - return gdbarch->pseudo_register_read_value (gdbarch, regcache, cookednum); + return gdbarch->pseudo_register_read_value (gdbarch, next_frame, cookednum); } void diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py index 694ac3660235..c597b38ad5a9 100644 --- a/gdb/gdbarch_components.py +++ b/gdb/gdbarch_components.py @@ -414,7 +414,7 @@ never be called. """, type="struct value *", name="pseudo_register_read_value", - params=[("readable_regcache *", "regcache"), ("int", "cookednum")], + params=[("frame_info_ptr", "next_frame"), ("int", "cookednum")], predicate=True, ) diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 59d77d1d574d..be1aa83bbbdb 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -3411,195 +3411,131 @@ i386_mmx_regnum_to_fp_regnum (readable_regcache *regcache, int regnum) return (I387_ST0_REGNUM (tdep) + fpreg); } +/* Map a cooked register onto a raw register or memory. For the i386, + the MMX registers need to be mapped onto floating point registers. */ + +static int +i386_mmx_regnum_to_fp_regnum (frame_info_ptr next_frame, int regnum) +{ + gdbarch *arch = frame_unwind_arch (next_frame); + i386_gdbarch_tdep *tdep = gdbarch_tdep (arch); + ULONGEST fstat + = frame_unwind_register_unsigned (next_frame, I387_FSTAT_REGNUM (tdep)); + int tos = (fstat >> 11) & 0x7; + int mmxreg = regnum - tdep->mm0_regnum; + int fpreg = (mmxreg + tos) % 8; + + return (I387_ST0_REGNUM (tdep) + fpreg); +} + /* A helper function for us by i386_pseudo_register_read_value and amd64_pseudo_register_read_value. It does all the work but reads the data into an already-allocated value. */ -void -i386_pseudo_register_read_into_value (struct gdbarch *gdbarch, - readable_regcache *regcache, - int regnum, - struct value *result_value) +value * +i386_pseudo_register_read_value (gdbarch *gdbarch, frame_info_ptr next_frame, + const int pseudo_reg_num) { - gdb_byte raw_buf[I386_MAX_REGISTER_SIZE]; - enum register_status status; - gdb_byte *buf = result_value->contents_raw ().data (); - - if (i386_mmx_regnum_p (gdbarch, regnum)) + if (i386_mmx_regnum_p (gdbarch, pseudo_reg_num)) { - int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum); + int fpnum = i386_mmx_regnum_to_fp_regnum (next_frame, pseudo_reg_num); /* Extract (always little endian). */ - status = regcache->raw_read (fpnum, raw_buf); - if (status != REG_VALID) - result_value->mark_bytes_unavailable (0, - result_value->type ()->length ()); - else - memcpy (buf, raw_buf, register_size (gdbarch, regnum)); + return pseudo_from_raw_part (next_frame, pseudo_reg_num, fpnum, 0); } else { i386_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - if (i386_bnd_regnum_p (gdbarch, regnum)) + if (i386_bnd_regnum_p (gdbarch, pseudo_reg_num)) { - regnum -= tdep->bnd0_regnum; + int i = pseudo_reg_num - tdep->bnd0_regnum; /* Extract (always little endian). Read lower 128bits. */ - status = regcache->raw_read (I387_BND0R_REGNUM (tdep) + regnum, - raw_buf); - if (status != REG_VALID) - result_value->mark_bytes_unavailable (0, 16); - else + value *bndr_value + = value_of_register (I387_BND0R_REGNUM (tdep) + i, next_frame); + int size = builtin_type (gdbarch)->builtin_data_ptr->length (); + value *result + = value::allocate_register (next_frame, pseudo_reg_num); + + /* Copy the lower. */ + bndr_value->contents_copy (result, 0, 0, size); + + /* Copy the upper. */ + bndr_value->contents_copy (result, size, 8, size); + + /* If upper bytes are available, compute ones' complement. */ + if (result->bytes_available (size, size)) { bfd_endian byte_order - = gdbarch_byte_order (current_inferior ()->arch ()); - LONGEST upper, lower; - int size = builtin_type (gdbarch)->builtin_data_ptr->length (); - - lower = extract_unsigned_integer (raw_buf, 8, byte_order); - upper = extract_unsigned_integer (raw_buf + 8, 8, byte_order); + = gdbarch_byte_order (frame_unwind_arch (next_frame)); + gdb::array_view upper_bytes + = result->contents_raw ().slice (size, size); + ULONGEST upper + = extract_unsigned_integer (upper_bytes, byte_order); upper = ~upper; - - memcpy (buf, &lower, size); - memcpy (buf + size, &upper, size); + store_unsigned_integer (upper_bytes, byte_order, upper); } + + return result; } - else if (i386_zmm_regnum_p (gdbarch, regnum)) + else if (i386_zmm_regnum_p (gdbarch, pseudo_reg_num)) { - regnum -= tdep->zmm0_regnum; - - if (regnum < num_lower_zmm_regs) - { - /* Extract (always little endian). Read lower 128bits. */ - status = regcache->raw_read (I387_XMM0_REGNUM (tdep) + regnum, - raw_buf); - if (status != REG_VALID) - result_value->mark_bytes_unavailable (0, 16); - else - memcpy (buf, raw_buf, 16); + /* Which register is it, relative to zmm0. */ + int i_0 = pseudo_reg_num - tdep->zmm0_regnum; - /* Extract (always little endian). Read upper 128bits. */ - status = regcache->raw_read (tdep->ymm0h_regnum + regnum, - raw_buf); - if (status != REG_VALID) - result_value->mark_bytes_unavailable (16, 16); - else - memcpy (buf + 16, raw_buf, 16); - } + if (i_0 < num_lower_zmm_regs) + return pseudo_from_concat_raw (next_frame, pseudo_reg_num, + I387_XMM0_REGNUM (tdep) + i_0, + tdep->ymm0h_regnum + i_0, + tdep->zmm0h_regnum + i_0); else { - /* Extract (always little endian). Read lower 128bits. */ - status = regcache->raw_read (I387_XMM16_REGNUM (tdep) + regnum - - num_lower_zmm_regs, - raw_buf); - if (status != REG_VALID) - result_value->mark_bytes_unavailable (0, 16); - else - memcpy (buf, raw_buf, 16); - - /* Extract (always little endian). Read upper 128bits. */ - status = regcache->raw_read (I387_YMM16H_REGNUM (tdep) + regnum - - num_lower_zmm_regs, - raw_buf); - if (status != REG_VALID) - result_value->mark_bytes_unavailable (16, 16); - else - memcpy (buf + 16, raw_buf, 16); - } + /* Which register is it, relative to zmm16. */ + int i_16 = i_0 - num_lower_zmm_regs; - /* Read upper 256bits. */ - status = regcache->raw_read (tdep->zmm0h_regnum + regnum, - raw_buf); - if (status != REG_VALID) - result_value->mark_bytes_unavailable (32, 32); - else - memcpy (buf + 32, raw_buf, 32); + return pseudo_from_concat_raw (next_frame, pseudo_reg_num, + I387_XMM16_REGNUM (tdep) + i_16, + I387_YMM16H_REGNUM (tdep) + i_16, + tdep->zmm0h_regnum + i_0); + } } - else if (i386_ymm_regnum_p (gdbarch, regnum)) + else if (i386_ymm_regnum_p (gdbarch, pseudo_reg_num)) { - regnum -= tdep->ymm0_regnum; + int i = pseudo_reg_num - tdep->ymm0_regnum; - /* Extract (always little endian). Read lower 128bits. */ - status = regcache->raw_read (I387_XMM0_REGNUM (tdep) + regnum, - raw_buf); - if (status != REG_VALID) - result_value->mark_bytes_unavailable (0, 16); - else - memcpy (buf, raw_buf, 16); - /* Read upper 128bits. */ - status = regcache->raw_read (tdep->ymm0h_regnum + regnum, - raw_buf); - if (status != REG_VALID) - result_value->mark_bytes_unavailable (16, 32); - else - memcpy (buf + 16, raw_buf, 16); + return pseudo_from_concat_raw (next_frame, pseudo_reg_num, + I387_XMM0_REGNUM (tdep) + i, + tdep->ymm0h_regnum + i); } - else if (i386_ymm_avx512_regnum_p (gdbarch, regnum)) + else if (i386_ymm_avx512_regnum_p (gdbarch, pseudo_reg_num)) { - regnum -= tdep->ymm16_regnum; - /* Extract (always little endian). Read lower 128bits. */ - status = regcache->raw_read (I387_XMM16_REGNUM (tdep) + regnum, - raw_buf); - if (status != REG_VALID) - result_value->mark_bytes_unavailable (0, 16); - else - memcpy (buf, raw_buf, 16); - /* Read upper 128bits. */ - status = regcache->raw_read (tdep->ymm16h_regnum + regnum, - raw_buf); - if (status != REG_VALID) - result_value->mark_bytes_unavailable (16, 16); - else - memcpy (buf + 16, raw_buf, 16); + int i = pseudo_reg_num - tdep->ymm16_regnum; + + return pseudo_from_concat_raw (next_frame, pseudo_reg_num, + I387_XMM16_REGNUM (tdep) + i, + tdep->ymm16h_regnum + i); } - else if (i386_word_regnum_p (gdbarch, regnum)) + else if (i386_word_regnum_p (gdbarch, pseudo_reg_num)) { - int gpnum = regnum - tdep->ax_regnum; + int gpnum = pseudo_reg_num - tdep->ax_regnum; /* Extract (always little endian). */ - status = regcache->raw_read (gpnum, raw_buf); - if (status != REG_VALID) - result_value->mark_bytes_unavailable (0, - result_value->type ()->length ()); - else - memcpy (buf, raw_buf, 2); + return pseudo_from_raw_part (next_frame, pseudo_reg_num, gpnum, 0); } - else if (i386_byte_regnum_p (gdbarch, regnum)) + else if (i386_byte_regnum_p (gdbarch, pseudo_reg_num)) { - int gpnum = regnum - tdep->al_regnum; + int gpnum = pseudo_reg_num - tdep->al_regnum; /* Extract (always little endian). We read both lower and upper registers. */ - status = regcache->raw_read (gpnum % 4, raw_buf); - if (status != REG_VALID) - result_value->mark_bytes_unavailable (0, - result_value->type ()->length ()); - else if (gpnum >= 4) - memcpy (buf, raw_buf + 1, 1); - else - memcpy (buf, raw_buf, 1); + return pseudo_from_raw_part (next_frame, pseudo_reg_num, gpnum % 4, + gpnum >= 4 ? 1 : 0); } else internal_error (_("invalid regnum")); } } -static struct value * -i386_pseudo_register_read_value (struct gdbarch *gdbarch, - readable_regcache *regcache, - int regnum) -{ - struct value *result; - - result = value::allocate (register_type (gdbarch, regnum)); - result->set_lval (lval_register); - VALUE_REGNUM (result) = regnum; - - i386_pseudo_register_read_into_value (gdbarch, regcache, regnum, result); - - return result; -} - void i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, int regnum, const gdb_byte *buf) diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h index 4283a52c9292..970dc8904f2a 100644 --- a/gdb/i386-tdep.h +++ b/gdb/i386-tdep.h @@ -376,10 +376,9 @@ extern const char *i386_pseudo_register_name (struct gdbarch *gdbarch, extern struct type *i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum); -extern void i386_pseudo_register_read_into_value (struct gdbarch *gdbarch, - readable_regcache *regcache, - int regnum, - struct value *result); +extern value *i386_pseudo_register_read_value (gdbarch *gdbarch, + frame_info_ptr next_frame, + int regnum); extern void i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, diff --git a/gdb/regcache.c b/gdb/regcache.c index 9b3fd4f060c7..9575988760ba 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -735,8 +735,9 @@ readable_regcache::cooked_read (int regnum, gdb::array_view dst) { register_status result = REG_VALID; scoped_value_mark mark; - value *computed - = gdbarch_pseudo_register_read_value (m_descr->gdbarch, this, regnum); + value *computed = gdbarch_pseudo_register_read_value + (m_descr->gdbarch, get_next_frame_sentinel_okay (get_current_frame ()), + regnum); if (computed->entirely_available ()) copy (computed->contents_raw (), dst); @@ -788,8 +789,9 @@ readable_regcache::cooked_read_value (int regnum) return result; } else - return gdbarch_pseudo_register_read_value (m_descr->gdbarch, - this, regnum); + return gdbarch_pseudo_register_read_value + (m_descr->gdbarch, get_next_frame_sentinel_okay (get_current_frame ()), + regnum); } enum register_status @@ -1952,10 +1954,18 @@ cooked_read_test (struct gdbarch *gdbarch) break; } - readwrite_regcache readwrite (&mockctx.mock_inferior, gdbarch); + /* Install this regcache in the regcaches global structure, so that. */ + pid_ptid_regcache_map &x = regcaches[&mockctx.mock_target]; + ptid_regcache_map &y = x[mockctx.mock_ptid.pid ()]; + regcache &readwrite + = *y.emplace (std::make_pair (mockctx.mock_ptid, + std::make_unique ( + &mockctx.mock_inferior, gdbarch))) + ->second; + readwrite.set_ptid (mockctx.mock_ptid); - gdb::byte_vector buf (register_size (gdbarch, nonzero_regnum)); + gdb::byte_vector buf (register_size (gdbarch, nonzero_regnum)); readwrite.raw_read (nonzero_regnum, buf); /* raw_read calls target_fetch_registers. */ @@ -2053,6 +2063,8 @@ cooked_read_test (struct gdbarch *gdbarch) mockctx.mock_target.reset (); } + + regcaches.erase (&mockctx.mock_target); } /* Test regcache::cooked_write by writing some expected contents to @@ -2067,7 +2079,17 @@ cooked_write_test (struct gdbarch *gdbarch) /* Create a mock environment. A process_stratum target pushed. */ scoped_mock_context ctx (gdbarch); - readwrite_regcache readwrite (&ctx.mock_inferior, gdbarch); + + + /* Install this regcache in the regcaches global structure, so that. */ + pid_ptid_regcache_map &x = regcaches[&ctx.mock_target]; + ptid_regcache_map &y = x[ctx.mock_ptid.pid ()]; + regcache &readwrite + = *y.emplace (std::make_pair (ctx.mock_ptid, + std::make_unique ( + &ctx.mock_inferior, gdbarch))) + ->second; + readwrite.set_ptid (ctx.mock_ptid); const int num_regs = gdbarch_num_cooked_regs (gdbarch); @@ -2148,6 +2170,8 @@ cooked_write_test (struct gdbarch *gdbarch) SELF_CHECK (readwrite.cooked_read (regnum, buf) == REG_VALID); SELF_CHECK (expected == buf); } + + regcaches.erase (&ctx.mock_target); } /* Verify that when two threads with the same ptid exist (from two different diff --git a/gdb/value.c b/gdb/value.c index 99af27b98700..9d826d4fdbed 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -4041,6 +4041,76 @@ value::fetch_lazy () set_lazy (false); } +/* See value.h. */ + +value * +pseudo_from_raw_part (frame_info_ptr next_frame, int pseudo_reg_num, + int raw_reg_num, int raw_offset) +{ + value *pseudo_reg_val + = value::allocate_register (next_frame, pseudo_reg_num); + value *raw_reg_val = value_of_register (raw_reg_num, next_frame); + raw_reg_val->contents_copy (pseudo_reg_val, 0, raw_offset, + pseudo_reg_val->type ()->length ()); + return pseudo_reg_val; +} + +/* See value.h. */ + +value * +pseudo_from_concat_raw (frame_info_ptr next_frame, int pseudo_reg_num, + int raw_reg_1_num, int raw_reg_2_num) +{ + value *pseudo_reg_val + = value::allocate_register (next_frame, pseudo_reg_num); + int dst_offset = 0; + + value *raw_reg_1_val = value_of_register (raw_reg_1_num, next_frame); + raw_reg_1_val->contents_copy (pseudo_reg_val, dst_offset, 0, + raw_reg_1_val->type ()->length ()); + dst_offset += raw_reg_1_val->type ()->length (); + + value *raw_reg_2_val = value_of_register (raw_reg_2_num, next_frame); + raw_reg_2_val->contents_copy (pseudo_reg_val, dst_offset, 0, + raw_reg_2_val->type ()->length ()); + dst_offset += raw_reg_2_val->type ()->length (); + + gdb_assert (dst_offset == pseudo_reg_val->type ()->length ()); + + return pseudo_reg_val; +} + +/* See value.h. */ + +value * +pseudo_from_concat_raw (frame_info_ptr next_frame, int pseudo_reg_num, + int raw_reg_1_num, int raw_reg_2_num, + int raw_reg_3_num) +{ + value *pseudo_reg_val + = value::allocate_register (next_frame, pseudo_reg_num); + int dst_offset = 0; + + value *raw_reg_1_val = value_of_register (raw_reg_1_num, next_frame); + raw_reg_1_val->contents_copy (pseudo_reg_val, dst_offset, 0, + raw_reg_1_val->type ()->length ()); + dst_offset += raw_reg_1_val->type ()->length (); + + value *raw_reg_2_val = value_of_register (raw_reg_2_num, next_frame); + raw_reg_2_val->contents_copy (pseudo_reg_val, dst_offset, 0, + raw_reg_2_val->type ()->length ()); + dst_offset += raw_reg_2_val->type ()->length (); + + value *raw_reg_3_val = value_of_register (raw_reg_3_num, next_frame); + raw_reg_3_val->contents_copy (pseudo_reg_val, dst_offset, 0, + raw_reg_3_val->type ()->length ()); + dst_offset += raw_reg_3_val->type ()->length (); + + gdb_assert (dst_offset == pseudo_reg_val->type ()->length ()); + + return pseudo_reg_val; +} + /* Implementation of the convenience function $_isvoid. */ static struct value * diff --git a/gdb/value.h b/gdb/value.h index 2f3b41e26ea4..935d9ebfd8c9 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -1650,4 +1650,30 @@ struct scoped_array_length_limiting std::optional m_old_value; }; +/* Helpers for building pseudo register values from raw registers. */ + +/* Create a value for pseudo register PSEUDO_REG_NUM by using bytes from + raw register RAW_REG_NUM starting at RAW_OFFSET. + + The size of the pseudo register specifies how many bytes to use. The + offset plus the size must not overflow the raw register's size. */ + +value *pseudo_from_raw_part (frame_info_ptr next_frame, int pseudo_reg_num, + int raw_reg_num, int raw_offset); + +/* Create a value for pseudo register PSEUDO_REG_NUM by concatenating raw + registers RAW_REG_1_NUM and RAW_REG_2_NUM. + + The sum of the sizes of raw registers must be equal to the size of the + pseudo register. */ + +value *pseudo_from_concat_raw (frame_info_ptr next_frame, int pseudo_reg_num, + int raw_reg_1_num, int raw_reg_2_num); + +/* Same as the above, but with three raw registers. */ + +value *pseudo_from_concat_raw (frame_info_ptr next_frame, int pseudo_reg_num, + int raw_reg_1_num, int raw_reg_2_num, + int raw_reg_3_num); + #endif /* !defined (VALUE_H) */ From patchwork Fri Dec 1 16:27:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81148 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 60E993861843 for ; Fri, 1 Dec 2023 16:32:12 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 779C5385C6E9 for ; Fri, 1 Dec 2023 16:29:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 779C5385C6E9 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 779C5385C6E9 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448201; cv=none; b=a/bIqPdTJTikPwi3pfA109YKhTv67Y/5pLnBqE3VHbBbTXQ9xSZrKdDAyO0yscbdi4rYyTCHGPT21xgv2Q63+47c/xxfq2YtR7TLia15ShfM//BIOcEAsV+7lh64/+qwsbDYYG9wm+ZnEaM0TO4jfEHIUipBMXTt3y7/DBIyboc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448201; c=relaxed/simple; bh=T3uAXInpTmoldraRbJp5yPbhVncKjyPEM8GeJbX0wpo=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=OrxmceMoYlNpjynN/XXtib9+vqk9GIysxCvGq/sRx/ufLa0D+08OO/CI2nHJB0xof8Bs8KRG0vQucnlZtPnKWgGFyaO7D6yvO+kPhd95FCaL1wWKF3uTQ/mNczAtOYShBBdJ1EdWMybApTwcX1OZECbRSznEZn1pKgKO+ifuyu4= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id B67C31E1A9; Fri, 1 Dec 2023 11:29:57 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 15/24] gdb: change parameter name in frame_unwind_register_unsigned declaration Date: Fri, 1 Dec 2023 11:27:28 -0500 Message-ID: <20231201162751.741751-16-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org For consistency with the declarations around. Change-Id: I398266a61eae6e93fb7e306923009da9dd7f8fc4 Reviewed-By: John Baldwin --- gdb/frame.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gdb/frame.h b/gdb/frame.h index 62f53ece9eaa..ec9b42115406 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -714,7 +714,7 @@ extern LONGEST frame_unwind_register_signed (frame_info_ptr next_frame, int regnum); extern LONGEST get_frame_register_signed (frame_info_ptr frame, int regnum); -extern ULONGEST frame_unwind_register_unsigned (frame_info_ptr frame, +extern ULONGEST frame_unwind_register_unsigned (frame_info_ptr next_frame, int regnum); extern ULONGEST get_frame_register_unsigned (frame_info_ptr frame, int regnum); From patchwork Fri Dec 1 16:27:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81151 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 B839D386181F for ; Fri, 1 Dec 2023 16:32:29 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 4A5FC3861831 for ; Fri, 1 Dec 2023 16:31:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4A5FC3861831 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 4A5FC3861831 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448323; cv=none; b=S92HPBIZPZWzbzM7wj11zS0JKceabkJC/Rt/CC5hn7q3Vm/8y2LQIgYCJidIReRfv5So3MMsCqEhsugYCJxMpT9/eAiASzftqC7DCvPUVklzr/FAY9EGXEdGQtXrFHtFaPj9FWuzTBejNWwhSna09M4DRyCJNFPRHybjgw5fsOM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448323; c=relaxed/simple; bh=35xdTsrgNHGk/RYIxrWlLrdSYTr+H0D9CwAYzHIMl2Q=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=TzLT9abME3P64HzXSkBPfT7i0C/nuoJG3ZvfsZjcxbsQe5n0GxpLD1knhX9L/u+X5EmZ050Fg7e6eQERHLeU2e3R4xnMvVmi4g2ab6m/S0zkdrh04eJHVGELYqwhtP9MYxtiQ16Xf4OYnPxLA6fBPbskZn+v4GtzltgeGspxphg= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 785C61E091; Fri, 1 Dec 2023 11:31:58 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 16/24] gdb: rename gdbarch_pseudo_register_write to gdbarch_deprecated_pseudo_register_write Date: Fri, 1 Dec 2023 11:27:29 -0500 Message-ID: <20231201162751.741751-17-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org The next patch introduces a new variant of gdbarch_pseudo_register_write that takes a frame instead of a regcache for implementations to write raw registers. Rename to old one to make it clear it's deprecated. Change-Id: If8872c89c6f8a1edfcab983eb064248fd5ff3115 Reviewed-By: John Baldwin --- gdb/aarch64-tdep.c | 2 +- gdb/amd64-tdep.c | 4 ++-- gdb/arm-tdep.c | 2 +- gdb/avr-tdep.c | 3 ++- gdb/bfin-tdep.c | 3 ++- gdb/csky-tdep.c | 4 ++-- gdb/frv-tdep.c | 3 ++- gdb/gdbarch-gen.h | 15 +++++++++++---- gdb/gdbarch.c | 30 +++++++++++++++--------------- gdb/gdbarch_components.py | 10 +++++++++- gdb/h8300-tdep.c | 3 ++- gdb/i386-tdep.c | 3 ++- gdb/ia64-tdep.c | 3 ++- gdb/m32c-tdep.c | 3 ++- gdb/m68hc11-tdep.c | 3 ++- gdb/mep-tdep.c | 3 ++- gdb/mips-tdep.c | 3 ++- gdb/msp430-tdep.c | 3 ++- gdb/nds32-tdep.c | 3 ++- gdb/regcache.c | 4 ++-- gdb/riscv-tdep.c | 9 +++++---- gdb/rl78-tdep.c | 3 ++- gdb/rs6000-tdep.c | 4 ++-- gdb/s390-tdep.c | 3 ++- gdb/sh-tdep.c | 9 ++++++--- gdb/sparc-tdep.c | 3 ++- gdb/sparc64-tdep.c | 3 ++- gdb/xtensa-tdep.c | 3 ++- 28 files changed, 90 insertions(+), 54 deletions(-) diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index d901b69ce11d..5b2d87be6bfc 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -4481,7 +4481,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_num_pseudo_regs (gdbarch, num_pseudo_regs); set_gdbarch_pseudo_register_read_value (gdbarch, aarch64_pseudo_read_value); - set_gdbarch_pseudo_register_write (gdbarch, aarch64_pseudo_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, aarch64_pseudo_write); set_tdesc_pseudo_register_name (gdbarch, aarch64_pseudo_register_name); set_tdesc_pseudo_register_type (gdbarch, aarch64_pseudo_register_type); set_tdesc_pseudo_register_reggroup_p (gdbarch, diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 955a6860631d..a0b4986d5b6c 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -3205,8 +3205,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch, set_gdbarch_pseudo_register_read_value (gdbarch, amd64_pseudo_register_read_value); - set_gdbarch_pseudo_register_write (gdbarch, - amd64_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + amd64_pseudo_register_write); set_gdbarch_ax_pseudo_register_collect (gdbarch, amd64_ax_pseudo_register_collect); diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 1ee8bdf46159..85fd37ba73a0 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -10906,7 +10906,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { set_gdbarch_num_pseudo_regs (gdbarch, num_pseudos); set_gdbarch_pseudo_register_read (gdbarch, arm_pseudo_read); - set_gdbarch_pseudo_register_write (gdbarch, arm_pseudo_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, arm_pseudo_write); } /* Add standard register aliases. We add aliases even for those diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c index be0601056a80..c0b954c4acc9 100644 --- a/gdb/avr-tdep.c +++ b/gdb/avr-tdep.c @@ -1510,7 +1510,8 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_num_pseudo_regs (gdbarch, AVR_NUM_PSEUDO_REGS); set_gdbarch_pseudo_register_read (gdbarch, avr_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, avr_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + avr_pseudo_register_write); set_gdbarch_return_value (gdbarch, avr_return_value); diff --git a/gdb/bfin-tdep.c b/gdb/bfin-tdep.c index 4b9067a2d0f7..0ff4355f573e 100644 --- a/gdb/bfin-tdep.c +++ b/gdb/bfin-tdep.c @@ -805,7 +805,8 @@ bfin_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_num_regs (gdbarch, BFIN_NUM_REGS); set_gdbarch_pseudo_register_read (gdbarch, bfin_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, bfin_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + bfin_pseudo_register_write); set_gdbarch_num_pseudo_regs (gdbarch, BFIN_NUM_PSEUDO_REGS); set_gdbarch_sp_regnum (gdbarch, BFIN_SP_REGNUM); set_gdbarch_pc_regnum (gdbarch, BFIN_PC_REGNUM); diff --git a/gdb/csky-tdep.c b/gdb/csky-tdep.c index e82b8dff546e..6cca72041a73 100644 --- a/gdb/csky-tdep.c +++ b/gdb/csky-tdep.c @@ -2872,8 +2872,8 @@ csky_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->fv_pseudo_registers_count); set_gdbarch_pseudo_register_read (gdbarch, csky_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, - csky_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write + (gdbarch, csky_pseudo_register_write); set_tdesc_pseudo_register_name (gdbarch, csky_pseudo_register_name); } diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c index 6528cf3e405e..7944228a6021 100644 --- a/gdb/frv-tdep.c +++ b/gdb/frv-tdep.c @@ -1499,7 +1499,8 @@ frv_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_register_sim_regno (gdbarch, frv_register_sim_regno); set_gdbarch_pseudo_register_read (gdbarch, frv_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, frv_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + frv_pseudo_register_write); set_gdbarch_skip_prologue (gdbarch, frv_skip_prologue); set_gdbarch_skip_main_prologue (gdbarch, frv_skip_main_prologue); diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h index c70bfc97634a..7b34dce3cfc8 100644 --- a/gdb/gdbarch-gen.h +++ b/gdb/gdbarch-gen.h @@ -200,11 +200,18 @@ typedef struct value * (gdbarch_pseudo_register_read_value_ftype) (struct gdbarc extern struct value * gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, frame_info_ptr next_frame, int cookednum); extern void set_gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value); -extern bool gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch); +/* Write bytes to a pseudo register. -typedef void (gdbarch_pseudo_register_write_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, const gdb_byte *buf); -extern void gdbarch_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, const gdb_byte *buf); -extern void set_gdbarch_pseudo_register_write (struct gdbarch *gdbarch, gdbarch_pseudo_register_write_ftype *pseudo_register_write); + This is marked as deprecated because it gets passed a regcache for + implementations to write raw registers in. This doesn't work for unwound + frames, where the raw registers backing the pseudo registers may have been + saved elsewhere. */ + +extern bool gdbarch_deprecated_pseudo_register_write_p (struct gdbarch *gdbarch); + +typedef void (gdbarch_deprecated_pseudo_register_write_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, const gdb_byte *buf); +extern void gdbarch_deprecated_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, const gdb_byte *buf); +extern void set_gdbarch_deprecated_pseudo_register_write (struct gdbarch *gdbarch, gdbarch_deprecated_pseudo_register_write_ftype *deprecated_pseudo_register_write); extern int gdbarch_num_regs (struct gdbarch *gdbarch); extern void set_gdbarch_num_regs (struct gdbarch *gdbarch, int num_regs); diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 06ff52576bdf..e198d339f6ba 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -74,7 +74,7 @@ struct gdbarch gdbarch_virtual_frame_pointer_ftype *virtual_frame_pointer = legacy_virtual_frame_pointer; gdbarch_pseudo_register_read_ftype *pseudo_register_read = nullptr; gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value = nullptr; - gdbarch_pseudo_register_write_ftype *pseudo_register_write = nullptr; + gdbarch_deprecated_pseudo_register_write_ftype *deprecated_pseudo_register_write = nullptr; int num_regs = -1; int num_pseudo_regs = 0; gdbarch_ax_pseudo_register_collect_ftype *ax_pseudo_register_collect = nullptr; @@ -330,7 +330,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of virtual_frame_pointer, invalid_p == 0 */ /* Skip verify of pseudo_register_read, has predicate. */ /* Skip verify of pseudo_register_read_value, has predicate. */ - /* Skip verify of pseudo_register_write, has predicate. */ + /* Skip verify of deprecated_pseudo_register_write, has predicate. */ if (gdbarch->num_regs == -1) log.puts ("\n\tnum_regs"); /* Skip verify of num_pseudo_regs, invalid_p == 0 */ @@ -650,11 +650,11 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: pseudo_register_read_value = <%s>\n", host_address_to_string (gdbarch->pseudo_register_read_value)); gdb_printf (file, - "gdbarch_dump: gdbarch_pseudo_register_write_p() = %d\n", - gdbarch_pseudo_register_write_p (gdbarch)); + "gdbarch_dump: gdbarch_deprecated_pseudo_register_write_p() = %d\n", + gdbarch_deprecated_pseudo_register_write_p (gdbarch)); gdb_printf (file, - "gdbarch_dump: pseudo_register_write = <%s>\n", - host_address_to_string (gdbarch->pseudo_register_write)); + "gdbarch_dump: deprecated_pseudo_register_write = <%s>\n", + host_address_to_string (gdbarch->deprecated_pseudo_register_write)); gdb_printf (file, "gdbarch_dump: num_regs = %s\n", plongest (gdbarch->num_regs)); @@ -1903,27 +1903,27 @@ set_gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, } bool -gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch) +gdbarch_deprecated_pseudo_register_write_p (struct gdbarch *gdbarch) { gdb_assert (gdbarch != NULL); - return gdbarch->pseudo_register_write != NULL; + return gdbarch->deprecated_pseudo_register_write != NULL; } void -gdbarch_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, const gdb_byte *buf) +gdbarch_deprecated_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, const gdb_byte *buf) { gdb_assert (gdbarch != NULL); - gdb_assert (gdbarch->pseudo_register_write != NULL); + gdb_assert (gdbarch->deprecated_pseudo_register_write != NULL); if (gdbarch_debug >= 2) - gdb_printf (gdb_stdlog, "gdbarch_pseudo_register_write called\n"); - gdbarch->pseudo_register_write (gdbarch, regcache, cookednum, buf); + gdb_printf (gdb_stdlog, "gdbarch_deprecated_pseudo_register_write called\n"); + gdbarch->deprecated_pseudo_register_write (gdbarch, regcache, cookednum, buf); } void -set_gdbarch_pseudo_register_write (struct gdbarch *gdbarch, - gdbarch_pseudo_register_write_ftype pseudo_register_write) +set_gdbarch_deprecated_pseudo_register_write (struct gdbarch *gdbarch, + gdbarch_deprecated_pseudo_register_write_ftype deprecated_pseudo_register_write) { - gdbarch->pseudo_register_write = pseudo_register_write; + gdbarch->deprecated_pseudo_register_write = deprecated_pseudo_register_write; } int diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py index c597b38ad5a9..ee3fd2b69454 100644 --- a/gdb/gdbarch_components.py +++ b/gdb/gdbarch_components.py @@ -419,8 +419,16 @@ never be called. ) Method( + comment=""" +Write bytes to a pseudo register. + +This is marked as deprecated because it gets passed a regcache for +implementations to write raw registers in. This doesn't work for unwound +frames, where the raw registers backing the pseudo registers may have been +saved elsewhere. +""", type="void", - name="pseudo_register_write", + name="deprecated_pseudo_register_write", params=[ ("struct regcache *", "regcache"), ("int", "cookednum"), diff --git a/gdb/h8300-tdep.c b/gdb/h8300-tdep.c index d1494916f594..20f503c209bf 100644 --- a/gdb/h8300-tdep.c +++ b/gdb/h8300-tdep.c @@ -1318,7 +1318,8 @@ h8300_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) } set_gdbarch_pseudo_register_read (gdbarch, h8300_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, h8300_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + h8300_pseudo_register_write); /* * Basic register fields and methods. diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index be1aa83bbbdb..228b390245f6 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -8678,7 +8678,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Pseudo registers may be changed by amd64_init_abi. */ set_gdbarch_pseudo_register_read_value (gdbarch, i386_pseudo_register_read_value); - set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + i386_pseudo_register_write); set_gdbarch_ax_pseudo_register_collect (gdbarch, i386_ax_pseudo_register_collect); diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c index b009b46ef6df..699959a8bf0b 100644 --- a/gdb/ia64-tdep.c +++ b/gdb/ia64-tdep.c @@ -3959,7 +3959,8 @@ ia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_register_type (gdbarch, ia64_register_type); set_gdbarch_pseudo_register_read (gdbarch, ia64_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, ia64_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + ia64_pseudo_register_write); set_gdbarch_dwarf2_reg_to_regnum (gdbarch, ia64_dwarf_reg_to_regnum); set_gdbarch_register_reggroup_p (gdbarch, ia64_register_reggroup_p); set_gdbarch_convert_register_p (gdbarch, ia64_convert_register_p); diff --git a/gdb/m32c-tdep.c b/gdb/m32c-tdep.c index a0f1779c41b0..3efeb0032e76 100644 --- a/gdb/m32c-tdep.c +++ b/gdb/m32c-tdep.c @@ -977,7 +977,8 @@ make_regs (struct gdbarch *arch) set_gdbarch_register_name (arch, m32c_register_name); set_gdbarch_register_type (arch, m32c_register_type); set_gdbarch_pseudo_register_read (arch, m32c_pseudo_register_read); - set_gdbarch_pseudo_register_write (arch, m32c_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (arch, + m32c_pseudo_register_write); set_gdbarch_register_sim_regno (arch, m32c_register_sim_regno); set_gdbarch_stab_reg_to_regnum (arch, m32c_debug_info_reg_to_regnum); set_gdbarch_dwarf2_reg_to_regnum (arch, m32c_debug_info_reg_to_regnum); diff --git a/gdb/m68hc11-tdep.c b/gdb/m68hc11-tdep.c index 1257c55ce667..668158f15a09 100644 --- a/gdb/m68hc11-tdep.c +++ b/gdb/m68hc11-tdep.c @@ -1491,7 +1491,8 @@ m68hc11_gdbarch_init (struct gdbarch_info info, set_gdbarch_register_name (gdbarch, m68hc11_register_name); set_gdbarch_register_type (gdbarch, m68hc11_register_type); set_gdbarch_pseudo_register_read (gdbarch, m68hc11_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, m68hc11_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + m68hc11_pseudo_register_write); set_gdbarch_push_dummy_call (gdbarch, m68hc11_push_dummy_call); diff --git a/gdb/mep-tdep.c b/gdb/mep-tdep.c index 6210b929f9d0..ad630d60bf1e 100644 --- a/gdb/mep-tdep.c +++ b/gdb/mep-tdep.c @@ -2424,7 +2424,8 @@ mep_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_register_type (gdbarch, mep_register_type); set_gdbarch_num_pseudo_regs (gdbarch, MEP_NUM_PSEUDO_REGS); set_gdbarch_pseudo_register_read (gdbarch, mep_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, mep_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + mep_pseudo_register_write); set_gdbarch_dwarf2_reg_to_regnum (gdbarch, mep_debug_reg_to_regnum); set_gdbarch_stab_reg_to_regnum (gdbarch, mep_debug_reg_to_regnum); diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index fc3193ea27a5..8749c7c9eeaf 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -8518,7 +8518,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_long_double_bit (gdbarch, 64); set_gdbarch_register_reggroup_p (gdbarch, mips_register_reggroup_p); set_gdbarch_pseudo_register_read (gdbarch, mips_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, mips_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + mips_pseudo_register_write); set_gdbarch_ax_pseudo_register_collect (gdbarch, mips_ax_pseudo_register_collect); diff --git a/gdb/msp430-tdep.c b/gdb/msp430-tdep.c index c03e12c9486f..cc2ac4d2621f 100644 --- a/gdb/msp430-tdep.c +++ b/gdb/msp430-tdep.c @@ -937,7 +937,8 @@ msp430_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_sp_regnum (gdbarch, MSP430_SP_REGNUM); set_gdbarch_register_reggroup_p (gdbarch, msp430_register_reggroup_p); set_gdbarch_pseudo_register_read (gdbarch, msp430_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, msp430_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + msp430_pseudo_register_write); set_gdbarch_dwarf2_reg_to_regnum (gdbarch, msp430_dwarf2_reg_to_regnum); set_gdbarch_register_sim_regno (gdbarch, msp430_register_sim_regno); diff --git a/gdb/nds32-tdep.c b/gdb/nds32-tdep.c index 7618a81fc256..83685d06f3ee 100644 --- a/gdb/nds32-tdep.c +++ b/gdb/nds32-tdep.c @@ -2001,7 +2001,8 @@ nds32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) else if (use_pseudo_fsrs == 1) { set_gdbarch_pseudo_register_read (gdbarch, nds32_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, nds32_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write + (gdbarch, nds32_pseudo_register_write); set_tdesc_pseudo_register_name (gdbarch, nds32_pseudo_register_name); set_tdesc_pseudo_register_type (gdbarch, nds32_pseudo_register_type); set_gdbarch_num_pseudo_regs (gdbarch, num_fsr_map[fpu_freg]); diff --git a/gdb/regcache.c b/gdb/regcache.c index 9575988760ba..0e3316aaa096 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -912,8 +912,8 @@ regcache::cooked_write (int regnum, gdb::array_view src) if (regnum < num_raw_registers ()) raw_write (regnum, src); else - gdbarch_pseudo_register_write (m_descr->gdbarch, this, regnum, - src.data ()); + gdbarch_deprecated_pseudo_register_write (m_descr->gdbarch, this, regnum, + src.data ()); } /* See regcache.h. */ diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index 8110a8deedbf..4c129a66652f 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -1002,9 +1002,9 @@ riscv_pseudo_register_read (struct gdbarch *gdbarch, return REG_UNKNOWN; } -/* Implement gdbarch_pseudo_register_write. Write the contents of BUF into - pseudo-register REGNUM in REGCACHE. BUF is sized based on the type of - register REGNUM. */ +/* Implement gdbarch_deprecated_pseudo_register_write. Write the contents of + BUF into pseudo-register REGNUM in REGCACHE. BUF is sized based on the type + of register REGNUM. */ static void riscv_pseudo_register_write (struct gdbarch *gdbarch, @@ -4229,7 +4229,8 @@ riscv_gdbarch_init (struct gdbarch_info info, set_tdesc_pseudo_register_reggroup_p (gdbarch, riscv_pseudo_register_reggroup_p); set_gdbarch_pseudo_register_read (gdbarch, riscv_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, riscv_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + riscv_pseudo_register_write); /* Finalise the target description registers. */ tdesc_use_registers (gdbarch, tdesc, std::move (tdesc_data), diff --git a/gdb/rl78-tdep.c b/gdb/rl78-tdep.c index 2f40fbddaa1e..19298063186f 100644 --- a/gdb/rl78-tdep.c +++ b/gdb/rl78-tdep.c @@ -1436,7 +1436,8 @@ rl78_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_pc_regnum (gdbarch, RL78_PC_REGNUM); set_gdbarch_sp_regnum (gdbarch, RL78_SP_REGNUM); set_gdbarch_pseudo_register_read (gdbarch, rl78_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, rl78_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + rl78_pseudo_register_write); set_gdbarch_dwarf2_reg_to_regnum (gdbarch, rl78_dwarf_reg_to_regnum); set_gdbarch_register_reggroup_p (gdbarch, rl78_register_reggroup_p); set_gdbarch_register_sim_regno (gdbarch, rl78_register_sim_regno); diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 643997e5bd7d..a7e0bf5305b5 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -8353,8 +8353,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) || have_vsx || have_htm_fpu || have_htm_vsx) { set_gdbarch_pseudo_register_read (gdbarch, rs6000_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, - rs6000_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write + (gdbarch, rs6000_pseudo_register_write); set_gdbarch_ax_pseudo_register_collect (gdbarch, rs6000_ax_pseudo_register_collect); } diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c index 5b58cb382e30..fcba7a1a5608 100644 --- a/gdb/s390-tdep.c +++ b/gdb/s390-tdep.c @@ -7081,7 +7081,8 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Pseudo registers. */ set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, s390_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + s390_pseudo_register_write); set_tdesc_pseudo_register_name (gdbarch, s390_pseudo_register_name); set_tdesc_pseudo_register_type (gdbarch, s390_pseudo_register_type); set_tdesc_pseudo_register_reggroup_p (gdbarch, diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c index babf85eeb906..ae1ce1e44713 100644 --- a/gdb/sh-tdep.c +++ b/gdb/sh-tdep.c @@ -2286,7 +2286,8 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_fp0_regnum (gdbarch, 25); set_gdbarch_num_pseudo_regs (gdbarch, 9); set_gdbarch_pseudo_register_read (gdbarch, sh_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, sh_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + sh_pseudo_register_write); set_gdbarch_return_value (gdbarch, sh_return_value_fpu); set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu); break; @@ -2297,7 +2298,8 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_num_pseudo_regs (gdbarch, 1); set_gdbarch_pseudo_register_read (gdbarch, sh_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, sh_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + sh_pseudo_register_write); break; case bfd_mach_sh_dsp: @@ -2337,7 +2339,8 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_fp0_regnum (gdbarch, 25); set_gdbarch_num_pseudo_regs (gdbarch, 13); set_gdbarch_pseudo_register_read (gdbarch, sh_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, sh_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + sh_pseudo_register_write); set_gdbarch_return_value (gdbarch, sh_return_value_fpu); set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu); break; diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index 78f240db04e7..3a053a99e351 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -1844,7 +1844,8 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_tdesc_pseudo_register_name (gdbarch, sparc32_pseudo_register_name); set_tdesc_pseudo_register_type (gdbarch, sparc32_pseudo_register_type); set_gdbarch_pseudo_register_read (gdbarch, sparc32_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, sparc32_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + sparc32_pseudo_register_write); /* Register numbers of various important registers. */ set_gdbarch_sp_regnum (gdbarch, SPARC_SP_REGNUM); /* %sp */ diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c index abbbb73d1db9..61f486689f15 100644 --- a/gdb/sparc64-tdep.c +++ b/gdb/sparc64-tdep.c @@ -1825,7 +1825,8 @@ sparc64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_tdesc_pseudo_register_name (gdbarch, sparc64_pseudo_register_name); set_tdesc_pseudo_register_type (gdbarch, sparc64_pseudo_register_type); set_gdbarch_pseudo_register_read (gdbarch, sparc64_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, sparc64_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + sparc64_pseudo_register_write); /* Register numbers of various important registers. */ set_gdbarch_pc_regnum (gdbarch, SPARC64_PC_REGNUM); /* %pc */ diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c index 9e7bfde193fc..6e426c457894 100644 --- a/gdb/xtensa-tdep.c +++ b/gdb/xtensa-tdep.c @@ -3176,7 +3176,8 @@ xtensa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Pseudo-Register read/write. */ set_gdbarch_pseudo_register_read (gdbarch, xtensa_pseudo_register_read); - set_gdbarch_pseudo_register_write (gdbarch, xtensa_pseudo_register_write); + set_gdbarch_deprecated_pseudo_register_write (gdbarch, + xtensa_pseudo_register_write); /* Set target information. */ set_gdbarch_num_regs (gdbarch, tdep->num_regs); From patchwork Fri Dec 1 16:27:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81155 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 2A2B838618A3 for ; Fri, 1 Dec 2023 16:32:52 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 9DBEE385E004 for ; Fri, 1 Dec 2023 16:31:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9DBEE385E004 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 9DBEE385E004 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448322; cv=none; b=gEQZYI0MizPyR2akMq/zxXeoGnz+vbkXTxPQiat9MYIRkLJu+9ocu9vfVD+AbVcFPQPxQHKQ2Wm5OjZ8qTkXC+Fh0hpyj1vRphZYl0JRnkPvdhiqqvO5S9devyXzYgImQ57L863pKUNfR79cstOCpeFeRsywWgh58iOSkFcm2Sg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448322; c=relaxed/simple; bh=WtcrcDv/rof8R/hAj8q6xKXbWp4KHF/7Oxi4/bmija8=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=InkkWcAZBvnczXLnQEX+X7v5NBvV1dBKkMFpBAIhAR/Rd4VxgwQT2JXy3ER+RzjTpN/VUktiXQDpGmGF8wyuoRO/RPTwiICIasrjfnEHJyFG3mw9MRjNWh1I4nQXYS492JibVUnkd07/owa4HwdoSwqlRMxjafXYCsPr+hOugVc= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id DAA521E0BB; Fri, 1 Dec 2023 11:31:58 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 17/24] gdb: add gdbarch_pseudo_register_write that takes a frame Date: Fri, 1 Dec 2023 11:27:30 -0500 Message-ID: <20231201162751.741751-18-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org New in v2: - Add missing comments, fix typos Add a new variant of gdbarch_pseudo_register_write that takes a frame_info in order to write raw registers. Use this new method when available: - in put_frame_register, when trying to write a pseudo register to a given frame - in regcache::cooked_write No implementation is migrated to use this new method (that will come in subsequent patches), so no behavior change is expected here. The objective is to fix writing pseudo registers to non-current frames. See previous commit "gdb: read pseudo register through frame" for a more detailed explanation. Change-Id: Ie7fe364a15a4d86c2ecb09de2b4baa08c45555ac Reviewed-By: John Baldwin --- gdb/frame.c | 9 +++++- gdb/gdbarch-gen.h | 15 ++++++++- gdb/gdbarch.c | 32 ++++++++++++++++++ gdb/gdbarch_components.py | 19 +++++++++++ gdb/regcache.c | 4 +++ gdb/value.c | 68 +++++++++++++++++++++++++++++++++++++++ gdb/value.h | 22 +++++++++++++ 7 files changed, 167 insertions(+), 2 deletions(-) diff --git a/gdb/frame.c b/gdb/frame.c index a9cad1dca8fb..5f4c8c621a04 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1453,7 +1453,14 @@ put_frame_register (frame_info_ptr next_frame, int regnum, break; } case lval_register: - get_thread_regcache (inferior_thread ())->cooked_write (realnum, buf); + /* Not sure if that's always true... but we have a problem if not. */ + gdb_assert (size == register_size (gdbarch, realnum)); + + if (realnum < gdbarch_num_regs (gdbarch) + || !gdbarch_pseudo_register_write_p (gdbarch)) + get_thread_regcache (inferior_thread ())->cooked_write (realnum, buf); + else + gdbarch_pseudo_register_write (gdbarch, next_frame, realnum, buf); break; default: error (_("Attempt to assign to an unmodifiable value.")); diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h index 7b34dce3cfc8..80d40136c379 100644 --- a/gdb/gdbarch-gen.h +++ b/gdb/gdbarch-gen.h @@ -200,12 +200,25 @@ typedef struct value * (gdbarch_pseudo_register_read_value_ftype) (struct gdbarc extern struct value * gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, frame_info_ptr next_frame, int cookednum); extern void set_gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value); +/* Write bytes in BUF to pseudo register with number PSEUDO_REG_NUM. + + Raw registers backing the pseudo register should be written to using + NEXT_FRAME. */ + +extern bool gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch); + +typedef void (gdbarch_pseudo_register_write_ftype) (struct gdbarch *gdbarch, frame_info_ptr next_frame, int pseudo_reg_num, gdb::array_view buf); +extern void gdbarch_pseudo_register_write (struct gdbarch *gdbarch, frame_info_ptr next_frame, int pseudo_reg_num, gdb::array_view buf); +extern void set_gdbarch_pseudo_register_write (struct gdbarch *gdbarch, gdbarch_pseudo_register_write_ftype *pseudo_register_write); + /* Write bytes to a pseudo register. This is marked as deprecated because it gets passed a regcache for implementations to write raw registers in. This doesn't work for unwound frames, where the raw registers backing the pseudo registers may have been - saved elsewhere. */ + saved elsewhere. + + Implementations should be migrated to implement pseudo_register_write instead. */ extern bool gdbarch_deprecated_pseudo_register_write_p (struct gdbarch *gdbarch); diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index e198d339f6ba..d584305fefb2 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -74,6 +74,7 @@ struct gdbarch gdbarch_virtual_frame_pointer_ftype *virtual_frame_pointer = legacy_virtual_frame_pointer; gdbarch_pseudo_register_read_ftype *pseudo_register_read = nullptr; gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value = nullptr; + gdbarch_pseudo_register_write_ftype *pseudo_register_write = nullptr; gdbarch_deprecated_pseudo_register_write_ftype *deprecated_pseudo_register_write = nullptr; int num_regs = -1; int num_pseudo_regs = 0; @@ -330,6 +331,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of virtual_frame_pointer, invalid_p == 0 */ /* Skip verify of pseudo_register_read, has predicate. */ /* Skip verify of pseudo_register_read_value, has predicate. */ + /* Skip verify of pseudo_register_write, has predicate. */ /* Skip verify of deprecated_pseudo_register_write, has predicate. */ if (gdbarch->num_regs == -1) log.puts ("\n\tnum_regs"); @@ -649,6 +651,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) gdb_printf (file, "gdbarch_dump: pseudo_register_read_value = <%s>\n", host_address_to_string (gdbarch->pseudo_register_read_value)); + gdb_printf (file, + "gdbarch_dump: gdbarch_pseudo_register_write_p() = %d\n", + gdbarch_pseudo_register_write_p (gdbarch)); + gdb_printf (file, + "gdbarch_dump: pseudo_register_write = <%s>\n", + host_address_to_string (gdbarch->pseudo_register_write)); gdb_printf (file, "gdbarch_dump: gdbarch_deprecated_pseudo_register_write_p() = %d\n", gdbarch_deprecated_pseudo_register_write_p (gdbarch)); @@ -1902,6 +1910,30 @@ set_gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, gdbarch->pseudo_register_read_value = pseudo_register_read_value; } +bool +gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->pseudo_register_write != NULL; +} + +void +gdbarch_pseudo_register_write (struct gdbarch *gdbarch, frame_info_ptr next_frame, int pseudo_reg_num, gdb::array_view buf) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->pseudo_register_write != NULL); + if (gdbarch_debug >= 2) + gdb_printf (gdb_stdlog, "gdbarch_pseudo_register_write called\n"); + gdbarch->pseudo_register_write (gdbarch, next_frame, pseudo_reg_num, buf); +} + +void +set_gdbarch_pseudo_register_write (struct gdbarch *gdbarch, + gdbarch_pseudo_register_write_ftype pseudo_register_write) +{ + gdbarch->pseudo_register_write = pseudo_register_write; +} + bool gdbarch_deprecated_pseudo_register_write_p (struct gdbarch *gdbarch) { diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py index ee3fd2b69454..4352f7066512 100644 --- a/gdb/gdbarch_components.py +++ b/gdb/gdbarch_components.py @@ -418,6 +418,23 @@ never be called. predicate=True, ) +Method( + comment=""" +Write bytes in BUF to pseudo register with number PSEUDO_REG_NUM. + +Raw registers backing the pseudo register should be written to using +NEXT_FRAME. +""", + type="void", + name="pseudo_register_write", + params=[ + ("frame_info_ptr", "next_frame"), + ("int", "pseudo_reg_num"), + ("gdb::array_view", "buf"), + ], + predicate=True, +) + Method( comment=""" Write bytes to a pseudo register. @@ -426,6 +443,8 @@ This is marked as deprecated because it gets passed a regcache for implementations to write raw registers in. This doesn't work for unwound frames, where the raw registers backing the pseudo registers may have been saved elsewhere. + +Implementations should be migrated to implement pseudo_register_write instead. """, type="void", name="deprecated_pseudo_register_write", diff --git a/gdb/regcache.c b/gdb/regcache.c index 0e3316aaa096..6140a05f02b2 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -911,6 +911,10 @@ regcache::cooked_write (int regnum, gdb::array_view src) if (regnum < num_raw_registers ()) raw_write (regnum, src); + else if (gdbarch_pseudo_register_write_p (m_descr->gdbarch)) + gdbarch_pseudo_register_write + (m_descr->gdbarch, get_next_frame_sentinel_okay (get_current_frame ()), + regnum, src); else gdbarch_deprecated_pseudo_register_write (m_descr->gdbarch, this, regnum, src.data ()); diff --git a/gdb/value.c b/gdb/value.c index 9d826d4fdbed..f61949bf9422 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -4057,6 +4057,23 @@ pseudo_from_raw_part (frame_info_ptr next_frame, int pseudo_reg_num, /* See value.h. */ +void +pseudo_to_raw_part (frame_info_ptr next_frame, + gdb::array_view pseudo_buf, + int raw_reg_num, int raw_offset) +{ + int raw_reg_size + = register_size (frame_unwind_arch (next_frame), raw_reg_num); + + /* When overflowing a register, put_frame_register_bytes writes to the + subsequent registers. We don't want that behavior here, so make sure + the write is wholly within register RAW_REG_NUM. */ + gdb_assert (raw_offset + pseudo_buf.size () <= raw_reg_size); + put_frame_register_bytes (next_frame, raw_reg_num, raw_offset, pseudo_buf); +} + +/* See value.h. */ + value * pseudo_from_concat_raw (frame_info_ptr next_frame, int pseudo_reg_num, int raw_reg_1_num, int raw_reg_2_num) @@ -4080,6 +4097,29 @@ pseudo_from_concat_raw (frame_info_ptr next_frame, int pseudo_reg_num, return pseudo_reg_val; } +/* See value.h. */ + +void +pseudo_to_concat_raw (frame_info_ptr next_frame, + gdb::array_view pseudo_buf, + int raw_reg_1_num, int raw_reg_2_num) +{ + int src_offset = 0; + gdbarch *arch = frame_unwind_arch (next_frame); + + int raw_reg_1_size = register_size (arch, raw_reg_1_num); + put_frame_register_bytes (next_frame, raw_reg_1_num, 0, + pseudo_buf.slice (src_offset, raw_reg_1_size)); + src_offset += raw_reg_1_size; + + int raw_reg_2_size = register_size (arch, raw_reg_2_num); + put_frame_register_bytes (next_frame, raw_reg_2_num, 0, + pseudo_buf.slice (src_offset, raw_reg_2_size)); + src_offset += raw_reg_2_size; + + gdb_assert (src_offset == pseudo_buf.size ()); +} + /* See value.h. */ value * @@ -4111,6 +4151,34 @@ pseudo_from_concat_raw (frame_info_ptr next_frame, int pseudo_reg_num, return pseudo_reg_val; } +/* See value.h. */ + +void +pseudo_to_concat_raw (frame_info_ptr next_frame, + gdb::array_view pseudo_buf, + int raw_reg_1_num, int raw_reg_2_num, int raw_reg_3_num) +{ + int src_offset = 0; + gdbarch *arch = frame_unwind_arch (next_frame); + + int raw_reg_1_size = register_size (arch, raw_reg_1_num); + put_frame_register_bytes (next_frame, raw_reg_1_num, 0, + pseudo_buf.slice (src_offset, raw_reg_1_size)); + src_offset += raw_reg_1_size; + + int raw_reg_2_size = register_size (arch, raw_reg_2_num); + put_frame_register_bytes (next_frame, raw_reg_2_num, 0, + pseudo_buf.slice (src_offset, raw_reg_2_size)); + src_offset += raw_reg_2_size; + + int raw_reg_3_size = register_size (arch, raw_reg_3_num); + put_frame_register_bytes (next_frame, raw_reg_3_num, 0, + pseudo_buf.slice (src_offset, raw_reg_3_size)); + src_offset += raw_reg_3_size; + + gdb_assert (src_offset == pseudo_buf.size ()); +} + /* Implementation of the convenience function $_isvoid. */ static struct value * diff --git a/gdb/value.h b/gdb/value.h index 935d9ebfd8c9..d7bda1e8d2c9 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -1661,6 +1661,13 @@ struct scoped_array_length_limiting value *pseudo_from_raw_part (frame_info_ptr next_frame, int pseudo_reg_num, int raw_reg_num, int raw_offset); +/* Write PSEUDO_BUF, the contents of a pseudo register, to part of raw register + RAW_REG_NUM starting at RAW_OFFSET. */ + +void pseudo_to_raw_part (frame_info_ptr next_frame, + gdb::array_view pseudo_buf, + int raw_reg_num, int raw_offset); + /* Create a value for pseudo register PSEUDO_REG_NUM by concatenating raw registers RAW_REG_1_NUM and RAW_REG_2_NUM. @@ -1670,10 +1677,25 @@ value *pseudo_from_raw_part (frame_info_ptr next_frame, int pseudo_reg_num, value *pseudo_from_concat_raw (frame_info_ptr next_frame, int pseudo_reg_num, int raw_reg_1_num, int raw_reg_2_num); +/* Write PSEUDO_BUF, the contents of a pseudo register, to the two raw registers + RAW_REG_1_NUM and RAW_REG_2_NUM. */ + +void pseudo_to_concat_raw (frame_info_ptr next_frame, + gdb::array_view pseudo_buf, + int raw_reg_1_num, int raw_reg_2_num); + /* Same as the above, but with three raw registers. */ value *pseudo_from_concat_raw (frame_info_ptr next_frame, int pseudo_reg_num, int raw_reg_1_num, int raw_reg_2_num, int raw_reg_3_num); +/* Write PSEUDO_BUF, the contents of a pseudo register, to the three raw + registers RAW_REG_1_NUM, RAW_REG_2_NUM and RAW_REG_3_NUM. */ + +void pseudo_to_concat_raw (frame_info_ptr next_frame, + gdb::array_view pseudo_buf, + int raw_reg_1_num, int raw_reg_2_num, + int raw_reg_3_num); + #endif /* !defined (VALUE_H) */ From patchwork Fri Dec 1 16:27:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81153 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 AFD28384F9AF for ; Fri, 1 Dec 2023 16:32:35 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id D9AEB386101B for ; Fri, 1 Dec 2023 16:31:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D9AEB386101B Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D9AEB386101B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448322; cv=none; b=MMeb8DKnmNll7wyxYsxwOjlumfJ8Fol5HSMTTYKfe2IuNHiKEzlowIZ+4z80dqOg2Uvt8x0EfYq/C0QW4+qlqUmPW5cHp6rrT3/S8DU7OPBH7gaUxwQYmYIDBIj5I5Iccu0hreeVmTZ3pvhdLrT6woB9aaXjdps6m7x0ZNrEj8s= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448322; c=relaxed/simple; bh=fSuD6VIy+SnFgKfhT6lMgxXkAsJmrfkRiJPGl6SLxj8=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=eB5/GIluQyLkltN1TaBUhkEBevrMSlinsd67Fi5HaJOovItIsq70nzhDF47crGEoMalcxclVakuVba/ifjYBud0wL3DsfDibE3JsDTnAw/W6bqV87/6Agcvo7HUxk9e64m+nxsvX4jhkuV2nKTA/Lk9m+xH8eBK9Us4/uTupcLE= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 270A31E0C0; Fri, 1 Dec 2023 11:31:59 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 18/24] gdb: migrate i386 and amd64 to the new gdbarch_pseudo_register_write Date: Fri, 1 Dec 2023 11:27:31 -0500 Message-ID: <20231201162751.741751-19-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org New in v2: - Move some changes from here to the previous patch (where they belong) Make i386 and amd64 use the new gdbarch_pseudo_register_write. This fixes writing to pseudo registers in non-current frames for those architectures. Change-Id: I4977e8fe12d2cef116f8834c34cdf6fec618554f Reviewed-By: John Baldwin --- gdb/amd64-tdep.c | 39 +++---------- gdb/i386-tdep.c | 146 +++++++++++++++++------------------------------ gdb/i386-tdep.h | 6 +- 3 files changed, 61 insertions(+), 130 deletions(-) diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index a0b4986d5b6c..4b9dbbab66e8 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -380,9 +380,8 @@ amd64_pseudo_register_read_value (gdbarch *gdbarch, frame_info_ptr next_frame, } static void -amd64_pseudo_register_write (struct gdbarch *gdbarch, - struct regcache *regcache, - int regnum, const gdb_byte *buf) +amd64_pseudo_register_write (gdbarch *gdbarch, frame_info_ptr next_frame, + int regnum, gdb::array_view buf) { i386_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); @@ -393,41 +392,18 @@ amd64_pseudo_register_write (struct gdbarch *gdbarch, if (gpnum >= AMD64_NUM_LOWER_BYTE_REGS) { gpnum -= AMD64_NUM_LOWER_BYTE_REGS; - gdb_byte raw_buf[register_size (gdbarch, gpnum)]; - - /* Read ... AH, BH, CH, DH. */ - regcache->raw_read (gpnum, raw_buf); - /* ... Modify ... (always little endian). */ - memcpy (raw_buf + 1, buf, 1); - /* ... Write. */ - regcache->raw_write (gpnum, raw_buf); + pseudo_to_raw_part (next_frame, buf, gpnum, 1); } else - { - gdb_byte raw_buf[register_size (gdbarch, gpnum)]; - - /* Read ... */ - regcache->raw_read (gpnum, raw_buf); - /* ... Modify ... (always little endian). */ - memcpy (raw_buf, buf, 1); - /* ... Write. */ - regcache->raw_write (gpnum, raw_buf); - } + pseudo_to_raw_part (next_frame, buf, gpnum, 0); } else if (i386_dword_regnum_p (gdbarch, regnum)) { int gpnum = regnum - tdep->eax_regnum; - gdb_byte raw_buf[register_size (gdbarch, gpnum)]; - - /* Read ... */ - regcache->raw_read (gpnum, raw_buf); - /* ... Modify ... (always little endian). */ - memcpy (raw_buf, buf, 4); - /* ... Write. */ - regcache->raw_write (gpnum, raw_buf); + pseudo_to_raw_part (next_frame, buf, gpnum, 0); } else - i386_pseudo_register_write (gdbarch, regcache, regnum, buf); + i386_pseudo_register_write (gdbarch, next_frame, regnum, buf); } /* Implement the 'ax_pseudo_register_collect' gdbarch method. */ @@ -3205,8 +3181,7 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch, set_gdbarch_pseudo_register_read_value (gdbarch, amd64_pseudo_register_read_value); - set_gdbarch_deprecated_pseudo_register_write (gdbarch, - amd64_pseudo_register_write); + set_gdbarch_pseudo_register_write (gdbarch, amd64_pseudo_register_write); set_gdbarch_ax_pseudo_register_collect (gdbarch, amd64_ax_pseudo_register_collect); diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 228b390245f6..d5602917aa8c 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -3391,26 +3391,6 @@ i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum) internal_error (_("invalid regnum")); } -/* Map a cooked register onto a raw register or memory. For the i386, - the MMX registers need to be mapped onto floating point registers. */ - -static int -i386_mmx_regnum_to_fp_regnum (readable_regcache *regcache, int regnum) -{ - gdbarch *arch = regcache->arch (); - i386_gdbarch_tdep *tdep = gdbarch_tdep (arch); - int mmxreg, fpreg; - ULONGEST fstat; - int tos; - - mmxreg = regnum - tdep->mm0_regnum; - regcache->raw_read (I387_FSTAT_REGNUM (tdep), &fstat); - tos = (fstat >> 11) & 0x7; - fpreg = (mmxreg + tos) % 8; - - return (I387_ST0_REGNUM (tdep) + fpreg); -} - /* Map a cooked register onto a raw register or memory. For the i386, the MMX registers need to be mapped onto floating point registers. */ @@ -3537,115 +3517,92 @@ i386_pseudo_register_read_value (gdbarch *gdbarch, frame_info_ptr next_frame, } void -i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, - int regnum, const gdb_byte *buf) +i386_pseudo_register_write (gdbarch *gdbarch, frame_info_ptr next_frame, + const int pseudo_reg_num, + gdb::array_view buf) { - gdb_byte raw_buf[I386_MAX_REGISTER_SIZE]; - - if (i386_mmx_regnum_p (gdbarch, regnum)) + if (i386_mmx_regnum_p (gdbarch, pseudo_reg_num)) { - int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum); + int fpnum = i386_mmx_regnum_to_fp_regnum (next_frame, pseudo_reg_num); - /* Read ... */ - regcache->raw_read (fpnum, raw_buf); - /* ... Modify ... (always little endian). */ - memcpy (raw_buf, buf, register_size (gdbarch, regnum)); - /* ... Write. */ - regcache->raw_write (fpnum, raw_buf); + pseudo_to_raw_part (next_frame, buf, fpnum, 0); } else { i386_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - if (i386_bnd_regnum_p (gdbarch, regnum)) + if (i386_bnd_regnum_p (gdbarch, pseudo_reg_num)) { - ULONGEST upper, lower; int size = builtin_type (gdbarch)->builtin_data_ptr->length (); bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ()); /* New values from input value. */ - regnum -= tdep->bnd0_regnum; - lower = extract_unsigned_integer (buf, size, byte_order); - upper = extract_unsigned_integer (buf + size, size, byte_order); + int reg_index = pseudo_reg_num - tdep->bnd0_regnum; + int raw_regnum = I387_BND0R_REGNUM (tdep) + reg_index; - /* Fetching register buffer. */ - regcache->raw_read (I387_BND0R_REGNUM (tdep) + regnum, - raw_buf); + value *bndr_value = value_of_register (raw_regnum, next_frame); + gdb::array_view bndr_view + = bndr_value->contents_writeable (); - upper = ~upper; + /* Copy lower bytes directly. */ + copy (buf.slice (0, size), bndr_view.slice (0, size)); - /* Set register bits. */ - memcpy (raw_buf, &lower, 8); - memcpy (raw_buf + 8, &upper, 8); + /* Convert and then copy upper bytes. */ + ULONGEST upper + = extract_unsigned_integer (buf.slice (size, size), byte_order); + upper = ~upper; + store_unsigned_integer (bndr_view.slice (8, size), byte_order, + upper); - regcache->raw_write (I387_BND0R_REGNUM (tdep) + regnum, raw_buf); + put_frame_register (next_frame, raw_regnum, bndr_view); } - else if (i386_zmm_regnum_p (gdbarch, regnum)) + else if (i386_zmm_regnum_p (gdbarch, pseudo_reg_num)) { - regnum -= tdep->zmm0_regnum; + /* Which register is it, relative to zmm0. */ + int reg_index_0 = pseudo_reg_num - tdep->zmm0_regnum; - if (regnum < num_lower_zmm_regs) - { - /* Write lower 128bits. */ - regcache->raw_write (I387_XMM0_REGNUM (tdep) + regnum, buf); - /* Write upper 128bits. */ - regcache->raw_write (I387_YMM0_REGNUM (tdep) + regnum, buf + 16); - } + if (reg_index_0 < num_lower_zmm_regs) + pseudo_to_concat_raw (next_frame, buf, + I387_XMM0_REGNUM (tdep) + reg_index_0, + I387_YMM0_REGNUM (tdep) + reg_index_0, + tdep->zmm0h_regnum + reg_index_0); else { - /* Write lower 128bits. */ - regcache->raw_write (I387_XMM16_REGNUM (tdep) + regnum - - num_lower_zmm_regs, buf); - /* Write upper 128bits. */ - regcache->raw_write (I387_YMM16H_REGNUM (tdep) + regnum - - num_lower_zmm_regs, buf + 16); + /* Which register is it, relative to zmm16. */ + int reg_index_16 = reg_index_0 - num_lower_zmm_regs; + + pseudo_to_concat_raw (next_frame, buf, + I387_XMM16_REGNUM (tdep) + reg_index_16, + I387_YMM16H_REGNUM (tdep) + reg_index_16, + tdep->zmm0h_regnum + +reg_index_0); } - /* Write upper 256bits. */ - regcache->raw_write (tdep->zmm0h_regnum + regnum, buf + 32); } - else if (i386_ymm_regnum_p (gdbarch, regnum)) + else if (i386_ymm_regnum_p (gdbarch, pseudo_reg_num)) { - regnum -= tdep->ymm0_regnum; + int i = pseudo_reg_num - tdep->ymm0_regnum; - /* ... Write lower 128bits. */ - regcache->raw_write (I387_XMM0_REGNUM (tdep) + regnum, buf); - /* ... Write upper 128bits. */ - regcache->raw_write (tdep->ymm0h_regnum + regnum, buf + 16); + pseudo_to_concat_raw (next_frame, buf, I387_XMM0_REGNUM (tdep) + i, + tdep->ymm0h_regnum + i); } - else if (i386_ymm_avx512_regnum_p (gdbarch, regnum)) + else if (i386_ymm_avx512_regnum_p (gdbarch, pseudo_reg_num)) { - regnum -= tdep->ymm16_regnum; + int i = pseudo_reg_num - tdep->ymm16_regnum; - /* ... Write lower 128bits. */ - regcache->raw_write (I387_XMM16_REGNUM (tdep) + regnum, buf); - /* ... Write upper 128bits. */ - regcache->raw_write (tdep->ymm16h_regnum + regnum, buf + 16); + pseudo_to_concat_raw (next_frame, buf, I387_XMM16_REGNUM (tdep) + i, + tdep->ymm16h_regnum + i); } - else if (i386_word_regnum_p (gdbarch, regnum)) + else if (i386_word_regnum_p (gdbarch, pseudo_reg_num)) { - int gpnum = regnum - tdep->ax_regnum; + int gpnum = pseudo_reg_num - tdep->ax_regnum; - /* Read ... */ - regcache->raw_read (gpnum, raw_buf); - /* ... Modify ... (always little endian). */ - memcpy (raw_buf, buf, 2); - /* ... Write. */ - regcache->raw_write (gpnum, raw_buf); + pseudo_to_raw_part (next_frame, buf, gpnum, 0); } - else if (i386_byte_regnum_p (gdbarch, regnum)) + else if (i386_byte_regnum_p (gdbarch, pseudo_reg_num)) { - int gpnum = regnum - tdep->al_regnum; + int gpnum = pseudo_reg_num - tdep->al_regnum; - /* Read ... We read both lower and upper registers. */ - regcache->raw_read (gpnum % 4, raw_buf); - /* ... Modify ... (always little endian). */ - if (gpnum >= 4) - memcpy (raw_buf + 1, buf, 1); - else - memcpy (raw_buf, buf, 1); - /* ... Write. */ - regcache->raw_write (gpnum % 4, raw_buf); + pseudo_to_raw_part (next_frame, buf, gpnum % 4, gpnum >= 4 ? 1 : 0); } else internal_error (_("invalid regnum")); @@ -8678,8 +8635,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Pseudo registers may be changed by amd64_init_abi. */ set_gdbarch_pseudo_register_read_value (gdbarch, i386_pseudo_register_read_value); - set_gdbarch_deprecated_pseudo_register_write (gdbarch, - i386_pseudo_register_write); + set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write); set_gdbarch_ax_pseudo_register_collect (gdbarch, i386_ax_pseudo_register_collect); diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h index 970dc8904f2a..b132da23a104 100644 --- a/gdb/i386-tdep.h +++ b/gdb/i386-tdep.h @@ -380,9 +380,9 @@ extern value *i386_pseudo_register_read_value (gdbarch *gdbarch, frame_info_ptr next_frame, int regnum); -extern void i386_pseudo_register_write (struct gdbarch *gdbarch, - struct regcache *regcache, - int regnum, const gdb_byte *buf); +extern void i386_pseudo_register_write (gdbarch *gdbarch, + frame_info_ptr next_frame, int regnum, + gdb::array_view buf); extern int i386_ax_pseudo_register_collect (struct gdbarch *gdbarch, struct agent_expr *ax, From patchwork Fri Dec 1 16:27:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81149 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 EA789384F9BF for ; Fri, 1 Dec 2023 16:32:15 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 2B3723861841 for ; Fri, 1 Dec 2023 16:32:00 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2B3723861841 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 2B3723861841 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448321; cv=none; b=XojAXoQsTbb/sBhmT8llg0AZpajQtmrpbfv3VNyMyZNPmOhNxXBuut27IkmQ1Tu4vbU9MPy8EVmKTBpvcn5EVMoCZ0HBwAxy6Z0wb32xJ/qg8fSNFNZTDHFwLsezcA9kpEIHBkMItbHkXr1IXYdE2ERxnWmBoXc4wXQkzdr6MKk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448321; c=relaxed/simple; bh=/q5UHmbDjNW5VCEAwpCRET1BV4AxLUYI/a3cgpfrGbc=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=Ehu5CbKvI3yTATMwI0x0nSWzSnmLd2DLUgHlXRJRJGh9RCFj45vWRU4PcRdSFMudEodBn3a0eHmazg7zSYoL8h9vEUa5YYjlDYU9EZeB4PAG2y+PcrlPp/+1PXYH3kItK175qYuEDaREJN4e775ylN0crABiB1L/HOnRyvQvTt8= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 53DBD1E11B; Fri, 1 Dec 2023 11:31:59 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 19/24] gdb: make aarch64_za_offsets_from_regnum return za_offsets Date: Fri, 1 Dec 2023 11:27:32 -0500 Message-ID: <20231201162751.741751-20-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org This is not necessary, but it seems more natural to me to make aarch64_za_offsets_from_regnum return a za_offsets object, rather than fill an instance passed by parameter. Change-Id: I40a185f055727da887ce7774be193eef1f4b9147 Approved-by: Luis Machado Reviewed-By: John Baldwin --- gdb/aarch64-tdep.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 5b2d87be6bfc..5c3b824ed0ad 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -3114,12 +3114,11 @@ aarch64_pseudo_read_value_1 (frame_info_ptr next_frame, } /* Helper function for reading/writing ZA pseudo-registers. Given REGNUM, - a ZA pseudo-register number, return, in OFFSETS, the information on positioning - of the bytes that must be read from/written to. */ + a ZA pseudo-register number, return the information on positioning of the + bytes that must be read from/written to. */ -static void -aarch64_za_offsets_from_regnum (struct gdbarch *gdbarch, int regnum, - struct za_offsets &offsets) +static za_offsets +aarch64_za_offsets_from_regnum (struct gdbarch *gdbarch, int regnum) { aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); @@ -3135,6 +3134,7 @@ aarch64_za_offsets_from_regnum (struct gdbarch *gdbarch, int regnum, /* Fetch the streaming vector length. */ size_t svl = sve_vl_from_vq (tdep->sme_svq); + za_offsets offsets; if (is_sme_tile_slice_pseudo_register (gdbarch, regnum)) { @@ -3190,6 +3190,8 @@ aarch64_za_offsets_from_regnum (struct gdbarch *gdbarch, int regnum, /* The chunk size is always svl bytes. */ offsets.chunk_size = svl; } + + return offsets; } /* Given REGNUM, a SME pseudo-register number, return its value in RESULT. */ @@ -3207,8 +3209,8 @@ aarch64_sme_pseudo_register_read (gdbarch *gdbarch, frame_info_ptr next_frame, /* Fetch the offsets that we need in order to read from the correct blocks of ZA. */ - struct za_offsets offsets; - aarch64_za_offsets_from_regnum (gdbarch, pseudo_reg_num, offsets); + za_offsets offsets + = aarch64_za_offsets_from_regnum (gdbarch, pseudo_reg_num); /* Fetch the contents of ZA. */ value *za_value = value_of_register (tdep->sme_za_regnum, next_frame); @@ -3330,8 +3332,7 @@ aarch64_sme_pseudo_register_write (struct gdbarch *gdbarch, /* Fetch the offsets that we need in order to write to the correct blocks of ZA. */ - struct za_offsets offsets; - aarch64_za_offsets_from_regnum (gdbarch, regnum, offsets); + za_offsets offsets = aarch64_za_offsets_from_regnum (gdbarch, regnum); /* Fetch the contents of ZA. */ size_t svl = sve_vl_from_vq (tdep->sme_svq); From patchwork Fri Dec 1 16:27:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81150 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 13854384DEDD for ; Fri, 1 Dec 2023 16:32:17 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 56AB2386184E for ; Fri, 1 Dec 2023 16:32:00 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 56AB2386184E Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 56AB2386184E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448321; cv=none; b=bpGycAh5Un+GjSBqlb9c7ILiMtZBuujxMwfym9xwOeas/mwNelmPJmqJPixm7iJZK1dXe4PMrvB/PiDsKmMcVx1P0INwyOpQ6SmOm0msgLcAex4ZKUmK3+8MY4zMiHqCvUIACpJ09cY+7ZJzAFopqP1V1FWnkXsQB6+XGx+nciA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448321; c=relaxed/simple; bh=4Foo7mPvNMENsXQkmUW1UZtUjDywn2d9aMWNReZPNfM=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=dGzF086jD3SS7BEgMoZzUh76D8AX3BuYSRKwVH9lLikvAhYPg0oe8K1bUo0luTAP7sSAUjfzZaWAXm6BWE1oWceNHojO0GEozIq8M3x/bKVmM0LYyvHSqfN3Xylo0uXvVnVidN8MCsgFwLIRmLRG6Jl/h3Kk2Y8tah87aapApMM= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 9297A1E11E; Fri, 1 Dec 2023 11:31:59 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 20/24] gdb: add missing raw register read in aarch64_sme_pseudo_register_write Date: Fri, 1 Dec 2023 11:27:33 -0500 Message-ID: <20231201162751.741751-21-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org It seems like the intention here is to read the contents of the ZA register and only write part of it. However, there's no actual read of the ZA register, so it looks like we'll write uninitialized bytes to the target, for the portion of the raw register where we don't write the pseudo register. Add a call to raw_read to fix this. I don't know how to test this though. Change-Id: I7548240bd4324f6a3b729a1ebf7502fae5a46e9e Reviewed-By: John Baldwin Approved-by: Luis Machado --- gdb/aarch64-tdep.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 5c3b824ed0ad..e3658c2c8e10 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -3337,6 +3337,7 @@ aarch64_sme_pseudo_register_write (struct gdbarch *gdbarch, /* Fetch the contents of ZA. */ size_t svl = sve_vl_from_vq (tdep->sme_svq); gdb::byte_vector za (std::pow (svl, 2)); + regcache->raw_read (tdep->sme_za_regnum, za); /* Copy the requested data. */ for (int chunks = 0; chunks < offsets.chunks; chunks++) From patchwork Fri Dec 1 16:27:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81154 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 8606F3847723 for ; Fri, 1 Dec 2023 16:32:50 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id D2C7A386074B for ; Fri, 1 Dec 2023 16:32:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D2C7A386074B Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D2C7A386074B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448323; cv=none; b=oEtZvV9VVb0n/WFv2sVXmypU2tsoSxeUwNGYEU5h6jXEaJHT5jKT4fWHyYxKZQwd8EkW7aZbxE7bzF0e8zHO+hlxDFNRL4MAkK0rTkNTPDBQl6aEP67Yg1TdnwB7yMvST7zdw4YiCrjNv7zp71m6PVHZ3n8FgcCmq2dq+/YFV/g= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448323; c=relaxed/simple; bh=MiPQnI+gp9HduWT1gFF0XsILrqEcrSnnuPnIOI5shJo=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=P09fh1kgYFmivHvkcmitrAQywku/ScNVM/5ZrX0iEDtP4/mzvfn77G/HVS/FWWc63mnipXmQ//iJ1+13hOl392rGzxiRiTb10WWhGeVT/pzKx7xkP1dkopol7sjNzoBgdPNXSWYAPJhtloslWk5SrP0UrcylCmSCxOA9uccy9rQ= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id DBD5D1E1A7; Fri, 1 Dec 2023 11:31:59 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 21/24] gdb: migrate aarch64 to new gdbarch_pseudo_register_write Date: Fri, 1 Dec 2023 11:27:34 -0500 Message-ID: <20231201162751.741751-22-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org New in v2: - Allocate enough space for an SVE register in aarch64_pseudo_write_1 (i.e. keep the logic that's there before the patch for the local buffer size) Make aarch64 use the new gdbarch_pseudo_register_write. This fixes writing pseudo registers to non-current frames on this architecture. Change-Id: Ic012a0b95ae728d45a7121f77a79d604c23a849e Reviewed-By: John Baldwin Tested-By: Luis Machado --- gdb/aarch64-tdep.c | 128 +++++++++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 58 deletions(-) diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index e3658c2c8e10..a1eab01abb8c 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -3296,32 +3296,35 @@ aarch64_pseudo_read_value (gdbarch *gdbarch, frame_info_ptr next_frame, /* Helper for aarch64_pseudo_write. */ static void -aarch64_pseudo_write_1 (struct gdbarch *gdbarch, struct regcache *regcache, - int regnum_offset, int regsize, const gdb_byte *buf) +aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame, + int regnum_offset, + gdb::array_view buf) { - unsigned v_regnum = AARCH64_V0_REGNUM + regnum_offset; + unsigned raw_regnum = AARCH64_V0_REGNUM + regnum_offset; /* Enough space for a full vector register. */ - gdb_byte reg_buf[register_size (gdbarch, AARCH64_V0_REGNUM)]; + int raw_reg_size = register_size (gdbarch, raw_regnum); + gdb_byte raw_buf[raw_reg_size]; static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM); /* Ensure the register buffer is zero, we want gdb writes of the various 'scalar' pseudo registers to behavior like architectural writes, register width bytes are written the remainder are set to zero. */ - memset (reg_buf, 0, register_size (gdbarch, AARCH64_V0_REGNUM)); + memset (raw_buf, 0, register_size (gdbarch, AARCH64_V0_REGNUM)); - memcpy (reg_buf, buf, regsize); - regcache->raw_write (v_regnum, reg_buf); + gdb::array_view raw_view (raw_buf, raw_reg_size); + copy (buf, raw_view.slice (0, buf.size ())); + put_frame_register (next_frame, raw_regnum, raw_view); } /* Given REGNUM, a SME pseudo-register number, store the bytes from DATA to the pseudo-register. */ static void -aarch64_sme_pseudo_register_write (struct gdbarch *gdbarch, - struct regcache *regcache, - int regnum, const gdb_byte *data) +aarch64_sme_pseudo_register_write (gdbarch *gdbarch, frame_info_ptr next_frame, + const int regnum, + gdb::array_view data) { aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); @@ -3335,33 +3338,39 @@ aarch64_sme_pseudo_register_write (struct gdbarch *gdbarch, za_offsets offsets = aarch64_za_offsets_from_regnum (gdbarch, regnum); /* Fetch the contents of ZA. */ - size_t svl = sve_vl_from_vq (tdep->sme_svq); - gdb::byte_vector za (std::pow (svl, 2)); - regcache->raw_read (tdep->sme_za_regnum, za); + value *za_value = value_of_register (tdep->sme_za_regnum, next_frame); - /* Copy the requested data. */ - for (int chunks = 0; chunks < offsets.chunks; chunks++) - { - const gdb_byte *source = data + chunks * offsets.chunk_size; - gdb_byte *destination - = za.data () + offsets.starting_offset + chunks * offsets.stride_size; + { + /* Create a view only on the portion of za we want to write. */ + gdb::array_view za_view + = za_value->contents_writeable ().slice (offsets.starting_offset); - memcpy (destination, source, offsets.chunk_size); - } + /* Copy the requested data. */ + for (int chunks = 0; chunks < offsets.chunks; chunks++) + { + gdb::array_view src + = data.slice (chunks * offsets.chunk_size, offsets.chunk_size); + gdb::array_view dst + = za_view.slice (chunks * offsets.stride_size, offsets.chunk_size); + copy (src, dst); + } + } /* Write back to ZA. */ - regcache->raw_write (tdep->sme_za_regnum, za.data ()); + put_frame_register (next_frame, tdep->sme_za_regnum, + za_value->contents_raw ()); } /* Implement the "pseudo_register_write" gdbarch method. */ static void -aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache, - int regnum, const gdb_byte *buf) +aarch64_pseudo_write (gdbarch *gdbarch, frame_info_ptr next_frame, + const int pseudo_reg_num, + gdb::array_view buf) { aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - if (is_w_pseudo_register (gdbarch, regnum)) + if (is_w_pseudo_register (gdbarch, pseudo_reg_num)) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); /* Default offset for little endian. */ @@ -3371,53 +3380,56 @@ aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache, offset = 4; /* Find the correct X register to extract the data from. */ - int x_regnum = AARCH64_X0_REGNUM + (regnum - tdep->w_pseudo_base); + int x_regnum = AARCH64_X0_REGNUM + (pseudo_reg_num - tdep->w_pseudo_base); /* First zero-out the contents of X. */ - ULONGEST zero = 0; - regcache->raw_write (x_regnum, zero); + gdb_byte bytes[8] {}; + gdb::array_view bytes_view (bytes); + copy (buf, bytes_view.slice (offset, 4)); + /* Write to the bottom 4 bytes of X. */ - regcache->raw_write_part (x_regnum, offset, 4, buf); + put_frame_register (next_frame, x_regnum, bytes_view); return; } - else if (is_sme_pseudo_register (gdbarch, regnum)) + else if (is_sme_pseudo_register (gdbarch, pseudo_reg_num)) { - aarch64_sme_pseudo_register_write (gdbarch, regcache, regnum, buf); + aarch64_sme_pseudo_register_write (gdbarch, next_frame, pseudo_reg_num, + buf); return; } - regnum -= gdbarch_num_regs (gdbarch); + /* Offset in the "pseudo-register space". */ + int pseudo_offset = pseudo_reg_num - gdbarch_num_regs (gdbarch); - if (regnum >= AARCH64_Q0_REGNUM && regnum < AARCH64_Q0_REGNUM + 32) - return aarch64_pseudo_write_1 (gdbarch, regcache, - regnum - AARCH64_Q0_REGNUM, Q_REGISTER_SIZE, - buf); + if (pseudo_offset >= AARCH64_Q0_REGNUM + && pseudo_offset < AARCH64_Q0_REGNUM + 32) + return aarch64_pseudo_write_1 (gdbarch, next_frame, + pseudo_offset - AARCH64_Q0_REGNUM, buf); - if (regnum >= AARCH64_D0_REGNUM && regnum < AARCH64_D0_REGNUM + 32) - return aarch64_pseudo_write_1 (gdbarch, regcache, - regnum - AARCH64_D0_REGNUM, D_REGISTER_SIZE, - buf); + if (pseudo_offset >= AARCH64_D0_REGNUM + && pseudo_offset < AARCH64_D0_REGNUM + 32) + return aarch64_pseudo_write_1 (gdbarch, next_frame, + pseudo_offset - AARCH64_D0_REGNUM, buf); - if (regnum >= AARCH64_S0_REGNUM && regnum < AARCH64_S0_REGNUM + 32) - return aarch64_pseudo_write_1 (gdbarch, regcache, - regnum - AARCH64_S0_REGNUM, S_REGISTER_SIZE, - buf); + if (pseudo_offset >= AARCH64_S0_REGNUM + && pseudo_offset < AARCH64_S0_REGNUM + 32) + return aarch64_pseudo_write_1 (gdbarch, next_frame, + pseudo_offset - AARCH64_S0_REGNUM, buf); - if (regnum >= AARCH64_H0_REGNUM && regnum < AARCH64_H0_REGNUM + 32) - return aarch64_pseudo_write_1 (gdbarch, regcache, - regnum - AARCH64_H0_REGNUM, H_REGISTER_SIZE, - buf); + if (pseudo_offset >= AARCH64_H0_REGNUM + && pseudo_offset < AARCH64_H0_REGNUM + 32) + return aarch64_pseudo_write_1 (gdbarch, next_frame, + pseudo_offset - AARCH64_H0_REGNUM, buf); - if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32) - return aarch64_pseudo_write_1 (gdbarch, regcache, - regnum - AARCH64_B0_REGNUM, B_REGISTER_SIZE, - buf); + if (pseudo_offset >= AARCH64_B0_REGNUM + && pseudo_offset < AARCH64_B0_REGNUM + 32) + return aarch64_pseudo_write_1 (gdbarch, next_frame, + pseudo_offset - AARCH64_B0_REGNUM, buf); - if (tdep->has_sve () && regnum >= AARCH64_SVE_V0_REGNUM - && regnum < AARCH64_SVE_V0_REGNUM + 32) - return aarch64_pseudo_write_1 (gdbarch, regcache, - regnum - AARCH64_SVE_V0_REGNUM, - V_REGISTER_SIZE, buf); + if (tdep->has_sve () && pseudo_offset >= AARCH64_SVE_V0_REGNUM + && pseudo_offset < AARCH64_SVE_V0_REGNUM + 32) + return aarch64_pseudo_write_1 (gdbarch, next_frame, + pseudo_offset - AARCH64_SVE_V0_REGNUM, buf); gdb_assert_not_reached ("regnum out of bound"); } @@ -4483,7 +4495,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_num_pseudo_regs (gdbarch, num_pseudo_regs); set_gdbarch_pseudo_register_read_value (gdbarch, aarch64_pseudo_read_value); - set_gdbarch_deprecated_pseudo_register_write (gdbarch, aarch64_pseudo_write); + set_gdbarch_pseudo_register_write (gdbarch, aarch64_pseudo_write); set_tdesc_pseudo_register_name (gdbarch, aarch64_pseudo_register_name); set_tdesc_pseudo_register_type (gdbarch, aarch64_pseudo_register_type); set_tdesc_pseudo_register_reggroup_p (gdbarch, From patchwork Fri Dec 1 16:27:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81156 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 46EF8384F983 for ; Fri, 1 Dec 2023 16:32:55 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 07616386182E for ; Fri, 1 Dec 2023 16:32:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 07616386182E Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 07616386182E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448323; cv=none; b=u1Kf5RcvJjB5CTKklTXS1STt90oUazj3SqZNUYT6v8xP/9PkJsjynzkZihPJ1Agfzs+Kvt3lR7ExEKxczthLTQ8LnCVZ1TTCQKl8F2T0byRCWVtF/VzguYAYfCrAyfW3jqoR/IyLVBvmqdEw3+k0y/7zpDOzQSPr5TQpGItnngs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448323; c=relaxed/simple; bh=l3qD/yMsCxZlDeV3t7cIz6HXBOb086Bl+KNamBlR31U=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=NkyWWaPSkcm09tdcMUVQfJSwk3MfAR3bdmOKSezoo/XTETD1L1O9vrUpSr2DDEDoZEn0W2CNccyShlmqDzfpGiTifSBHHSIXNRmD8OGUTdEMT/AgxK/kuk4NiaczUfeH6Nt9R7H9JTmjl7T1/NM2LSP89wePjvMTpBC7dZ3hVnE= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 19EF21E1A8; Fri, 1 Dec 2023 11:32:00 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 22/24] gdb: migrate arm to gdbarch_pseudo_register_read_value Date: Fri, 1 Dec 2023 11:27:35 -0500 Message-ID: <20231201162751.741751-23-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Make arm use the "newer" gdbarch_pseudo_register_read_value. This fixes reading pseudo registers in non-current frames on that architecture. Change-Id: Ic4d3d5d96957a4addfa3443c7b567dc4a31794a9 Reviewed-By: John Baldwin Approved-by: Luis Machado --- gdb/arm-tdep.c | 76 +++++++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 85fd37ba73a0..36ca867da5c2 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -9816,61 +9816,73 @@ arm_neon_quad_read (struct gdbarch *gdbarch, readable_regcache *regcache, return REG_VALID; } -/* Read the contents of the MVE pseudo register REGNUM and store it - in BUF. */ +/* Read the contents of a NEON quad register, by reading from two double + registers, and return it as a value. QUAD_REG_INDEX is the index of the quad + register, in [0, 15]. */ -static enum register_status -arm_mve_pseudo_read (struct gdbarch *gdbarch, readable_regcache *regcache, - int regnum, gdb_byte *buf) +static value * +arm_neon_quad_read_value (gdbarch *gdbarch, frame_info_ptr next_frame, + int pseudo_reg_num, int quad_reg_index) +{ + std::string raw_reg_name = string_printf ("d%d", quad_reg_index << 1); + int double_regnum + = user_reg_map_name_to_regnum (gdbarch, raw_reg_name.c_str (), + raw_reg_name.length ()); + + return pseudo_from_concat_raw (next_frame, pseudo_reg_num, double_regnum, + double_regnum + 1); +} + +/* Read the contents of the MVE pseudo register REGNUM and return it as a + value. */ +static value * +arm_mve_pseudo_read_value (gdbarch *gdbarch, frame_info_ptr next_frame, + int pseudo_reg_num) { arm_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); /* P0 is the first 16 bits of VPR. */ - return regcache->raw_read_part (tdep->mve_vpr_regnum, 0, 2, buf); + return pseudo_from_raw_part (next_frame, pseudo_reg_num, + tdep->mve_vpr_regnum, 0); } -static enum register_status -arm_pseudo_read (struct gdbarch *gdbarch, readable_regcache *regcache, - int regnum, gdb_byte *buf) +static value * +arm_pseudo_read_value (gdbarch *gdbarch, frame_info_ptr next_frame, + const int pseudo_reg_num) { - const int num_regs = gdbarch_num_regs (gdbarch); - char name_buf[4]; - gdb_byte reg_buf[8]; - int offset, double_regnum; arm_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - gdb_assert (regnum >= num_regs); + gdb_assert (pseudo_reg_num >= gdbarch_num_regs (gdbarch)); - if (is_q_pseudo (gdbarch, regnum)) + if (is_q_pseudo (gdbarch, pseudo_reg_num)) { /* Quad-precision register. */ - return arm_neon_quad_read (gdbarch, regcache, - regnum - tdep->q_pseudo_base, buf); + return arm_neon_quad_read_value (gdbarch, next_frame, pseudo_reg_num, + pseudo_reg_num - tdep->q_pseudo_base); } - else if (is_mve_pseudo (gdbarch, regnum)) - return arm_mve_pseudo_read (gdbarch, regcache, regnum, buf); + else if (is_mve_pseudo (gdbarch, pseudo_reg_num)) + return arm_mve_pseudo_read_value (gdbarch, next_frame, pseudo_reg_num); else { - enum register_status status; + int s_reg_index = pseudo_reg_num - tdep->s_pseudo_base; - regnum -= tdep->s_pseudo_base; /* Single-precision register. */ - gdb_assert (regnum < 32); + gdb_assert (s_reg_index < 32); /* s0 is always the least significant half of d0. */ + int offset; if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) - offset = (regnum & 1) ? 0 : 4; + offset = (s_reg_index & 1) ? 0 : 4; else - offset = (regnum & 1) ? 4 : 0; + offset = (s_reg_index & 1) ? 4 : 0; - xsnprintf (name_buf, sizeof (name_buf), "d%d", regnum >> 1); - double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf, - strlen (name_buf)); + std::string raw_reg_name = string_printf ("d%d", s_reg_index >> 1); + int double_regnum + = user_reg_map_name_to_regnum (gdbarch, raw_reg_name.c_str (), + raw_reg_name.length ()); - status = regcache->raw_read (double_regnum, reg_buf); - if (status == REG_VALID) - memcpy (buf, reg_buf + offset, 4); - return status; + return pseudo_from_raw_part (next_frame, pseudo_reg_num, double_regnum, + offset); } } @@ -10905,7 +10917,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) if (tdep->have_s_pseudos || have_mve || have_pacbti) { set_gdbarch_num_pseudo_regs (gdbarch, num_pseudos); - set_gdbarch_pseudo_register_read (gdbarch, arm_pseudo_read); + set_gdbarch_pseudo_register_read_value (gdbarch, arm_pseudo_read_value); set_gdbarch_deprecated_pseudo_register_write (gdbarch, arm_pseudo_write); } From patchwork Fri Dec 1 16:27:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81157 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 AF7DB3861870 for ; Fri, 1 Dec 2023 16:33:07 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id DE29A386074C for ; Fri, 1 Dec 2023 16:32:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DE29A386074C Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org DE29A386074C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448323; cv=none; b=v7AY0PtG0W0OJC1736vptHFCzws8db3bVvg5hx5mEI9G6Y1YWQcHvwKuKlFmXqtl3ynDaqhYn17R+fzXVqdV5yJDbK+kNK6AKOzfaDb30j+t6sggOhM+HW0NE8HThUaWIywIiLYoGXVVLvWiuhMW3IusXXEWaRqcM/5QdTlZu3g= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448323; c=relaxed/simple; bh=QplsI6FvE90JnkMxSkgC+AAf5YLoT3Mva7rhYeW1wbc=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=VNHZ7gS5IHbzoboDIENf8tKOzrMXGHSE76tadRJM1CI5V29NcPMty4cmxCudQQgxLK7w3vRlLNDbTDXQmq5tqm6IkDscQaqWhntr737Ls6Jz4JWjQRcUtN9o2ZzzBiP3qI++cZ8tuTYZNxrzfLTa2JKAhnPd6rV9jipBNoKK18w= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 4D3D01E1A9; Fri, 1 Dec 2023 11:32:00 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 23/24] gdb: migrate arm to new gdbarch_pseudo_register_write Date: Fri, 1 Dec 2023 11:27:36 -0500 Message-ID: <20231201162751.741751-24-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Make arm use the new gdbarch_pseudo_register_write. This fixes writing pseudo registers to non-current frames for that architecture. Change-Id: Icb2a649ab6394817844230e9e94c3d0564d2f765 Reviewed-By: John Baldwin Approved-by: Luis Machado --- gdb/arm-tdep.c | 62 +++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 36ca867da5c2..0e333290e1e5 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -9908,57 +9908,67 @@ arm_neon_quad_write (struct gdbarch *gdbarch, struct regcache *regcache, regcache->raw_write (double_regnum + 1, buf + 8); } +static void +arm_neon_quad_write (gdbarch *gdbarch, frame_info_ptr next_frame, + int quad_reg_index, gdb::array_view buf) +{ + std::string raw_reg_name = string_printf ("d%d", quad_reg_index << 1); + int double_regnum + = user_reg_map_name_to_regnum (gdbarch, raw_reg_name.data (), + raw_reg_name.length ()); + + pseudo_to_concat_raw (next_frame, buf, double_regnum, double_regnum + 1); +} + /* Store the contents of BUF to the MVE pseudo register REGNUM. */ static void -arm_mve_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache, - int regnum, const gdb_byte *buf) +arm_mve_pseudo_write (gdbarch *gdbarch, frame_info_ptr next_frame, + int pseudo_reg_num, gdb::array_view buf) { arm_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); /* P0 is the first 16 bits of VPR. */ - regcache->raw_write_part (tdep->mve_vpr_regnum, 0, 2, buf); + pseudo_to_raw_part(next_frame, buf, tdep->mve_vpr_regnum, 0); } static void -arm_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache, - int regnum, const gdb_byte *buf) +arm_pseudo_write (gdbarch *gdbarch, frame_info_ptr next_frame, + const int pseudo_reg_num, + gdb::array_view buf) { - const int num_regs = gdbarch_num_regs (gdbarch); - char name_buf[4]; - gdb_byte reg_buf[8]; - int offset, double_regnum; arm_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - gdb_assert (regnum >= num_regs); + gdb_assert (pseudo_reg_num >= gdbarch_num_regs (gdbarch)); - if (is_q_pseudo (gdbarch, regnum)) + if (is_q_pseudo (gdbarch, pseudo_reg_num)) { /* Quad-precision register. */ - arm_neon_quad_write (gdbarch, regcache, - regnum - tdep->q_pseudo_base, buf); + arm_neon_quad_write (gdbarch, next_frame, + pseudo_reg_num - tdep->q_pseudo_base, buf); } - else if (is_mve_pseudo (gdbarch, regnum)) - arm_mve_pseudo_write (gdbarch, regcache, regnum, buf); + else if (is_mve_pseudo (gdbarch, pseudo_reg_num)) + arm_mve_pseudo_write (gdbarch, next_frame, pseudo_reg_num, buf); else { - regnum -= tdep->s_pseudo_base; + int s_reg_index = pseudo_reg_num - tdep->s_pseudo_base; + /* Single-precision register. */ - gdb_assert (regnum < 32); + gdb_assert (s_reg_index < 32); /* s0 is always the least significant half of d0. */ + int offset; if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) - offset = (regnum & 1) ? 0 : 4; + offset = (s_reg_index & 1) ? 0 : 4; else - offset = (regnum & 1) ? 4 : 0; + offset = (s_reg_index & 1) ? 4 : 0; - xsnprintf (name_buf, sizeof (name_buf), "d%d", regnum >> 1); - double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf, - strlen (name_buf)); + std::string raw_reg_name = string_printf ("d%d", s_reg_index >> 1); + int double_regnum + = user_reg_map_name_to_regnum (gdbarch, raw_reg_name.c_str (), + raw_reg_name.length ()); - regcache->raw_read (double_regnum, reg_buf); - memcpy (reg_buf + offset, buf, 4); - regcache->raw_write (double_regnum, reg_buf); + pseudo_to_raw_part (next_frame, buf, double_regnum, offset); } } @@ -10918,7 +10928,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { set_gdbarch_num_pseudo_regs (gdbarch, num_pseudos); set_gdbarch_pseudo_register_read_value (gdbarch, arm_pseudo_read_value); - set_gdbarch_deprecated_pseudo_register_write (gdbarch, arm_pseudo_write); + set_gdbarch_pseudo_register_write (gdbarch, arm_pseudo_write); } /* Add standard register aliases. We add aliases even for those From patchwork Fri Dec 1 16:27:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 81158 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 828DA3857C65 for ; Fri, 1 Dec 2023 16:34:23 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id C6E803858C2C for ; Fri, 1 Dec 2023 16:34:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C6E803858C2C Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C6E803858C2C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448445; cv=none; b=h/rRZIiyTPzE4Ox4NXNYoHEVxKEDTsM/E6YqFqTHnvx9Zte6J9wHd3m342Jzkh7GfAnBmv6SvBBfedBCbd2FolNkXJu0YURLl40JXQ6AbQz440hcb+B9ZJY/wuIvFfLN9d7tuMdDd0ItksGu6vtY57faaufrgNQoeL8OQ979YsA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701448445; c=relaxed/simple; bh=Am3w7n/WReh2rOTW/YGYPry7Hui7/IBTALMAwQUdSoA=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=C7PsQ4KCJw+D2LfBMsvZi0BD9n1in2LVMegMYrq0iFyQ3X3XC87MudEZivj6FXDA+IOa5NeW76zqWSdNGWn2On1TwHUyO1SwEhwKpKpdUeHBZi6cmWEb4kE41Nv+4wtWEtvuEN/U+8NLW0HUWiXEN9YWpkQLHKSanpeHtgdszFk= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smarchi-efficios.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) (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 ESMTPSA id 361B91E091; Fri, 1 Dec 2023 11:34:01 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Luis Machado , John Baldwin , "Aktemur, Tankut Baris" , Simon Marchi , John Baldwin Subject: [PATCH 24/24] gdb/testsuite: add tests for unwinding of pseudo registers Date: Fri, 1 Dec 2023 11:27:37 -0500 Message-ID: <20231201162751.741751-25-simon.marchi@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201162751.741751-1-simon.marchi@efficios.com> References: <20231201162751.741751-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3496.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, KAM_SHORT, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org From: Simon Marchi New in v2: - Switched to using x19/w19 in the aarch64 test This patch adds tests to exercise the previous patches' changes. All three tests: - aarch64-pseudo-unwind - amd64-pseudo-unwind - arm-pseudo-unwind follow the same pattern, just with different registers. The other test, arm-pseudo-unwind-legacy, tests the special case where the unwind information contains an entry for a register considered a pseudo-register by GDB. Change-Id: Ic29ac040c5eb087b4a0d79f9d02f65b7979df30f Reviewed-By: John Baldwin Reviewed-by: Luis Machado Tested-By: Luis Machado (aarch64/arm) --- .../gdb.arch/aarch64-pseudo-unwind-asm.S | 82 +++++++++++++++++ .../gdb.arch/aarch64-pseudo-unwind.c | 33 +++++++ .../gdb.arch/aarch64-pseudo-unwind.exp | 88 ++++++++++++++++++ .../gdb.arch/amd64-pseudo-unwind-asm.S | 66 ++++++++++++++ gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c | 33 +++++++ .../gdb.arch/amd64-pseudo-unwind.exp | 91 +++++++++++++++++++ .../gdb.arch/arm-pseudo-unwind-asm.S | 79 ++++++++++++++++ .../gdb.arch/arm-pseudo-unwind-legacy-asm.S | 84 +++++++++++++++++ .../gdb.arch/arm-pseudo-unwind-legacy.c | 33 +++++++ .../gdb.arch/arm-pseudo-unwind-legacy.exp | 86 ++++++++++++++++++ gdb/testsuite/gdb.arch/arm-pseudo-unwind.c | 33 +++++++ gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp | 88 ++++++++++++++++++ 12 files changed, 796 insertions(+) create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind-asm.S create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-asm.S create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy-asm.S create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind.c create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp diff --git a/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind-asm.S b/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind-asm.S new file mode 100644 index 000000000000..575ed75ae9f5 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind-asm.S @@ -0,0 +1,82 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +.section .note.GNU-stack,"",%progbits + +.data +value_callee: +.quad 0x2021222324252627 +value_caller: +.quad 0x1011121314151617 + +.text +.global callee +callee: + /* Standard prologue: + - push fp (x29) and lr (x30) to the stack. + - mov sp to fp */ +.cfi_startproc + stp x29, x30, [sp, -16]! +.cfi_def_cfa 29, 16 +.cfi_offset 29, -16 +.cfi_offset 30, -8 + mov x29, sp + + /* Save caller's x19 value on the stack. */ +.cfi_offset 19, -32 + str x19, [sp, -16]! + + /* Put our own x19 value. */ + adr x0, value_callee + ldr x19, [x0] + +break_here_asm: + + /* Restore caller's x19 value. */ + ldr x19, [sp], 16 + + /* Standard epilogue: + - pop fp (x29) and lr (x30) from the stack */ + ldp x29, x30, [sp], 16 + ret +.cfi_endproc + + +.global caller +caller: + /* Standard prologue. */ +.cfi_startproc + stp x29, x30, [sp, -16]! +.cfi_def_cfa 29, 16 +.cfi_offset x29, -16 +.cfi_offset x30, -8 + add x29, sp, 0 + + /* Put our own x19 value. */ + adr x0, value_caller + ldr x19, [x0] + + /* Call callee. */ + bl callee + + /* Store our x19 value in x0 to return it. */ + mov x0, x19 + + /* Standard epilogue. */ + ldp x29, x30, [sp], 16 + ret +.cfi_endproc diff --git a/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.c b/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.c new file mode 100644 index 000000000000..d18876fe3be3 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.c @@ -0,0 +1,33 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + +uint64_t caller (void); + +static void +break_here_c (uint64_t value) +{ +} + +int +main (void) +{ + uint64_t value = caller (); + break_here_c (value); + return 0; +} diff --git a/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp b/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp new file mode 100644 index 000000000000..62b3f8c4337c --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp @@ -0,0 +1,88 @@ +# Copyright 2018-2023 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 test is equivalent to amd64-pseudo-unwind, but specific to AArch64. We +# use the raw register x19 which is 64 bits long and pseudo register w19, which +# is the bottom half of x19. + +if { ![istarget aarch64-*-* ] } { + verbose "Skipping aarch64 pseudo register unwind." + return +} + +standard_testfile aarch64-pseudo-unwind.c aarch64-pseudo-unwind-asm.S + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + "${srcfile} ${srcfile2}" {debug}] } { + return -1 +} + +clean_restart ${binfile} + +if ![runto_main] then { + fail "could not run to main" +} + +gdb_breakpoint break_here_asm temporary +gdb_continue_to_breakpoint "continue to callee" + +# Verify the value of x19/w19 in the inner frame (callee). +with_test_prefix "callee, before change" { + gdb_test "p/x \$x19" " = 0x2021222324252627" + gdb_test "p/x \$w19" " = 0x24252627" +} + +# Verify that we can change the value of the pseudo register (w19) in the inner +# frame (callee). +gdb_test_no_output "set \$w19 = 0x34353637" + +# Verify the value of x19/w19 in the inner frame (callee) after the change. +with_test_prefix "callee, after change" { + gdb_test "p/x \$x19" " = 0x34353637" + gdb_test "p/x \$w19" " = 0x34353637" +} + +# Go up one frame (to caller) and do the same. +gdb_test "up" + +# Verify the value of x19/w19 in the outer frame (caller). +with_test_prefix "caller, before change" { + gdb_test "p/x \$x19" " = 0x1011121314151617" + gdb_test "p/x \$w19" " = 0x14151617" +} + +# Verify that we can change the value of the pseudo register (w19) in the outer +# frame (caller). +gdb_test_no_output "set \$w19 = 0x44454647" + +# Verify the value of x19/w19 in the outer frame (caller) after the change. +with_test_prefix "caller, after change" { + gdb_test "p/x \$x19" " = 0x44454647" + gdb_test "p/x \$w19" " = 0x44454647" +} + +# Go back to frame 0 (callee), check that the change to the outer frame didn't +# mess up anything there. +gdb_test "down" +with_test_prefix "callee, after change in caller" { + gdb_test "p/x \$x19" " = 0x34353637" + gdb_test "p/x \$w19" " = 0x34353637" +} + +# Verify that the value of the saved x19 we changed is correctly seen by the +# inferior. +gdb_breakpoint break_here_c temporary +gdb_continue_to_breakpoint "continue to break_here_c" +gdb_test "p/x value" " = 0x44454647" diff --git a/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S b/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S new file mode 100644 index 000000000000..c306b82e4864 --- /dev/null +++ b/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S @@ -0,0 +1,66 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +.section .note.GNU-stack,"",%progbits + +.text +.global callee +callee: + /* Standard prologue. */ +.cfi_startproc + push %rbp +.cfi_def_cfa rbp, 16 + mov %rsp, %rbp + + /* Save caller's rbx value on the stack. */ +.cfi_offset rbx, -24 + push %rbx + + /* Put our own rbx value. */ + mov $0x2021222324252627, %rbx +break_here_asm: + + /* Restore caller's rbx value. */ + pop %rbx + + /* Standard epilogue. */ + pop %rbp + ret +.cfi_endproc + + +.global caller +caller: +.cfi_startproc + /* Standard prologue. */ + push %rbp +.cfi_def_cfa_offset 16 + mov %rsp, %rbp + + /* Put our own rbx value. */ + mov $0x1011121314151617, %rbx + + /* Call callee. */ + call callee + + /* Store our rbx value in rax to return it. */ + mov %rbx, %rax + + /* Standard epilogue. */ + pop %rbp + ret +.cfi_endproc diff --git a/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c b/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c new file mode 100644 index 000000000000..d18876fe3be3 --- /dev/null +++ b/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c @@ -0,0 +1,33 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + +uint64_t caller (void); + +static void +break_here_c (uint64_t value) +{ +} + +int +main (void) +{ + uint64_t value = caller (); + break_here_c (value); + return 0; +} diff --git a/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp b/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp new file mode 100644 index 000000000000..45e9a3c96224 --- /dev/null +++ b/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp @@ -0,0 +1,91 @@ +# Copyright 2018-2023 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 test verifies that we can read and write the value of a pseudo register +# in unwound frames. For the test, we choose one raw register, rbx, and one +# pseudo register that is backed by rbx, ebx. We have two frames (the inner one, +# #0 and the outer one, #1) that each set a value for rbx. We verify that we +# can read both rbx and ebx correctly for each frame, and that when we write to +# ebx, rbx for that frame is correctly updated. + +if { ![istarget x86_64-*-* ] || ![is_lp64_target] } { + verbose "Skipping amd64 pseudo register unwind." + return +} + +standard_testfile amd64-pseudo-unwind.c amd64-pseudo-unwind-asm.S + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + "${srcfile} ${srcfile2}" {debug}] } { + return -1 +} + +clean_restart ${binfile} + +if ![runto_main] then { + fail "could not run to main" +} + +gdb_breakpoint break_here_asm temporary +gdb_continue_to_breakpoint "continue to callee" + +# Verify the value of rbx/ebx in the inner frame (callee). +with_test_prefix "callee, before change" { + gdb_test "p/x \$rbx" " = 0x2021222324252627" + gdb_test "p/x \$ebx" " = 0x24252627" +} + +# Verify that we can change the value of the pseudo register (ebx) in the inner +# frame (callee). +gdb_test_no_output "set \$ebx = 0x34353637" + +# Verify the value of rbx/ebx in the inner frame (callee) after the change. +with_test_prefix "callee, after change" { + gdb_test "p/x \$rbx" " = 0x2021222334353637" + gdb_test "p/x \$ebx" " = 0x34353637" +} + +# Go up one frame, and do the same. +gdb_test "up" + +# Verify the value of rbx/ebx in the outer frame (caller). +with_test_prefix "caller, before change" { + gdb_test "p/x \$rbx" " = 0x1011121314151617" + gdb_test "p/x \$ebx" " = 0x14151617" +} + +# Verify that we can change the value of the pseudo register (ebx) in the outer +# frame (caller). +gdb_test_no_output "set \$ebx = 0x44454647" + +# Verify the value of rbx/ebx in the outer frame (caller) after the change. +with_test_prefix "caller, after change" { + gdb_test "p/x \$rbx" " = 0x1011121344454647" + gdb_test "p/x \$ebx" " = 0x44454647" +} + +# Go back to frame 0 (callee), check that the change to the outer frame didn't +# mess up anything there. +gdb_test "down" +with_test_prefix "callee, after change in caller" { + gdb_test "p/x \$rbx" " = 0x2021222334353637" + gdb_test "p/x \$ebx" " = 0x34353637" +} + +# Verify that the value of the saved rbx we changed is correctly seen by the +# inferior. +gdb_breakpoint break_here_c temporary +gdb_continue_to_breakpoint "continue to break_here_c" +gdb_test "p/x value" " = 0x1011121344454647" diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind-asm.S b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-asm.S new file mode 100644 index 000000000000..0e5ad1b9bee1 --- /dev/null +++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-asm.S @@ -0,0 +1,79 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +.section .note.GNU-stack,"",%progbits + +.data +value_callee: +.quad 0x2021222324252627 +value_caller: +.quad 0x1011121314151617 + +.text +.arm +.global callee +callee: + /* Standard prologue. */ +.cfi_startproc + push {fp, lr} +.cfi_def_cfa fp, 4 +.cfi_offset fp, -8 +.cfi_offset lr, -4 + add fp, sp, #4 + + /* Save caller's d8 value on the stack. */ +.cfi_offset d8, -16 + vpush {d8} + + /* Put our own d8 value. */ + ldr r0, =value_callee + vldr d8, [r0] +break_here_asm: + + /* Restore caller's d8 value. */ + vpop {d8} + + /* Standard epilogue. */ + pop {fp, pc} +.cfi_endproc + + +.global caller +caller: + /* Standard prologue. */ +.cfi_startproc + push {fp, lr} +.cfi_def_cfa fp, 4 +.cfi_offset fp, -8 +.cfi_offset lr, -4 + add fp, sp, #4 + + /* Put our own d8 value. */ + ldr r0, =value_caller + vldr d8, [r0] + + /* Call callee. */ + bl callee + + /* Store our d8 value in r0-r1 to return it. */ + vpush {d8} + pop {r0} + pop {r1} + + /* Standard epilogue. */ + pop {fp, pc} +.cfi_endproc diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy-asm.S b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy-asm.S new file mode 100644 index 000000000000..786e79a0543e --- /dev/null +++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy-asm.S @@ -0,0 +1,84 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +/* The difference between this and arm-pseudo-unwind is that here, the CFI + directives use the obsolete DWARF number for the s16 register (a + pseudo-register in GDB), whereas arm-pseudo-unwind uses the number for the d8 + register (the underlying raw register for s16). */ + +.section .note.GNU-stack,"",%progbits + +.data +value_callee: +.quad 0x20212223 +value_caller: +.quad 0x10111213 + +.text +.arm +.global callee +callee: +.cfi_startproc + /* Standard prologue. */ + push {fp, lr} +.cfi_def_cfa fp, 4 +.cfi_offset fp, -8 +.cfi_offset lr, -4 + add fp, sp, #4 + + /* Save caller's s16 value on the stack. */ +.cfi_offset 80, -12 + vpush {s16} + + /* Put our own s16 value. */ + ldr r0, =value_callee + vldr s16, [r0] +break_here_asm: + + /* Restore caller's s16 value. */ + vpop {s16} + + /* Standard epilogue. */ + pop {fp, pc} +.cfi_endproc + + +.global caller +caller: +.cfi_startproc + /* Standard prologue. */ + push {fp, lr} +.cfi_def_cfa fp, 4 +.cfi_offset fp, -8 +.cfi_offset lr, -4 + add fp, sp, #4 + + /* Put our own s16 value. */ + ldr r0, =value_caller + vldr s16, [r0] + + /* Call callee. */ + bl callee + + /* Store our s16 value in r0-r1 to return it. */ + vpush {s16} + pop {r0} + mov r1, #0 + + /* Standard epilogue. */ + pop {fp, pc} +.cfi_endproc diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c new file mode 100644 index 000000000000..d18876fe3be3 --- /dev/null +++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c @@ -0,0 +1,33 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + +uint64_t caller (void); + +static void +break_here_c (uint64_t value) +{ +} + +int +main (void) +{ + uint64_t value = caller (); + break_here_c (value); + return 0; +} diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp new file mode 100644 index 000000000000..c3d0979799dc --- /dev/null +++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp @@ -0,0 +1,86 @@ +# Copyright 2018-2023 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 test is in the same vein as amd64-pseudo-unwind, making sure we can +# read write pseudo registers in outer frames. However, it tests a special +# case where the debug info includes unwind information for a pseudo register +# but not the underlying raw register. This can happen for the pseudo register +# s16, which is the bottom half of the raw register d8. +# +# See "DWARF for the ARM architecture": +# https://github.com/ARM-software/abi-aa/releases/download/2023Q3/aadwarf32.pdf + +if { ![istarget arm*-*-* ] } { + verbose "Skipping arm pseudo register unwind." + return +} + +standard_testfile arm-pseudo-unwind-legacy.c arm-pseudo-unwind-legacy-asm.S + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + "${srcfile} ${srcfile2}" {debug additional_flags=-marm}] } { + return -1 +} + +clean_restart ${binfile} + +if ![runto_main] then { + fail "could not run to main" +} + +gdb_breakpoint break_here_asm temporary +gdb_continue_to_breakpoint "continue to callee" + +# Verify the value of s16 in the inner frame (callee). +with_test_prefix "callee, before change" { + gdb_test "p/x \$s16" " = 0x20212223" +} + +# Verify that we can change the value of s16 in the inner frame (callee). +gdb_test_no_output "set \$s16 = 1.0" + +# Verify the value of s16 in the inner frame (callee) after the change. +with_test_prefix "callee, after change" { + gdb_test "p/x \$s16" " = 0x3f800000" +} + +# Go up one frame, and do the same. +gdb_test "up" + +# Verify the value of s16 in the outer frame (caller). +with_test_prefix "caller, before change" { + gdb_test "p/x \$s16" " = 0x10111213" +} + +# Verify that we can change the value of s16 in the outer frame (caller). +gdb_test_no_output "set \$s16 = 2.0" + +# Verify the value of s16 in the outer frame (caller) after the change. +with_test_prefix "caller, after change" { + gdb_test "p/x \$s16" " = 0x40000000" +} + +# Go back to frame 0 (callee), check that the change to the outer frame didn't +# mess up anything there. +gdb_test "down" +with_test_prefix "callee, after change in caller" { + gdb_test "p/x \$s16" " = 0x3f800000" +} + +# Verify that the value of the saved s16 we changed is correctly seen by the +# inferior. +gdb_breakpoint break_here_c temporary +gdb_continue_to_breakpoint "continue to break_here_c" +gdb_test "p/x value" " = 0x40000000" diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind.c b/gdb/testsuite/gdb.arch/arm-pseudo-unwind.c new file mode 100644 index 000000000000..d18876fe3be3 --- /dev/null +++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind.c @@ -0,0 +1,33 @@ +/* Copyright 2018-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + +uint64_t caller (void); + +static void +break_here_c (uint64_t value) +{ +} + +int +main (void) +{ + uint64_t value = caller (); + break_here_c (value); + return 0; +} diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp b/gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp new file mode 100644 index 000000000000..bfe81b7d5f21 --- /dev/null +++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp @@ -0,0 +1,88 @@ +# Copyright 2018-2023 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 test is equivalent to amd64-pseudo-unwind, but specific to ARM. We +# use the raw register d8 which is 64 bits long. We use pseudo register s16, +# which is the low 32 bits of d8. + +if { ![istarget arm*-*-* ] } { + verbose "Skipping arm pseudo register unwind." + return +} + +standard_testfile arm-pseudo-unwind.c arm-pseudo-unwind-asm.S + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + "${srcfile} ${srcfile2}" {debug additional_flags=-marm}] } { + return -1 +} + +clean_restart ${binfile} + +if ![runto_main] then { + fail "could not run to main" +} + +gdb_breakpoint break_here_asm temporary +gdb_continue_to_breakpoint "continue to callee" + +# Verify the value of d8/s16 in the inner frame (callee). +with_test_prefix "callee, before change" { + gdb_test "p/x \$d8" " = 0x2021222324252627" + gdb_test "p/x \$s16" " = 0x24252627" +} + +# Verify that we can change the value of the pseudo register (s16) in the inner +# frame (callee). +gdb_test_no_output "set \$s16 = 1.0" + +# Verify the value of d8/s16 in the inner frame (callee) after the change. +with_test_prefix "callee, after change" { + gdb_test "p/x \$d8" " = 0x202122233f800000" + gdb_test "p/x \$s16" " = 0x3f800000" +} + +# Go up one frame (to caller), and do the same. +gdb_test "up" + +# Verify the value of d8/s16 in the outer frame (caller). +with_test_prefix "caller, before change" { + gdb_test "p/x \$d8" " = 0x1011121314151617" + gdb_test "p/x \$s16" " = 0x14151617" +} + +# Verify that we can change the value of the pseudo register (s16) in the outer +# frame (caller). +gdb_test_no_output "set \$s16 = 2.0" + +# Verify the value of d8/s16 in the outer frame (caller) after the change. +with_test_prefix "caller, after change" { + gdb_test "p/x \$d8" " = 0x1011121340000000" + gdb_test "p/x \$s16" " = 0x40000000" +} + +# Go back to frame 0 (callee), check that the change to the outer frame didn't +# mess up anything there. +gdb_test "down" +with_test_prefix "callee, after change in caller" { + gdb_test "p/x \$d8" " = 0x202122233f800000" + gdb_test "p/x \$s16" " = 0x3f800000" +} + +# Verify that the value of the saved d8 we changed is correctly seen by the +# inferior. +gdb_breakpoint break_here_c temporary +gdb_continue_to_breakpoint "continue to break_here_c" +gdb_test "p/x value" " = 0x1011121340000000"