From patchwork Sat Nov 2 02:56:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840272 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1158177wrb; Fri, 1 Nov 2024 19:57:10 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCUQcFXRwnOvrxzOIaEmFA010M6Lz89j1fTw4ssteoLlAmaC2ABDsYLaZJ4WraGYWiN9IrruQQ==@linaro.org X-Google-Smtp-Source: AGHT+IGy+UiyfgVmvLt5k7g77M7LBUPO/l288dBWBnD0Pt+w9wZW5g6r7r7MPQ84iaMNECaFqtTm X-Received: by 2002:a05:620a:2956:b0:7ac:9b07:dbd3 with SMTP id af79cd13be357-7b2fa60b808mr1046363385a.5.1730516229838; Fri, 01 Nov 2024 19:57:09 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516229; cv=pass; d=google.com; s=arc-20240605; b=c6yW3mRAryHsQGzdQJfiduxUG9JfaB7GTjlCz+WYITpjV6bj4P8a/ZSlmN4TCgBBbJ YmsyHNPeyYegeTQfTOyXz/AeG0cUfaliRqFy/hqahj671S5SU/kw82e35oZG3jarimYR aaTVd2ZalnH07cmC11geADTSDvBvarjaJ7l+xajdwc+IuEwb1L7TdHll0+FEBPaZadx9 Q0pbgz/nl5OHYUahzGtz4gpnZVyitRcynCkLYQJLFqmAdS0sYPxcxswJJFk2wwOS9o2/ pgyKZkmKDMYxwC105NnAPQx5RYlVvq0LGYmzQcR5PArJytedRRmtE0ZvI9q1PBVXXIVU nJZA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=z45Ff2s4LjQ/0w6LVeLeQfQt9FRqNzLjr/0CDjBSMAM=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=jqQYQKR9DaHJw6Cs6avec3srs35puM9fpQrMzvAc06G7+FKzurQ0i39K/el0f9fNAs K40Rg9IglnslAGS8BO9zQFm1uRLLP7MtH/HGyKQOPmGFJ9kbzcmcfR2rQ9woYEUKOL5F gRq945nStQfSpzcTawlSeNm09TB1CspmKM5XjhQ8OcJfm2Zb9lM6700PjkIF4gzUre4i 8aMaJ5zRgZdf/KubGiCi0jVRgN3EifkT0oqmk6ZgkEQ8QKVkNSgFbGWuQiUL4Sha8NVv Ng6DPX3UgrMAvDBV3euv5JBUp0ET4QxWIU7CKWzUMRUpIOCiopeVO6W5bMFWXtkTUCR1 EQNw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=JG4FryKs; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id af79cd13be357-7b2f3a813ccsi580647685a.298.2024.11.01.19.57.09 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:57:09 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=JG4FryKs; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 75487385801B for ; Sat, 2 Nov 2024 02:57:09 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pf1-x432.google.com (mail-pf1-x432.google.com [IPv6:2607:f8b0:4864:20::432]) by sourceware.org (Postfix) with ESMTPS id CB6D33858C51 for ; Sat, 2 Nov 2024 02:56:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CB6D33858C51 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org CB6D33858C51 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::432 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516205; cv=none; b=Zn7zWvQdffz0e26dmUrO+2u1p4QA/v/MPBwUMMUuO64gKMgtTcC0kgVpMLQjj9biwLet5DO8DfZy2ZGeqhGKT5KY2QOtFqvJamx77aw/XFZDZLMZwzAzW9XcfRH8ie4LvDH/1b6FowOa2ZBxeL5YaQmk3jWRoarJEGClGx+aXD8= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516205; c=relaxed/simple; bh=QJuNnoeQNvkwQmf+cB0CwrcyTmw1Bb4cuYLMeWvhMR8=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=WQdU9HztQAqPIhUPHwT87GWGdoeDVoPX0ABs3ciUDuIKlNbpZSkG8lKTsWOiOKdgXA4y9oL4SENW75x7Y/R9cotyeuVtTORkGJXcxY4ed6vwqQQWQOFt7+wY3/5YFJgkRUSMXkOf6ooF0jKxYaEiOSjp6cRXB5tutnGL6UYtxKA= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x432.google.com with SMTP id d2e1a72fcca58-720be27db74so1617907b3a.1 for ; Fri, 01 Nov 2024 19:56:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516202; x=1731121002; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=z45Ff2s4LjQ/0w6LVeLeQfQt9FRqNzLjr/0CDjBSMAM=; b=JG4FryKsAnRl9dJCCQef0o25M/VrHFWMjUVo+QRCuv568gyBXqY2L4mlqrl9F6FDJm njTABqT9C5QpV6WFhHegZvvv9gSK2d+15XtrYkAs/lWfTscHw1C3Qlz+obTTfaeu6tRV +nmoo8rKHG+2ugw1ZsA6Tzkq4Gyx3+7TogY2FzzS+RiBt3gDim4TwX5BqaGlZCiDUbM0 amvGTqnYYSNrvrF6SLfavy1jnKhBl6SFlk8Oj1nmuWsoDdhtP+ieccjBwHpVBJ/4RwXQ 58yQOk5W7Puv2+g2uOSQfVczfXt0B+L2KaYH3W1gMxyQGFVTpqSgycTl44NwwUrejDEI 4TXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516202; x=1731121002; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=z45Ff2s4LjQ/0w6LVeLeQfQt9FRqNzLjr/0CDjBSMAM=; b=S8i/uXgFvg0f8Qi7D6j327oVJrtUpPSgIeH9qvkfMzRaQKFhfZ/u7qChPk1cIxNkaN Em3ylD/owRg2G7209G8xYmCb338a5KtZDHXmqKtlk5DvYXfmOlNChnFfnCx+0MXrbNZT BDs27XEL5AJq6gQ961MMRAtYrKhTwiemCtstH/HfXWXwldmD3D72Y9CRWt8Oe0fuC3hC t95c5yIHk/ctUzXEawPCiCeX8xO1lBKxaczPI9SkXqVFM5u0T7nyLI50LiBsUf7hlLJ7 efgOJdu5bqS0hUuf5ydtCYtpS8OSvni26nerfC+pZJBT8uDqADTMU90ZEjRjqtcoKc2v T+6g== X-Gm-Message-State: AOJu0YxZWVG4lyMYTUoHdJDyKsVuvLhICs84j/imsbCJmhVbthntOBO/ +BSyN+HZyO4h/VfcMoumI3z9LZJhXI49AmXzRqykRdq7qOF3nxW2HFfI84gbmY2FtRArs/P9VUv t X-Received: by 2002:a05:6a00:790:b0:71e:52f0:1c28 with SMTP id d2e1a72fcca58-720c945c433mr8479869b3a.0.1730516201612; Fri, 01 Nov 2024 19:56:41 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-720bc1b8ce8sm3376866b3a.35.2024.11.01.19.56.40 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:56:41 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 01/15] GDB, gdbserver: Convert regcache_register_size function to method Date: Fri, 1 Nov 2024 23:56:21 -0300 Message-ID: <20241102025635.586759-2-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org The regcache_register_size function has one implementation in GDB, and one in gdbserver. Both of them have a gdb::checked_static_cast to their corresponding regcache class. This can be avoided by defining a pure virtual register_size method in the reg_buffer_common class, which is then implemented by the reg_buffer class in GDB, and by the regcache class in gdbserver. Calls to the register_size () function from methods of classes in the reg_buffer_common hierarchy need to be changed to calls to the newly defined method, otherwise the compiler complains that a matching method cannot be found. --- gdb/i387-tdep.c | 4 ++-- gdb/nat/aarch64-hw-point.c | 2 +- gdb/regcache-dump.c | 2 +- gdb/regcache.c | 18 ++++++++---------- gdb/regcache.h | 3 +++ gdbserver/regcache.cc | 5 ++--- gdbserver/regcache.h | 3 +++ gdbsupport/common-regcache.h | 16 +++++----------- 8 files changed, 25 insertions(+), 28 deletions(-) diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c index 3bda88807943..92f898caf770 100644 --- a/gdb/i387-tdep.c +++ b/gdb/i387-tdep.c @@ -1565,7 +1565,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, byte_order, I387_FCTRL_INIT_VAL); else memset (FXSAVE_ADDR (tdep, regs, i), 0, - regcache_register_size (regcache, i)); + regcache->register_size (i)); } } } @@ -1888,7 +1888,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, int regsize; regcache->raw_collect (i, raw); - regsize = regcache_register_size (regcache, i); + regsize = regcache->register_size (i); p = FXSAVE_ADDR (tdep, regs, i); if (memcmp (raw, p, regsize)) { diff --git a/gdb/nat/aarch64-hw-point.c b/gdb/nat/aarch64-hw-point.c index 6acee0fb814c..8ab91fe85142 100644 --- a/gdb/nat/aarch64-hw-point.c +++ b/gdb/nat/aarch64-hw-point.c @@ -166,7 +166,7 @@ aarch64_point_is_aligned (ptid_t ptid, int is_watchpoint, CORE_ADDR addr, /* Set alignment to 2 only if the current process is 32-bit, since thumb instruction can be 2-byte aligned. Otherwise, set alignment to AARCH64_HBP_ALIGNMENT. */ - if (regcache_register_size (regcache, 0) == 8) + if (regcache->register_size (0) == 8) alignment = AARCH64_HBP_ALIGNMENT; else alignment = 2; diff --git a/gdb/regcache-dump.c b/gdb/regcache-dump.c index 3e6880535235..0a851e3ed771 100644 --- a/gdb/regcache-dump.c +++ b/gdb/regcache-dump.c @@ -110,7 +110,7 @@ class register_dump_reg_buffer : public register_dump, reg_buffer { if (regnum < gdbarch_num_regs (m_gdbarch) || m_has_pseudo) { - auto size = register_size (m_gdbarch, regnum); + auto size = register_size (regnum); if (size == 0) return; diff --git a/gdb/regcache.c b/gdb/regcache.c index f04354d822f9..6e0c730d0d59 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -179,10 +179,9 @@ register_size (struct gdbarch *gdbarch, int regnum) /* See gdbsupport/common-regcache.h. */ int -regcache_register_size (const reg_buffer_common *regcache, int n) +reg_buffer::register_size (int regnum) const { - return register_size - (gdb::checked_static_cast (regcache)->arch (), n); + return ::register_size (this->arch (), regnum); } reg_buffer::reg_buffer (gdbarch *gdbarch, bool has_pseudo) @@ -939,7 +938,7 @@ register_status readable_regcache::read_part (int regnum, int offset, gdb::array_view dst, bool is_raw) { - int reg_size = register_size (arch (), regnum); + int reg_size = register_size (regnum); gdb_assert (offset >= 0); gdb_assert (offset + dst.size () <= reg_size); @@ -983,7 +982,7 @@ void reg_buffer::raw_collect_part (int regnum, int offset, gdb::array_view dst) const { - int reg_size = register_size (arch (), regnum); + int reg_size = register_size (regnum); gdb_assert (offset >= 0); gdb_assert (offset + dst.size () <= reg_size); @@ -1013,7 +1012,7 @@ register_status regcache::write_part (int regnum, int offset, gdb::array_view src, bool is_raw) { - int reg_size = register_size (arch (), regnum); + int reg_size = register_size (regnum); gdb_assert (offset >= 0); gdb_assert (offset + src.size () <= reg_size); @@ -1065,7 +1064,7 @@ void reg_buffer::raw_supply_part (int regnum, int offset, gdb::array_view src) { - int reg_size = register_size (arch (), regnum); + int reg_size = register_size (regnum); gdb_assert (offset >= 0); gdb_assert (offset + src.size () <= reg_size); @@ -1226,8 +1225,7 @@ regcache::transfer_regset_register (struct regcache *out_regcache, int regnum, const gdb_byte *in_buf, gdb_byte *out_buf, int slot_size, int offs) const { - struct gdbarch *gdbarch = arch (); - int reg_size = std::min (register_size (gdbarch, regnum), slot_size); + int reg_size = std::min (register_size (regnum), slot_size); /* Use part versions and reg_size to prevent possible buffer overflows when accessing the regcache. */ @@ -1244,7 +1242,7 @@ regcache::transfer_regset_register (struct regcache *out_regcache, int regnum, else if (in_buf != nullptr) { /* Zero-extend the register value if the slot is smaller than the register. */ - if (slot_size < register_size (gdbarch, regnum)) + if (slot_size < register_size (regnum)) out_regcache->raw_supply_zeroed (regnum); out_regcache->raw_supply_part (regnum, 0, gdb::make_array_view (in_buf + offs, diff --git a/gdb/regcache.h b/gdb/regcache.h index 2f4b7d94c693..65e9f7bb79da 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -256,6 +256,9 @@ class reg_buffer : public reg_buffer_common /* See gdbsupport/common-regcache.h. */ bool raw_compare (int regnum, const void *buf, int offset) const override; + /* See gdbsupport/common-regcache.h. */ + int register_size (int regnum) const override; + protected: /* Assert on the range of REGNUM. */ void assert_regnum (int regnum) const; diff --git a/gdbserver/regcache.cc b/gdbserver/regcache.cc index 1bb71d103288..6a1526246867 100644 --- a/gdbserver/regcache.cc +++ b/gdbserver/regcache.cc @@ -308,10 +308,9 @@ register_size (const struct target_desc *tdesc, int n) /* See gdbsupport/common-regcache.h. */ int -regcache_register_size (const reg_buffer_common *regcache, int n) +regcache::register_size (int regnum) const { - return register_size - (gdb::checked_static_cast (regcache)->tdesc, n); + return ::register_size (tdesc, regnum); } static gdb::array_view diff --git a/gdbserver/regcache.h b/gdbserver/regcache.h index 1752c3979d39..df0feca102e0 100644 --- a/gdbserver/regcache.h +++ b/gdbserver/regcache.h @@ -49,6 +49,9 @@ struct regcache : public reg_buffer_common /* See gdbsupport/common-regcache.h. */ enum register_status get_register_status (int regnum) const override; + /* See gdbsupport/common-regcache.h. */ + int register_size (int regnum) const override; + /* See gdbsupport/common-regcache.h. */ void raw_supply (int regnum, gdb::array_view src) override; diff --git a/gdbsupport/common-regcache.h b/gdbsupport/common-regcache.h index f8704c16939a..4594999346fd 100644 --- a/gdbsupport/common-regcache.h +++ b/gdbsupport/common-regcache.h @@ -48,11 +48,6 @@ enum register_status : signed char 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 reg_buffer_common *regcache, int n); - /* Read the PC register. This function must be provided by the client. */ @@ -78,6 +73,9 @@ struct reg_buffer_common buffer. */ virtual register_status get_register_status (int regnum) const = 0; + /* Return the size of register numbered REGNUM in this buffer. */ + virtual int register_size (int regnum) const = 0; + /* Supply register REGNUM, whose contents are stored in SRC, to this register buffer. */ virtual void raw_supply (int regnum, gdb::array_view src) @@ -91,9 +89,7 @@ struct reg_buffer_common void raw_supply (int regnum, const gdb_byte *src) { - raw_supply (regnum, - gdb::make_array_view (src, - regcache_register_size (this, regnum))); + raw_supply (regnum, gdb::make_array_view (src, register_size (regnum))); } /* Collect register REGNUM from this register buffer and store its contents in @@ -109,9 +105,7 @@ struct reg_buffer_common void raw_collect (int regnum, gdb_byte *dst) { - raw_collect (regnum, - gdb::make_array_view (dst, - regcache_register_size (this, regnum))); + raw_collect (regnum, gdb::make_array_view (dst, register_size (regnum))); } /* Compare the contents of the register stored in the regcache (ignoring the From patchwork Sat Nov 2 02:56:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840273 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1158221wrb; Fri, 1 Nov 2024 19:57:26 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCW+D9EakoNKLKDupjLDOWT4swSEfEA4RNveDEEbP1TXfXTbBIhEyJTxjBL2kn0fOfLjM6IoMQ==@linaro.org X-Google-Smtp-Source: AGHT+IGj3F39fcpfBknsId+83iGCa6aXZn+imMw6zmkrybDfTKUvHL43MjVDlATTE+T1YAukN4Yz X-Received: by 2002:a05:620a:28cf:b0:7b1:8dcd:b7a6 with SMTP id af79cd13be357-7b2fb9582c3mr824202885a.8.1730516246011; Fri, 01 Nov 2024 19:57:26 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516245; cv=pass; d=google.com; s=arc-20240605; b=Ie0/cjCiG3zhPl8ORdbn7ofYMoSFWZnf/b/mRxTBCqIw7sUVXSvOkPl8TVukLdyigi 7Op4BFl8uxXQ0KY3T5jWj1L80qThysQ2kTmNTNWPp75ZSIWfmd8bO7dZQq856KKKsC/b DylsPbi4//XDjUaCBcgHMGHyYLlU/auOizFu2T6feFzyiY3La4KmE/IF3x65Vjsxn9lt RzXYkBdYgbHUx+te4AiBjqTq+5nByzcu9/cCAl46LQMCSh1uCIYuC/noLto5VSLxjFmy DVDrWlIQa+whlu5tgAFu5DsVzGQsLxJnh7mKfnYWoICnFuwoGSzZNu25cWrrYPn+NuAg gtkw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=OjXzt0ucyiIABJ/qp8lzbeE5zXEHcul8QSmCZaiXmdY=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=CKY0G76s469ohx3n3pQ0al+8INSVSaxw68aWRpL0KEHo8AUmqUDi7GBofuCuRT9dTr zDpOVrB3s5hy4cMn9LEdWwn1l61T78D288EHYbNazjyptiyaBcDmzbNynJtvJsHqM/gw lXdUHCa9fivn1X3bowoumT1cMYXsvmned5v3s9Qodie4Dwt06ZFSxz7ansciOn8PcD5F Exo31vpZsZrUbx8VMxhFSw74e3WBVFWJuwTI078khflfsW61J6hHf/n/HbcXT7kbP/qg dfw7SWvCUUqc4O+BvKb9UMVNKGmZup67/ejZlL/J4Qs/1c3u8P0ZKO9XKFzm3YUcZYD7 1g8g==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Rg1DwZ7n; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id af79cd13be357-7b2f3aae2desi553475185a.531.2024.11.01.19.57.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:57:25 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Rg1DwZ7n; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 51E533857C4F for ; Sat, 2 Nov 2024 02:57:25 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pf1-x434.google.com (mail-pf1-x434.google.com [IPv6:2607:f8b0:4864:20::434]) by sourceware.org (Postfix) with ESMTPS id 66A263858C32 for ; Sat, 2 Nov 2024 02:56:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 66A263858C32 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 66A263858C32 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::434 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516209; cv=none; b=f7BdCNuq3GLTVIzG3CdC36uzo0tjogf1gHCoyH7s+HPMuGKXErVJxT3qVqRH/j5slIWuhQpfsjZQlHrrWybTV8PJc0gnr2z6BdgXAf5iEfiSt0PWilLol4jFQRCMRHAxtvID1/6yZCTcGxFfA0ABQrWr1KvkkDEJ3W2f0oPOxPM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516209; c=relaxed/simple; bh=REue7UjN0DvJvB+GZaIK/039jpSDYPp5/5Y/ykhXV/I=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=k2W/xJyDjQZ7/dkS9GS4i5NOX3OUmAfWnsRtVFoJOOM1Q36VjLdosGrRvNaz2NP5AF0SgWpX9GPPgiBej8dCN9jRGeB7pfWytSNUesvOqvSqxS7jMbxD2sX5fUy+uttObgEDsRCHYvZhwWQH4+N2l63Tk1rlB25fBijc6OTdsxo= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-71e4244fdc6so2084460b3a.0 for ; Fri, 01 Nov 2024 19:56:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516205; x=1731121005; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=OjXzt0ucyiIABJ/qp8lzbeE5zXEHcul8QSmCZaiXmdY=; b=Rg1DwZ7n2SSNThuoXTce0Eex+/2e4Wv1Q/laAmjn8y3QnvIYE18jhBEgGBAF1JaUDs 3Nnx9fOqtnsFgdfQppjYAca18bGSDSiXCmNgE1jLZjiQEy79MlvYX9KnUBmAwIaoQnVR UTmWxTqD95pFyTEFPRTeIXXNrbpR8+fAtIP7BymWA3HhgRmGTLdoXuuCFQDHEikPAXk1 oyJEnq668e/R7n+k7uLOmJFR3YYBeR2FeWNGlbb0q3m3aYSjgvVrTl2509EVKJYOrCVW nhBryU/ioFcpmBspQCXvcFA9YPOTrknnG6d4t4MLTwObf+ADT5Ojwqjd1dgRhwaGh3Ql /xNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516205; x=1731121005; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=OjXzt0ucyiIABJ/qp8lzbeE5zXEHcul8QSmCZaiXmdY=; b=RVfl9fzORJwiSL1fsceb8MMHhu7DUi2RzwuJJjk2AncEz7q0YihFLpo8CaXCtaMsUz 4P19ld7mTB9EXhSxXg7R/0S/3vhSv05ZqNOi1l0j/4auZCBiyEhGpy2TMRaGPBaWRw5/ 57cl1zos2hrJDNpFdhy+a94J3q//fZ1qP1nEZWW8KdqS6cW2tTwQPPNp/Jp+NQ3IsyqE 6IEoXfPaelHXZbZjoRUp9kiVIA71G6tWUZ//8LyY/GqduJymJd6jvpMTx+rOJQzvgSuV KuETb40YUMoPkGtubYZn1axqQRunBRffDd52GkWzoKQZ+MIjBgRTTRvXOMhpYMB0C96U A4NA== X-Gm-Message-State: AOJu0YwxrVEFgwIkG29NpUHiu43PGeoqFT0Pd0z0MJ5rHipc7QU8Srna eVXKT5kXIw5cwNbqdybSlA95THzBm7Cj3hwG+dpcXLaK0BdzKhMMWRTU2j5bHQ7tmyjjd4PQ+17 4 X-Received: by 2002:a05:6a21:1743:b0:1cf:2853:bc6c with SMTP id adf61e73a8af0-1dba55ab0e3mr7349945637.33.1730516205341; Fri, 01 Nov 2024 19:56:45 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-7ee452b1643sm3160799a12.38.2024.11.01.19.56.44 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:56:44 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 02/15] GDB: Use gdb::array_view for buffers used in register reading and unwinding Date: Fri, 1 Nov 2024 23:56:22 -0300 Message-ID: <20241102025635.586759-3-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org This allows checking the size of the given buffer. Changes frame_register_unwind (), frame_unwind_register (), get_frame_register () and deprecated_frame_register_read (). --- gdb/frame.c | 24 ++++++++++++++---------- gdb/frame.h | 8 ++++---- gdb/mips-tdep.c | 19 +++++++++++++------ gdb/stack.c | 2 +- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/gdb/frame.c b/gdb/frame.c index a6900b280724..2c1ea012191b 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1112,7 +1112,7 @@ frame_save_as_regcache (const frame_info_ptr &this_frame) { auto cooked_read = [this_frame] (int regnum, gdb::array_view buf) { - if (!deprecated_frame_register_read (this_frame, regnum, buf.data ())) + if (!deprecated_frame_register_read (this_frame, regnum, buf)) return REG_UNAVAILABLE; else return REG_VALID; @@ -1177,7 +1177,8 @@ void frame_register_unwind (const frame_info_ptr &next_frame, int regnum, int *optimizedp, int *unavailablep, enum lval_type *lvalp, CORE_ADDR *addrp, - int *realnump, gdb_byte *bufferp) + int *realnump, + std::optional> bufferp) { struct value *value; @@ -1204,11 +1205,13 @@ frame_register_unwind (const frame_info_ptr &next_frame, int regnum, if (bufferp) { + gdb_assert (bufferp->size () >= value->type ()->length ()); + if (!*optimizedp && !*unavailablep) - memcpy (bufferp, value->contents_all ().data (), + memcpy (bufferp->data (), value->contents_all ().data (), value->type ()->length ()); else - memset (bufferp, 0, value->type ()->length ()); + memset (bufferp->data (), 0, value->type ()->length ()); } /* Dispose of the new value. This prevents watchpoints from @@ -1217,7 +1220,8 @@ frame_register_unwind (const frame_info_ptr &next_frame, int regnum, } void -frame_unwind_register (const frame_info_ptr &next_frame, int regnum, gdb_byte *buf) +frame_unwind_register (const frame_info_ptr &next_frame, int regnum, + gdb::array_view buf) { int optimized; int unavailable; @@ -1238,7 +1242,7 @@ frame_unwind_register (const frame_info_ptr &next_frame, int regnum, gdb_byte *b void get_frame_register (const frame_info_ptr &frame, - int regnum, gdb_byte *buf) + int regnum, gdb::array_view buf) { frame_unwind_register (frame_info_ptr (frame->next), regnum, buf); } @@ -1447,7 +1451,7 @@ put_frame_register (const frame_info_ptr &next_frame, int regnum, gdb_assert (buf.size () == size); frame_register_unwind (next_frame, regnum, &optim, &unavail, &lval, &addr, - &realnum, nullptr); + &realnum); if (optim) error (_("Attempt to assign to a register that was not saved.")); switch (lval) @@ -1482,7 +1486,7 @@ put_frame_register (const frame_info_ptr &next_frame, int regnum, bool deprecated_frame_register_read (const frame_info_ptr &frame, int regnum, - gdb_byte *myaddr) + gdb::array_view myaddr) { int optimized; int unavailable; @@ -1541,7 +1545,7 @@ get_frame_register_bytes (const frame_info_ptr &next_frame, int regnum, int realnum; frame_register_unwind (next_frame, regnum, optimizedp, unavailablep, - &lval, &addr, &realnum, buffer.data ()); + &lval, &addr, &realnum, buffer); if (*optimizedp || *unavailablep) return false; } @@ -2159,7 +2163,7 @@ frame_register_unwind_location (const frame_info_ptr &initial_this_frame, int unavailable; frame_register_unwind (this_frame, regnum, optimizedp, &unavailable, - lvalp, addrp, realnump, NULL); + lvalp, addrp, realnump); if (*optimizedp) break; diff --git a/gdb/frame.h b/gdb/frame.h index e784c17b4807..23a3ade69c92 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -692,7 +692,7 @@ extern void frame_register_unwind (const frame_info_ptr &frame, int regnum, int *optimizedp, int *unavailablep, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, - gdb_byte *valuep); + std::optional> valuep = {}); /* Fetch a register from this, or unwind a register from the next frame. Note that the get_frame methods are wrappers to @@ -701,9 +701,9 @@ extern void frame_register_unwind (const frame_info_ptr &frame, int regnum, do return a lazy value. */ extern void frame_unwind_register (const frame_info_ptr &next_frame, - int regnum, gdb_byte *buf); + int regnum, gdb::array_view buf); extern void get_frame_register (const frame_info_ptr &frame, - int regnum, gdb_byte *buf); + int regnum, gdb::array_view buf); struct value *frame_unwind_register_value (const frame_info_ptr &next_frame, int regnum); @@ -889,7 +889,7 @@ extern void print_frame_info (const frame_print_options &fp_opts, extern frame_info_ptr block_innermost_frame (const struct block *); extern bool deprecated_frame_register_read (const frame_info_ptr &frame, int regnum, - gdb_byte *buf); + gdb::array_view buf); /* From stack.c. */ diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index c00efbd02ad0..24970c7637ad 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -951,14 +951,17 @@ mips_register_to_value (const frame_info_ptr &frame, int regnum, 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); + gdb::array_view first_half = gdb::make_array_view (to, 4); + gdb::array_view second_half = gdb::make_array_view (to + 4, 4); - if (!get_frame_register_bytes (next_frame, regnum + 0, 0, { to + 4, 4 }, + get_frame_register (frame, regnum + 0, second_half); + get_frame_register (frame, regnum + 1, first_half); + + if (!get_frame_register_bytes (next_frame, regnum + 0, 0, second_half, optimizedp, unavailablep)) return 0; - if (!get_frame_register_bytes (next_frame, regnum + 1, 0, { to + 0, 4 }, + if (!get_frame_register_bytes (next_frame, regnum + 1, 0, first_half, optimizedp, unavailablep)) return 0; *optimizedp = *unavailablep = 0; @@ -6257,8 +6260,10 @@ mips_read_fp_register_single (const frame_info_ptr &frame, int regno, struct gdbarch *gdbarch = get_frame_arch (frame); int raw_size = register_size (gdbarch, regno); gdb_byte *raw_buffer = (gdb_byte *) alloca (raw_size); + gdb::array_view raw_view = gdb::make_array_view (raw_buffer, + raw_size); - if (!deprecated_frame_register_read (frame, regno, raw_buffer)) + if (!deprecated_frame_register_read (frame, regno, raw_view)) error (_("can't read register %d (%s)"), regno, gdbarch_register_name (gdbarch, regno)); if (raw_size == 8) @@ -6295,7 +6300,9 @@ mips_read_fp_register_double (const frame_info_ptr &frame, int regno, { /* We have a 64-bit value for this register, and we should use all 64 bits. */ - if (!deprecated_frame_register_read (frame, regno, rare_buffer)) + gdb::array_view rare_view = gdb::make_array_view (rare_buffer, + raw_size); + if (!deprecated_frame_register_read (frame, regno, rare_view)) error (_("can't read register %d (%s)"), regno, gdbarch_register_name (gdbarch, regno)); } diff --git a/gdb/stack.c b/gdb/stack.c index 4a3e7e4ff006..b585e6e636d5 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -1750,7 +1750,7 @@ info_frame_command_core (const frame_info_ptr &fi, bool selected_frame_p) /* Find out the location of the saved register without fetching the corresponding value. */ frame_register_unwind (fi, i, &optimized, &unavailable, - &lval, &addr, &realnum, NULL); + &lval, &addr, &realnum); /* For moment, only display registers that were saved on the stack. */ if (!optimized && !unavailable && lval == lval_memory) From patchwork Sat Nov 2 02:56:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840274 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1158292wrb; Fri, 1 Nov 2024 19:57:54 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCXPxgncJouusACFvt6+/oAF/ym89u9hL4xgARzpAwa6ADDfCu8vWIbkhymEnXucDkMcp7VktQ==@linaro.org X-Google-Smtp-Source: AGHT+IEV9oMwOhYD7A/jF+S22N49H/EgMFbxGL5Imi+6tHCzpP7jrciGmEVchtHD7m3ZHcqtWcwO X-Received: by 2002:a05:622a:40e:b0:460:ae0f:470c with SMTP id d75a77b69052e-462b875457fmr82123271cf.47.1730516274352; Fri, 01 Nov 2024 19:57:54 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516274; cv=pass; d=google.com; s=arc-20240605; b=bNS3AUSVwPU0lZfLtajUFZvUglNmhvDfgWXoueUuQ/cggz0CzktjfcW1IOIWCbAtwk Mfbbn9uN6ASlLflbHDuLgvkhYXBn0K4IAjqb2UfN3QFhe0z6tLglLsCVVdn/P3CgnHUd fqf4/QT0gqwRrLSRF7mtBIlA6mzFP+FXYO5oqHcQOGJykId/RJ5YcdbQGbC/QjspwRRK BFk5+WRwf0z+kOP0pmnA+K8sIhNlm5ZzA36xQRNNwYKuVrJrG4+KsSUBBR1Jq76fSRCb VRC5QJ979Hn2Piar1Jyq9GhZD9Sh/hIIjB6zEMD1eQ0nAfO86JwkZ6WLj7cZNNOrzBUw MYvw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=+5/JIjjk3fjKXdNt7jCgPnHuRRfHZJz4B273m5YwTKs=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=PQnYJTfD/UhQ//IRzczbJ4+WdyC3IY/sC+iWt1mSxFMj9+zR8PtsAuRzMfV+dCBdKO J2MKJVyGLhEiFtvraKAZE/N9OT9X7tK6HzQdnb1Ejft/Y05XIYtdsoO7pRzy0EGHx1jd YkNk7uhHHpFTr65CDY9BILaMvcF473BL617e95g6xXWDF0k/8gKdd9XYbQfW2K8rllVh zDRuq+ofKfKrg7yNPbGpX5XMLM9N8lSNPs3gXbJ4ZTxfXNnumvAJ5YkjkEyB+BtG6tsp Hxw3zJ+oA6CX/9MtAG4btJkMkMmHJQEnaFPVDWIbU00yYCO+C3tcdL5xXKC9JKYUELD3 XIVA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=D3Lsjl9E; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id d75a77b69052e-462ad249a7dsi54556311cf.613.2024.11.01.19.57.54 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:57:54 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=D3Lsjl9E; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id F0D9D385842A for ; Sat, 2 Nov 2024 02:57:53 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pf1-x431.google.com (mail-pf1-x431.google.com [IPv6:2607:f8b0:4864:20::431]) by sourceware.org (Postfix) with ESMTPS id 37A353857B98 for ; Sat, 2 Nov 2024 02:56:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 37A353857B98 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 37A353857B98 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::431 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516213; cv=none; b=slw4yqMo6/XuUiuxAv1XgflG2iQ75aEGQB+qvWaatHuSmLicKBet+mu91baV1RO2MdHqzKLf09ASO+NxvTBH14HXajFfFxmsPFAshcfHJVwDwL8UX0K6D+HyMO3qC6QjCANHZtLMrd/T6u7e6AtMUZOZg82WVoHR53ObI76G/s0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516213; c=relaxed/simple; bh=2+GTJ+aHCcySfy03FIwn7Q4juZV5AptkC4LNjaY6pQQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=PmBh/mdTzRMSsFsKZo9t194TXJfZVMYfR0qPksazmrpQ0p03mG/Oq5jvFnQYkcTz7usTueqMc15cFRPlu4kKAW13GDRxdmzmOkniH/2nM1Td3VlmmuQLCU+tBTTCPbPfLNRjUgBUOXpdtdziOpyVc21XVx2Hf2VWcKxVC+IDeXM= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x431.google.com with SMTP id d2e1a72fcca58-72061bfec2dso2281073b3a.2 for ; Fri, 01 Nov 2024 19:56:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516208; x=1731121008; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=+5/JIjjk3fjKXdNt7jCgPnHuRRfHZJz4B273m5YwTKs=; b=D3Lsjl9E2SWuwL2EPW+OahyQ1eBVGHEbgehEHxUsqj+DIz9pjSQfgNovxDNYb5moix wCf5iM27OllUJRG8ttyfMhI+pus2iqk7XwQRndwZ2tfoafhoyzfgpT7midRtIZShIqRV 5n+JNfRd7a3Z4RvW6LfAyS2eH+vZR3Hj5plL4cSSqat+NMPlPLELNDJyNhkvP0mGL1dp DSRm/KCaEzrFQgcVdFxWOOm/bJPetBpYDAjOWGvM/ccWqMUFTAZKXWOkvDkcTp9uASA0 qjQKmzTqwEySuBwZ/Ueg8HImTcpBaC6tDByqP5WjEeB7/VQBKQFgA0Td9iTuOPmZn1YM f2cA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516208; x=1731121008; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+5/JIjjk3fjKXdNt7jCgPnHuRRfHZJz4B273m5YwTKs=; b=S7Dh9HcM8PKJRCRFY+oB9Ds/q29r1/CXmV0FRFE0i13QyFYAx5Su+JSbyNQGmdJq9D N19KWHQ1PdRab94Oqz+R8dZcyCtGMKf3yFvEEUy7GFL2n5zC7L534LAdvLEjzLRT1EMa lIPkSG+sg4oDo73eWsVdJ333c31BoVa04kSG3+DdjW4rIT2wEBMKuJo2ApvEwSlO4HSs ZTmfOk83qvfq2T6SlV6h3HotYjkjR7r+ICp3MvwIXcXbe7WcxsV4qLzzIeSRPsFOcpRS DDF8XA/7SlZMbuwBA/nabOlNUkF9lMUDSUicWaxw7Xbore9arXIx7eiRWkYoGaX3U0+p ZEJQ== X-Gm-Message-State: AOJu0YxuQaH/gK2AfK7piGbW14TGt4FQuNF4V26mnGwuqh7UoFeOQhzt o69NcO/UtriZd9Xh/Rl3YHFfg2t0NlzMNQNJFCUDYOJFJyNj8AAiDmP2SJnvzd9pJ0faZZy/Kqx b X-Received: by 2002:a05:6a21:e92:b0:1cf:6c86:231c with SMTP id adf61e73a8af0-1dba532816fmr7415234637.26.1730516208174; Fri, 01 Nov 2024 19:56:48 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-7ee4606c58bsm2543485a12.19.2024.11.01.19.56.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:56:47 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 03/15] GDB: remote: Print total bytes received in debug message Date: Fri, 1 Nov 2024 23:56:23 -0300 Message-ID: <20241102025635.586759-4-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org This is useful information I missed while debugging issues with the g packet reply. --- gdb/remote.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gdb/remote.c b/gdb/remote.c index b65a1c3094ae..6ffc51e4e2f5 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -10484,8 +10484,8 @@ remote_target::getpkt (gdb::char_vector *buf, bool forever, bool *is_notif) if (val > max_chars) remote_debug_printf_nofunc - ("Packet received: %s [%d bytes omitted]", str.c_str (), - val - max_chars); + ("Packet received: %s [%d bytes omitted, %d bytes total]", str.c_str (), + val - max_chars, val); else remote_debug_printf_nofunc ("Packet received: %s", str.c_str ()); From patchwork Sat Nov 2 02:56:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840275 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1158344wrb; Fri, 1 Nov 2024 19:58:15 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWtiQjcqco0MJxTZn2d2rpv3J7+fu61EkRy8Ys1sg6mpHjuXtI3xPZuS2Mszlb7TxIG2IYUOg==@linaro.org X-Google-Smtp-Source: AGHT+IEIsO5fCTNrFfP8c0VJPDpyHnZzruXR7Ky8cBki4GSivYDEiW0aWHm1QOsM2SslPQsLlo/6 X-Received: by 2002:a05:620a:3955:b0:7b1:48d1:574d with SMTP id af79cd13be357-7b2f3cf9e5dmr1496011685a.8.1730516295637; Fri, 01 Nov 2024 19:58:15 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516295; cv=pass; d=google.com; s=arc-20240605; b=GW938/mQcsyoxHOhPURAAGTzyuWGQ+SroX2Stizb6jNI8tu8ca94ib9FzCzVFfCpKG Q8F3wG8KIwDWXPsDnMx2a4xTQjPHAFcGH94o/QndvKXAb3W9ZN2kqqpMQEgfjqPJXZpd fQD3epkxShBBwPpD8CrxFOdUz8ohjW8e32DABXOHfTEYY9P5QGOtN5BGQEhULuAbBQ3I 7kfHoHM/U07oTBnMvFQyCHTMJPkJEu5CNy+mhKI+KGJJGu8AikblMRFlC4+CrFmQ2zYV QnA112xpBeQXUEEdA0rxxlBFmHZl6ijpGrilnl1sKyhYVX21BO3XNoUsd8iSuR2PaNRY QehQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=1eQqNcBj1MQz2Sf2r0uuvgO3/g229SbHldgXqqPTm7k=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=ZL8Rj2Bj5xMpvzGMP9LYr09JPw2yOAcYf8csIXodPxVoT0RMGs8KfP45NkA71ly6rC 2bKdIPRP48yE3oZMtP2sBeQaPT0+vV1CsHoAzL62d//6nT0Gh0vbFPvOftsS9vKzbtLs RAVGA7T39zn1TOTDeMZ2BmHNk+LPRFXf5a3vpv6io+U0p2Ss8/gB9ZJy6qXn25NAu9YD DqDSwezoobqLc95uutZSJf93efj1LkVGKhu99xGekkSeodeZaGkz3XDXmtK4Cec/wCVD dRgE1EGhqkux6y/Lpu0VCWoEkRSOpKyNRfg3Z66wRVAiHY/oUm1yu0CKYdYajzirU/wx y8mw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=AvdmcZGR; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id af79cd13be357-7b2f3ab2150si655599685a.542.2024.11.01.19.58.15 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:58:15 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=AvdmcZGR; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 50AB43857BA7 for ; Sat, 2 Nov 2024 02:58:15 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pg1-x530.google.com (mail-pg1-x530.google.com [IPv6:2607:f8b0:4864:20::530]) by sourceware.org (Postfix) with ESMTPS id C4D953858428 for ; Sat, 2 Nov 2024 02:56:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C4D953858428 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C4D953858428 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::530 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516215; cv=none; b=nVNg+cOBo+Ac9CtKOTCB8wdRI9ribBHQ8ysOi0t3k9uGyuCyxuYy68OPBB/TXjv7Z/80dzPDxzYW4RssaTmgQla8Evij4813d0Ze9eZr+Lf95VqVYceu9D7CmT1loSR/5THY/9eicBhRdzP/PnKhuIgiSqPN9b2eYwu+awdGf1o= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516215; c=relaxed/simple; bh=XasmZICvVOXT3tJNDECChC1zwk8I0AB4IAIXQArU9R4=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=M7ryXsp6CfOZ48+6KfBF2UlxPZWpp5+HOvpX+C2xJs511dZ31JVqEpBMUaPUF42v8Sm1b3JMXOT9CXtlDmr2RsxX5Sbx7CzqmFYTYqPAoLm7eS8DAI0lLdGmdtpvblKO8cP6aUR8tMtpKPiGfeeJInd++X5h2vqpNIwt+rZzVwY= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pg1-x530.google.com with SMTP id 41be03b00d2f7-7ea7ad1e01fso1821698a12.0 for ; Fri, 01 Nov 2024 19:56:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516212; x=1731121012; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=1eQqNcBj1MQz2Sf2r0uuvgO3/g229SbHldgXqqPTm7k=; b=AvdmcZGRx6KDJJkS9mbSHZUEqE45orTWP8dSC15+cTIGeI4AevkRRwykXKRmnJVPgZ Qt8KsqV31or0H1AiBqKItayCsGgT8xbdswcK7RQYcmSB7UX41otzJFyyQ/uo+zS+0B5x z4WIZePmtycBt2ZNxeWK56qPtJlwyBcS7m3Woh1YxGH9bQVK6PmCIYjl2le/2RMeR1lV W8uHS95JmGSt1G5XXpaDqbwDXaZh6WYjWQoR3iWjAUD5LaqK9bO8Nb4Zbl2pqLInGXDa Z9K9ByEMhW0FDbbqCqv/CySRkwQbjKVPLvst8fnZoaR8dKpX6FjH101k6NRlHK12cdix XjpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516212; x=1731121012; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1eQqNcBj1MQz2Sf2r0uuvgO3/g229SbHldgXqqPTm7k=; b=GJI3LYoocoQuLsnLdW4OwBYg1Ewcw4dMAM3gQFiLclPiBU2GCj1an9YZZsVs/R0vlQ njzThNPCBoGb6xhiExoYCK/gVhgwmIpdRhhynGjUZloRDpWmcl/Dn+iH9+hyn2E5vfuY 5pK4FNGNMF+3xH2QkgcplkAFXwV+3rYQ9C3Ep+tXeKbUFYNARSCNF7UXEW1Vwfi16BhM 4VLlF1zpu+nwss/dSfyex+3NxbsC5J81xZnKl5rR8aMC1qTrWcR72ajW0rer13hHvy8u W7USRfjTVeRAVZHH8g62jPCxlrf/Bw7wNVEmEgt+Nz6srXt7jA5zzoKIODjU24eeGg9h P9vQ== X-Gm-Message-State: AOJu0YyqRwlQOBcGFjUM9HcdswpjQL+OmLaCH5GXv1K6+rrGoCJImRoJ ZzaQenFBw+KFJasn+4p/TnhFSNK9S9oDEL61YWgkzs6xv5wqWX7Th2eTYOnggoNwmCcS3nrM3yC d X-Received: by 2002:a17:902:d492:b0:20b:5ef8:10a6 with SMTP id d9443c01a7336-211056b23d9mr124045795ad.8.1730516211625; Fri, 01 Nov 2024 19:56:51 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-211056ee412sm27794985ad.40.2024.11.01.19.56.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:56:51 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 04/15] GDB: trad-frame: Store length of value_bytes in trad_frame_saved_reg Date: Fri, 1 Nov 2024 23:56:24 -0300 Message-ID: <20241102025635.586759-5-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org The goal is to ensure that it is available in frame_unwind_got_bytes () to make sure that the provided buf isn't larger than the size of the register being provisioned. In the process, regcache's cached_reg_t::data also needed to be converted to a gdb::byte_vector, so that the register contents' size can be tracked. --- gdb/frame-unwind.c | 18 +++++++++++++++--- gdb/frame-unwind.h | 2 +- gdb/jit.c | 2 +- gdb/python/py-unwind.c | 7 ++++--- gdb/regcache.h | 2 +- gdb/remote.c | 11 +++++------ gdb/trad-frame.h | 10 +++++++--- 7 files changed, 34 insertions(+), 18 deletions(-) diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c index fecd1070e912..ad8ebb29d736 100644 --- a/gdb/frame-unwind.c +++ b/gdb/frame-unwind.c @@ -313,14 +313,26 @@ frame_unwind_got_constant (const frame_info_ptr &frame, int regnum, } struct value * -frame_unwind_got_bytes (const frame_info_ptr &frame, int regnum, const gdb_byte *buf) +frame_unwind_got_bytes (const frame_info_ptr &frame, int regnum, + gdb::array_view buf) { struct gdbarch *gdbarch = frame_unwind_arch (frame); struct value *reg_val; reg_val = value::zero (register_type (gdbarch, regnum), not_lval); - memcpy (reg_val->contents_raw ().data (), buf, - register_size (gdbarch, regnum)); + gdb::array_view val_contents = reg_val->contents_raw (); + + /* The value's contents buffer is zeroed on allocation so if buf is + smaller, the remaining space will be filled with zero. + + This can happen when unwinding through signal frames. For example, if + an AArch64 program doesn't use SVE, then the Linux kernel will only + save in the signal frame the first 128 bits of the vector registers, + which is their minimum size, even if the vector length says they're + bigger. */ + gdb_assert (buf.size () <= val_contents.size ()); + + memcpy (val_contents.data (), buf.data (), buf.size ()); return reg_val; } diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h index 53fcd6869e95..36e7fbdb4f9c 100644 --- a/gdb/frame-unwind.h +++ b/gdb/frame-unwind.h @@ -226,7 +226,7 @@ value *frame_unwind_got_constant (const frame_info_ptr &frame, int regnum, inside BUF. */ value *frame_unwind_got_bytes (const frame_info_ptr &frame, int regnum, - const gdb_byte *buf); + gdb::array_view buf); /* Return a value which indicates that FRAME's saved version of REGNUM has a known constant (computed) value of ADDR. Convert the diff --git a/gdb/jit.c b/gdb/jit.c index ed3b26cd4bd1..e068b0a4b572 100644 --- a/gdb/jit.c +++ b/gdb/jit.c @@ -1094,7 +1094,7 @@ jit_frame_prev_register (const frame_info_ptr &this_frame, void **cache, int reg return frame_unwind_got_optimized (this_frame, reg); gdbarch = priv->regcache->arch (); - gdb_byte *buf = (gdb_byte *) alloca (register_size (gdbarch, reg)); + gdb::byte_vector buf (register_size (gdbarch, reg)); enum register_status status = priv->regcache->cooked_read (reg, buf); if (status == REG_VALID) diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c index 68deaf98d81f..c1a01bf7cfe4 100644 --- a/gdb/python/py-unwind.c +++ b/gdb/python/py-unwind.c @@ -812,7 +812,7 @@ pyuw_prev_register (const frame_info_ptr &this_frame, void **cache_ptr, for (; reg_info < reg_info_end; ++reg_info) { if (regnum == reg_info->num) - return frame_unwind_got_bytes (this_frame, regnum, reg_info->data.get ()); + return frame_unwind_got_bytes (this_frame, regnum, reg_info->data); } return frame_unwind_got_optimized (this_frame, regnum); @@ -936,8 +936,9 @@ pyuw_sniffer (const struct frame_unwind *self, const frame_info_ptr &this_frame, cached_reg_t *cached = new (&cached_frame->reg[i]) cached_reg_t (); cached->num = reg->number; - cached->data.reset ((gdb_byte *) xmalloc (data_size)); - memcpy (cached->data.get (), value->contents ().data (), data_size); + cached->data.resize (data_size); + gdb::array_view contents = value->contents (); + cached->data.assign (contents.begin (), contents.end ()); } } diff --git a/gdb/regcache.h b/gdb/regcache.h index 65e9f7bb79da..739172a249b8 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -177,7 +177,7 @@ using register_read_ftype struct cached_reg_t { int num; - gdb::unique_xmalloc_ptr data; + gdb::byte_vector data; cached_reg_t () = default; cached_reg_t (cached_reg_t &&rhs) = default; diff --git a/gdb/remote.c b/gdb/remote.c index 6ffc51e4e2f5..2da2c5a4789a 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -8225,13 +8225,12 @@ Packet: '%s'\n"), hex_string (pnum), p, buf); cached_reg.num = reg->regnum; - cached_reg.data.reset ((gdb_byte *) - xmalloc (register_size (event->arch, - reg->regnum))); + cached_reg.data.resize (register_size (event->arch, + reg->regnum)); p = p1 + 1; - fieldsize = hex2bin (p, cached_reg.data.get (), - register_size (event->arch, reg->regnum)); + fieldsize = hex2bin (p, cached_reg.data.data (), + cached_reg.data.size ()); p += 2 * fieldsize; if (fieldsize < register_size (event->arch, reg->regnum)) warning (_("Remote reply is too short: %s"), buf); @@ -8572,7 +8571,7 @@ remote_target::process_stop_reply (stop_reply_up stop_reply, for (cached_reg_t ® : stop_reply->regcache) { - regcache->raw_supply (reg.num, reg.data.get ()); + regcache->raw_supply (reg.num, reg.data); rs->last_seen_expedited_registers.insert (reg.num); } } diff --git a/gdb/trad-frame.h b/gdb/trad-frame.h index ca8792baa17d..ef84a24c0bc7 100644 --- a/gdb/trad-frame.h +++ b/gdb/trad-frame.h @@ -122,6 +122,7 @@ struct trad_frame_saved_reg m_kind = trad_frame_saved_reg_kind::VALUE_BYTES; m_reg.value_bytes = data; + m_reg.bytes_len = bytes.size (); } /* Getters */ @@ -144,10 +145,10 @@ struct trad_frame_saved_reg return m_reg.addr; } - const gdb_byte *value_bytes () const + gdb::array_view value_bytes () const { gdb_assert (m_kind == trad_frame_saved_reg_kind::VALUE_BYTES); - return m_reg.value_bytes; + return { m_reg.value_bytes, m_reg.bytes_len }; } /* Convenience functions, return true if the register has been @@ -185,7 +186,10 @@ struct trad_frame_saved_reg LONGEST value; int realreg; LONGEST addr; - const gdb_byte *value_bytes; + struct { + const gdb_byte *value_bytes; + size_t bytes_len; + }; } m_reg; }; From patchwork Sat Nov 2 02:56:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840276 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1158449wrb; Fri, 1 Nov 2024 19:58:41 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVRosI2vmjVsQqW9E9x6MCdf1uzTCs/22ia8548yYvY7K6+dSo2nDy+LVgS1tQ2EAjEQ3qfBg==@linaro.org X-Google-Smtp-Source: AGHT+IHg2usSMst2SC/th9b9Z5b24vKZF2NWlk20fcbd0M1HAHb114OOSxkalnUpCEc0T5SEeXpf X-Received: by 2002:a05:620a:c47:b0:7b1:50ba:76ec with SMTP id af79cd13be357-7b2fb9aac98mr642382285a.52.1730516321125; Fri, 01 Nov 2024 19:58:41 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516321; cv=pass; d=google.com; s=arc-20240605; b=EyzsOrcqGHhCvrM0d6iT+TNGpVwXmnVADzlmoOQacskHG68MqZrxIzEhNFO4/cz99i 1UP0MdVFCzvGWQyC0RLMGU8smUnGgmig7jatxmLD5FSGFBW+IfjiEj5CAtz1Adq1vRcC 6uF2l+1mp4A/kr1r/VznLWgDg1CZ379OY2MbheOVS0xnnSROJJ12VNOSoWakpMt2bUEt OcMrWzoosgw63DCzE+5iwNpqbiK7vTFiLvh1uwyk7Rhs+soM+P0OLqyY3MasPIZPxofR AHEQiosquSqMbgzkv2iut9Ih+JOoRQhMvGQdCtg3zVqT2WZTjGj7uYPvW3QDjjhLsMHl i3oA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=QdH4OoR5Wvm2r3w24heUTDGEVBM84lMNOz8fxSsHI7s=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=AMb7rt5IGf1iWYwI0QKYJqkccQXiQ34Lc05JbxxfbKQcIMQrLogJJe1H4xXpZHbaVC SiJdjRn8g07YAVtshlYQlf99MW33g4fGUNkX83sRRkRo72Vt7vSOzTmnRmjsTsNLpBEe HB7CxJfg4ReK9gtDwsLOr9cIAiQvtAE3lbXtmB6GocPOKBF7amS7NZ93tx5C7COp8N/c Jieqvo/wkvz/S2cfU5F1TumsI75WTBHff02D3vaRxs42l7WCWAuWnZHfoAWXpB2L1wWP ub5ebxmn/GsMUEFp/rwCYv3pI8jil00c5CyosH3GPwsoQLXVUC7yb3xm0frq67/lVZE3 1GDg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=xniiD2Bx; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id af79cd13be357-7b2f3a9ab78si573297385a.382.2024.11.01.19.58.40 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:58:41 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=xniiD2Bx; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B22D5385842A for ; Sat, 2 Nov 2024 02:58:40 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pj1-x102a.google.com (mail-pj1-x102a.google.com [IPv6:2607:f8b0:4864:20::102a]) by sourceware.org (Postfix) with ESMTPS id 16A843857BA3 for ; Sat, 2 Nov 2024 02:56:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 16A843857BA3 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 16A843857BA3 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::102a ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516218; cv=none; b=TV38RVhe8AvH01k53YKYd4pYlqphKnn0n2OkxyTg37eheyedDv67y37siZ963Cm/tezCbpfqkUeusD7ibJOzOKBiNhcDSKpZPUDtpJwKQklDJR0zx65ahy20IXgT4wxKrgqo4edEdVYyMXKTmL9+gIN4dSsLrkICBiVuOAoPCgY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516218; c=relaxed/simple; bh=IL5z5XlN29m6QvGfO5K/Khz45Ky0m1iG3EgYR1ieuxY=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=XcsGn4Jft9gjn+8fzWHveXDmS5TF675g8ZZsiybCw8Mf88H1IX5RFYKbnhFpBjDCneFM+RmqruZfaTDUmhnO8fM2KiIhywz5ELj7fTwmEk/aZZdFzopK6u0LS/m98SkClSv3G3MoDjYDj/RWK5KSRtjE2P65rpPCfkzg/lIiyY4= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pj1-x102a.google.com with SMTP id 98e67ed59e1d1-2e2e23f2931so1944799a91.0 for ; Fri, 01 Nov 2024 19:56:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516215; x=1731121015; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=QdH4OoR5Wvm2r3w24heUTDGEVBM84lMNOz8fxSsHI7s=; b=xniiD2BxepxMJdabjqoJXfFRANY0aIRQvEhf9Jzs62yY61pmdYxjoN49EdnaaJl7vM RB8haTbUfhA8QEuJXn7rtPPp9slRNartmEU7y7JlDLjaAigJFqxwa1xmLlHgJm8w6Jzq /CfnZfYKlP6eW6zwYVZ35ky7Jne9JbszJoOcdeoncbZOllL98D+5nI7joySofrhyO13C JVCRgU9m6NyFrsZRwTivk0z7kAT2cAOfN7lIAmNV8H1HfTcB6506vhRulAUldYYprl7N d787ATmjN1F1GcjPCy5TJjSTHzAlQ9u+QJTEkgYJpVsQmBev+n3LLvm9E5d8u/B8jsu+ 6coA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516215; x=1731121015; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=QdH4OoR5Wvm2r3w24heUTDGEVBM84lMNOz8fxSsHI7s=; b=G6T/MdiIdd04z9V/Y+DNMi1RhtgYRyo2+dikREDoTsnuNYNOSAt2eq01eYnZ7M0vJZ HISKPpm3QJCUT6zPDAuqbD3PRIlpDtahUAofFtmRSoOJwng9URKy92qofG/aWOhO9YW3 9M1eELKJhYVtfQW4DGWXRdHh1P+gZ2TfDdDHLr84OTgKFoHVumtlu2OCX3+oShdiZSRg HmIevNjMLKgVzvSgD+DCEVeOXDpE0uJUpxGvKVNJzuL1UYd1cUnl5tkt3QcjHWJ5+qsr E/DhQjT2u3XmzGeNuDmFBEBnWl0ddh8j/9ifRMAVM4q1jekkcxq5TpvWChYPtG5PtOcY ws1A== X-Gm-Message-State: AOJu0YxtMEH3Ci7FJGdadcfxID0VDH75TOcG5ocj7fc3nLL0WPU/yOfr lRAGqyxtvwuWxxaRoM1wE8ehxgnUMnn/hWG+4EeQJJh4YS8P8TcAq8CNUMZvu53LC1UdtB9VZ1Z P X-Received: by 2002:a17:90b:3c91:b0:2e8:f58e:27c7 with SMTP id 98e67ed59e1d1-2e94c2c0b9cmr7736038a91.14.1730516215072; Fri, 01 Nov 2024 19:56:55 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2e93dac02acsm3919877a91.27.2024.11.01.19.56.54 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:56:54 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 05/15] gdbserver: nat/aarch64: Only check Z registers for extra contents if they can have it Date: Fri, 1 Nov 2024 23:56:25 -0300 Message-ID: <20241102025635.586759-6-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org The bottom 128 bits of Z registers overlap with the V registers. If the vector length is 128 bits, then they have no extra contents and in that case this code will hit the gdb_assert (offset < regbuf.size ()); in gdbserver's regcache::raw_compare (). Therefore in that case we need to skip the meaningless comparison. --- gdb/nat/aarch64-scalable-linux-ptrace.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/gdb/nat/aarch64-scalable-linux-ptrace.c b/gdb/nat/aarch64-scalable-linux-ptrace.c index 0f1bedf78002..ac375b78541a 100644 --- a/gdb/nat/aarch64-scalable-linux-ptrace.c +++ b/gdb/nat/aarch64-scalable-linux-ptrace.c @@ -745,15 +745,16 @@ aarch64_sve_regs_copy_from_reg_buf (int tid, /* Check in the reg_buf if any of the Z registers are set after the first 128 bits, or if any of the other SVE registers are set. */ bool has_sve_state = false; - for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++) - { - if (!reg_buf->raw_compare (AARCH64_SVE_Z0_REGNUM + i, reg, - V_REGISTER_SIZE)) - { - has_sve_state = true; - break; - } - } + if (reg_buf->register_size (AARCH64_SVE_Z0_REGNUM) > V_REGISTER_SIZE) + for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++) + { + if (!reg_buf->raw_compare (AARCH64_SVE_Z0_REGNUM + i, reg, + V_REGISTER_SIZE)) + { + has_sve_state = true; + break; + } + } if (!has_sve_state) for (int i = 0; i < AARCH64_SVE_P_REGS_NUM; i++) From patchwork Sat Nov 2 02:56:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840277 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1158458wrb; Fri, 1 Nov 2024 19:58:43 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCW14vDI5qHqk+lobMSkajHZ/KRFe3tew9i15mSK6J5YWkvgBe5IreaSNo3MVbB12Bc3iuY0fA==@linaro.org X-Google-Smtp-Source: AGHT+IH7f3YI+IjsjLFir2EX316cW3UeRwM3r3hrW7zODeZu97bQSwHd8iBBB9ljN5AHQpAAG4q+ X-Received: by 2002:a05:620a:2996:b0:7b1:55ae:a9bb with SMTP id af79cd13be357-7b1aed6f6a3mr1791487285a.13.1730516323733; Fri, 01 Nov 2024 19:58:43 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516323; cv=pass; d=google.com; s=arc-20240605; b=b9FJ7jlYFR/QeMXtQ2Z+vrYcuaWaGxjKGQ46efusjB1g+Onn5cK3GAayrTuK/eiWKI XeuTMpZhCrGpvCHtrge492vFMWDgYt+Nu4xS/jk12/QyojSqyfMz/uUwlwVMJxgfljH9 P8sA4UhRQZAf9u68ux5CfayUUDKG6Jaz9sEz/N+qeUF6xyjU1OV56Hu/A8IFvInMYzYz CuuZCFUXMISUz26SiG9x1nohs0gkpgWTOmWYZa7Npmnrue4MMn24sVz008goTgTPM/DC /u791aCmy0vHZE1hGGDLWaquBa6L5OhyJ75/vn9tVP4af6HF2AdJozViFdxIqmp497OP x5PQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=y/M8LV+vonvkcoXieKZ5UXuMkIdNIqGy6GN2AoX4d8Q=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=e2jTsFkn24QTR7LwNAYaHDXtN/EJY39f6yHazyNC9F2/xZBnarj6nAJjZtbBDl/fWT SDNAqfx6N0gKKuFrpayCYLB/NoJcuImWq/8H6UryXmvkOo04IjBBteITuOOh1y7nPTXT /30CyqZmaySymLW1jJ/5xBsjYIhnFy0fUvMgvuips/SVjeJq078r/r+eX3SCN7OtVPLI g3zZWgIGe58tHHW1iMBWPzgGFICSjfm/uEgdJNyDj5GzwaC0sQQtbr+BClyIAZi/y0tS 5sh41KrXrYl1piiJdGSSk3tjcLxenECg+/PekZEFK7klWKNcspFg1/qAtG0R2Rrg7iYM sgoA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dLr0g4B3; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id af79cd13be357-7b2f3a81742si576302785a.349.2024.11.01.19.58.43 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:58:43 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dLr0g4B3; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5E5AD3857C5F for ; Sat, 2 Nov 2024 02:58:43 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pf1-x436.google.com (mail-pf1-x436.google.com [IPv6:2607:f8b0:4864:20::436]) by sourceware.org (Postfix) with ESMTPS id 106E5385780F for ; Sat, 2 Nov 2024 02:56:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 106E5385780F Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 106E5385780F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::436 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516223; cv=none; b=sVUTHTy8tW/+AnsdEzTEyYc+V4eh8n4KDdbL1wn852LjNKLeoF7ND9Y/nMgI+Pa7e4Piy552+w/3hSPPYDyCL0OjSD1qKBsY+ncoyGfIKtxx+to+bbIGGL5tVmH5mKfWFW2SJCulEnv98j/cmw+JnqlsI3X1HadIrmon3iwqK0A= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516223; c=relaxed/simple; bh=4ibFN7DKdxqfsM5QEzMYRh5gjsDYRvlucWW6tsqrtGU=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=vXWuc30A7Tn8qR9doubSm2SGnrdbQPzC8CUmm7AZHP4u6QGPInRdN8/wFxAQU2R9b70d5upw4WpBIeTHzUIZnt/vwVc3lyvX17+hMksqavYtN6sGB3z1fvqwfCCDLqEcGXBNUw9RlxSOJ15Z5kvHvrrvMtSXuTXheUfN0MVEheo= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x436.google.com with SMTP id d2e1a72fcca58-71e5a1c9071so2272113b3a.0 for ; Fri, 01 Nov 2024 19:56:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516218; x=1731121018; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=y/M8LV+vonvkcoXieKZ5UXuMkIdNIqGy6GN2AoX4d8Q=; b=dLr0g4B3Pc1sp1cm2XpAJ6DfW6YZhLwy1rvZ7h72V8vtkomPChBrdWJuI0pUN5j2U/ has6MAw/Hk4+vr3/H6FhJVxhCVWt+uelIq8u9TFLRS6uBzIGu5EcXzLm8nBNJX2hwFWV OG7abg5IySUUtOYR4CN/3CDrnbq6YbJePHypv0pXmDXVZ3Bhr4Dz3QG3CPhKtdOGy58k wiueBU2CJ/kIvljz1qHxFIlogXW1A6i8Cx8Nni9jfR4Gc63hHH6//sT01iFQxy/pU/cl s1ASettF35VPZBP3Kzl+oI6zQFhQAhyKEADilM2LyLmwAAd17DDVAaL2xZEEBLwVkLd7 LEFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516218; x=1731121018; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=y/M8LV+vonvkcoXieKZ5UXuMkIdNIqGy6GN2AoX4d8Q=; b=ZMAsV/bnFNQWQbmCkbO3y1Rr8v84G4FUcqA625LjF3SqcaOEW+1aN6Iwa2SXfOo0iA d67NKSWjIAZY6WUv+u13qkPltZ2X9qUqjbr2DxBlVrQImzFVORV3VJn0RQt11PLblVo7 be93fzf28N7skIlTRhF+FXXjFJpA83TMTmeFDr6n3GPeWtqG9LpnAzEYkewqqU+3y7Ao PA78mVbk4cwqnuxVpsSj53tG6Z0Xuj9nxfs0drjvyTckQJA44KpikgKUUxSwvHnkOs2H cu6ARJa5XZfDcR/4p64tNdiW5cAIUrF5DOOQKEtuFCbQE+kixNxi0BFeyulG3L54YHEU oNXA== X-Gm-Message-State: AOJu0Yy5e00q1wrKWM/kvV4XZ8EGqbzSj5gxvmKUK6djdMtS0A+bDqfN EaN7OqVx4gWlIoBGE58CBxYNasAG3nlj5qH3ZARE6Ti+nvnWsn51+3uEgiJpiVg33496qixMBL6 x X-Received: by 2002:a05:6a00:4f93:b0:71e:55e2:2c58 with SMTP id d2e1a72fcca58-720ab3f31a7mr16409713b3a.15.1730516218018; Fri, 01 Nov 2024 19:56:58 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-720bc1e6bdcsm3365234b3a.58.2024.11.01.19.56.57 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:56:57 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 06/15] gdbserver: Implement p and P packets Date: Fri, 1 Nov 2024 23:56:26 -0300 Message-ID: <20241102025635.586759-7-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org GDB will need the p packet to individually request "load early" registers before using the g packet. Not sure if P is necessary, but if p is supported, why not implement P? Alternatively, to be more efficient there could be a packet where GDB can specify a list of registers it wants do load or set. Or there could be a register to request/set the expedited registers. --- gdbserver/regcache.cc | 44 +++++++++++++++++++++++++ gdbserver/regcache.h | 9 ++++++ gdbserver/server.cc | 75 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) diff --git a/gdbserver/regcache.cc b/gdbserver/regcache.cc index 6a1526246867..ec19864bd690 100644 --- a/gdbserver/regcache.cc +++ b/gdbserver/regcache.cc @@ -208,6 +208,50 @@ find_register_by_number (const struct target_desc *tdesc, int n) #ifndef IN_PROCESS_AGENT +static gdb::array_view register_data (const struct regcache *regcache, + int n); + +/* See regcache.h. */ + +void +register_to_string (struct regcache *regcache, int regnum, char *buf) +{ + if (regcache->register_status[regnum] == REG_VALID) + { + gdb::array_view value = register_data (regcache, regnum); + + bin2hex (value.data (), buf, value.size ()); + buf[value.size () * 2] = '\0'; + } + else + { + int len = regcache->register_size (regnum) * 2; + + memset (buf, 'x', len); + buf[len] = '\0'; + } +} + +/* See regcache.h. */ + +void +register_from_string (struct regcache *regcache, int regnum, char *buf) +{ + int len = strlen (buf); + gdb::array_view value = register_data (regcache, regnum); + int expected_len = value.size () * 2; + + if (len != expected_len) + { + warning ("Wrong sized packet for register %d (expected %d bytes, got %d)", + regnum, expected_len, len); + if (len > expected_len) + len = expected_len; + } + + hex2bin (buf, value.data (), len / 2); +} + void registers_to_string (struct regcache *regcache, char *buf) { diff --git a/gdbserver/regcache.h b/gdbserver/regcache.h index df0feca102e0..5de8fd3d127e 100644 --- a/gdbserver/regcache.h +++ b/gdbserver/regcache.h @@ -96,6 +96,15 @@ void regcache_invalidate (void); void regcache_release (void); +/* Save contents of register REGNUM to BUF as an hexadecimal string. */ + +void register_to_string (struct regcache *regcache, int regnum, char *buf); + +/* Set contents of register REGNUM from BUF, interpreted as an hexadecimal + string. */ + +void register_from_string (struct regcache *regcache, int regnum, char *buf); + /* Convert all registers to a string in the currently specified remote format. */ diff --git a/gdbserver/server.cc b/gdbserver/server.cc index 5190df4aed5f..4d075fce2359 100644 --- a/gdbserver/server.cc +++ b/gdbserver/server.cc @@ -4712,6 +4712,81 @@ process_serial_event (void) } } break; + case 'p': + { + require_running_or_break (cs.own_buf); + if (cs.current_traceframe >= 0) + { + write_enn (cs.own_buf); + break; + } + if (!set_desired_thread ()) + { + write_enn (cs.own_buf); + break; + } + + int i = 1, regnum = 0; + char c; + while ((c = cs.own_buf[i++]) != '\0') + { + regnum = regnum << 4; + regnum |= fromhex (c) & 0x0f; + } + + struct regcache *regcache = get_thread_regcache (current_thread, true); + + if (regnum < 0 || regnum >= regcache->tdesc->reg_defs.size ()) + { + write_enn (cs.own_buf); + break; + } + + fetch_inferior_registers (regcache, regnum); + register_to_string (regcache, regnum, cs.own_buf); + } + break; + case 'P': + { + require_running_or_break (cs.own_buf); + if (cs.current_traceframe >= 0) + { + write_enn (cs.own_buf); + break; + } + if (!set_desired_thread ()) + { + write_enn (cs.own_buf); + break; + } + if (strchr (cs.own_buf, '=') == nullptr) + { + write_enn (cs.own_buf); + break; + } + + int i = 1, regnum = 0; + char c; + while ((c = cs.own_buf[i++]) != '=') + { + regnum = regnum << 4; + regnum |= fromhex (c) & 0x0f; + } + + struct regcache *regcache = get_thread_regcache (current_thread, true); + + if (regnum < 0 || regnum >= regcache->tdesc->reg_defs.size ()) + { + write_enn (cs.own_buf); + break; + } + + register_from_string (regcache, regnum, &cs.own_buf[i]); + /* FIXME: Why doesn't the G packet need this as well? */ + store_inferior_registers (regcache, regnum); + write_ok (cs.own_buf); + } + break; case 'm': { require_running_or_break (cs.own_buf); From patchwork Sat Nov 2 02:56:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840278 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1158513wrb; Fri, 1 Nov 2024 19:59:04 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCW+VLQGfhJlPGqbLbp3GlnQ4Q7PywearBnEE5rJHJeTFKu5QXnnDw4mhe/kJBAvMtPa2J9AvQ==@linaro.org X-Google-Smtp-Source: AGHT+IE4gu+ngl6v65NcQtDU87Mrk/DCcr4r48GZy0BZXD7T8MDUTBOc0GpdrFdV57EpIhlxqVcE X-Received: by 2002:a05:620a:4554:b0:7a1:c40d:7573 with SMTP id af79cd13be357-7b193f4d92bmr3566560985a.49.1730516344270; Fri, 01 Nov 2024 19:59:04 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516344; cv=pass; d=google.com; s=arc-20240605; b=AASnmO6+2HG1VGNz2r4dTL00zmu1evCuZi2NDKt/sfUdsK8AzTayOqWa4puag+c1tZ nFpsGh2ipOQ0m+o2dY0ufNDjD306Y78A2F9hAUfCXMo9flALTmf3KDK1iZCg2JBLFOhb hI0ML52cXv/aSKEYPfRn3nVByjU8xXgNhWsOrkEVd0042ArjfBCw1TY8DcdsVy9DqpV/ BqDJ0QelpwL1seRc4Vxx/ZRwJ/EkjLZsQ2MlWx9BxuHnIxbjjNfGyPgxGXuJvwQzJp2t P4aVAfS+t84048WXEs1wO00UUo8uXQ2Yhil+jnVrNACZ7qUp9Szhw9XEDYt78LqyxUrV Oe4Q== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=mjiW781HPoF9ScVavlKTVhjEajTu5UIvyl8t76EYeLY=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=a2y2McR2j+TFX9Cd3hM3PFfXPJLYeCRV45silh+ICXDFHOuEmiXLkfe3DDv026+P/n PQDDOv1w+DvGpiSZLVs54Y05rK+0kf+WM3+abG2yvZ2lAdHl8ZZSWJTvo+XFGq/6IuQQ Klgc5IXgQkh/Uzezhcbyhe1cZKSHCuGQXuo/PGw3Pqy2Zw0B6AI/XqZbygRzZo9bitrV dKPGQTALbN9XPHE1vVMtGe8hFGMKintGaIe4bqxQmxfv0B8YZHKVoa3PqMebolD/9H98 eOPPp4ybsTIjZiMPAKhgA3Y5eNBVqJ8/T9Cs6925HMsgkYqBiodT40xT7dkracnhMsvZ tOFQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=JC46uhGc; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id af79cd13be357-7b2f39f3ce1si570050485a.147.2024.11.01.19.59.04 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:59:04 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=JC46uhGc; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D603C3857BA0 for ; Sat, 2 Nov 2024 02:59:03 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pl1-x633.google.com (mail-pl1-x633.google.com [IPv6:2607:f8b0:4864:20::633]) by sourceware.org (Postfix) with ESMTPS id 6FE303858415 for ; Sat, 2 Nov 2024 02:57:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6FE303858415 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 6FE303858415 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::633 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516227; cv=none; b=wvGhEEPZY53vb73nPFds0JoW3HvE1W0VUFqtcKNI0tLMWfjRj80C/7rzR3mDoVvXmH6AyLZr3yzmhbRo1D+KzMYWvI0aAips91UW13626adrgFaEsvJbC8PV/h9yNe/F+duj7IqTI1QiP48nHFDfbrxtzbhtwmIwh8AN3GUtV98= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516227; c=relaxed/simple; bh=MnltwfHuLvb9OioBA+Cmy4wdevNgTOvu5yn9TM046iQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=LBZ2ZBwD6N4QQHgdB/6vL0wXU+mDg9dte0vwYdwe66cilPDSnehL1zr5eBha6ii3fyH2apmucx6pLosP187zU9V52Dwyo0lfqpCZcLqRe14Np96K3p87VHtaqs/tGNvd05l70ofdEv3W82cM6YH5OTeeWoGK4O2wiaRrM5ikk/w= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x633.google.com with SMTP id d9443c01a7336-20c7ee8fe6bso24676485ad.2 for ; Fri, 01 Nov 2024 19:57:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516221; x=1731121021; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=mjiW781HPoF9ScVavlKTVhjEajTu5UIvyl8t76EYeLY=; b=JC46uhGc9fny4q5vSq+e4VPASrypMLkwrc82FJmm0UAz/No0usT/7ELfrVO3AI8JHa v+I9VL6z7SccdlTV6KOxSABTTTEKev/43YMThTWfWtZMLXuGWN7CQwf7l5Lr3nUN4hEL zfyBeDD+ghmUxKjhZJ+9XXdMrJBIYuadNd0nAex17hD+xgoRq8tUGVbj9E5iRiSj7s0q sVeHQB7LTMN98oSc49ziWl544OPTbu+FJdQ1xO9G3c9DOzc55Yj6Ur7w8oTvA6J2TxIV HhWeBeBrWqwKiscQZT2uXl6UbAUmDT0JXkTcPHVtlDcg7QZOgCSaUJUEMFGPreSf+VCb rEFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516221; x=1731121021; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=mjiW781HPoF9ScVavlKTVhjEajTu5UIvyl8t76EYeLY=; b=kt9slJRghsi6NY2eZdyzXETgp/BWDElm/IfpWEh6HO5UV0F0HJSkoxyDi5b2EFUOV3 E5R8ZdrAxT8nmi3ZpaWCB63TzdWsKLCK539DDIxG47lRX87T5tJ2zUqC34bzGvaFmWDK izG6ySg3rh5pBZvrJ0ljo68XDE3l3nUj2GRDVCneMMGNrjPRSjyTYsmvMtU/blEJSysC Bys8IpjqHbIPr2OZ8V0/85eAyqHpnmEAzjcTyaH4sizRGiaNdXAH96qauV60BRwzWbp/ tF4LcNkfquigfk/LexO3RI+LW2bKl4wZqivSGRO8+niRQO4wLyTAQbGDpKsGlePHAEuj M3Dg== X-Gm-Message-State: AOJu0Yw5iRqLtA1BxSXk+cEvmNWnRY0h2Gpwq7qeFSbT/dx9QmnUeh+O BPvxa4AxGwQa6klYhWY3nc9rxdQozb/iL+0W8bWA9nIA1BOMW11XcHNYdzk61oYptuwk2m9p4/Q x X-Received: by 2002:a17:902:e851:b0:20c:94f6:3e03 with SMTP id d9443c01a7336-210c6c6a272mr328375245ad.47.1730516221053; Fri, 01 Nov 2024 19:57:01 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-211057d3bb8sm27610635ad.246.2024.11.01.19.57.00 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:57:00 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 07/15] GDB, gdbserver: Create concept of load-early registers Date: Fri, 1 Nov 2024 23:56:27 -0300 Message-ID: <20241102025635.586759-8-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org These are registers that need to be saved first into the regcache. Consequently, also gdbserver needs to send these registers as expedited registers so that GDB can use them as early as possible. When debugging a remote target, load early registers using expedited registers and the p packet. For now the load-early registers concept is unused, as nothing in this patch adds registers to the load-early set. It is being sent separately to facilitate review. In a subsequent patch, registers which are used in location expressions that determine the size of other registers will need to be loaded early into the regcache so that they can be used to resolve the dynamic types of the variable-sized registers. This will be done by calling tdesc_create_reg () with the new load_early argument set to true. If I can move the VG register before the Z registers as Pedro suggested, this patch may be unnecessary. --- gdb/process-stratum-target.h | 3 ++ gdb/record-full.c | 18 +++++-- gdb/regcache.c | 99 +++++++++++++++++++++++++++++++++++- gdb/regcache.h | 17 +++++++ gdb/regformats/regdef.h | 16 ++++-- gdb/remote.c | 88 ++++++++++++++++++++++++++++---- gdb/target-descriptions.c | 24 ++++++++- gdb/target-descriptions.h | 5 ++ gdbserver/regcache.cc | 8 +++ gdbserver/regcache.h | 2 + gdbserver/tdesc.cc | 12 ++++- gdbsupport/common-regcache.h | 3 ++ gdbsupport/tdesc.cc | 9 ++-- gdbsupport/tdesc.h | 11 +++- 14 files changed, 285 insertions(+), 30 deletions(-) diff --git a/gdb/process-stratum-target.h b/gdb/process-stratum-target.h index 9aa9d874ecbb..4d4ad3431d16 100644 --- a/gdb/process-stratum-target.h +++ b/gdb/process-stratum-target.h @@ -55,6 +55,9 @@ class process_stratum_target : public target_ops gdbarch. */ struct gdbarch *thread_architecture (ptid_t ptid) override; + /* Supply the load-early registers to REGCACHE when it's first created. */ + virtual void supply_initial_registers (regcache *regcache) {}; + /* Default implementations for process_stratum targets. Return true if there's a selected inferior, false otherwise. */ bool has_all_memory () override; diff --git a/gdb/record-full.c b/gdb/record-full.c index 22a513ac79ab..8e4915abd083 100644 --- a/gdb/record-full.c +++ b/gdb/record-full.c @@ -926,15 +926,20 @@ record_full_core_open_1 () { regcache *regcache = get_thread_regcache (inferior_thread ()); int regnum = gdbarch_num_regs (regcache->arch ()); - int i; /* Get record_full_core_regbuf. */ target_fetch_registers (regcache, -1); record_full_core_regbuf = new detached_regcache (regcache->arch (), false); - for (i = 0; i < regnum; i ++) + /* Supply load-early registers first. */ + for (int i : regcache->load_early_registers ()) record_full_core_regbuf->raw_supply (i, *regcache); + for (int i = 0; i < regnum; i ++) + /* Load-early registers were already supplied. */ + if (!regcache->is_load_early_register (i)) + record_full_core_regbuf->raw_supply (i, *regcache); + record_full_core_sections = build_section_table (current_program_space->core_bfd ()); @@ -2107,10 +2112,15 @@ record_full_core_target::fetch_registers (struct regcache *regcache, if (regno < 0) { int num = gdbarch_num_regs (regcache->arch ()); - int i; - for (i = 0; i < num; i ++) + /* Supply load-early registers first. */ + for (int i : regcache->load_early_registers ()) regcache->raw_supply (i, *record_full_core_regbuf); + + for (int i = 0; i < num; i ++) + /* Load-early registers were already supplied. */ + if (!regcache->is_load_early_register (i)) + regcache->raw_supply (i, *record_full_core_regbuf); } else regcache->raw_supply (regno, *record_full_core_regbuf); diff --git a/gdb/regcache.c b/gdb/regcache.c index 6e0c730d0d59..61289d46f4b1 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -30,6 +30,7 @@ #include "regset.h" #include #include "cli/cli-cmds.h" +#include "target-descriptions.h" /* * DATA STRUCTURE @@ -68,6 +69,9 @@ struct regcache_descr long *register_offset = nullptr; long *sizeof_register = nullptr; + /* Registers that need to be loaded early in the register cache. */ + std::set load_early_regs; + /* Cached table containing the type of each register. */ struct type **register_type = nullptr; }; @@ -120,6 +124,9 @@ init_regcache_descr (struct gdbarch *gdbarch) descr->sizeof_register[i] = descr->register_type[i]->length (); descr->register_offset[i] = offset; offset += descr->sizeof_register[i]; + + if (tdesc_register_is_early_load (gdbarch, i)) + descr->load_early_regs.insert (i); } /* Set the real size of the raw register cache buffer. */ descr->sizeof_raw_registers = offset; @@ -230,6 +237,50 @@ reg_buffer::arch () const return m_descr->gdbarch; } +/* Utility functions returning useful register attributes stored in + the regcache descr. */ + +/* See regcache.h. */ + +bool +reg_buffer::fetch_load_early_registers () +{ + for (int regnum : this->load_early_registers ()) + if (this->get_register_status (regnum) != REG_VALID) + /* A reg_buffer can't fetch registers, so we can only report failure. */ + return false; + + return true; +} + +/* See regcache.h. */ + +bool +regcache::fetch_load_early_registers () +{ + for (int regnum : this->load_early_registers ()) + if (this->get_register_status (regnum) != REG_VALID) + target_fetch_registers (this, regnum); + + return true; +} + +/* See regcache.h. */ + +bool +reg_buffer::has_load_early_registers () +{ + return !m_descr->load_early_regs.empty (); +} + +/* See regcache.h. */ + +const std::set & +reg_buffer::load_early_registers () +{ + return m_descr->load_early_regs; +} + /* Helper for reg_buffer::register_buffer. */ template @@ -268,12 +319,31 @@ reg_buffer::save (register_read_ftype cooked_read) /* Clear the dest. */ memset (m_registers.get (), 0, m_descr->sizeof_cooked_registers); memset (m_register_status.get (), REG_UNKNOWN, m_descr->nr_cooked_registers); + + /* Save load early registers first. */ + for (int regnum : m_descr->load_early_regs) + { + 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.data (), 0, dst_buf.size ()); + + m_register_status[regnum] = status; + } + /* Copy over any registers (identified by their membership in the 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 (int regnum = 0; regnum < m_descr->nr_cooked_registers; regnum++) { + /* Load-early registers were already saved. */ + if (this->is_load_early_register (regnum)) + continue; + if (gdbarch_register_reggroup_p (gdbarch, regnum, save_reggroup)) { gdb::array_view dst_buf = register_buffer (regnum); @@ -293,19 +363,34 @@ void regcache::restore (readonly_detached_regcache *src) { struct gdbarch *gdbarch = m_descr->gdbarch; - int regnum; gdb_assert (src != NULL); gdb_assert (src->m_has_pseudo); gdb_assert (gdbarch == src->arch ()); + /* Restore load early registers first. */ + for (int regnum : m_descr->load_early_regs) + { + if (!gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup)) + continue; + + if (src->m_register_status[regnum] != REG_VALID) + continue; + + cooked_write (regnum, src->register_buffer (regnum)); + } + /* Copy over any registers, being careful to only restore those that were both saved and need to be restored. 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++) { + /* Load-early registers were already restored. */ + if (this->is_load_early_register (regnum)) + continue; + if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup)) { if (src->m_register_status[regnum] == REG_VALID) @@ -324,6 +409,14 @@ reg_buffer::get_register_status (int regnum) const return m_register_status[regnum]; } +/* See gdbsupport/common-regcache.h. */ + +bool +reg_buffer::is_load_early_register (int regnum) const +{ + return m_descr->load_early_regs.count (regnum) > 0; +} + void reg_buffer::invalidate (int regnum) { @@ -394,6 +487,8 @@ get_thread_arch_regcache (inferior *inf_for_target_calls, ptid_t ptid, constructor explicitly instead of implicitly. */ ptid_regc_map.insert (std::make_pair (ptid, regcache_up (new_regcache))); + proc_target->supply_initial_registers (new_regcache); + return new_regcache; } diff --git a/gdb/regcache.h b/gdb/regcache.h index 739172a249b8..5c28fec4af11 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -20,6 +20,7 @@ #ifndef REGCACHE_H #define REGCACHE_H +#include #include "gdbsupport/array-view.h" #include "gdbsupport/common-regcache.h" #include "gdbsupport/function-view.h" @@ -198,6 +199,9 @@ class reg_buffer : public reg_buffer_common /* See gdbsupport/common-regcache.h. */ enum register_status get_register_status (int regnum) const override; +/* See gdbsupport/common-regcache.h. */ + bool is_load_early_register (int regnum) const override; + /* See gdbsupport/common-regcache.h. */ void raw_collect (int regnum, gdb::array_view dst) const override; @@ -256,6 +260,12 @@ class reg_buffer : public reg_buffer_common /* See gdbsupport/common-regcache.h. */ bool raw_compare (int regnum, const void *buf, int offset) const override; + /* Whether any register needs to be loaded before other registers. */ + bool has_load_early_registers (); + + /* Return set of regnums which need to be loaded before other registers. */ + const std::set &load_early_registers (); + /* See gdbsupport/common-regcache.h. */ int register_size (int regnum) const override; @@ -265,6 +275,10 @@ class reg_buffer : public reg_buffer_common int num_raw_registers () const; + /* Ensure all load early registers are fetched in this cache. + Return false if they aren't. */ + virtual bool fetch_load_early_registers (); + /* Return a view on register REGNUM's buffer cache. */ template gdb::array_view register_buffer (int regnum) const; @@ -485,6 +499,9 @@ class regcache : public detached_regcache gdb::array_view src, bool is_raw); + /* See class reg_buffer. */ + bool fetch_load_early_registers () override; + /* The inferior to switch to, to make target calls. This may not be the inferior of thread M_PTID. For instance, this diff --git a/gdb/regformats/regdef.h b/gdb/regformats/regdef.h index 0ba7a08bb0c5..09339d495209 100644 --- a/gdb/regformats/regdef.h +++ b/gdb/regformats/regdef.h @@ -26,13 +26,15 @@ struct reg reg (int _offset) : name (""), offset (_offset), - size (0) + size (0), + load_early (false) {} - reg (const char *_name, int _offset, int _size) + reg (const char *_name, int _offset, int _size, bool _load_early) : name (_name), offset (_offset), - size (_size) + size (_size), + load_early (_load_early) {} /* The name of this register - NULL for pad entries. */ @@ -49,11 +51,17 @@ struct reg /* The size (in bits) of the value of this register, as transmitted. */ int size; + /* Whether this register needs to be loaded early in the register cache, + because variable-size registers depend on it to calculate their + size. */ + bool load_early; + bool operator== (const reg &other) const { return (strcmp (name, other.name) == 0 && offset == other.offset - && size == other.size); + && size == other.size + && load_early == other.load_early); } bool operator!= (const reg &other) const diff --git a/gdb/remote.c b/gdb/remote.c index 2da2c5a4789a..0217c05bce52 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -683,6 +683,9 @@ class remote_state immediately, so queue is not needed for them. */ std::vector stop_reply_queue; + /* Contains the stop reply packet when first starting the inferior. */ + gdb::char_vector first_stop_reply; + /* FIXME: cagney/1999-09-23: Even though getpkt was called with ``forever'' still use the normal timeout mechanism. This is currently used by the ASYNC code to guarantee that target reads @@ -1218,6 +1221,8 @@ class remote_target : public process_stratum_target ptid_t select_thread_for_ambiguous_stop_reply (const struct target_waitstatus &status); + void supply_initial_registers (regcache *regcache) override; + void remote_notice_new_inferior (ptid_t currthread, bool executing); void print_one_stopped_thread (thread_info *thread); @@ -1317,6 +1322,8 @@ class remote_target : public process_stratum_target int fetch_register_using_p (struct regcache *regcache, packet_reg *reg); + + void fetch_early_registers (struct regcache *regcache); int send_g_packet (); void process_g_packet (struct regcache *regcache); void fetch_registers_using_g (struct regcache *regcache); @@ -1417,6 +1424,9 @@ class remote_target : public process_stratum_target bool start_remote_1 (int from_tty, int extended_p); + void supply_expedited_regs (struct regcache *regcache, + std::vector &expedited_regs); + /* The remote state. Don't reference this directly. Use the get_remote_state method instead. */ remote_state m_remote_state; @@ -8530,6 +8540,21 @@ remote_target::select_thread_for_ambiguous_stop_reply return first_resumed_thread->ptid; } +/* Supply the contents of EXPEDITED_REGS to REGCACHE. */ + +void +remote_target::supply_expedited_regs (struct regcache *regcache, + std::vector &expedited_regs) +{ + remote_state *rs = get_remote_state (); + + for (cached_reg_t ® : expedited_regs) + { + regcache->raw_supply (reg.num, reg.data); + rs->last_seen_expedited_registers.insert (reg.num); + } +} + /* Called when it is decided that STOP_REPLY holds the info of the event that is to be returned to the core. This function always destroys STOP_REPLY. */ @@ -8568,12 +8593,7 @@ remote_target::process_stop_reply (stop_reply_up stop_reply, regcache *regcache = get_thread_arch_regcache (find_inferior_ptid (this, ptid), ptid, stop_reply->arch); - - for (cached_reg_t ® : stop_reply->regcache) - { - regcache->raw_supply (reg.num, reg.data); - rs->last_seen_expedited_registers.insert (reg.num); - } + supply_expedited_regs (regcache, stop_reply->regcache); } remote_thread_info *remote_thr = get_remote_thread_info (this, ptid); @@ -8599,6 +8619,28 @@ remote_target::process_stop_reply (stop_reply_up stop_reply, return ptid; } +/* See gdb/process-stratum-target.h. */ + +void +remote_target::supply_initial_registers (regcache *regcache) +{ + remote_state *rs = get_remote_state (); + + if (rs->first_stop_reply.empty ()) + return; + + notif_event_up reply + = remote_notif_parse (this, ¬if_client_stop, + rs->first_stop_reply.data ()); + std::vector &expedited_regs + = ((struct stop_reply *) reply.get ())->regcache; + + if (!expedited_regs.empty ()) + supply_expedited_regs (regcache, expedited_regs); + + rs->first_stop_reply.clear (); +} + /* The non-stop mode version of target_wait. */ ptid_t @@ -8918,6 +8960,27 @@ remote_target::fetch_register_using_p (struct regcache *regcache, return 1; } +/* Fetch load-early registers individually with the 'p' packet. */ + +void +remote_target::fetch_early_registers (struct regcache *regcache) +{ + struct remote_state *rs = get_remote_state (); + remote_arch_state *rsa = rs->get_remote_arch_state (regcache->arch ()); + + for (int regnum : regcache->load_early_registers ()) + { + /* We may already have it from a stop reply packet. */ + if (regcache->get_register_status (regnum) == REG_VALID) + continue; + + packet_reg *reg = packet_reg_from_regnum (regcache->arch (), rsa, regnum); + int res = fetch_register_using_p (regcache, reg); + if (res == 0) + error (_("Could not load early register %d using p packet."), regnum); + } +} + /* Fetch the registers included in the target's 'g' packet. */ int @@ -9062,6 +9125,9 @@ remote_target::process_g_packet (struct regcache *regcache) void remote_target::fetch_registers_using_g (struct regcache *regcache) { + if (regcache->has_load_early_registers ()) + fetch_early_registers (regcache); + send_g_packet (); process_g_packet (regcache); } @@ -10920,7 +10986,6 @@ extended_remote_target::create_inferior (const char *exec_file, char **env, int from_tty) { int run_worked; - char *stop_reply; struct remote_state *rs = get_remote_state (); const char *remote_exec_file = get_remote_exec_file (); @@ -10953,7 +11018,10 @@ Remote replied unexpectedly while setting startup-with-shell: %s"), /* Now restart the remote server. */ run_worked = extended_remote_run (args) != -1; - if (!run_worked) + if (run_worked) + /* vRun's success return is a stop reply. */ + rs->first_stop_reply = rs->buf; + else { /* vRun was not supported. Fail if we need it to do what the user requested. */ @@ -10966,9 +11034,7 @@ Remote replied unexpectedly while setting startup-with-shell: %s"), extended_remote_restart (); } - /* vRun's success return is a stop reply. */ - stop_reply = run_worked ? rs->buf.data () : NULL; - add_current_inferior_and_thread (stop_reply); + add_current_inferior_and_thread (run_worked ? rs->buf.data () : nullptr); /* Get updated offsets, if the stub uses qOffsets. */ get_offsets (); diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c index 1bd22c273a29..82e4d96276e3 100644 --- a/gdb/target-descriptions.c +++ b/gdb/target-descriptions.c @@ -850,6 +850,16 @@ tdesc_register_name (struct gdbarch *gdbarch, int regno) return ""; } +/* See target-descriptions.h. */ + +bool +tdesc_register_is_early_load (struct gdbarch *gdbarch, int regno) +{ + struct tdesc_reg *reg = tdesc_find_register (gdbarch, regno); + + return reg == nullptr ? false : reg->load_early; +} + struct type * tdesc_register_type (struct gdbarch *gdbarch, int regno) { @@ -1484,7 +1494,12 @@ class print_c_tdesc : public tdesc_element_visitor gdb_printf ("\"%s\", ", reg->group.c_str ()); else gdb_printf ("NULL, "); - gdb_printf ("%d, \"%s\");\n", reg->bitsize, reg->type.c_str ()); + gdb_printf ("%d, \"%s\"", reg->bitsize, reg->type.c_str ()); + + if (reg->load_early) + gdb_printf (", true"); + + gdb_printf (");\n"); } protected: @@ -1627,7 +1642,12 @@ class print_c_feature : public print_c_tdesc gdb_printf ("\"%s\", ", reg->group.c_str ()); else gdb_printf ("NULL, "); - gdb_printf ("%d, \"%s\");\n", reg->bitsize, reg->type.c_str ()); + gdb_printf ("%d, \"%s\"", reg->bitsize, reg->type.c_str ()); + + if (reg->load_early) + gdb_printf (", true"); + + gdb_printf (");\n"); m_next_regnum++; } diff --git a/gdb/target-descriptions.h b/gdb/target-descriptions.h index dc83db0acf28..e40c7db5f79f 100644 --- a/gdb/target-descriptions.h +++ b/gdb/target-descriptions.h @@ -199,6 +199,11 @@ const char *tdesc_feature_name (const struct tdesc_feature *feature); const char *tdesc_register_name (struct gdbarch *gdbarch, int regno); +/* Return whether register REGNO needs to be loaded early in the + register cache. */ + +bool tdesc_register_is_early_load (struct gdbarch *gdbarch, int regno); + /* Return the type of register REGNO, from the target description or from an architecture-provided pseudo_register_type method. */ diff --git a/gdbserver/regcache.cc b/gdbserver/regcache.cc index ec19864bd690..cd1ee2e5f145 100644 --- a/gdbserver/regcache.cc +++ b/gdbserver/regcache.cc @@ -568,6 +568,14 @@ regcache::get_register_status (int regnum) const /* See gdbsupport/common-regcache.h. */ +bool +regcache::is_load_early_register (int regnum) const +{ + return find_register_by_number (this->tdesc, regnum).load_early; +} + +/* See gdbsupport/common-regcache.h. */ + bool regcache::raw_compare (int regnum, const void *buf, int offset) const { diff --git a/gdbserver/regcache.h b/gdbserver/regcache.h index 5de8fd3d127e..07e48a7432b7 100644 --- a/gdbserver/regcache.h +++ b/gdbserver/regcache.h @@ -49,6 +49,8 @@ struct regcache : public reg_buffer_common /* See gdbsupport/common-regcache.h. */ enum register_status get_register_status (int regnum) const override; + bool is_load_early_register (int regnum) const override; + /* See gdbsupport/common-regcache.h. */ int register_size (int regnum) const override; diff --git a/gdbserver/tdesc.cc b/gdbserver/tdesc.cc index d052f43c76e6..6f7ebb7c5c76 100644 --- a/gdbserver/tdesc.cc +++ b/gdbserver/tdesc.cc @@ -56,6 +56,8 @@ init_target_desc (struct target_desc *tdesc, const char **expedite_regs) { int offset = 0; + /* Additional registers to expedite from the features. */ + std::vector expedite_from_features; /* Go through all the features and populate reg_defs. */ for (const tdesc_feature_up &feature : tdesc->features) @@ -70,8 +72,11 @@ init_target_desc (struct target_desc *tdesc, tdesc->reg_defs.resize (regnum, gdb::reg (offset)); tdesc->reg_defs.emplace_back (treg->name.c_str (), offset, - treg->bitsize); + treg->bitsize, treg->load_early); offset += treg->bitsize; + + if (treg->load_early) + expedite_from_features.push_back (treg->name.c_str ()); } tdesc->registers_size = offset / 8; @@ -88,6 +93,11 @@ init_target_desc (struct target_desc *tdesc, int expedite_count = 0; while (expedite_regs[expedite_count] != nullptr) tdesc->expedite_regs.push_back (expedite_regs[expedite_count++]); + + if (!expedite_from_features.empty ()) + tdesc->expedite_regs.insert (tdesc->expedite_regs.end (), + expedite_from_features.cbegin (), + expedite_from_features.cend ()); #endif } diff --git a/gdbsupport/common-regcache.h b/gdbsupport/common-regcache.h index 4594999346fd..93b1b5d522f2 100644 --- a/gdbsupport/common-regcache.h +++ b/gdbsupport/common-regcache.h @@ -73,6 +73,9 @@ struct reg_buffer_common buffer. */ virtual register_status get_register_status (int regnum) const = 0; + /* Does this register need to be loaded before others? */ + virtual bool is_load_early_register (int regnum) const = 0; + /* Return the size of register numbered REGNUM in this buffer. */ virtual int register_size (int regnum) const = 0; diff --git a/gdbsupport/tdesc.cc b/gdbsupport/tdesc.cc index 080d39c485dc..a99119274f44 100644 --- a/gdbsupport/tdesc.cc +++ b/gdbsupport/tdesc.cc @@ -21,12 +21,13 @@ tdesc_reg::tdesc_reg (struct tdesc_feature *feature, const std::string &name_, int regnum, int save_restore_, const char *group_, - int bitsize_, const char *type_) + int bitsize_, const char *type_, bool load_early_) : name (name_), target_regnum (regnum), save_restore (save_restore_), group (group_ != NULL ? group_ : ""), bitsize (bitsize_), - type (type_ != NULL ? type_ : "") + type (type_ != NULL ? type_ : ""), + load_early (load_early_) { /* If the register's type is target-defined, look it up now. We may not have easy access to the containing feature when we want it later. */ @@ -137,10 +138,10 @@ tdesc_named_type (const struct tdesc_feature *feature, const char *id) void tdesc_create_reg (struct tdesc_feature *feature, const char *name, int regnum, int save_restore, const char *group, - int bitsize, const char *type) + int bitsize, const char *type, bool load_early) { tdesc_reg *reg = new tdesc_reg (feature, name, regnum, save_restore, - group, bitsize, type); + group, bitsize, type, load_early); feature->registers.emplace_back (reg); } diff --git a/gdbsupport/tdesc.h b/gdbsupport/tdesc.h index c9e7603369cb..7e483486139b 100644 --- a/gdbsupport/tdesc.h +++ b/gdbsupport/tdesc.h @@ -70,7 +70,7 @@ struct tdesc_reg : tdesc_element { tdesc_reg (struct tdesc_feature *feature, const std::string &name_, int regnum, int save_restore_, const char *group_, - int bitsize_, const char *type_); + int bitsize_, const char *type_, bool load_early_ = false); virtual ~tdesc_reg () = default; @@ -110,6 +110,12 @@ struct tdesc_reg : tdesc_element /* The target-described type corresponding to TYPE, if found. */ struct tdesc_type *tdesc_type; + /* Whether this register needs to be loaded early in GDB's regcache. + + In addition, if true gdbserver will send it as an expedited register + in stop replies. */ + bool load_early; + void accept (tdesc_element_visitor &v) const override { v.visit (this); @@ -415,7 +421,8 @@ void tdesc_add_enum_value (tdesc_type_with_fields *type, int value, /* Create a register in feature FEATURE. */ void tdesc_create_reg (struct tdesc_feature *feature, const char *name, int regnum, int save_restore, const char *group, - int bitsize, const char *type); + int bitsize, const char *type, + bool load_early = false); /* Return the tdesc in string XML format. */ From patchwork Sat Nov 2 02:56:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840279 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1158542wrb; Fri, 1 Nov 2024 19:59:15 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVj+NnKoC9gxZkxo65my24uNlkabC3yuwsQt6qW4Vk/TF4FJNXF+povsP+q3bsgjcqJy/NOcg==@linaro.org X-Google-Smtp-Source: AGHT+IERziMiaCUIU462lsU65FI4B2kH/c3srfY05925SCYhrB7yR6cOO/RvHEH9ae4fl0LHrCoq X-Received: by 2002:a05:620a:29ca:b0:7b1:4ff4:69f3 with SMTP id af79cd13be357-7b1aedb9fd5mr1506001985a.29.1730516354781; Fri, 01 Nov 2024 19:59:14 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516354; cv=pass; d=google.com; s=arc-20240605; b=ZwPGwoUqMjgVsV5J1W4oh6099BrpB6mQTazboQN94fRjxwzxizi63C6GL8mw9eI1io MxsEwEeveJfvCsU0VZJptCO1gHpIVsGvkyKIlu82deSzPr7DM1RFY2TI62/DaTuvkkqT S94o5FRNr0kqyqii8KShrNWXpg2JZ4C0TokMD+tYjBvf1RFX21WVAytaSr0AVpk95v1V 3VOgRyOZBStcrlwGugvj9IQ96nLSp4kZd55oudlwwzxuGOBdlEvHKAxNvXTaLgasQ6rY Dp/UTqLRSzinKinOtZdQpU/Vi9BZEVUehmRKHxvuiAdSPJW/rGLcpPBQOhwTIy7vTuLe Mp3w== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=Fgy85mf7FAd/+4Qn9FNEByi9VYvsuM3Y314OR32iWmo=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=kU5YVL6uz6KOtkvg0VihAwvRAmPboRQyUKp1DP33O0QxP2IbUkZ5d/o2UGLHOvdbZn oC6rfKDqjaFcqkZQVtpOYly7Nw1pR4qgpTuLqsiF1rmmpTo6ufzHkL85yaY2S8SEJ4XM xJQJe7Ew6aLOBCFYw0/MN2OUpCXe2woVHntlWHrtBN3/n8dP7mAyg7G2MVSE+zWc90mD a4LAdXKPKPaMKVXc9K5W4h52Lc5wqU2nKMeVFGHEeF8LryeyP/X4UVC+CwzIzYl5qeWY dvYQPpw6ySKPFsi26u64mJLUIRdLrWg4MoKwEmJwNzLYNZBE/1U2zDy54vPOLy0JMNpw rovQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=u89ZmSDV; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id 6a1803df08f44-6d35416a9d8si55441186d6.263.2024.11.01.19.59.14 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:59:14 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=u89ZmSDV; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 68A813857BAF for ; Sat, 2 Nov 2024 02:59:14 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pf1-x434.google.com (mail-pf1-x434.google.com [IPv6:2607:f8b0:4864:20::434]) by sourceware.org (Postfix) with ESMTPS id 5F9633858019 for ; Sat, 2 Nov 2024 02:57:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5F9633858019 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 5F9633858019 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::434 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516229; cv=none; b=NBtC18lVojg2HflcUVRmmYjAyUTgd+/rFDPOE6cWhVDnY3anApRgJjZArrL5JTPwDQOPCbkhxChXPWp21nVo+fJuIEdYNkD1+8KkKLCBmO1+z3i7302VVmFlghXJWPCiVTmqbpE0Do4Z59sjqlhwmWqe8ikLoYHtz8fZUGhWcRQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516229; c=relaxed/simple; bh=javaxhnSj17ex2NysK1LiHJh9C1+zmIJaslM+ApknCU=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=PgYYSCwJXc6eQ39NkLAUXrzjVA1SVfjr0/jYm9ANnG6W7sMnkNK2MPit9/rCDFz+C9lfaCTWtTVxvBu0CbLBmfRyI9+DJ6wy+RVcG/RyWlW7znU5hfSGLpMlY8lmX4E7sOkKSz+7dGsvAsB/xhABkI/DAZ05xkx5WXHH7rIK5lU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-71ec997ad06so2175246b3a.3 for ; Fri, 01 Nov 2024 19:57:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516224; x=1731121024; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=Fgy85mf7FAd/+4Qn9FNEByi9VYvsuM3Y314OR32iWmo=; b=u89ZmSDVPcA8zAclpNeeFjcdLLpCLc+otPCAKsIr1fmWe/vLKK7wZksearGYGY2FHZ WbZ7xjG7I+FaJhdjLnGyfSK6k5RdtaUPTHxlJuYwOV2bp/FXF+6uAr6M4BUiJ7tQ3n/T WEcNzVnE+/U8ECwwjnGZsRQNj/HRayfzobhs4KyR0VjOrhAwXkGnXxbnOF91Tpv6JBHm dy566M/jh1fwIDGlGhZ9XozK4FQhFl3U3todA2DkivvIXXQFzWxSBQpAwSBLLMPHCypx YYJG0O7mf+ai/GA9vij9oGHvVwkBIW4LaV9/hBquGg/PxMoj13jpwQf4NFBJP7QiM21/ j/1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516224; x=1731121024; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Fgy85mf7FAd/+4Qn9FNEByi9VYvsuM3Y314OR32iWmo=; b=nLkMRvMxtpR8G2FgoE1/ErWGqYceW8NnpKF90+Z5da6V5ofX6y7QXn3a2YV7JK9zJg 7Lcu4I8uJJtWzeSgYqhkQle5ngzEic9U0GV8bhECexYG1MArBd1geMQe+BtCq0ZzXwiF zuqCzi4gk73Wma57qzin/VrHLsGRDYn503H8SELNuA5ZxGFTJCZrTzHWLagc1/MAh8hv +DkfrsfCKfWYpIkyef80VZNkKP4oZyjVcHkQOX9My4jTcEyOYlLWaqA0PCo6X5Y/mKGT kmiKmxBUkhqyvPS9OQs8YpEyHJ/4X/cahLf8mdSbq6LmJaXIAbT5at9sR8oErknzuIEw 04XQ== X-Gm-Message-State: AOJu0YywSkBfFjt4pAva334d0z7Rrd+AYVgzCBsCV6NacIyqmZruX5VD xtf/6STptrRx5AgPxR2QA5nOHyciy8VzgUi3u/syFO8rmMuPyiUEJdWRUQR1frsZayF51MmPmOe V X-Received: by 2002:a05:6a20:9d8e:b0:1d9:ed47:3b7d with SMTP id adf61e73a8af0-1d9eeb95e1cmr19404245637.13.1730516224159; Fri, 01 Nov 2024 19:57:04 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-7ee74cc2a59sm181737a12.54.2024.11.01.19.57.03 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:57:03 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 08/15] GDB: Allow DWARF expression evaluation to use regcache Date: Fri, 1 Nov 2024 23:56:28 -0300 Message-ID: <20241102025635.586759-9-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org Currently, expression evaluation is done in the context of a frame. However, for variable-size registers we will need to evaluate expressions when no frame is available, but we do have a regcache. Therefore, allow passing a regcache to dwarf2_evaluate_property. This requires adding a regcache parameter to resolve_dynamic_type and its internal functions. Also, this means that a DWARF expression may not be associated with an objfile, so when it needs a gdbarch it may not be possible to get the one from the objfile. The solution is to add an m_gdbarch member to dwarf_expr_context, and make it point to the gdbarch of either the objfile, frame or regcache associated with the expression. Simon suggested using GDB Agent Expressions rather than DWARF expressions to encode the register length. I will try it out, and if it works then this patch can be dropped. --- gdb/dwarf2/expr.c | 63 +++++++++++++++++++++++++++++++------ gdb/dwarf2/expr.h | 17 +++++++++- gdb/dwarf2/frame.c | 2 +- gdb/dwarf2/loc.c | 41 +++++++++++++++++------- gdb/dwarf2/loc.h | 2 ++ gdb/findvar.c | 17 ++++++++++ gdb/frame.c | 3 +- gdb/gdbtypes.c | 77 ++++++++++++++++++++++++++-------------------- gdb/gdbtypes.h | 5 ++- gdb/gnu-v3-abi.c | 2 +- gdb/value.h | 3 ++ 11 files changed, 173 insertions(+), 59 deletions(-) diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c index 5ad17eaaaff8..4a667dbd8107 100644 --- a/gdb/dwarf2/expr.c +++ b/gdb/dwarf2/expr.c @@ -56,6 +56,20 @@ ensure_have_frame (const frame_info_ptr &frame, const char *op_name) _("%s evaluation requires a frame."), op_name); } +/* Ensure that either a FRAME or a REGCACHE is defined, throw an exception + otherwise. */ + +static void +ensure_have_frame_or_regcache (const frame_info_ptr &frame, + const reg_buffer *regcache, + const char *op_name) +{ + if (frame == nullptr && regcache == nullptr) + throw_error (GENERIC_ERROR, + _("%s evaluation requires a frame or register cache."), + op_name); +} + /* Ensure that a PER_CU is defined and throw an exception otherwise. */ static void @@ -86,6 +100,16 @@ read_addr_from_reg (const frame_info_ptr &frame, int reg) return address_from_register (regnum, frame); } +/* See expr.h. */ + +CORE_ADDR +read_addr_from_reg (reg_buffer *regcache, int reg) +{ + int regnum = dwarf_reg_to_regnum_or_error (regcache->arch (), reg); + + return address_from_register (regnum, regcache); +} + struct piece_closure { /* Reference count. */ @@ -690,7 +714,8 @@ sect_variable_value (sect_offset sect_off, struct type * dwarf_expr_context::address_type () const { - gdbarch *arch = this->m_per_objfile->objfile->arch (); + gdbarch *arch = (m_gdbarch == nullptr ? this->m_per_objfile->objfile->arch () + : m_gdbarch); dwarf_gdbarch_types *types = dwarf_arch_cookie.get (arch); if (types == nullptr) types = dwarf_arch_cookie.emplace (arch); @@ -720,9 +745,11 @@ dwarf_expr_context::address_type () const /* Create a new context for the expression evaluator. */ dwarf_expr_context::dwarf_expr_context (dwarf2_per_objfile *per_objfile, - int addr_size) + int addr_size, + gdbarch *gdbarch) : m_addr_size (addr_size), - m_per_objfile (per_objfile) + m_per_objfile (per_objfile), + m_gdbarch (gdbarch) { } @@ -915,7 +942,6 @@ dwarf_expr_context::fetch_result (struct type *type, struct type *subobj_type, LONGEST subobj_offset, bool as_lval) { value *retval = nullptr; - gdbarch *arch = this->m_per_objfile->objfile->arch (); if (type == nullptr) type = address_type (); @@ -948,6 +974,9 @@ dwarf_expr_context::fetch_result (struct type *type, struct type *subobj_type, } else { + gdbarch *arch = (m_gdbarch == nullptr ? this->m_per_objfile->objfile->arch () + : m_gdbarch); + /* If AS_LVAL is false, means that the implicit conversion from a location description to value is expected. */ if (!as_lval) @@ -1077,12 +1106,14 @@ dwarf_expr_context::fetch_result (struct type *type, struct type *subobj_type, value * dwarf_expr_context::evaluate (const gdb_byte *addr, size_t len, bool as_lval, dwarf2_per_cu_data *per_cu, const frame_info_ptr &frame, + reg_buffer *regcache, const struct property_addr_info *addr_info, struct type *type, struct type *subobj_type, LONGEST subobj_offset) { this->m_per_cu = per_cu; this->m_frame = frame; + this->m_regcache = regcache; this->m_addr_info = addr_info; eval (addr, len); @@ -1149,7 +1180,8 @@ get_signed_type (struct gdbarch *gdbarch, struct type *type) CORE_ADDR dwarf_expr_context::fetch_address (int n) { - gdbarch *arch = this->m_per_objfile->objfile->arch (); + gdbarch *arch = (m_gdbarch == nullptr ? this->m_per_objfile->objfile->arch () + : m_gdbarch); value *result_val = fetch (n); bfd_endian byte_order = gdbarch_byte_order (arch); ULONGEST result; @@ -1493,7 +1525,8 @@ void dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, const gdb_byte *op_end) { - gdbarch *arch = this->m_per_objfile->objfile->arch (); + gdbarch *arch = (this->m_gdbarch ? this->m_gdbarch + : this->m_per_objfile->objfile->arch ()); bfd_endian byte_order = gdbarch_byte_order (arch); /* Old-style "untyped" DWARF values need special treatment in a couple of places, specifically DW_OP_mod and DW_OP_shr. We need @@ -1784,9 +1817,14 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, case DW_OP_breg31: { op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset); - ensure_have_frame (this->m_frame, "DW_OP_breg"); + ensure_have_frame_or_regcache (this->m_frame, this->m_regcache, + "DW_OP_breg"); + + if (this->m_frame != nullptr) + result = read_addr_from_reg (this->m_frame, op - DW_OP_breg0); + else + result = read_addr_from_reg (this->m_regcache, op - DW_OP_breg0); - result = read_addr_from_reg (this->m_frame, op - DW_OP_breg0); result += offset; result_val = value_from_ulongest (address_type, result); } @@ -1795,9 +1833,14 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, { op_ptr = safe_read_uleb128 (op_ptr, op_end, ®); op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset); - ensure_have_frame (this->m_frame, "DW_OP_bregx"); + ensure_have_frame_or_regcache (this->m_frame, this->m_regcache, + "DW_OP_bregx"); + + if (this->m_frame != nullptr) + result = read_addr_from_reg (this->m_frame, reg); + else + result = read_addr_from_reg (this->m_regcache, reg); - result = read_addr_from_reg (this->m_frame, reg); result += offset; result_val = value_from_ulongest (address_type, result); } diff --git a/gdb/dwarf2/expr.h b/gdb/dwarf2/expr.h index b02cc5316406..9a3c92650664 100644 --- a/gdb/dwarf2/expr.h +++ b/gdb/dwarf2/expr.h @@ -115,12 +115,14 @@ struct dwarf_stack_value bool in_stack_memory; }; +struct reg_buffer; + /* The expression evaluator works with a dwarf_expr_context, describing its current state and its callbacks. */ struct dwarf_expr_context { dwarf_expr_context (dwarf2_per_objfile *per_objfile, - int addr_size); + int addr_size, gdbarch *gdbarch = nullptr); virtual ~dwarf_expr_context () = default; void push_address (CORE_ADDR value, bool in_stack_memory); @@ -128,6 +130,8 @@ struct dwarf_expr_context /* Evaluate the expression at ADDR (LEN bytes long) in a given PER_CU and FRAME context. + If FRAME is nullptr, then registers are read from REGCACHE. + AS_LVAL defines if the returned struct value is expected to be a value (false) or a location description (true). @@ -138,6 +142,7 @@ struct dwarf_expr_context memory addresses with the passed in buffer. */ value *evaluate (const gdb_byte *addr, size_t len, bool as_lval, dwarf2_per_cu_data *per_cu, const frame_info_ptr &frame, + reg_buffer *regcache, const struct property_addr_info *addr_info = nullptr, struct type *type = nullptr, struct type *subobj_type = nullptr, @@ -198,6 +203,12 @@ struct dwarf_expr_context /* Frame information used for the evaluation. */ frame_info_ptr m_frame = nullptr; + /* Register cache used for the evaluation, in case there's no frame. */ + reg_buffer *m_regcache = nullptr; + + /* gdbarch used for the evaluation. */ + gdbarch *m_gdbarch = nullptr; + /* Compilation unit used for the evaluation. */ dwarf2_per_cu_data *m_per_cu = nullptr; @@ -258,6 +269,10 @@ struct dwarf_expr_context read as an address in a given FRAME. */ CORE_ADDR read_addr_from_reg (const frame_info_ptr &frame, int reg); +/* Return the value of register number REG (a DWARF register number), + read as an address in a given REGCACHE. */ +CORE_ADDR read_addr_from_reg (reg_buffer *regcache, int reg); + void dwarf_expr_require_composition (const gdb_byte *, const gdb_byte *, const char *); diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c index 841d2d4a2fec..3da9551a7ace 100644 --- a/gdb/dwarf2/frame.c +++ b/gdb/dwarf2/frame.c @@ -237,7 +237,7 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size, scoped_value_mark free_values; ctx.push_address (initial, initial_in_stack_memory); - value *result_val = ctx.evaluate (exp, len, true, nullptr, this_frame); + value *result_val = ctx.evaluate (exp, len, true, nullptr, this_frame, nullptr); if (result_val->lval () == lval_memory) return result_val->address (); diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c index d5153862a01d..d7fa58047cdd 100644 --- a/gdb/dwarf2/loc.c +++ b/gdb/dwarf2/loc.c @@ -1518,7 +1518,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, const frame_info_ptr &frame, try { retval = ctx.evaluate (data, size, as_lval, per_cu, frame, nullptr, - type, subobj_type, subobj_byte_offset); + nullptr, type, subobj_type, subobj_byte_offset); } catch (const gdb_exception_error &ex) { @@ -1565,11 +1565,12 @@ dwarf2_evaluate_loc_desc (struct type *type, const frame_info_ptr &frame, per_objfile, NULL, 0, as_lval); } -/* Evaluates a dwarf expression and stores the result in VAL, - expecting that the dwarf expression only produces a single - CORE_ADDR. FRAME is the frame in which the expression is - evaluated. ADDR_STACK is a context (location of a variable) and - might be needed to evaluate the location expression. +/* Evaluates a dwarf expression and stores the result in VAL, expecting + that the dwarf expression only produces a single CORE_ADDR. FRAME is + the frame in which the expression is evaluated. If FRAME is nullptr, + then registers are read from REGCACHE instead. ADDR_STACK is a context + (location of a variable) and might be needed to evaluate the location + expression. PUSH_VALUES is an array of values to be pushed to the expression stack before evaluation starts. PUSH_VALUES[0] is pushed first, then @@ -1580,6 +1581,7 @@ dwarf2_evaluate_loc_desc (struct type *type, const frame_info_ptr &frame, static int dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton, const frame_info_ptr &frame, + reg_buffer *regcache, const struct property_addr_info *addr_stack, CORE_ADDR *valp, gdb::array_view push_values, @@ -1590,7 +1592,21 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton, dwarf2_per_objfile *per_objfile = dlbaton->per_objfile; dwarf2_per_cu_data *per_cu = dlbaton->per_cu; - dwarf_expr_context ctx (per_objfile, per_cu->addr_size ()); + gdbarch *gdbarch; + + if (per_objfile != nullptr) + gdbarch = per_objfile->objfile->arch (); + else if (frame != nullptr) + gdbarch = get_frame_arch (frame); + else + { + gdb_assert (regcache != nullptr); + gdbarch = regcache->arch (); + } + + int addr_size = (per_cu == nullptr ? gdbarch_addr_bit (gdbarch) / 8 + : per_cu->addr_size ()); + dwarf_expr_context ctx (per_objfile, addr_size, gdbarch); value *result; scoped_value_mark free_values; @@ -1602,7 +1618,7 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton, try { result = ctx.evaluate (dlbaton->data, dlbaton->size, - true, per_cu, frame, addr_stack); + true, per_cu, frame, regcache, addr_stack); } catch (const gdb_exception_error &ex) { @@ -1641,6 +1657,7 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton, bool dwarf2_evaluate_property (const dynamic_prop *prop, const frame_info_ptr &initial_frame, + reg_buffer *regcache, const property_addr_info *addr_stack, CORE_ADDR *value, gdb::array_view push_values) @@ -1654,7 +1671,8 @@ dwarf2_evaluate_property (const dynamic_prop *prop, scoped_restore_current_language save_language; frame_info_ptr frame = initial_frame; - if (frame == NULL && has_stack_frames ()) + /* Only try to get a frame if no regcache was provided. */ + if (frame == nullptr && regcache == nullptr && has_stack_frames ()) frame = get_selected_frame (NULL); switch (prop->kind ()) @@ -1665,8 +1683,9 @@ dwarf2_evaluate_property (const dynamic_prop *prop, gdb_assert (baton->property_type != NULL); bool is_reference = baton->locexpr.is_reference; - if (dwarf2_locexpr_baton_eval (&baton->locexpr, frame, addr_stack, - value, push_values, &is_reference)) + if (dwarf2_locexpr_baton_eval (&baton->locexpr, frame, regcache, + addr_stack, value, push_values, + &is_reference)) { if (is_reference) { diff --git a/gdb/dwarf2/loc.h b/gdb/dwarf2/loc.h index 4fb743618e7c..679c4962d137 100644 --- a/gdb/dwarf2/loc.h +++ b/gdb/dwarf2/loc.h @@ -118,8 +118,10 @@ struct property_addr_info etc. This means the during evaluation PUSH_VALUES[0] will be at the bottom of the stack. */ +struct reg_buffer; bool dwarf2_evaluate_property (const struct dynamic_prop *prop, const frame_info_ptr &frame, + reg_buffer *regcache, const property_addr_info *addr_stack, CORE_ADDR *value, gdb::array_view push_values = {}); diff --git a/gdb/findvar.c b/gdb/findvar.c index f7760aa61ca9..d65bf2fc278c 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -656,3 +656,20 @@ address_from_register (int regnum, const frame_info_ptr &frame) return value_as_address (v.get ()); } + +/* Return contents of register REGNUM in REGCACHE as address. + Will abort if register value is not available. */ + +CORE_ADDR +address_from_register (int regnum, reg_buffer *regcache) +{ + if (regcache->get_register_status (regnum) != REG_VALID) + throw_error (NOT_AVAILABLE_ERROR, _("register %d is not available"), + regnum); + + gdb_byte buffer[sizeof (CORE_ADDR)]; + regcache->raw_collect (regnum, buffer); + + type *type = builtin_type (regcache->arch ())->builtin_data_ptr; + return extract_typed_address (buffer, type); +} diff --git a/gdb/frame.c b/gdb/frame.c index 2c1ea012191b..663ff7fa773b 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -3175,7 +3175,8 @@ frame_follow_static_link (const frame_info_ptr &initial_frame) CORE_ADDR upper_frame_base; - if (!dwarf2_evaluate_property (static_link, initial_frame, NULL, &upper_frame_base)) + if (!dwarf2_evaluate_property (static_link, initial_frame, nullptr, nullptr, + &upper_frame_base)) return {}; /* Now climb up the stack frame until we reach the frame we are interested diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 2a3aea229cb0..ea8bad4e826c 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -2146,7 +2146,7 @@ is_dynamic_type (struct type *type) static struct type *resolve_dynamic_type_internal (struct type *type, struct property_addr_info *addr_stack, - const frame_info_ptr &frame, bool top_level); + const frame_info_ptr &frame, reg_buffer *regcache, bool top_level); /* Given a dynamic range type (dyn_range_type) and a stack of struct property_addr_info elements, return a static version @@ -2168,6 +2168,7 @@ static struct type * resolve_dynamic_range (struct type *dyn_range_type, struct property_addr_info *addr_stack, const frame_info_ptr &frame, + reg_buffer *regcache, int rank, bool resolve_p = true) { CORE_ADDR value; @@ -2180,7 +2181,7 @@ resolve_dynamic_range (struct type *dyn_range_type, const struct dynamic_prop *prop = &dyn_range_type->bounds ()->low; if (resolve_p) { - if (dwarf2_evaluate_property (prop, frame, addr_stack, &value, + if (dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value, { (CORE_ADDR) rank })) low_bound.set_const_val (value); else if (prop->kind () == PROP_UNDEFINED) @@ -2194,7 +2195,7 @@ resolve_dynamic_range (struct type *dyn_range_type, prop = &dyn_range_type->bounds ()->high; if (resolve_p) { - if (dwarf2_evaluate_property (prop, frame, addr_stack, &value, + if (dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value, { (CORE_ADDR) rank })) { high_bound.set_const_val (value); @@ -2213,8 +2214,8 @@ resolve_dynamic_range (struct type *dyn_range_type, bool byte_stride_p = dyn_range_type->bounds ()->flag_is_byte_stride; prop = &dyn_range_type->bounds ()->stride; - if (resolve_p && dwarf2_evaluate_property (prop, frame, addr_stack, &value, - { (CORE_ADDR) rank })) + if (resolve_p && dwarf2_evaluate_property (prop, frame, regcache, addr_stack, + &value, { (CORE_ADDR) rank })) { stride.set_const_val (value); @@ -2236,7 +2237,7 @@ resolve_dynamic_range (struct type *dyn_range_type, static_target_type = resolve_dynamic_type_internal (dyn_range_type->target_type (), - addr_stack, frame, false); + addr_stack, frame, regcache, false); LONGEST bias = dyn_range_type->bounds ()->bias; type_allocator alloc (dyn_range_type); static_range_type = create_range_type_with_stride @@ -2270,6 +2271,7 @@ static struct type * resolve_dynamic_array_or_string_1 (struct type *type, struct property_addr_info *addr_stack, const frame_info_ptr &frame, + reg_buffer *regcache, int rank, bool resolve_p) { CORE_ADDR value; @@ -2299,7 +2301,7 @@ resolve_dynamic_array_or_string_1 (struct type *type, dimension of the array. */ prop = TYPE_ALLOCATED_PROP (type); if (prop != NULL && resolve_p - && dwarf2_evaluate_property (prop, frame, addr_stack, &value)) + && dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value)) { prop->set_const_val (value); if (value == 0) @@ -2308,7 +2310,7 @@ resolve_dynamic_array_or_string_1 (struct type *type, prop = TYPE_ASSOCIATED_PROP (type); if (prop != NULL && resolve_p - && dwarf2_evaluate_property (prop, frame, addr_stack, &value)) + && dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value)) { prop->set_const_val (value); if (value == 0) @@ -2317,14 +2319,15 @@ resolve_dynamic_array_or_string_1 (struct type *type, range_type = check_typedef (type->index_type ()); range_type - = resolve_dynamic_range (range_type, addr_stack, frame, rank, resolve_p); + = resolve_dynamic_range (range_type, addr_stack, frame, regcache, rank, + resolve_p); ary_dim = check_typedef (type->target_type ()); if (ary_dim != NULL && ary_dim->code () == TYPE_CODE_ARRAY) { ary_dim = copy_type (ary_dim); elt_type = resolve_dynamic_array_or_string_1 (ary_dim, addr_stack, - frame, rank - 1, + frame, regcache, rank - 1, resolve_p); } else if (ary_dim != nullptr && ary_dim->code () == TYPE_CODE_STRING) @@ -2355,7 +2358,7 @@ resolve_dynamic_array_or_string_1 (struct type *type, Fortran, and hope that this doesn't cause problems for anyone else. */ elt_type = resolve_dynamic_type_internal (type->target_type (), - addr_stack, frame, 0); + addr_stack, frame, regcache, 0); } else elt_type = type->target_type (); @@ -2365,7 +2368,7 @@ resolve_dynamic_array_or_string_1 (struct type *type, prop = nullptr; if (prop != NULL && resolve_p) { - if (dwarf2_evaluate_property (prop, frame, addr_stack, &value)) + if (dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value)) { type->remove_dyn_prop (DYN_PROP_BYTE_STRIDE); bit_stride = (unsigned int) (value * 8); @@ -2397,7 +2400,8 @@ resolve_dynamic_array_or_string_1 (struct type *type, static struct type * resolve_dynamic_array_or_string (struct type *type, struct property_addr_info *addr_stack, - const frame_info_ptr &frame) + const frame_info_ptr &frame, + reg_buffer *regcache) { CORE_ADDR value; int rank = 0; @@ -2411,7 +2415,7 @@ resolve_dynamic_array_or_string (struct type *type, /* Resolve the rank property to get rank value. */ struct dynamic_prop *prop = TYPE_RANK_PROP (type); - if (dwarf2_evaluate_property (prop, frame, addr_stack, &value)) + if (dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value)) { prop->set_const_val (value); rank = value; @@ -2479,8 +2483,8 @@ resolve_dynamic_array_or_string (struct type *type, reduce the rank by 1 here. */ --rank; - return resolve_dynamic_array_or_string_1 (type, addr_stack, frame, rank, - true); + return resolve_dynamic_array_or_string_1 (type, addr_stack, frame, regcache, + rank, true); } /* Resolve dynamic bounds of members of the union TYPE to static @@ -2490,7 +2494,8 @@ resolve_dynamic_array_or_string (struct type *type, static struct type * resolve_dynamic_union (struct type *type, struct property_addr_info *addr_stack, - const frame_info_ptr &frame) + const frame_info_ptr &frame, + reg_buffer *regcache) { struct type *resolved_type; int i; @@ -2508,7 +2513,7 @@ resolve_dynamic_union (struct type *type, continue; t = resolve_dynamic_type_internal (resolved_type->field (i).type (), - addr_stack, frame, false); + addr_stack, frame, regcache, false); resolved_type->field (i).set_type (t); struct type *real_type = check_typedef (t); @@ -2682,7 +2687,8 @@ compute_variant_fields (struct type *type, static struct type * resolve_dynamic_struct (struct type *type, struct property_addr_info *addr_stack, - const frame_info_ptr &frame) + const frame_info_ptr &frame, + reg_buffer *regcache) { struct type *resolved_type; int i; @@ -2725,8 +2731,8 @@ resolve_dynamic_struct (struct type *type, prop.set_locexpr (&baton); CORE_ADDR addr; - if (dwarf2_evaluate_property (&prop, frame, addr_stack, &addr, - {addr_stack->addr})) + if (dwarf2_evaluate_property (&prop, frame, regcache, addr_stack, + &addr, {addr_stack->addr})) resolved_type->field (i).set_loc_bitpos (TARGET_CHAR_BIT * (addr - addr_stack->addr)); } @@ -2752,7 +2758,7 @@ resolve_dynamic_struct (struct type *type, resolved_type->field (i).set_type (resolve_dynamic_type_internal (resolved_type->field (i).type (), - &pinfo, frame, false)); + &pinfo, frame, regcache, false)); gdb_assert (resolved_type->field (i).loc_kind () == FIELD_LOC_KIND_BITPOS); @@ -2798,6 +2804,7 @@ static struct type * resolve_dynamic_type_internal (struct type *type, struct property_addr_info *addr_stack, const frame_info_ptr &frame, + reg_buffer *regcache, bool top_level) { struct type *real_type = check_typedef (type); @@ -2811,7 +2818,7 @@ resolve_dynamic_type_internal (struct type *type, std::optional type_length; prop = TYPE_DYNAMIC_LENGTH (type); if (prop != NULL - && dwarf2_evaluate_property (prop, frame, addr_stack, &value)) + && dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value)) type_length = value; if (type->code () == TYPE_CODE_TYPEDEF) @@ -2819,7 +2826,7 @@ resolve_dynamic_type_internal (struct type *type, resolved_type = copy_type (type); resolved_type->set_target_type (resolve_dynamic_type_internal (type->target_type (), addr_stack, - frame, top_level)); + frame, regcache, top_level)); } else { @@ -2849,8 +2856,8 @@ resolve_dynamic_type_internal (struct type *type, { resolved_type = copy_type (type); resolved_type->set_target_type - (resolve_dynamic_type_internal (type->target_type (), - &pinfo, frame, true)); + (resolve_dynamic_type_internal (type->target_type (), &pinfo, + frame, regcache, true)); } break; } @@ -2860,7 +2867,7 @@ resolve_dynamic_type_internal (struct type *type, treated as one here. */ case TYPE_CODE_ARRAY: resolved_type = resolve_dynamic_array_or_string (type, addr_stack, - frame); + frame, regcache); break; case TYPE_CODE_RANGE: @@ -2869,15 +2876,18 @@ resolve_dynamic_type_internal (struct type *type, this rank value is not actually required for the resolution of the dynamic range, otherwise, we'd be resolving this range within the context of a dynamic array. */ - resolved_type = resolve_dynamic_range (type, addr_stack, frame, 0); + resolved_type = resolve_dynamic_range (type, addr_stack, frame, + regcache, 0); break; case TYPE_CODE_UNION: - resolved_type = resolve_dynamic_union (type, addr_stack, frame); + resolved_type = resolve_dynamic_union (type, addr_stack, frame, + regcache); break; case TYPE_CODE_STRUCT: - resolved_type = resolve_dynamic_struct (type, addr_stack, frame); + resolved_type = resolve_dynamic_struct (type, addr_stack, frame, + regcache); break; } } @@ -2894,7 +2904,7 @@ resolve_dynamic_type_internal (struct type *type, /* Resolve data_location attribute. */ prop = TYPE_DATA_LOCATION (resolved_type); if (prop != NULL - && dwarf2_evaluate_property (prop, frame, addr_stack, &value)) + && dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value)) { /* Start of Fortran hack. See comment in f-lang.h for what is going on here.*/ @@ -2915,7 +2925,8 @@ struct type * resolve_dynamic_type (struct type *type, gdb::array_view valaddr, CORE_ADDR addr, - const frame_info_ptr *in_frame) + const frame_info_ptr *in_frame, + reg_buffer *regcache) { struct property_addr_info pinfo = {check_typedef (type), valaddr, addr, NULL}; @@ -2924,7 +2935,7 @@ resolve_dynamic_type (struct type *type, if (in_frame != nullptr) frame = *in_frame; - return resolve_dynamic_type_internal (type, &pinfo, frame, true); + return resolve_dynamic_type_internal (type, &pinfo, frame, regcache, true); } /* See gdbtypes.h */ diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index f80bd7e071a3..514af300de3b 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -2625,9 +2625,12 @@ extern CORE_ADDR get_pointer_type_max (struct type *); have a different type when resolved (depending on the contents of memory). In this situation, 'is_dynamic_type' will still return true for the return value of this function. */ + +struct reg_buffer; extern struct type *resolve_dynamic_type (struct type *type, gdb::array_view valaddr, - CORE_ADDR addr, const frame_info_ptr *frame = nullptr); + CORE_ADDR addr, const frame_info_ptr *frame = nullptr, + reg_buffer *regcache = nullptr); /* * Predicate if the type has dynamic values, which are not resolved yet. See the caveat in 'resolve_dynamic_type' to understand a scenario diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c index aefbee542703..5cc0d1d2d4f4 100644 --- a/gdb/gnu-v3-abi.c +++ b/gdb/gnu-v3-abi.c @@ -493,7 +493,7 @@ gnuv3_baseclass_offset (struct type *type, int index, addr_stack.next = nullptr; CORE_ADDR result; - if (dwarf2_evaluate_property (&prop, nullptr, &addr_stack, &result, + if (dwarf2_evaluate_property (&prop, nullptr, nullptr, &addr_stack, &result, {addr_stack.addr})) return (int) (result - addr_stack.addr); } diff --git a/gdb/value.h b/gdb/value.h index 13cfb007aa2c..802a49066288 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -1133,6 +1133,9 @@ extern struct value *value_from_register (struct type *type, int regnum, extern CORE_ADDR address_from_register (int regnum, const frame_info_ptr &frame); +struct reg_buffer; +extern CORE_ADDR address_from_register (int regnum, + reg_buffer *regcache); extern struct value *value_of_variable (struct symbol *var, const struct block *b); From patchwork Sat Nov 2 02:56:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840280 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1158708wrb; Fri, 1 Nov 2024 20:00:05 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVD6agw8iR7LlIWqCQWCb/Gler+9xFCl4uozx/3BIqldYaxrlGUUwe925tDi08c55baInWMGw==@linaro.org X-Google-Smtp-Source: AGHT+IGaKfSEFfKqOC3b2uRmLpcoZlRWjJcwfQ578jF5STteSoa1+XrNUHvoSGqY/0tzcMAtGirs X-Received: by 2002:a05:620a:444c:b0:7b1:461c:5244 with SMTP id af79cd13be357-7b2fb96a9f2mr707391785a.25.1730516404840; Fri, 01 Nov 2024 20:00:04 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516404; cv=pass; d=google.com; s=arc-20240605; b=E1suENRGBbxUJhyZRmBALLLhb7MBlQiO8lz85+gkN0A3wAXBAEkqWI4YUFfqaspCEA 99W2XPQLgYUcOK8BI3HBuKiVz9agUTth0ygrP9f/KiZEqRtDZoP5NooHpu3vstufxHjj Tsz5XzJvsahcMR1HPUe70dfXq4Reb3UFiffWsdQg+vffiIUzouUZqFhTELKxUA+8OdAt g1B8ZYKinWPS/74719Q5ehQzzX0jh/oKTsYKkHnQkLDzaYYSdFjx44VDTedZRmYfePPv QAYIFtJn1ZpuquXSOD+4cDEZFfgw6fLnHBEyiz3Guzv6MyzbFY2WHhCmYbC9ow8Shg+n HDjA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=ZxwG7/Emx6c4RPsgLfMLF5LSDyQwJlHvHX5oec+UK/k=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=FxMx73V3qI6piTI6jiB/LcZ15ap6+RlJXZ7jbN2tgLjfFqFPfIj8EhQOjlgi7CmfWN NdvYJI5WL69IUtS1qL5GvURmYGNoxOVpYnd3VfJwU2MPkUqoLBdi2dGvF11CZ1k1hXHD 5rBmF02B6a0eQEoVY/+/5qycTKeC99vVXWZueAL80Bvc0XZtORaMgk3Zlc9frNI+vKDV F3q2GnUVp/y3TR4pa1Iqrftcr35OLMjqb2Fd6xAj5GjXO8NeX8WIREGDR6z4Xhuz5yls txeG6X5q8X6I+KqZHuIW/932TomGQ7YFixXac7w7AaJQHywE6i4zTATSXojHzrAfen2U Hylw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Nx9FGJ8p; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id af79cd13be357-7b2f3a81706si573440785a.227.2024.11.01.20.00.04 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 20:00:04 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Nx9FGJ8p; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6DAAA3857C5D for ; Sat, 2 Nov 2024 03:00:04 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pf1-x429.google.com (mail-pf1-x429.google.com [IPv6:2607:f8b0:4864:20::429]) by sourceware.org (Postfix) with ESMTPS id 0485B3857835 for ; Sat, 2 Nov 2024 02:57:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0485B3857835 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 0485B3857835 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::429 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516235; cv=none; b=jB2Px2Po5t0BOozgbxZCAfT6YDreCNcOtChKziM47S5ZxxcAQPBwWh/mU8jBCBxc7tuSXjVsY1/OXec6oRow9DGfLfRaKuTQ01q+35FpBF8AdMH05RnmhU6MgcdkMDVa0YaPYMCfL8DTjTYNnM+Lns8fICotosdW5QwM5TT809Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516235; c=relaxed/simple; bh=rrrjpQcEf+9ikwdsEbCcc2febBO2VIKRvt1p1qTHQ/A=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=wcAK7Q99snNnbFXY4V9iky5t33QCty0xTyrfxfGZY4EacTv46Tuvgy9Sb+vL/orjbfpwF0/IvmCtWybCUOV/b/C2ygKCNMDxeIW1Uqn/ycQL4ZR5n7GoBjihE8sncCUOqP0+4hTuvJezQS2Xx+NYNh9EJ2MDrVvJuIoumY/HNIY= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-72041ff06a0so2220568b3a.2 for ; Fri, 01 Nov 2024 19:57:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516228; x=1731121028; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=ZxwG7/Emx6c4RPsgLfMLF5LSDyQwJlHvHX5oec+UK/k=; b=Nx9FGJ8pct3HQkz3uXPBCzM1HgZaRbyrPANP2BoGImxnacG/GD9wxJgil79VdRtIYo WlAoVauUChOXbG2/FMrUcBcUj4tBLcoRNNBL7QYCrWS+vbUqFPQDv4zo37eGBhsqMhn1 n15y0+uhbO1kjyB2yYBqGUlNNHIZxC/qlrla4ieiaMAsVjBKxbCiN4utVsq/0gmU/Wi7 mX4ySzIdfKFM5YmpdA3BwwKo4LwdTOJyXDNX9whusAzvSjZGeghNP/UE7KvO8Mnchpmq bwUMOJjHeRQNkGlf7baCyyoo3qNbLkjGJkocZSwAP37iDN1yzdqqqdJ7fxlhI6Rb9R12 GUNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516228; x=1731121028; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ZxwG7/Emx6c4RPsgLfMLF5LSDyQwJlHvHX5oec+UK/k=; b=VMKORIc6gDTVJFb7/WsDXgCgJdpM6EyjnKMxFQ9+S4HJl1noBBYXDozsie5wke2AB8 8IZ6XL5wHfUzIpHuCKHCmGYuIm2rDK09lKhcjzmHEg1rWl2cYR4YtKwiUJfXmqEzUa3K NgT1ZhexGZ1ntsGkMJWeTjJeqRswSnunoql3Ub8aw+Dn1eY+KTDkdGI8QBFOztAy1FLF QwF6uaRBcFA4dD7jEQu+uZswtxfpEcZn3e+yRj27toj95W2x1tXEATmFrdsRYsFsmabq BC93HtLDPl3O5DCTMP1z4Avc6/cIw5iSJhsTnwU9T+r2N/db40MLzzWWPynLWJME2AU/ zqvA== X-Gm-Message-State: AOJu0Yz4vodfG2rWV40mX0iKfKC3/bMdR1QDL9DNP1dEuG8wUFBNUT8+ eFxqU/wdwcPrVdL4opWoKa5S14oKEG+kNdkAEL2stiTdIBHcRojNq9jb3Gh9+z6G4b/WNw0ukiX G X-Received: by 2002:a05:6a20:c999:b0:1d9:28f8:f287 with SMTP id adf61e73a8af0-1dba54a4dd3mr5862104637.36.1730516227306; Fri, 01 Nov 2024 19:57:07 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-720bc2eb676sm3382525b3a.164.2024.11.01.19.57.06 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:57:06 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 09/15] GDB tdesc: Add vector type with number of elements given by math expression. Date: Fri, 1 Nov 2024 23:56:29 -0300 Message-ID: <20241102025635.586759-10-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org This allows using MathML¹ to express the vector count, including referencing the contents of other registers. E.g.: 85 2 The element (meaning "content identifier") is used to represent variables. In this case, it represents the VG register which has regnum 85 in the SVE AArch64 feature. The element is used to represent numbers. MathML has two sets of markup. One for representing a math expression visually, and another to represent its meaning. This patch uses the latter markup, which is suited for computation. It currently implements just a subset of MathML to enable simple expressions. If this approach is accepted, we don't have to implement everything from the standard. We could add things as we need them. Currently, registers are referenced by their numbers but this is a temporary hack. I'll fix it to reference registers by their names instead. When the XML above is parsed, it's converted to a DWARF expression which is stored in the GDB type. When an XML feature contains a math expression referencing a register, it needs to have an tag. This is because when generating the C code corresponding to the XML, the feature XML is parsed in isolation and not as part of a whole target description (which would contain the architecture information). One minor disadvantage of this approach is that gdbserver needs to have a DWARF expression interpreter. Since this feature only needs a subset of the DWARF expression opcodes, it's a small amount of simple code and thus it's not really a problem IMHO. ¹ https://www.w3.org/TR/MathML/ --- gdb/features/gdb-target.dtd | 17 +- gdb/gdbarch-gen.c | 32 +++ gdb/gdbarch-gen.h | 9 + gdb/gdbarch_components.py | 11 + gdb/gdbtypes.c | 61 ++++++ gdb/gdbtypes.h | 2 + gdb/target-descriptions.c | 94 +++++++- gdb/target-descriptions.h | 6 + gdb/xml-tdesc.c | 416 +++++++++++++++++++++++++++++++++--- gdbserver/Makefile.in | 2 + gdbserver/config.in | 3 + gdbserver/configure | 6 + gdbserver/configure.ac | 5 + gdbserver/locexpr.cc | 107 ++++++++++ gdbserver/locexpr.h | 31 +++ gdbserver/tdesc.cc | 18 ++ gdbsupport/tdesc.cc | 134 +++++++++++- gdbsupport/tdesc.h | 47 ++++ 18 files changed, 963 insertions(+), 38 deletions(-) create mode 100644 gdbserver/locexpr.cc create mode 100644 gdbserver/locexpr.h diff --git a/gdb/features/gdb-target.dtd b/gdb/features/gdb-target.dtd index d07703fca8b6..d38ca6f90bce 100644 --- a/gdb/features/gdb-target.dtd +++ b/gdb/features/gdb-target.dtd @@ -20,7 +20,7 @@ + (architecture?, (vector | flags | struct | union )*, reg*)> @@ -34,11 +34,22 @@ group CDATA #IMPLIED > - + + count CDATA #IMPLIED> + + + + + + + + + register_name == 0) log.puts ("\n\tregister_name"); if (gdbarch->register_type == 0) @@ -711,6 +713,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) gdb_printf (file, "gdbarch_dump: dwarf2_reg_to_regnum = <%s>\n", host_address_to_string (gdbarch->dwarf2_reg_to_regnum)); + gdb_printf (file, + "gdbarch_dump: gdbarch_regnum_to_dwarf2_reg_p() = %d\n", + gdbarch_regnum_to_dwarf2_reg_p (gdbarch)); + gdb_printf (file, + "gdbarch_dump: regnum_to_dwarf2_reg = <%s>\n", + host_address_to_string (gdbarch->regnum_to_dwarf2_reg)); gdb_printf (file, "gdbarch_dump: register_name = <%s>\n", host_address_to_string (gdbarch->register_name)); @@ -2201,6 +2209,30 @@ set_gdbarch_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, gdbarch->dwarf2_reg_to_regnum = dwarf2_reg_to_regnum; } +bool +gdbarch_regnum_to_dwarf2_reg_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->regnum_to_dwarf2_reg != NULL; +} + +int +gdbarch_regnum_to_dwarf2_reg (struct gdbarch *gdbarch, int regnum) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->regnum_to_dwarf2_reg != NULL); + if (gdbarch_debug >= 2) + gdb_printf (gdb_stdlog, "gdbarch_regnum_to_dwarf2_reg called\n"); + return gdbarch->regnum_to_dwarf2_reg (gdbarch, regnum); +} + +void +set_gdbarch_regnum_to_dwarf2_reg (struct gdbarch *gdbarch, + gdbarch_regnum_to_dwarf2_reg_ftype regnum_to_dwarf2_reg) +{ + gdbarch->regnum_to_dwarf2_reg = regnum_to_dwarf2_reg; +} + const char * gdbarch_register_name (struct gdbarch *gdbarch, int regnr) { diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h index b982fd7cd092..1d4d19cf6774 100644 --- a/gdb/gdbarch-gen.h +++ b/gdb/gdbarch-gen.h @@ -308,6 +308,15 @@ typedef int (gdbarch_dwarf2_reg_to_regnum_ftype) (struct gdbarch *gdbarch, int d extern int gdbarch_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int dwarf2_regnr); extern void set_gdbarch_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, gdbarch_dwarf2_reg_to_regnum_ftype *dwarf2_reg_to_regnum); +/* Provide a default mapping from a gdb REGNUM to a DWARF2 register number. + Return -1 for bad REGNUM. */ + +extern bool gdbarch_regnum_to_dwarf2_reg_p (struct gdbarch *gdbarch); + +typedef int (gdbarch_regnum_to_dwarf2_reg_ftype) (struct gdbarch *gdbarch, int regnum); +extern int gdbarch_regnum_to_dwarf2_reg (struct gdbarch *gdbarch, int regnum); +extern void set_gdbarch_regnum_to_dwarf2_reg (struct gdbarch *gdbarch, gdbarch_regnum_to_dwarf2_reg_ftype *regnum_to_dwarf2_reg); + /* Return the name of register REGNR for the specified architecture. REGNR can be any value greater than, or equal to zero, and less than 'gdbarch_num_cooked_regs (GDBARCH)'. If REGNR is not supported for diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py index 4006380076dc..0764a6c31d92 100644 --- a/gdb/gdbarch_components.py +++ b/gdb/gdbarch_components.py @@ -589,6 +589,17 @@ Return -1 for bad REGNUM. Note: Several targets get this wrong. invalid=False, ) +Method( + comment=""" +Provide a default mapping from a gdb REGNUM to a DWARF2 register number. +Return -1 for bad REGNUM. +""", + type="int", + name="regnum_to_dwarf2_reg", + params=[("int", "regnum")], + predicate=True, +) + Method( comment=""" Return the name of register REGNR for the specified architecture. diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index ea8bad4e826c..8037283e3706 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1030,6 +1030,40 @@ create_static_range_type (type_allocator &alloc, struct type *index_type, return result_type; } +/* Create a range type using ALLOC. + + Indices will be of type INDEX_TYPE, and will range from 0 to the value + LOC_EXPR_ evaluates to, inclusive. */ + +static struct type * +create_dynamic_range_type (type_allocator &alloc, struct type *index_type, + const gdb::array_view locexpr_) +{ + struct dynamic_prop low, high; + struct dwarf2_property_baton *baton + = GDBARCH_OBSTACK_ZALLOC (alloc.arch (), dwarf2_property_baton); + size_t len = locexpr_.size () + 2; + gdb_byte *locexpr = GDBARCH_OBSTACK_CALLOC (alloc.arch (), len, gdb_byte); + + memcpy (locexpr, locexpr_.data (), locexpr_.size()); + + /* The high bound is inclusive, so decrement the element count by one. */ + locexpr[len - 2] = DW_OP_lit1; + locexpr[len - 1] = DW_OP_minus; + + baton->property_type = builtin_type (alloc.arch ())->builtin_unsigned_int; + baton->locexpr.data = locexpr; + baton->locexpr.size = len; + baton->locexpr.is_reference = false; + baton->locexpr.per_objfile = nullptr; + baton->locexpr.per_cu = nullptr; + + low.set_const_val (0); + high.set_locexpr (baton); + + return create_range_type (alloc, index_type, &low, &high, 0); +} + /* Predicate tests whether BOUNDS are static. Returns 1 if all bounds values are static, otherwise returns 0. */ @@ -1409,6 +1443,21 @@ lookup_array_range_type (struct type *element_type, return create_array_type (alloc, element_type, range_type); } +/* Create type for array ranges where the low bound is 0 and the high + bound is given by the provided DWARF LOCEXPR_. */ + +static struct type * +lookup_array_range_type (struct type *element_type, + const gdb::array_view locexpr_) +{ + type_allocator alloc (element_type); + struct type *index_type, *range_type; + + index_type = builtin_type (element_type->arch ())->builtin_unsigned_int; + range_type = create_dynamic_range_type (alloc, index_type, locexpr_); + return create_array_type (alloc, element_type, range_type); +} + /* See gdbtypes.h. */ struct type * @@ -1497,6 +1546,18 @@ init_vector_type (struct type *elt_type, int n) return array_type; } +/* Create vector type of elements of type ELT_TYPE, where the number of + elements is given by the provided DWARF LOCEXPR. */ + +struct type * +init_vector_type (struct type *elt_type, + const gdb::array_view locexpr) +{ + struct type *array_type = lookup_array_range_type (elt_type, locexpr); + make_vector_type (array_type); + return array_type; +} + /* Internal routine called by TYPE_SELF_TYPE to return the type that TYPE belongs to. In c++ this is the class of "this", but TYPE_THIS_TYPE is too confusing. "self" is a common enough replacement for "this". diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 514af300de3b..46103ea44656 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -2427,6 +2427,8 @@ extern void append_flags_type_flag (struct type *type, int bitpos, extern void make_vector_type (struct type *array_type); extern struct type *init_vector_type (struct type *elt_type, int n); +extern struct type *init_vector_type (struct type *elt_type, + const gdb::array_view locexpr); extern struct type *lookup_reference_type (struct type *, enum type_code); extern struct type *lookup_lvalue_reference_type (struct type *); diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c index 82e4d96276e3..9c9cc2ceadba 100644 --- a/gdb/target-descriptions.c +++ b/gdb/target-descriptions.c @@ -159,7 +159,10 @@ make_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *ttype) return; type *element_gdb_type = make_gdb_type (m_gdbarch, e->element_type); - m_type = init_vector_type (element_gdb_type, e->count); + if (e->locexpr.size() > 0) + m_type = init_vector_type (element_gdb_type, e->locexpr); + else + m_type = init_vector_type (element_gdb_type, e->count); m_type->set_name (xstrdup (e->name.c_str ())); return; } @@ -364,6 +367,10 @@ struct target_desc : tdesc_element /* The features associated with this target. */ std::vector features; + /* Location expressions for variable-size vector registers may use constants + defined in the DWARF header. */ + bool include_dwarf_header = false; + /* Used to cache the generated xml version of the target description. */ mutable char *xmltarget = nullptr; @@ -452,6 +459,23 @@ get_arch_data (struct gdbarch *gdbarch) return result; } +/* See gdbsupport/tdesc.h. */ + +int +tdesc_dwarf_reg_to_regnum (const char *arch, int dwarf_reg) +{ + struct gdbarch_info info; + info.bfd_arch_info = bfd_scan_arch (arch); + if (info.bfd_arch_info == nullptr) + return -1; + + gdbarch *gdbarch = gdbarch_find_by_info (info); + if (gdbarch == nullptr) + return -1; + + return gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_reg); +} + /* The string manipulated by the "set tdesc filename ..." command. */ static std::string tdesc_filename_cmd_string; @@ -1214,6 +1238,14 @@ set_tdesc_osabi (struct target_desc *target_desc, enum gdb_osabi osabi) { target_desc->osabi = osabi; } + +/* See gdb/target-descriptions.h. */ + +void +set_tdesc_include_dwarf_header (struct target_desc *target_desc, bool include) +{ + target_desc->include_dwarf_header = include; +} static struct cmd_list_element *tdesc_set_cmdlist, *tdesc_show_cmdlist; @@ -1372,9 +1404,45 @@ class print_c_tdesc : public tdesc_element_visitor gdb_printf (" element_type = tdesc_named_type (feature, \"%s\");\n", type->element_type->name.c_str ()); - gdb_printf - (" tdesc_create_vector (feature, \"%s\", element_type, %d);\n", - type->name.c_str (), type->count); + + if (type->count == TDESC_REG_VARIABLE_SIZE) + { + const std::string *prefix; + + if (type->locexpr_id.has_value ()) + prefix = &*type->locexpr_id; + else if (type->locexpr_idref.has_value ()) + prefix = &*type->locexpr_idref; + else + prefix = &type->name; + + if (!type->locexpr_idref.has_value ()) + { + gdb_printf (" gdb_byte %s_locexpr[%zu];\n", prefix->c_str (), + type->locexpr.size ()); + for (unsigned int i = 0; i < type->locexpr.size (); i++) + { + const char *op_name; + + if (type->locexpr_str.has_value ()) + op_name = type->locexpr_str->at (i); + else + op_name = nullptr; + + if (op_name == nullptr) + gdb_printf (" %s_locexpr[%u] = %u;\n", prefix->c_str (), i, + type->locexpr[i]); + else + gdb_printf (" %s_locexpr[%u] = %s;\n", prefix->c_str (), i, + op_name); + } + } + gdb_printf (" tdesc_create_vector (feature, \"%s\", element_type, %s_locexpr);\n", + type->name.c_str (), prefix->c_str ()); + } + else + gdb_printf (" tdesc_create_vector (feature, \"%s\", element_type, %d);\n", + type->name.c_str (), type->count); gdb_printf ("\n"); } @@ -1494,7 +1562,13 @@ class print_c_tdesc : public tdesc_element_visitor gdb_printf ("\"%s\", ", reg->group.c_str ()); else gdb_printf ("NULL, "); - gdb_printf ("%d, \"%s\"", reg->bitsize, reg->type.c_str ()); + + if (reg->bitsize == TDESC_REG_VARIABLE_SIZE) + gdb_printf ("TDESC_REG_VARIABLE_SIZE, "); + else + gdb_printf ("%d, ", reg->bitsize); + + gdb_printf ("\"%s\"", reg->type.c_str ()); if (reg->load_early) gdb_printf (", true"); @@ -1558,6 +1632,8 @@ class print_c_feature : public print_c_tdesc lbasename (m_filename_after_features.c_str ())); gdb_printf ("#include \"gdbsupport/tdesc.h\"\n"); + if (e->include_dwarf_header) + gdb_printf ("#include \"dwarf2.h\"\n"); gdb_printf ("\n"); } @@ -1642,7 +1718,13 @@ class print_c_feature : public print_c_tdesc gdb_printf ("\"%s\", ", reg->group.c_str ()); else gdb_printf ("NULL, "); - gdb_printf ("%d, \"%s\"", reg->bitsize, reg->type.c_str ()); + + if (reg->bitsize == TDESC_REG_VARIABLE_SIZE) + gdb_printf ("TDESC_REG_VARIABLE_SIZE, "); + else + gdb_printf ("%d, ", reg->bitsize); + + gdb_printf ("\"%s\"", reg->type.c_str ()); if (reg->load_early) gdb_printf (", true"); diff --git a/gdb/target-descriptions.h b/gdb/target-descriptions.h index e40c7db5f79f..c65e5d203933 100644 --- a/gdb/target-descriptions.h +++ b/gdb/target-descriptions.h @@ -229,6 +229,12 @@ void set_tdesc_property (struct target_desc *, void tdesc_add_compatible (struct target_desc *, const struct bfd_arch_info *); +/* Set whether the C version of the target description should include + dwarf2.h. */ + +void set_tdesc_include_dwarf_header (struct target_desc *target_desc, + bool include); + #if GDB_SELF_TEST namespace selftests { diff --git a/gdb/xml-tdesc.c b/gdb/xml-tdesc.c index 436c493d4f91..2f28968838d6 100644 --- a/gdb/xml-tdesc.c +++ b/gdb/xml-tdesc.c @@ -71,21 +71,62 @@ static std::unordered_map xml_cache; struct tdesc_parsing_data { /* The target description we are building. */ - struct target_desc *tdesc; + struct target_desc *tdesc = nullptr; /* The target feature we are currently parsing, or last parsed. */ - struct tdesc_feature *current_feature; + struct tdesc_feature *current_feature = nullptr; /* The register number to use for the next register we see, if it does not have its own. This starts at zero. */ - int next_regnum; + int next_regnum = 0; /* The struct or union we are currently parsing, or last parsed. */ - tdesc_type_with_fields *current_type; + tdesc_type_with_fields *current_type = nullptr; /* The byte size of the current struct/flags type, if specified. Zero if not specified. Flags values must specify a size. */ - int current_type_size; + int current_type_size = 0; + + /* Map used to implement id/idref attribute support for the + element in a vector type. The fist member is the count id, and the + second is the DWARF expression it corresponds to. */ + std::unordered_map vector_count_locexprs; + + /* Information needed to parse element. */ + struct { + /* id attribute for the element being processed. */ + std::string id; + + /* Type of field in element being processed. */ + struct tdesc_type *field_type = nullptr; + + /* Holds number of elements, if has "count" attribute. */ + std::optional count; + + /* Holds DWARF expression, if has a child. */ + gdb::byte_vector locexpr; + + /* Holds string representation of opcodes in locexpr. Used to provide + more readable code when converting to C. Needs to have the same + number of elements as locexpr. */ + std::optional> locexpr_str; + + /* id attribute for the element being processed. */ + std::string count_id; + + std::string count_idref; + + std::optional apply_operator; + + std::optional apply_operator_str; + } current_vector; + + /* gdbarch that roughly corresponds to the XML target description being + parsed. Used to gather basic facts about the architecture such as the + DWARF register numbering. */ + gdbarch *preliminary_gdbarch = nullptr; + + std::set load_early_regnums; }; /* Handle the end of an element and its value. */ @@ -166,6 +207,36 @@ tdesc_start_feature (struct gdb_xml_parser *parser, data->current_feature = tdesc_create_feature (data->tdesc, name); } +/* Handle the end of a element. */ + +static void +tdesc_end_feature (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, void *user_data, + const char *body_text) +{ + struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data; + + for (int regnum : data->load_early_regnums) + { + std::vector ®isters = data->current_feature->registers; + auto reg = std::find_if (registers.begin (), registers.end (), + [=] (tdesc_reg_up &i) { + if (i->target_regnum == regnum) + return true; + else + return false; + }); + if (reg == registers.end ()) + gdb_xml_error (parser, + _("Register number %d used in expression but not found in feature."), + regnum); + + (*reg)->load_early = true; + } + + data->load_early_regnums.clear (); +} + /* Handle the start of a element. Fill in the optional attributes and attach it to the containing feature. */ @@ -474,27 +545,287 @@ tdesc_start_vector (struct gdb_xml_parser *parser, void *user_data, std::vector &attributes) { struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data; - struct tdesc_type *field_type; - char *id, *field_type_id; - ULONGEST count; + char *field_type_id; - id = (char *) attributes[0].value.get (); + data->current_vector.id = (char *) attributes[0].value.get (); field_type_id = (char *) attributes[1].value.get (); - count = * (ULONGEST *) attributes[2].value.get (); - if (count > MAX_VECTOR_SIZE) + if (attributes.size () >= 3) { - gdb_xml_error (parser, - _("Vector size %s is larger than maximum (%d)"), - pulongest (count), MAX_VECTOR_SIZE); + ULONGEST count = *(ULONGEST *)attributes[2].value.get (); + + if (count > MAX_VECTOR_SIZE) + gdb_xml_error (parser, + _ ("Vector \"%s\": size %s is larger than maximum (%d)"), + data->current_vector.id.c_str (), pulongest (count), + MAX_VECTOR_SIZE); + + data->current_vector.count = (int) count; } - field_type = tdesc_named_type (data->current_feature, field_type_id); - if (field_type == NULL) + data->current_vector.field_type = tdesc_named_type (data->current_feature, + field_type_id); + if (data->current_vector.field_type == nullptr) gdb_xml_error (parser, _("Vector \"%s\" references undefined type \"%s\""), - id, field_type_id); + data->current_vector.id.c_str (), field_type_id); +} + +/* Handle the end of a element. */ + +static void +tdesc_end_vector (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, void *user_data, + const char *body_text) +{ + struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data; + + if (data->current_vector.count.has_value () + && !data->current_vector.locexpr.empty ()) + gdb_xml_error (parser, + _ ("Vector \"%s\" has both a count attribute and a count expression"), + data->current_vector.id.c_str ()); + else if (!data->current_vector.count.has_value () + && data->current_vector.locexpr.empty ()) + gdb_xml_error (parser, + _ ("Vector \"%s\" has neither a count attribute nor a count expression"), + data->current_vector.id.c_str ()); + + if (data->current_vector.count.has_value ()) + tdesc_create_vector (data->current_feature, + data->current_vector.id.c_str (), + data->current_vector.field_type, + *data->current_vector.count); + else + { + tdesc_type *type = tdesc_create_vector (data->current_feature, + data->current_vector.id.c_str (), + data->current_vector.field_type, + data->current_vector.locexpr, + data->current_vector.locexpr_str); + tdesc_type_vector *type_vector = static_cast (type); + + if (!data->current_vector.count_id.empty ()) + type_vector->locexpr_id = data->current_vector.count_id; + else if (!data->current_vector.count_idref.empty ()) + type_vector->locexpr_idref = data->current_vector.count_idref; + + set_tdesc_include_dwarf_header (data->tdesc, true); + } + + data->current_vector = {}; +} + +/* Handle the start of a element. Store any given count ID and process + IDREFs. */ + +static void +tdesc_start_count (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, + void *user_data, std::vector &attributes) +{ + struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data; + const char *id = nullptr, *idref = nullptr; + + for (gdb_xml_value &attr : attributes) + { + if (!strcmp (attr.name, "id")) + id = (const char *) attr.value.get (); + else if (!strcmp (attr.name, "idref")) + idref = (const char *) attr.value.get (); + } + + if (id != nullptr && idref != nullptr) + gdb_xml_error (parser, + _ ("Vector \"%s\": count expression has both an id and an idref"), + data->current_vector.id.c_str ()); + + if (id != nullptr) + { + std::string current_count_id = id; + + if (data->vector_count_locexprs.find (current_count_id) + != data->vector_count_locexprs.end ()) + gdb_xml_error (parser, + _ ("Vector \"%s\": count expression has duplicate id \"%s\""), + data->current_vector.id.c_str (), id); + + data->current_vector.count_id = std::move (current_count_id); + } + else if (idref != nullptr) + { + std::string current_count_idref = idref; + + if (data->vector_count_locexprs.find (current_count_idref) + == data->vector_count_locexprs.end ()) + gdb_xml_error (parser, + _ ("Vector \"%s\": count expression references unknown id \"%s\""), + data->current_vector.id.c_str (), idref); - tdesc_create_vector (data->current_feature, id, field_type, count); + data->current_vector.count_idref = idref; + } +} + +/* Handle the end of a element. If the element has an id attribute, store the + location expression in the map. If it has an idref attribute, fetch the location + expression from the map. */ + +static void +tdesc_end_count (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, void *user_data, + const char *body_text) +{ + struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data; + + if (!data->current_vector.count_id.empty ()) + { + bool inserted + = data->vector_count_locexprs + .insert ({ data->current_vector.count_id, + data->current_vector.locexpr }) + .second; + + /* Insertion isn't supposed to fail: we already checked in the start + handler that this id isn't present in the map. */ + gdb_assert (inserted); + } + else if (!data->current_vector.count_idref.empty ()) + data->current_vector.locexpr + = data->vector_count_locexprs.at (data->current_vector.count_idref); +} + +/* Handle the start of a element. It just has to check whether it's inside + a element with an idref and initialize data->current_vector.locexpr_str. */ + +static void +tdesc_start_math (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, void *user_data, + std::vector &attributes) +{ + struct tdesc_parsing_data *data = (struct tdesc_parsing_data *)user_data; + + if (!data->current_vector.count_idref.empty ()) + gdb_xml_error (parser, + _ ("Vector \"%s\": count element with an idref isn't empty."), + data->current_vector.id.c_str ()); + + data->current_vector.locexpr_str.emplace (); +} + +/* Handle the end of an element. We just need to store the expression + operator at the end of the location expression. */ + +static void +tdesc_end_apply (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, void *user_data, + const char *body_text) +{ + struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data; + + if (!data->current_vector.apply_operator.has_value ()) + gdb_xml_error (parser, + _ ("Vector \"%s\": apply element doesn't have an operator."), + data->current_vector.id.c_str ()); + + data->current_vector.locexpr.push_back (*data->current_vector.apply_operator); + data->current_vector.locexpr_str->push_back (*data->current_vector.apply_operator_str); +} + +/* Handle the end of a element and its value. */ + +static void +tdesc_end_ci (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, void *user_data, + const char *body_text) +{ + struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data; + + if (data->preliminary_gdbarch == nullptr) { + gdbarch_info arch_info; + arch_info.bfd_arch_info = tdesc_architecture (data->tdesc); + arch_info.osabi = tdesc_osabi (data->tdesc); + data->preliminary_gdbarch = gdbarch_find_by_info (arch_info); + + if (data->preliminary_gdbarch == nullptr) + gdb_xml_error (parser, + _("Vector \"%s\": couldn't find basic architecture information."), + data->current_vector.id.c_str ()); + + if (!gdbarch_regnum_to_dwarf2_reg_p (data->preliminary_gdbarch)) + gdb_xml_error (parser, + _("Vector \"%s\": architecture %s doesn't support vector count based on another register."), + data->current_vector.id.c_str (), + gdbarch_bfd_arch_info (data->preliminary_gdbarch)->printable_name); + } + + ULONGEST regnum = gdb_xml_parse_ulongest (parser, body_text); + if (regnum > INT_MAX) + gdb_xml_error (parser, + _("Vector \"%s\": count expression uses register number %s out of range."), + data->current_vector.id.c_str (), pulongest (regnum)); + + int dwarf_reg = gdbarch_regnum_to_dwarf2_reg (data->preliminary_gdbarch, + regnum); + if (dwarf_reg < 0 || dwarf_reg > 255) + gdb_xml_error (parser, + _("Vector \"%s\": count expression uses register number %s out of range."), + data->current_vector.id.c_str (), pulongest (dwarf_reg)); + + data->current_vector.locexpr.push_back (DW_OP_bregx); + data->current_vector.locexpr.push_back ((gdb_byte) dwarf_reg); + data->current_vector.locexpr.push_back (0); + + data->current_vector.locexpr_str->push_back ("DW_OP_bregx"); + data->current_vector.locexpr_str->push_back (nullptr); + data->current_vector.locexpr_str->push_back (nullptr); + + data->load_early_regnums.insert (regnum); +} + +/* Handle the end of a element and its value. */ + +static void +tdesc_end_cn (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, void *user_data, + const char *body_text) +{ + struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data; + ULONGEST number = gdb_xml_parse_ulongest (parser, body_text); + + /* We only support DW_OP_lit0 to DW_OP_lit31. */ + if (number > 31) + gdb_xml_error (parser, + _ ("Vector \"%s\": count expression uses value %s larger than maximum of 31."), + data->current_vector.id.c_str (), pulongest (number)); + + gdb_byte value = DW_OP_lit0 + number; + data->current_vector.locexpr.push_back (value); + data->current_vector.locexpr_str->push_back (get_DW_OP_name (value)); +} + +/* Handle the end of a element. */ + +static void +tdesc_end_divide (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, void *user_data, + const char *body_text) +{ + struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data; + + data->current_vector.apply_operator = DW_OP_div; + data->current_vector.apply_operator_str = "DW_OP_div"; +} + +/* Handle the end of a element. */ + +static void +tdesc_end_times (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, void *user_data, + const char *body_text) +{ + struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data; + + data->current_vector.apply_operator = DW_OP_mul; + data->current_vector.apply_operator_str = "DW_OP_mul"; } /* The elements and attributes of an XML target description. */ @@ -525,6 +856,43 @@ static const struct gdb_xml_element enum_children[] = { { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } }; +/* MathML allows recursing elements, but we don't have a need for it + yet, so for simplicity we don't. */ +static const struct gdb_xml_element apply_children[] = { + { "ci", nullptr, nullptr, GDB_XML_EF_NONE, nullptr, tdesc_end_ci }, + { "cn", nullptr, nullptr, GDB_XML_EF_OPTIONAL, nullptr, tdesc_end_cn }, + { "divide", nullptr, nullptr, GDB_XML_EF_OPTIONAL, nullptr, + tdesc_end_divide }, + { "times", nullptr, nullptr, GDB_XML_EF_OPTIONAL, nullptr, tdesc_end_times }, + { nullptr, nullptr, nullptr, GDB_XML_EF_NONE, nullptr, nullptr } +}; + +static const struct gdb_xml_element math_children[] = { + { "apply", nullptr, apply_children, GDB_XML_EF_OPTIONAL, nullptr, + tdesc_end_apply }, + { "ci", nullptr, nullptr, GDB_XML_EF_OPTIONAL, nullptr, tdesc_end_ci }, + { "cn", nullptr, nullptr, GDB_XML_EF_OPTIONAL, nullptr, tdesc_end_cn }, + { nullptr, nullptr, nullptr, GDB_XML_EF_NONE, nullptr, nullptr } +}; + +static const struct gdb_xml_element count_children[] = { + { "math", nullptr, math_children, GDB_XML_EF_OPTIONAL, tdesc_start_math, + nullptr }, + { nullptr, nullptr, nullptr, GDB_XML_EF_NONE, nullptr, nullptr } +}; + +static const struct gdb_xml_attribute count_attributes[] = { + { "id", GDB_XML_AF_OPTIONAL, nullptr, nullptr }, + { "idref", GDB_XML_AF_OPTIONAL, nullptr, nullptr }, + { nullptr, GDB_XML_AF_NONE, nullptr, nullptr } +}; + +static const struct gdb_xml_element vector_children[] = { + { "count", count_attributes, count_children, GDB_XML_EF_OPTIONAL, + tdesc_start_count, tdesc_end_count }, + { nullptr, nullptr, nullptr, GDB_XML_EF_NONE, nullptr, nullptr } +}; + static const struct gdb_xml_attribute reg_attributes[] = { { "name", GDB_XML_AF_NONE, NULL, NULL }, { "bitsize", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, @@ -557,7 +925,7 @@ static const struct gdb_xml_attribute enum_attributes[] = { static const struct gdb_xml_attribute vector_attributes[] = { { "id", GDB_XML_AF_NONE, NULL, NULL }, { "type", GDB_XML_AF_NONE, NULL, NULL }, - { "count", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, + { "count", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL }, { NULL, GDB_XML_AF_NONE, NULL, NULL } }; @@ -582,9 +950,10 @@ static const struct gdb_xml_element feature_children[] = { { "enum", enum_attributes, enum_children, GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE, tdesc_start_enum, NULL }, - { "vector", vector_attributes, NULL, - GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE, - tdesc_start_vector, NULL }, + { "vector", vector_attributes, vector_children, + GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE, tdesc_start_vector, + tdesc_end_vector }, + { "architecture", NULL, NULL, GDB_XML_EF_OPTIONAL, NULL, tdesc_end_arch }, { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } }; @@ -602,7 +971,7 @@ static const struct gdb_xml_element target_children[] = { NULL, tdesc_end_compatible }, { "feature", feature_attributes, feature_children, GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE, - tdesc_start_feature, NULL }, + tdesc_start_feature, tdesc_end_feature }, { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } }; @@ -636,7 +1005,6 @@ tdesc_parse_xml (const char *document, xml_fetch_another fetcher) if (it != xml_cache.end ()) return it->second.get (); - memset (&data, 0, sizeof (struct tdesc_parsing_data)); target_desc_up description = allocate_target_description (); data.tdesc = description.get (); diff --git a/gdbserver/Makefile.in b/gdbserver/Makefile.in index 6148ccf9121b..3315a0c95f19 100644 --- a/gdbserver/Makefile.in +++ b/gdbserver/Makefile.in @@ -208,6 +208,7 @@ SFILES = \ $(srcdir)/linux-sparc-low.cc \ $(srcdir)/linux-x86-low.cc \ $(srcdir)/linux-xtensa-low.cc \ + $(srcdir)/locexpr.cc \ $(srcdir)/mem-break.cc \ $(srcdir)/netbsd-aarch64-low.cc \ $(srcdir)/netbsd-amd64-low.cc \ @@ -262,6 +263,7 @@ OBS = \ dll.o \ hostio.o \ inferiors.o \ + locexpr.o \ mem-break.o \ notif.o \ regcache.o \ diff --git a/gdbserver/config.in b/gdbserver/config.in index 65f9ff6e6470..25aefbecae4f 100644 --- a/gdbserver/config.in +++ b/gdbserver/config.in @@ -104,6 +104,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H +/* Define if the target provides DWARF register to regnum mapping. */ +#undef HAVE_DWARF_REG_TO_REGNUM + /* Define to 1 if the system has the type `Elf32_auxv_t'. */ #undef HAVE_ELF32_AUXV_T diff --git a/gdbserver/configure b/gdbserver/configure index 09cb3c5bf434..c310d522ef10 100755 --- a/gdbserver/configure +++ b/gdbserver/configure @@ -14743,6 +14743,12 @@ if $want_ipa ; then fi fi +if test "${srv_dwarf_reg_to_regnum}" = "yes"; then + +$as_echo "#define HAVE_DWARF_REG_TO_REGNUM 1" >>confdefs.h + +fi + diff --git a/gdbserver/configure.ac b/gdbserver/configure.ac index ee0de9decbde..35ec08da06e4 100644 --- a/gdbserver/configure.ac +++ b/gdbserver/configure.ac @@ -441,6 +441,11 @@ if $want_ipa ; then fi fi +if test "${srv_dwarf_reg_to_regnum}" = "yes"; then + AC_DEFINE(HAVE_DWARF_REG_TO_REGNUM, 1, + [Define if the target provides DWARF register to regnum mapping.]) +fi + AC_SUBST(GDBSERVER_DEPFILES) AC_SUBST(GDBSERVER_LIBS) AC_SUBST(srv_xmlbuiltin) diff --git a/gdbserver/locexpr.cc b/gdbserver/locexpr.cc new file mode 100644 index 000000000000..25d614c3a2bb --- /dev/null +++ b/gdbserver/locexpr.cc @@ -0,0 +1,107 @@ +/* Simplified DWARF location expression evaluator for gdbserver. + Copyright (C) 2024 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 "server.h" +#include "leb128.h" +#include "locexpr.h" +#include "regcache.h" +#include "arch/aarch64.h" + +#define DW_OP_lit0 0x30 +#define DW_OP_lit2 0x32 +#define DW_OP_lit4 0x34 +#define DW_OP_lit8 0x38 +#define DW_OP_bregx 0x92 +#define DW_OP_div 0x1b +#define DW_OP_mul 0x1e + +/* See gdbserver/locexpr.h. */ + +long +evaluate_locexpr (const gdb::array_view locexpr, + const struct regcache *regcache) +{ + std::vector stack; + + for (auto it = locexpr.begin (); it != locexpr.end ();) + { + gdb_byte op = *it; + long result; + + it++; + switch (op) + { + case DW_OP_div: + { + long divisor = stack.back (); + stack.pop_back (); + long dividend = stack.back (); + stack.pop_back (); + result = dividend / divisor; + break; + } + case DW_OP_mul: + { + long multiplicand = stack.back (); + stack.pop_back (); + long multiplier = stack.back (); + stack.pop_back (); + result = multiplier * multiplicand; + break; + } + case DW_OP_lit0: + case DW_OP_lit2: + case DW_OP_lit4: + case DW_OP_lit8: + result = op - DW_OP_lit0; + break; + case DW_OP_bregx: + { + uint64_t reg; + int read = read_uleb128_to_uint64 (it, locexpr.end (), ®); + gdb_assert (read != 0); + + it += read; + + int64_t offset; + read = read_sleb128_to_int64 (it, locexpr.end (), &offset); + gdb_assert (read != 0); + + it += read; + + const char *arch = tdesc_architecture_name (regcache->tdesc); + reg = tdesc_dwarf_reg_to_regnum (arch, reg); + gdb_assert (reg != -1); + + register_status reg_status = regcache->get_register_status (reg); + gdb_assert (reg_status == REG_VALID); + regcache->raw_collect (reg, + gdb::make_array_view ((gdb_byte *) &result, + sizeof (result))); + result += offset; + break; + } + default: + gdb_assert_not_reached ("Unsupported locexpr operation: %c\n", op); + } + + stack.push_back (result); + } + + return stack.back (); +} diff --git a/gdbserver/locexpr.h b/gdbserver/locexpr.h new file mode 100644 index 000000000000..7b768058697d --- /dev/null +++ b/gdbserver/locexpr.h @@ -0,0 +1,31 @@ +/* Simplified DWARF location expression evaluator for gdbserver. + Copyright (C) 2024 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 . */ + +#ifndef GDBSERVER_LOCEXPR_H +#define GDBSERVER_LOCEXPR_H + +#include "gdbsupport/array-view.h" +#include "gdbsupport/common-types.h" +#include "regcache.h" + +/* Evaluate the given DWARF LOCEXPR, using REGCACHE to get register values. */ + +long evaluate_locexpr (const gdb::array_view locexpr, + const struct regcache *regcache); + +#endif /* GDBSERVER_LOCEXPR_H */ diff --git a/gdbserver/tdesc.cc b/gdbserver/tdesc.cc index 6f7ebb7c5c76..fbaf756f5050 100644 --- a/gdbserver/tdesc.cc +++ b/gdbserver/tdesc.cc @@ -129,6 +129,9 @@ copy_target_description (struct target_desc *dest, dest->expedite_regs = src->expedite_regs; dest->registers_size = src->registers_size; dest->xmltarget = src->xmltarget; + + if (src->arch) + set_tdesc_architecture (dest, src->arch.get ()); } const struct target_desc * @@ -242,3 +245,18 @@ tdesc_contains_feature (const target_desc *tdesc, const std::string &feature) return false; } + +#ifndef HAVE_DWARF_REG_TO_REGNUM + +/* See gdbsupport/tdesc.h. + + This is a dummy implementation. It's not used if the target description + doesn't have variable-length registers. */ + +int +tdesc_dwarf_reg_to_regnum (const char *arch, int dwarf_reg) +{ + return -1; +} + +#endif /* HAVE_DWARF_REG_TO_REGNUM */ diff --git a/gdbsupport/tdesc.cc b/gdbsupport/tdesc.cc index a99119274f44..05b348fd8077 100644 --- a/gdbsupport/tdesc.cc +++ b/gdbsupport/tdesc.cc @@ -18,6 +18,7 @@ along with this program. If not, see . */ #include "gdbsupport/tdesc.h" +#include "dwarf2.h" tdesc_reg::tdesc_reg (struct tdesc_feature *feature, const std::string &name_, int regnum, int save_restore_, const char *group_, @@ -160,6 +161,21 @@ tdesc_create_vector (struct tdesc_feature *feature, const char *name, /* See gdbsupport/tdesc.h. */ +struct tdesc_type * +tdesc_create_vector (struct tdesc_feature *feature, const char *name, + struct tdesc_type *field_type, + const gdb::array_view locexpr, + std::optional> locexpr_str) +{ + tdesc_type_vector *type = new tdesc_type_vector (name, field_type, locexpr, + locexpr_str); + feature->types.emplace_back (type); + + return type; +} + +/* See gdbsupport/tdesc.h. */ + tdesc_type_with_fields * tdesc_create_struct (struct tdesc_feature *feature, const char *name) { @@ -312,8 +328,113 @@ void print_xml_feature::visit (const tdesc_type_builtin *t) void print_xml_feature::visit (const tdesc_type_vector *t) { - add_line ("", - t->name.c_str (), t->element_type->name.c_str (), t->count); + if (t->locexpr.empty ()) + add_line ("", + t->name.c_str (), t->element_type->name.c_str (), t->count); + else + { + add_line ("", + t->name.c_str (), t->element_type->name.c_str ()); + + if (t->locexpr_idref.has_value ()) + add_line (" ", t->locexpr_idref->c_str ()); + else + { + if (t->locexpr_id.has_value ()) + add_line (" ", t->locexpr_id->c_str ()); + else + add_line (" "); + + add_line (" "); + + std::vector stack; + + /* Convert DWARF location expression to MathML. */ + for (int i = 0; i < t->locexpr.size (); i++) + { + switch (t->locexpr[i]) + { + case DW_OP_bregx: + { + gdb_byte arg1 = t->locexpr[i + 1]; + gdb_byte arg2 = t->locexpr[i + 2]; + gdb_byte dwarf_reg; + + if (arg1 == 0) + dwarf_reg = arg2; + else if (arg2 == 0) + dwarf_reg = arg1; + else + error (_("In a vector count locexpr one of the " + "operands of DW_OP_bregx must be 0.")); + + if (m_arch == nullptr) + error (_("Feature references a register in locexpr but " + "the architecture is unknown.")); + + int regnum = tdesc_dwarf_reg_to_regnum (m_arch, dwarf_reg); + if (regnum == -1) + error (_("Unknown DWARF register %d."), dwarf_reg); + + stack.push_back (string_printf ("%d", regnum)); + + i += 2; + } + break; + case DW_OP_div: + { + std::string divisor = stack.back (); + stack.pop_back (); + std::string dividend = stack.back (); + stack.pop_back (); + + stack.push_back (""); + stack.push_back (" " + divisor); + stack.push_back (" " + dividend); + stack.push_back (" "); + stack.push_back (""); + } + break; + case DW_OP_mul: + { + std::string multiplicand = stack.back (); + stack.pop_back (); + std::string multiplier = stack.back (); + stack.pop_back (); + + stack.push_back (""); + stack.push_back (" " + multiplicand); + stack.push_back (" " + multiplier); + stack.push_back (" "); + stack.push_back (""); + } + break; + default: + { + gdb_byte val = t->locexpr[i]; + + if (val > DW_OP_lit0 && val <= DW_OP_lit31) + stack.push_back (string_printf ("%d", + val - DW_OP_lit0)); + else + error (_ ("Unsupported DWARF operator %d."), val); + } + break; + } + } + + while (!stack.empty ()) + { + add_line (" " + stack.back ()); + stack.pop_back (); + } + + add_line (" "); + add_line (" "); + } + + add_line (""); + } } void print_xml_feature::visit (const tdesc_type_with_fields *t) @@ -405,9 +526,12 @@ void print_xml_feature::visit_pre (const target_desc *e) add_line (""); add_line (""); indent (1); - if (tdesc_architecture_name (e)) - add_line ("%s", - tdesc_architecture_name (e)); + const char *arch = tdesc_architecture_name (e); + if (arch != nullptr) + { + add_line ("%s", arch); + m_arch = arch; + } const char *osabi = tdesc_osabi_name (e); if (osabi != nullptr) diff --git a/gdbsupport/tdesc.h b/gdbsupport/tdesc.h index 7e483486139b..5f20e6ab8627 100644 --- a/gdbsupport/tdesc.h +++ b/gdbsupport/tdesc.h @@ -64,6 +64,11 @@ class tdesc_element virtual void accept (tdesc_element_visitor &v) const = 0; }; +/* Used in vector type element count or register bitsize to indicate that + the corresponding value is given by a DWARF expression. */ + +#define TDESC_REG_VARIABLE_SIZE -1 + /* An individual register from a target description. */ struct tdesc_reg : tdesc_element @@ -242,13 +247,40 @@ struct tdesc_type_vector : tdesc_type element_type (element_type_), count (count_) {} + tdesc_type_vector (const std::string &name, tdesc_type *element_type_, + const gdb::array_view locexpr_, + std::optional> locexpr_str_) + : tdesc_type (name, TDESC_TYPE_VECTOR), element_type (element_type_), + count (TDESC_REG_VARIABLE_SIZE), locexpr (locexpr_.begin (), + locexpr_.end()), + locexpr_str (locexpr_str_) + { + if (locexpr_str.has_value () && locexpr.size () != locexpr_str->size ()) + error (_ ("Vector locexpr and its string representation must have the same size.")); + } + void accept (tdesc_element_visitor &v) const override { v.visit (this); } struct tdesc_type *element_type; + + /* Ignored if LOCEXPR isn't empty. */ int count; + + /* DWARF location expression providing number of elements. */ + gdb::byte_vector locexpr; + + /* Vector with strings to use instead of the corresponding raw bytecode + in C code that creates the vector type. */ + std::optional> locexpr_str; + + /* XML id used to reference this location expression. */ + std::optional locexpr_id; + + /* XML id of location expression to be used for number of elements. */ + std::optional locexpr_idref; }; /* A named type from a target description. */ @@ -368,6 +400,14 @@ struct tdesc_type *tdesc_create_vector (struct tdesc_feature *feature, struct tdesc_type *field_type, int count); +/* Return the created vector tdesc_type named NAME in FEATURE, + with number of elements given by DWARF LOCEXPR. */ +struct tdesc_type * tdesc_create_vector (struct tdesc_feature *feature, + const char *name, + struct tdesc_type *field_type, + const gdb::array_view locexpr, + std::optional> locexpr_str = {}); + /* Return the created struct tdesc_type named NAME in FEATURE. */ tdesc_type_with_fields *tdesc_create_struct (struct tdesc_feature *feature, const char *name); @@ -469,6 +509,13 @@ class print_xml_feature : public tdesc_element_visitor /* The current indentation depth. */ int m_depth; + + /* The current feature's architecture, if any. */ + const char *m_arch = nullptr; }; +/* Convert ARCH's DWARF register number DWARF_REG to GDB's register number. + Returns -1 if ARCH or DWARF_REG are unknown. */ +int tdesc_dwarf_reg_to_regnum (const char *arch, int dwarf_reg); + #endif /* COMMON_TDESC_H */ From patchwork Sat Nov 2 02:56:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840281 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1158778wrb; Fri, 1 Nov 2024 20:00:17 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCUwk8lBPi/Id0UFmmqGDiqoUcwUxm0FOWUod5rx1Qw9vKDRkTGt+xGiMHCpGqmRtEP8e7/6Rw==@linaro.org X-Google-Smtp-Source: AGHT+IFgi8jM9pHolXVZUZuQHHaEChGBCYEfjgf263fePo0KhVqerODGdjD5eaZRFpTOCNeLELt1 X-Received: by 2002:a05:620a:4504:b0:7af:c818:bdd with SMTP id af79cd13be357-7b193f5c275mr3721756485a.53.1730516417185; Fri, 01 Nov 2024 20:00:17 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516417; cv=pass; d=google.com; s=arc-20240605; b=dAKsuJmKSH7Pz65xeuz7T+jZRFTyCShNP9qq8uPqweoaxi5ZlbxHetoCdm9FGEYlMC tdfCaaUWyFcV39aYRqaZvjvwn9utinhj2sfTnImV3r5FvfkUpVPtB940suPH51f6PZyn 06SfFc/IwLwHdQ8Rp0/QebhGCzRpZRYAMzEmcTXLxWinSFXOAXa2deKpQ+xeQQ5IxuEP pSoqFWYJR26vHBmTHDJiPhFenxa49gh3e/3Kq/HmJ+Lp7AKEcCjsJ8AKQGX6xwXTBD+Q jg3G2bItM2NZ6RZBKOezReM82H57za0r49V41mXHj9zm7aIx6Wg1M58O+OIIbqrUOrs1 Gv9g== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=TjpzGrnsL13WQqOD4TM0r4eNciZz8ObLqi+8sGv2Dyw=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=L5CxroFgSGCYeKtpf9JxkCfNLqEXuW4or4YOOCfAdswr/yaxGOd6apSwDryUIX2XjN Uu2qPJ1nUs5HiWZvxFW7oZNHpBu7Elkwc8VIN93oB1AyF1clmqubFiYPqXt8N3HzHAGR FnJrNk4wEoSqxyxDffZZ+cgRL5I0/Q08K4Jox7QeUza8kmfJKvCHKOemoeIzrSZyNfkr voT4PTwmrRMkSzO7RukQcHmlPpDbPs60ayEa/1ZWwEQEfIwkmsHP7ebtlsB6GbjigMN/ Lu7I0BdL41UW7sFimRYE7q8I3dZHo0/RMgR+nCxQ6wvfgQuIxZayOemrtQVubSLOew0K bl7A==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="Co/6hSVz"; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id af79cd13be357-7b2f3a811f8si587697985a.320.2024.11.01.20.00.15 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 20:00:17 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="Co/6hSVz"; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5F9993857C5D for ; Sat, 2 Nov 2024 03:00:15 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pg1-x532.google.com (mail-pg1-x532.google.com [IPv6:2607:f8b0:4864:20::532]) by sourceware.org (Postfix) with ESMTPS id 394703857C68 for ; Sat, 2 Nov 2024 02:57:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 394703857C68 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 394703857C68 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::532 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516238; cv=none; b=r/sevi9juIIoKEzrnZaRRJ43N5uiqkZQckh2dJWN+XIK72MHF7vVCacKVZY9gHOdF63zvsnUGGKLDCqb784v8e1mmv2sN5Z/0IG+bS9ps74XfZSe3XKleJCOKdjeSBhr+x42jNsaD4ABQWo0wHPLx2/WTkMoiRZhAjLWC6AiYK4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516238; c=relaxed/simple; bh=QRyiiwAfnrp3RXmn9bNNjY/up8oxDSwToSUC3yoyYvM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=DTWXRoqAUIL0BFNdJ5qsX6sNsra2tFKUkzMVQvuqapk9PWfo+oANyepFxGwH0nor4zINbjdhRo2gKdnf+SY1L4jnDJKvk9pYynmlsQZXj8f26pLUf5U6GwEJTnYqdoh28ZaD59JBOLgogTRlKo6kgEtAe8U6v6G1szQR+YJtgtU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pg1-x532.google.com with SMTP id 41be03b00d2f7-7eab7622b61so2021567a12.1 for ; Fri, 01 Nov 2024 19:57:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516231; x=1731121031; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=TjpzGrnsL13WQqOD4TM0r4eNciZz8ObLqi+8sGv2Dyw=; b=Co/6hSVz2mY5IhrGDhhSpRwbnRLAH9E0XPzJxvhlAFuYMrwvKeimPKgGowNCvoGghu 0faQqbeg/M2ytjrGhOxC1it+y+JIwrXezwKVM226iYIDhQ1j6WZK+XhvZMs6YMw231Ki cxeUNA3YK7KBYu1B7gTGKkp4WncNT2nBvNL5uEJVlnC8zoZ+5PzNZjdy11Tg+Z56rqJC 0PLcswTtljI4cafgJeqYyBn1Qd89Aa8KAbfOYzJHmZhKUYIgm85vEQCXla1jDQNf+KD9 oKzvpF5ohgf2P0GOhUNxdjngla/IwqSIrkxBy1MBeLxdY1GfoOPNjz5vEMsPLJFetDjV ZYKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516231; x=1731121031; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=TjpzGrnsL13WQqOD4TM0r4eNciZz8ObLqi+8sGv2Dyw=; b=qRP8PX01Yu6rhkplrvQR/9HU9ovTROAK3/dRjSaaMoGwcoNhk5Hk90oMNMoY8eVEL7 VhbDbJhsy6sSskICjKlbgNLqmvy4OKxiE1SHAoZyuaLc5sWkf2qEGgzIAmf97aebRmNS us9TWt/PULQEaYlc+WTzAzH4tE3wzaWYThRcqiZV0hHAjWolUfxyXKtcMVebAVzEyit/ /JjACBP2EeQLK18bpv/r8qnpVIfq6nn5XYaNmGIw1GE4t+KUkOqXqsqnTm4bPY3qTcqG VRcPy+TkDVR3bAhTObOFNe3HoT1m7UpXIjlfEsLxTwqUN0qfJF41C7FCXtVPw3G1901k z9Kg== X-Gm-Message-State: AOJu0YwjNo9tTOd4n4N01QgBsQKw/58kXQQ/3JYoXzaZEWAoCJrxa7pY o353W6Wq68u/Igmt5Ziy36Jk3xMitDF+7E1dBn7Qb+Tmb+H6z86S1+NmVMOXAPjSblSJujYfoIU W X-Received: by 2002:a05:6a21:1796:b0:1d8:a1dc:b43 with SMTP id adf61e73a8af0-1d9a8402d85mr35656025637.24.1730516230658; Fri, 01 Nov 2024 19:57:10 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-720bc31874bsm3353844b3a.213.2024.11.01.19.57.09 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:57:10 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 10/15] GDB: Add concept of variable-size registers to the regcache Date: Fri, 1 Nov 2024 23:56:30 -0300 Message-ID: <20241102025635.586759-11-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org The contents of variable-size registers are placed in a separate buffer, because their size will only be known a while after the buffer is created but some fixed-size registers (particularly the program counter) need to be stored or fetched before then. This is also why the state related to variable-size registers is lazily initialised at the moment it's first needed (by calling the initialize_variable_size_registers () method). Simon suggested placing the variable-size registers at the end of the existing contents buffer to avoid having to use a separate one. I will experiment with that idea and see if it simplifies the code. The regcache now also stores the resolved type and size of the variable-size registers. Some places needed to be changed from calling the register_size () function to calling the register_size () method instead, because they may call them for variable-size registers. The frame-unwinding code doesn't have a regcache readily available, so the register_size () function is changed to optionally accept a frame_info_ptr which it uses to create a readonly_detached_regcache. When debugging a remote target, if the regcache has variable-size registers the maximum packet size may change with new values of expedited registers. Therefore, update the maximum packet size when expedited registers are supplied, or load-early registers are fetched. Finally, there are FIXMEs related to the const_casts needed to remove the const from the "this" pointer when calling reg_buffer::initialize_variable_size_registers (). I'm still thinking about what to do with them. I tried the simple solution of changing the calling methods to be non-const, but the change escalates quickly. --- gdb/aarch64-tdep.c | 9 +- gdb/eval.c | 13 ++- gdb/findvar.c | 5 +- gdb/frame.c | 45 +++++--- gdb/record-full.c | 3 +- gdb/regcache.c | 269 +++++++++++++++++++++++++++++++++++++-------- gdb/regcache.h | 39 ++++++- gdb/remote.c | 62 +++++++++-- gdb/value.c | 16 ++- gdbsupport/tdesc.h | 4 +- 10 files changed, 377 insertions(+), 88 deletions(-) diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 8a2a9b1e23c1..04442f22ea3f 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -1728,7 +1728,7 @@ pass_in_v (struct gdbarch *gdbarch, { int regnum = AARCH64_V0_REGNUM + info->nsrn; /* Enough space for a full vector register. */ - gdb::byte_vector reg (register_size (gdbarch, regnum), 0); + gdb::byte_vector reg (regcache->register_size (regnum), 0); gdb_assert (len <= reg.size ()); info->argnum++; @@ -2543,7 +2543,7 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs, { int regno = AARCH64_V0_REGNUM + i; /* Enough space for a full vector register. */ - gdb::byte_vector buf (register_size (gdbarch, regno)); + gdb::byte_vector buf (regs->register_size (regno)); gdb_assert (len <= buf.size ()); aarch64_debug_printf @@ -2657,7 +2657,7 @@ aarch64_store_return_value (struct type *type, struct regcache *regs, { int regno = AARCH64_V0_REGNUM + i; /* Enough space for a full vector register. */ - gdb::byte_vector tmpbuf (register_size (gdbarch, regno)); + gdb::byte_vector tmpbuf (regs->register_size (regno)); gdb_assert (len <= tmpbuf.size ()); aarch64_debug_printf @@ -3308,7 +3308,8 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, const frame_info_ptr &next_frame, various 'scalar' pseudo registers to behavior like architectural writes, register width bytes are written the remainder are set to zero. */ - gdb::byte_vector raw_buf (register_size (gdbarch, raw_regnum), 0); + int raw_reg_size = register_size (gdbarch, raw_regnum, &next_frame); + gdb::byte_vector raw_buf (raw_reg_size, 0); static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM); gdb::array_view raw_view (raw_buf); diff --git a/gdb/eval.c b/gdb/eval.c index 457a4362289d..9f20ec557db3 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -1151,13 +1151,14 @@ eval_op_register (struct type *expect_type, struct expression *exp, if (regno == -1) error (_("Register $%s not available."), name); - /* In EVAL_AVOID_SIDE_EFFECTS mode, we only need to return - a value with the appropriate register type. Unfortunately, - we don't have easy access to the type of user registers. - So for these registers, we fetch the register value regardless - of the evaluation mode. */ + /* In EVAL_AVOID_SIDE_EFFECTS mode, we only need to return a value with + the appropriate register type. Unfortunately, we don't have easy + access to the type of user registers and variable-size registers. So + for these registers, we fetch the register value regardless of the + evaluation mode. */ if (noside == EVAL_AVOID_SIDE_EFFECTS - && regno < gdbarch_num_cooked_regs (exp->gdbarch)) + && regno < gdbarch_num_cooked_regs (exp->gdbarch) + && !register_is_variable_size (exp->gdbarch, regno)) val = value::zero (register_type (exp->gdbarch, regno), not_lval); else val = value_of_register diff --git a/gdb/findvar.c b/gdb/findvar.c index d65bf2fc278c..1ecfd3558383 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -562,11 +562,12 @@ read_frame_register_value (value *value) LONGEST reg_offset = value->offset (); int regnum = value->regnum (); int len = type_length_units (check_typedef (value->type ())); + int reg_size = register_size (gdbarch, regnum, &next_frame); /* Skip registers wholly inside of REG_OFFSET. */ - while (reg_offset >= register_size (gdbarch, regnum)) + while (reg_offset >= reg_size) { - reg_offset -= register_size (gdbarch, regnum); + reg_offset -= reg_size; regnum++; } diff --git a/gdb/frame.c b/gdb/frame.c index 663ff7fa773b..0f480ce75b09 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1322,12 +1322,24 @@ frame_unwind_register_value (const frame_info_ptr &next_frame, int regnum) gdb_printf (&debug_file, " lazy"); else if (value->entirely_available ()) { - int i; + int i, reg_size; gdb::array_view buf = value->contents (); gdb_printf (&debug_file, " bytes="); gdb_printf (&debug_file, "["); - for (i = 0; i < register_size (gdbarch, regnum); i++) + + if (register_is_variable_size (gdbarch, regnum)) + /* To get the size of a variable-size register, we need to + call frame_save_as_regcache () so that we can call + regcache::register_size (). Unfortunatlly the former + ends up calling this function so we enter into an + infinite recursion. So just assume that the value has + the correct size. */ + reg_size = buf.size (); + else + reg_size = register_size (gdbarch, regnum); + + for (i = 0; i < reg_size; i++) gdb_printf (&debug_file, "%02x", buf[i]); gdb_printf (&debug_file, "]"); } @@ -1446,7 +1458,7 @@ put_frame_register (const frame_info_ptr &next_frame, int regnum, int unavail; enum lval_type lval; CORE_ADDR addr; - int size = register_size (gdbarch, regnum); + int size = register_size (gdbarch, regnum, &next_frame); gdb_assert (buf.size () == size); @@ -1462,8 +1474,9 @@ put_frame_register (const frame_info_ptr &next_frame, int regnum, break; } case lval_register: - /* Not sure if that's always true... but we have a problem if not. */ - gdb_assert (size == register_size (gdbarch, realnum)); + if (regnum != realnum) + /* 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)) @@ -1509,9 +1522,9 @@ get_frame_register_bytes (const frame_info_ptr &next_frame, int regnum, gdbarch *gdbarch = frame_unwind_arch (next_frame); /* Skip registers wholly inside of OFFSET. */ - while (offset >= register_size (gdbarch, regnum)) + while (offset >= register_size (gdbarch, regnum, &next_frame)) { - offset -= register_size (gdbarch, regnum); + offset -= register_size (gdbarch, regnum, &next_frame); regnum++; } @@ -1521,7 +1534,7 @@ get_frame_register_bytes (const frame_info_ptr &next_frame, int regnum, int numregs = gdbarch_num_cooked_regs (gdbarch); for (int i = regnum; i < numregs; i++) { - int thissize = register_size (gdbarch, i); + int thissize = register_size (gdbarch, i, &next_frame); if (thissize == 0) break; /* This register is not available on this architecture. */ @@ -1535,10 +1548,10 @@ get_frame_register_bytes (const frame_info_ptr &next_frame, int regnum, /* Copy the data. */ while (!buffer.empty ()) { - int curr_len = std::min (register_size (gdbarch, regnum) - offset, - buffer.size ()); + int reg_size = register_size (gdbarch, regnum, &next_frame); + int curr_len = std::min (reg_size - offset, buffer.size ()); - if (curr_len == register_size (gdbarch, regnum)) + if (curr_len == reg_size) { enum lval_type lval; CORE_ADDR addr; @@ -1586,19 +1599,19 @@ put_frame_register_bytes (const frame_info_ptr &next_frame, int regnum, gdbarch *gdbarch = frame_unwind_arch (next_frame); /* Skip registers wholly inside of OFFSET. */ - while (offset >= register_size (gdbarch, regnum)) + while (offset >= register_size (gdbarch, regnum, &next_frame)) { - offset -= register_size (gdbarch, regnum); + offset -= register_size (gdbarch, regnum, &next_frame); regnum++; } /* Copy the data. */ while (!buffer.empty ()) { - int curr_len = std::min (register_size (gdbarch, regnum) - offset, - buffer.size ()); + int reg_size = register_size (gdbarch, regnum, &next_frame); + int curr_len = std::min (reg_size - offset, buffer.size ()); - if (curr_len == register_size (gdbarch, regnum)) + if (curr_len == reg_size) put_frame_register (next_frame, regnum, buffer.slice (0, curr_len)); else { diff --git a/gdb/record-full.c b/gdb/record-full.c index 8e4915abd083..0ce370ae32bf 100644 --- a/gdb/record-full.c +++ b/gdb/record-full.c @@ -399,12 +399,11 @@ static inline struct record_full_entry * record_full_reg_alloc (struct regcache *regcache, int regnum) { struct record_full_entry *rec; - struct gdbarch *gdbarch = regcache->arch (); rec = XCNEW (struct record_full_entry); rec->type = record_full_reg; rec->u.reg.num = regnum; - rec->u.reg.len = register_size (gdbarch, regnum); + rec->u.reg.len = regcache->register_size (regnum); if (rec->u.reg.len > sizeof (rec->u.reg.u.buf)) rec->u.reg.u.ptr = (gdb_byte *) xmalloc (rec->u.reg.len); diff --git a/gdb/regcache.c b/gdb/regcache.c index 61289d46f4b1..dfcfffb02aa0 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -51,7 +51,7 @@ struct regcache_descr redundant information - if the PC is constructed from two registers then those registers and not the PC lives in the raw cache. */ - long sizeof_raw_registers = 0; + long sizeof_fixed_size_raw_registers = 0; /* The cooked register space. Each cooked register in the range [0..NR_RAW_REGISTERS) is direct-mapped onto the corresponding raw @@ -60,7 +60,7 @@ struct regcache_descr both raw registers and memory by the architecture methods gdbarch_pseudo_register_read and gdbarch_pseudo_register_write. */ int nr_cooked_registers = 0; - long sizeof_cooked_registers = 0; + long sizeof_fixed_size_cooked_registers = 0; /* Offset and size (in 8 bit bytes), of each register in the register cache. All registers (including those in the range @@ -69,9 +69,16 @@ struct regcache_descr long *register_offset = nullptr; long *sizeof_register = nullptr; - /* Registers that need to be loaded early in the register cache. */ + /* Registers that need to be loaded early in the register cache, because + variable-size registers depend on them to calculate their size. */ std::set load_early_regs; + /* Vector indicating whether a given register is variable-size. */ + bool *register_is_variable_size = nullptr; + + /* Does the regcache contains any variable-size register? */ + bool has_variable_size_registers = false; + /* Cached table containing the type of each register. */ struct type **register_type = nullptr; }; @@ -119,26 +126,52 @@ init_regcache_descr (struct gdbarch *gdbarch) = GDBARCH_OBSTACK_CALLOC (gdbarch, descr->nr_cooked_registers, long); descr->register_offset = GDBARCH_OBSTACK_CALLOC (gdbarch, descr->nr_cooked_registers, long); + descr->register_is_variable_size + = GDBARCH_OBSTACK_CALLOC (gdbarch, descr->nr_cooked_registers, bool); + for (i = 0; i < gdbarch_num_regs (gdbarch); i++) { - descr->sizeof_register[i] = descr->register_type[i]->length (); - descr->register_offset[i] = offset; - offset += descr->sizeof_register[i]; + descr->register_is_variable_size[i] + = is_dynamic_type (descr->register_type[i]); + if (descr->register_is_variable_size[i]) + { + descr->sizeof_register[i] = -1; + descr->register_offset[i] = -1; + descr->has_variable_size_registers = true; + } + else + { + descr->sizeof_register[i] = descr->register_type[i]->length (); + descr->register_offset[i] = offset; + offset += descr->sizeof_register[i]; + } if (tdesc_register_is_early_load (gdbarch, i)) descr->load_early_regs.insert (i); } + /* Set the real size of the raw register cache buffer. */ - descr->sizeof_raw_registers = offset; + descr->sizeof_fixed_size_raw_registers = offset; for (; i < descr->nr_cooked_registers; i++) { - descr->sizeof_register[i] = descr->register_type[i]->length (); - descr->register_offset[i] = offset; - offset += descr->sizeof_register[i]; + descr->register_is_variable_size[i] + = is_dynamic_type (descr->register_type[i]); + if (descr->register_is_variable_size[i]) + { + descr->sizeof_register[i] = -1; + descr->register_offset[i] = -1; + descr->has_variable_size_registers = true; + } + else + { + descr->sizeof_register[i] = descr->register_type[i]->length (); + descr->register_offset[i] = offset; + offset += descr->sizeof_register[i]; + } } /* Set the real size of the readonly register cache buffer. */ - descr->sizeof_cooked_registers = offset; + descr->sizeof_fixed_size_cooked_registers = offset; } return descr; @@ -160,27 +193,60 @@ regcache_descr (struct gdbarch *gdbarch) /* Utility functions returning useful register attributes stored in the regcache descr. */ +/* See gdb/regcache.h. */ + struct type * register_type (struct gdbarch *gdbarch, int regnum) { struct regcache_descr *descr = regcache_descr (gdbarch); gdb_assert (regnum >= 0 && regnum < descr->nr_cooked_registers); - return descr->register_type[regnum]; + + struct type *type = descr->register_type[regnum]; + + if (descr->register_is_variable_size[regnum]) + { + frame_info_ptr current_frame = get_current_frame (); + type = resolve_dynamic_type (type, {}, 0, ¤t_frame); + } + + return type; } -/* Utility functions returning useful register attributes stored in - the regcache descr. */ +/* See gdb/regcache.h. */ int -register_size (struct gdbarch *gdbarch, int regnum) +register_size (struct gdbarch *gdbarch, int regnum, + const frame_info_ptr *next_frame) { struct regcache_descr *descr = regcache_descr (gdbarch); - int size; - gdb_assert (regnum >= 0 && regnum < gdbarch_num_cooked_regs (gdbarch)); - size = descr->sizeof_register[regnum]; - return size; + gdb_assert (regnum >= 0); + gdb_assert (regnum < descr->nr_cooked_registers); + + if (descr->register_is_variable_size[regnum]) + { + gdb_assert (next_frame != nullptr); + + std::unique_ptr regcache = + frame_save_as_regcache (get_prev_frame (*next_frame)); + return regcache->register_size (regnum); + } + + return descr->sizeof_register[regnum]; +} + +/* See gdb/regcache.h. */ + +bool +register_is_variable_size (struct gdbarch *gdbarch, int regnum) +{ + struct regcache_descr *descr = regcache_descr (gdbarch); + + gdb_assert (regnum >= 0); + gdb_assert (regnum < descr->nr_cooked_registers); + + return descr->register_is_variable_size[regnum]; } /* See gdbsupport/common-regcache.h. */ @@ -188,7 +254,47 @@ register_size (struct gdbarch *gdbarch, int regnum) int reg_buffer::register_size (int regnum) const { - return ::register_size (this->arch (), regnum); + gdb_assert (regnum >= 0); + gdb_assert (regnum < m_descr->nr_cooked_registers); + + int size; + + if (m_descr->register_is_variable_size[regnum]) + { + if (!m_variable_size_registers) + const_cast (this) + ->initialize_variable_size_registers (); // FIXME: Remove cast. + + size = m_variable_size_register_sizeof[regnum]; + } + else + size = m_descr->sizeof_register[regnum]; + + return size; +} + +/* See gdb/regcache.h. */ + +struct type * +reg_buffer::register_type (int regnum) const +{ + gdb_assert (regnum >= 0); + gdb_assert (regnum < m_descr->nr_cooked_registers); + + struct type *type; + + if (m_descr->register_is_variable_size[regnum]) + { + if (!m_variable_size_registers) + const_cast (this) + ->initialize_variable_size_registers (); // FIXME: Remove cast. + + type = m_variable_size_register_type[regnum]; + } + else + type = m_descr->register_type[regnum]; + + return type; } reg_buffer::reg_buffer (gdbarch *gdbarch, bool has_pseudo) @@ -202,13 +308,13 @@ reg_buffer::reg_buffer (gdbarch *gdbarch, bool has_pseudo) REG_VALID. */ if (has_pseudo) { - m_registers.reset (new gdb_byte[m_descr->sizeof_cooked_registers]); + m_fixed_size_registers.reset (new gdb_byte[m_descr->sizeof_fixed_size_cooked_registers]); m_register_status.reset (new register_status[m_descr->nr_cooked_registers] ()); } else { - m_registers.reset (new gdb_byte[m_descr->sizeof_raw_registers]); + m_fixed_size_registers.reset (new gdb_byte[m_descr->sizeof_fixed_size_raw_registers]); m_register_status.reset (new register_status[gdbarch_num_regs (gdbarch)] ()); } @@ -237,9 +343,6 @@ reg_buffer::arch () const return m_descr->gdbarch; } -/* Utility functions returning useful register attributes stored in - the regcache descr. */ - /* See regcache.h. */ bool @@ -281,6 +384,55 @@ reg_buffer::load_early_registers () return m_descr->load_early_regs; } +/* See regcache.h. */ + +void +reg_buffer::initialize_variable_size_registers () +{ + unsigned long total_size = 0; + + /* We need load early registers to resolve types of variable-size + registers. */ + if (!this->fetch_load_early_registers ()) + error (_("Missing register contents for variable-size registers.")); + + m_variable_size_register_type.resize (m_descr->nr_cooked_registers); + m_variable_size_register_sizeof.resize (m_descr->nr_cooked_registers); + m_variable_size_register_offset.resize (m_descr->nr_cooked_registers); + + for (unsigned int i = 0; i < m_descr->nr_cooked_registers; i++) + { + if (!m_descr->register_is_variable_size[i]) + { + m_variable_size_register_type[i] = nullptr; + m_variable_size_register_sizeof[i] = -1; + m_variable_size_register_offset[i] = -1; + continue; + } + + m_variable_size_register_type[i] + = resolve_dynamic_type (m_descr->register_type[i], {}, + /* Unused address. */ 0, nullptr, this); + + ULONGEST size = m_variable_size_register_type[i]->length (); + gdb_assert (size != 0); + m_variable_size_register_sizeof[i] = size; + m_variable_size_register_offset[i] = total_size; + m_register_status[i] = REG_UNKNOWN; + total_size += size; + } + + m_variable_size_registers.reset (new gdb_byte[total_size]); +} + +/* See regcache.h. */ + +bool +reg_buffer::has_variable_size_registers () +{ + return m_descr->has_variable_size_registers; +} + /* Helper for reg_buffer::register_buffer. */ template @@ -288,8 +440,19 @@ gdb::array_view reg_buffer::register_buffer (int regnum) const { assert_regnum (regnum); - ElemType *start = &m_registers[m_descr->register_offset[regnum]]; - int size = m_descr->sizeof_register[regnum]; + ElemType *start; + + if (m_descr->register_is_variable_size[regnum]) + { + if (!m_variable_size_registers) + const_cast(this)->initialize_variable_size_registers (); // FIXME: Remove cast. + + start = &m_variable_size_registers[m_variable_size_register_offset[regnum]]; + } + else + start = &m_fixed_size_registers[m_descr->register_offset[regnum]]; + + int size = register_size (regnum); return gdb::array_view (start, size); } @@ -317,9 +480,14 @@ reg_buffer::save (register_read_ftype cooked_read) /* It should have pseudo registers. */ gdb_assert (m_has_pseudo); /* Clear the dest. */ - memset (m_registers.get (), 0, m_descr->sizeof_cooked_registers); + memset (m_fixed_size_registers.get (), 0, m_descr->sizeof_fixed_size_cooked_registers); memset (m_register_status.get (), REG_UNKNOWN, m_descr->nr_cooked_registers); + /* For data related to variable-size registers, we only need to reset + their buffer at this point. Other data will be resized/re-set by + initialize_variable_size_registers (). */ + m_variable_size_registers.reset (); + /* Save load early registers first. */ for (int regnum : m_descr->load_early_regs) { @@ -379,6 +547,12 @@ regcache::restore (readonly_detached_regcache *src) continue; cooked_write (regnum, src->register_buffer (regnum)); + + if (m_variable_size_registers) + /* For data related to variable-size registers, we only need to reset + their buffer at this point. Other data will be resized/re-set by + initialize_variable_size_registers (). */ + m_variable_size_registers.reset (); } /* Copy over any registers, being careful to only restore those that @@ -709,7 +883,7 @@ register_status readable_regcache::raw_read (int regnum, gdb::array_view dst) { assert_regnum (regnum); - gdb_assert (dst.size () == m_descr->sizeof_register[regnum]); + gdb_assert (dst.size () == register_size (regnum)); raw_update (regnum); @@ -725,7 +899,7 @@ register_status readable_regcache::raw_read (int regnum, gdb_byte *dst) { assert_regnum (regnum); - int size = m_descr->sizeof_register[regnum]; + int size = register_size (regnum); return raw_read (regnum, gdb::make_array_view (dst, size)); } @@ -741,7 +915,7 @@ enum register_status readable_regcache::raw_read (int regnum, T *val) { assert_regnum (regnum); - size_t size = m_descr->sizeof_register[regnum]; + size_t size = register_size (regnum); gdb_byte *buf = (gdb_byte *) alloca (size); auto view = gdb::make_array_view (buf, size); register_status status = raw_read (regnum, view); @@ -776,7 +950,7 @@ regcache::raw_write (int regnum, T val) { assert_regnum (regnum); - int size = m_descr->sizeof_register[regnum]; + int size = register_size (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); @@ -815,7 +989,7 @@ readable_regcache::cooked_read (int regnum, gdb::array_view dst) if (regnum < num_raw_registers ()) return raw_read (regnum, dst); - gdb_assert (dst.size () == m_descr->sizeof_register[regnum]); + gdb_assert (dst.size () == register_size (regnum)); if (m_has_pseudo && m_register_status[regnum] != REG_UNKNOWN) { @@ -857,7 +1031,7 @@ 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]; + int size = register_size (regnum); return cooked_read (regnum, gdb::make_array_view (dst, size)); } @@ -871,8 +1045,12 @@ 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)) { + /* Provide the register type if its size is fixed to avoid infinite + recursion in the case of variable-size registers. */ + struct type *type = (m_descr->register_is_variable_size[regnum] ? + nullptr : m_descr->register_type[regnum]); value *result = value::allocate_register - (get_next_frame_sentinel_okay (get_current_frame ()), regnum); + (get_next_frame_sentinel_okay (get_current_frame ()), regnum, type); /* It is more efficient in general to do this delegation in this direction than in the other one, even though the value-based @@ -902,7 +1080,7 @@ enum register_status readable_regcache::cooked_read (int regnum, T *val) { gdb_assert (regnum >= 0 && regnum < m_descr->nr_cooked_registers); - size_t size = m_descr->sizeof_register[regnum]; + size_t size = register_size (regnum); gdb_byte *buf = (gdb_byte *) alloca (size); auto view = gdb::make_array_view (buf, size); register_status status = cooked_read (regnum, view); @@ -936,7 +1114,7 @@ regcache::cooked_write (int regnum, T val) gdb_assert (regnum >= 0); gdb_assert (regnum < m_descr->nr_cooked_registers); - int size = m_descr->sizeof_register[regnum]; + int size = register_size (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); @@ -955,7 +1133,7 @@ void regcache::raw_write (int regnum, gdb::array_view src) { assert_regnum (regnum); - gdb_assert (src.size () == m_descr->sizeof_register[regnum]); + gdb_assert (src.size () == register_size (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. */ @@ -992,7 +1170,7 @@ regcache::raw_write (int regnum, const gdb_byte *src) { assert_regnum (regnum); - int size = m_descr->sizeof_register[regnum]; + int size = register_size (regnum); raw_write (regnum, gdb::make_array_view (src, size)); } @@ -1023,7 +1201,7 @@ 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]; + int size = register_size (regnum); return cooked_write (regnum, gdb::make_array_view (src, size)); } @@ -1235,6 +1413,11 @@ reg_buffer::raw_supply (int regnum, gdb::array_view src) { copy (src, dst); m_register_status[regnum] = REG_VALID; + + if (this->is_load_early_register (regnum) + && memcmp (src.data (), dst.data (), dst.size ())) + /* Invalidate variable-size registers. */ + this->initialize_variable_size_registers (); } else { @@ -1253,7 +1436,7 @@ reg_buffer::raw_supply (int regnum, const void *src) { assert_regnum (regnum); - int size = m_descr->sizeof_register[regnum]; + int size = register_size (regnum); raw_supply (regnum, gdb::make_array_view ((const gdb_byte *) src, size)); } @@ -1297,7 +1480,7 @@ reg_buffer::raw_collect (int regnum, void *dst) const { assert_regnum (regnum); - int size = m_descr->sizeof_register[regnum]; + int size = register_size (regnum); return raw_collect (regnum, gdb::make_array_view ((gdb_byte *) dst, size)); } @@ -1372,7 +1555,7 @@ regcache::transfer_regset (const struct regset *regset, int regbase, regno += regbase; if (slot_size == 0 && regno != REGCACHE_MAP_SKIP) - slot_size = m_descr->sizeof_register[regno]; + slot_size = register_size (regnum); if (regno == REGCACHE_MAP_SKIP || (regnum != -1 diff --git a/gdb/regcache.h b/gdb/regcache.h index 5c28fec4af11..6b6687b9f349 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -165,10 +165,15 @@ extern bool regcache_map_supplies (const struct regcache_map_entry *map, extern struct type *register_type (struct gdbarch *gdbarch, int regnum); -/* Return the size of register REGNUM. All registers should have only - one size. */ +/* Return the size of register REGNUM. FRAME is needed in case regnum is a + variable-size register. */ -extern int register_size (struct gdbarch *gdbarch, int regnum); +extern int register_size (struct gdbarch *gdbarch, int regnum, + const frame_info_ptr *next_frame = nullptr); + +/* Return whether REGNUM is a variable-size register. */ + +extern bool register_is_variable_size (struct gdbarch *gdbarch, int regnum); using register_read_ftype = gdb::function_view)>; @@ -266,6 +271,12 @@ class reg_buffer : public reg_buffer_common /* Return set of regnums which need to be loaded before other registers. */ const std::set &load_early_registers (); + /* Whether any register in this regcache has a dynamic type. */ + bool has_variable_size_registers (); + + /* Return type of register REGNUM. */ + struct type *register_type (int regnum) const; + /* See gdbsupport/common-regcache.h. */ int register_size (int regnum) const override; @@ -279,6 +290,10 @@ class reg_buffer : public reg_buffer_common Return false if they aren't. */ virtual bool fetch_load_early_registers (); + /* Initialize (or reset) information about variable-size registers in this + reg_buffer. */ + void initialize_variable_size_registers (); + /* Return a view on register REGNUM's buffer cache. */ template gdb::array_view register_buffer (int regnum) const; @@ -293,11 +308,25 @@ class reg_buffer : public reg_buffer_common struct regcache_descr *m_descr; bool m_has_pseudo; - /* The register buffers. */ - std::unique_ptr m_registers; + + /* The fixed-size register buffers. */ + std::unique_ptr m_fixed_size_registers; + + /* The variable-size register buffers (if any). */ + std::unique_ptr m_variable_size_registers; + /* Register cache status. */ std::unique_ptr m_register_status; + /* The resolved types for variable-size registers (if any). */ + std::vector m_variable_size_register_type; + + /* The size of resolved types for variable-size registers (if any). */ + std::vector m_variable_size_register_sizeof; + + /* The offset of resolved types for variable-size registers (if any). */ + std::vector m_variable_size_register_offset; + friend class regcache; friend class detached_regcache; }; diff --git a/gdb/remote.c b/gdb/remote.c index 0217c05bce52..0930977d4304 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -471,6 +471,8 @@ struct packet_reg at present. */ }; +struct remote_state; + struct remote_arch_state { explicit remote_arch_state (struct gdbarch *gdbarch); @@ -493,6 +495,10 @@ struct remote_arch_state /* This is the maximum size (in chars) of a non read/write packet. It is also used as a cap on the size of read/write packets. */ long remote_packet_size; + + /* Make sure the maximum packet size reflects current size of variable-size + registers. */ + void update_packet_size (const struct regcache *regcache, remote_state *rs); }; /* Description of the remote protocol state for the currently @@ -1897,7 +1903,8 @@ show_remote_exec_file (struct ui_file *file, int from_tty, } static int -map_regcache_remote_table (struct gdbarch *gdbarch, struct packet_reg *regs) +map_regcache_remote_table (struct gdbarch *gdbarch, struct packet_reg *regs, + const struct regcache *regcache = nullptr) { int regnum, num_remote_regs, offset; struct packet_reg **remote_regs; @@ -1905,8 +1912,15 @@ map_regcache_remote_table (struct gdbarch *gdbarch, struct packet_reg *regs) for (regnum = 0; regnum < gdbarch_num_regs (gdbarch); regnum++) { struct packet_reg *r = ®s[regnum]; + bool skip_register; - if (register_size (gdbarch, regnum) == 0) + if (regcache == nullptr) + skip_register = (register_is_variable_size (gdbarch, regnum) + || register_size (gdbarch, regnum) == 0); + else + skip_register = regcache->register_size (regnum) == 0; + + if (skip_register) /* Do not try to fetch zero-sized (placeholder) registers. */ r->pnum = -1; else @@ -1934,7 +1948,10 @@ map_regcache_remote_table (struct gdbarch *gdbarch, struct packet_reg *regs) { remote_regs[regnum]->in_g_packet = 1; remote_regs[regnum]->offset = offset; - offset += register_size (gdbarch, remote_regs[regnum]->regnum); + if (regcache == nullptr) + offset += register_size (gdbarch, remote_regs[regnum]->regnum); + else + offset += regcache->register_size (remote_regs[regnum]->regnum); } return offset; @@ -1995,6 +2012,29 @@ remote_arch_state::remote_arch_state (struct gdbarch *gdbarch) this->remote_packet_size = (this->sizeof_g_packet * 2 + 32); } +/* See remote_arch_state class declaration. */ + +void +remote_arch_state::update_packet_size (const struct regcache *regcache, + remote_state *rs) +{ + /* Record the maximum possible size of the g packet - it may turn out + to be smaller. */ + this->sizeof_g_packet + = map_regcache_remote_table (regcache->arch (), this->regs.get (), + regcache); + + this->remote_packet_size = 400 - 1; + + if (this->sizeof_g_packet > (this->remote_packet_size - 32) / 2) + this->remote_packet_size = this->sizeof_g_packet * 2 + 32; + + /* Make sure that the packet buffer is plenty big enough for + this architecture. */ + if (rs->buf.size () < this->remote_packet_size) + rs->buf.resize (2 * this->remote_packet_size); +} + /* Get a pointer to the current remote target. If not connected to a remote target, return NULL. */ @@ -8553,6 +8593,10 @@ remote_target::supply_expedited_regs (struct regcache *regcache, regcache->raw_supply (reg.num, reg.data); rs->last_seen_expedited_registers.insert (reg.num); } + + if (regcache->has_variable_size_registers ()) + get_remote_state ()->get_remote_arch_state (regcache->arch ()) + ->update_packet_size (regcache, &m_remote_state); } /* Called when it is decided that STOP_REPLY holds the info of the @@ -8979,6 +9023,9 @@ remote_target::fetch_early_registers (struct regcache *regcache) if (res == 0) error (_("Could not load early register %d using p packet."), regnum); } + + get_remote_state ()->get_remote_arch_state (regcache->arch ()) + ->update_packet_size (regcache, &m_remote_state); } /* Fetch the registers included in the target's 'g' packet. */ @@ -9054,7 +9101,7 @@ remote_target::process_g_packet (struct regcache *regcache) for (i = 0; i < gdbarch_num_regs (gdbarch); i++) { long offset = rsa->regs[i].offset; - long reg_size = register_size (gdbarch, i); + long reg_size = regcache->register_size (i); if (rsa->regs[i].pnum == -1) continue; @@ -9102,7 +9149,7 @@ remote_target::process_g_packet (struct regcache *regcache) for (i = 0; i < gdbarch_num_regs (gdbarch); i++) { struct packet_reg *r = &rsa->regs[i]; - long reg_size = register_size (gdbarch, i); + long reg_size = regcache->register_size (i); if (r->in_g_packet) { @@ -9240,7 +9287,8 @@ remote_target::store_register_using_P (const struct regcache *regcache, struct remote_state *rs = get_remote_state (); /* Try storing a single register. */ char *buf = rs->buf.data (); - gdb_byte *regp = (gdb_byte *) alloca (register_size (gdbarch, reg->regnum)); + int reg_size = regcache->register_size (reg->regnum); + gdb_byte *regp = (gdb_byte *) alloca (reg_size); char *p; if (m_features.packet_support (PACKET_P) == PACKET_DISABLE) @@ -9252,7 +9300,7 @@ remote_target::store_register_using_P (const struct regcache *regcache, xsnprintf (buf, get_remote_packet_size (), "P%s=", phex_nz (reg->pnum, 0)); p = buf + strlen (buf); regcache->raw_collect (reg->regnum, regp); - bin2hex (regp, p, register_size (gdbarch, reg->regnum)); + bin2hex (regp, p, reg_size); putpkt (rs->buf); getpkt (&rs->buf); diff --git a/gdb/value.c b/gdb/value.c index d9b3c6ece04c..2b88279bd845 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -4071,12 +4071,24 @@ value::fetch_lazy_register () if (new_val->entirely_available ()) { - int i; + int i, reg_size; gdb::array_view buf = new_val->contents (); gdb_printf (&debug_file, " bytes="); gdb_printf (&debug_file, "["); - for (i = 0; i < register_size (gdbarch, regnum); i++) + + if (register_is_variable_size (gdbarch, regnum)) + /* To get the size of a variable-size register, we need to + call frame_save_as_regcache () so that we can call + regcache::register_size (). Unfortunatlly the former + ends up calling this function so we enter into an + infinite recursion. So just assume that the value has + the correct size. */ + reg_size = buf.size (); + else + reg_size = register_size (gdbarch, regnum); + + for (i = 0; i < reg_size; i++) gdb_printf (&debug_file, "%02x", buf[i]); gdb_printf (&debug_file, "]"); } diff --git a/gdbsupport/tdesc.h b/gdbsupport/tdesc.h index 5f20e6ab8627..74c5ff4deaf1 100644 --- a/gdbsupport/tdesc.h +++ b/gdbsupport/tdesc.h @@ -115,7 +115,9 @@ struct tdesc_reg : tdesc_element /* The target-described type corresponding to TYPE, if found. */ struct tdesc_type *tdesc_type; - /* Whether this register needs to be loaded early in GDB's regcache. + /* Whether this register needs to be loaded early in GDB's regcache, + because it is used to evaluate the DWARF expression giving the size of + another register. In addition, if true gdbserver will send it as an expedited register in stop replies. */ From patchwork Sat Nov 2 02:56:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840282 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1158792wrb; Fri, 1 Nov 2024 20:00:19 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVK9JeqsbE140cGJ0P5qzgSyYqo7JEkXSpzohLyqh80hXVPc8ZefclOk4S5cD/f8ikSUkcNjQ==@linaro.org X-Google-Smtp-Source: AGHT+IEkoX5LPeZP+01INivmGBkzS9vWo02sCdya1dIExnooWxodwowHPo1M+Moh0liegkgDhVc7 X-Received: by 2002:a05:622a:1a87:b0:461:1532:d6b9 with SMTP id d75a77b69052e-462ab2eafd2mr119584611cf.39.1730516419070; Fri, 01 Nov 2024 20:00:19 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516419; cv=pass; d=google.com; s=arc-20240605; b=YA428u1a0lGF50cw8uGDtVhut4QVeVVDiXEfgItv1kj8zCIsDj9w6VB7SxGO0jH/zU 5FRcZZ+DroMZ7dNA2PnwzGMTNcuzdUzhfbZ7h88rfldd9QqR9DeTl1zolT+m1/x/Idok M1fAZKXLG8RYrX38ACNwGkHpY/NXZeHs5ojasiPnf4qMe1BpK3/0/v58KxSKOS49q1oX /rGz1TwfR7hj5YQDz4t9MX9BDEGVa57Ca1kFwneyON/QHsj6YuQzyYq9aU9ImtFEJBG6 13fzdtKiVVA72HCHUKMTveXqIHkJbr/lD5KWshZiYNNIvAzu+8jT/dmD8yDF7PybcY2P /E7Q== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=ElE3bsCEQcm7LvqgbxwrmjcUYJGYG38Mj7DxZ9WA7BY=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=bEewve0LoEMMerwOpaodKe37Xm4zLqelx7HUHgoXAHMFWkWpjUQ9c7mMWD4dGh6gqD JImNCYxBzJyDaOPKTkImXdv6Zil7JgVStWr0lqJMamcYfvXM85Pt5Y2WNjs3J/lOcEEz 6VnmGhi2M19rgIY9Qjg4FVg3MSeVe1UwXy0Az77TNxR+EipPQXJozBYrjrxSth5hg0Hu XYBXSft02mAR3dGRRkb6uznz0PrEN9fsvca0OMa4jzQxDsWw1pu0bSkNAiblDSv2DpgZ YThsbbWPsslzAeeF2Yc3LAFl54Efb/WbPVdIb/BsS0NDel7yJoySwEam4Xy+MoHOsvGg Q55Q==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=toXYH0qh; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id af79cd13be357-7b2f39f15ecsi578300985a.101.2024.11.01.20.00.18 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 20:00:19 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=toXYH0qh; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A46753858283 for ; Sat, 2 Nov 2024 03:00:18 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pl1-x629.google.com (mail-pl1-x629.google.com [IPv6:2607:f8b0:4864:20::629]) by sourceware.org (Postfix) with ESMTPS id EB2CA3858031 for ; Sat, 2 Nov 2024 02:57:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org EB2CA3858031 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org EB2CA3858031 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::629 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516239; cv=none; b=rCdcv7PYoiM3VBPnhEFhsyJz6V2s9uLsGviPU4l4sOodsZrWV100ScVDkC0JPtGOUXa4ljcDZmvxSKXIljBbs4LtRP37fSDfGsi2ASAFTshgXzEYDN/tUlsHE6Bm3DwOVJRACjT0Qu65DudOw76IgKCXy/buVb99VgYpFYnI30c= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516239; c=relaxed/simple; bh=MJK+H6xZ9G5P48ySU2AadyWcw9PCeCvKGUccW8LqiIA=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=KYd7aWbZHddyXegSKSfPChF7EyZ+oK2ijixyTqnOoJW6LgxUlwbopLlkkUYk5YvOkShdlF+03ikrcNdgHcvhb47qAW7zo6Tuu+elYbQxMPcLK8HwBCHVF0fNlX6OMWEIlmAAuZPiD0H7CrXGdYw8nJOqfR+63zfAGbAPMmhbV0E= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x629.google.com with SMTP id d9443c01a7336-20cdda5cfb6so25305495ad.3 for ; Fri, 01 Nov 2024 19:57:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516234; x=1731121034; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=ElE3bsCEQcm7LvqgbxwrmjcUYJGYG38Mj7DxZ9WA7BY=; b=toXYH0qhN5MB5JP3i4HkilbDwu7YANTEQZKLGXSnHT81OPATyRDqa4ckIbjRy3vUs4 hfqy5sPq/oYBD7liZkP89nF6VTat0Loztu0adeTla3V2XUqLJh4f2zlgX4dJUaTtFsr6 o2GN2YVITgIFpmE7ezd2nnKVyi1fzHC+UVHh223U/GtY7kra3UjF5VuXMo8WdCBltJQB 6UDtwcID60TSfve44KchCtdCdzzbUxBaMi/TTykpECo+0cMazlnJKP4qTbA1IFXK8JgG 8fYNyiB1HxhapuC0NpN8tFJHWizUEjcLSsXHcm+5m72cmHWKW4wZrPrQcfB3lRyDhTil Ew9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516234; x=1731121034; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ElE3bsCEQcm7LvqgbxwrmjcUYJGYG38Mj7DxZ9WA7BY=; b=NHJtf7Tzp0JNC1OzRjO3BdcWZIPD4LttkHsSV2ybT2lvgb096cM2DfVXWylwb2Jhae LC7VvuLAKmGx7tmmkcEGiEPbyMqyDZmYpaAZTL8qxP2UpbDwoFWw9qsmp6pffLgOkUaN r8r/mHbsGQZHIkg3P/jLbPe1zhKVum7mpT9DX5rBMputb9vRXLIXAi0oXNVtzL0nQeJ/ FN8lEckufzFyLVDtpmPWokJ/Xw3omgWeHefkIXTUJp51l6bhWs/9/7IybBS0jS0kJVUR ZxlCpKkJCpohaK/Bm6NeRy//5devw/ECUAnptiLNIRqqWv0lXMh3NU+TmMLbkh3N4S2u XNZQ== X-Gm-Message-State: AOJu0YyUrClvtbLMuihrr896lYh+VsvaXupfBOfkYOJGQAM5dVjDs6y9 1NIt6mjMhJEJJDYun1B5WHtQPcjG0LKcC4naPeTndaocJF1Vv4/gBGsX/DDuMm8K3517NJ72z2/ 0 X-Received: by 2002:a17:902:d4c2:b0:20c:7bee:a7d3 with SMTP id d9443c01a7336-21103c8c62fmr99346905ad.50.1730516233645; Fri, 01 Nov 2024 19:57:13 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-211057d8ae2sm27394675ad.274.2024.11.01.19.57.12 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:57:13 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 11/15] gdbserver: Add concept of variable-size registers to the regcache Date: Fri, 1 Nov 2024 23:56:31 -0300 Message-ID: <20241102025635.586759-12-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org This is the gdbserver equivalent of the previous patch, and many of the same remarks also apply: 1. The contents of variable-size registers are placed in a separate buffer. 2. Some places needed to be changed from calling he register_size () function to calling the register_size () method instead. 3. There are FIXMEs related to the const_casts needed to remove the const from the "this" pointer when calling initialize_variable_size_registers (). Probably the main thing to note in this patch is that it adds a puny DWARF location expression parser which supports only the subset of opcodes needed for variable-size registers. Finally, this patch doesn't add support for handling variable-size registers in tracepoints. This causes some FAILs in gdb.base/internal-string-values.exp when it uses tracepoints. --- gdb/regformats/regdef.h | 19 ++++- gdbserver/ax.cc | 2 +- gdbserver/regcache.cc | 162 ++++++++++++++++++++++++++++++++------ gdbserver/regcache.h | 18 ++++- gdbserver/remote-utils.cc | 2 +- gdbserver/tdesc.cc | 80 ++++++++++++++++++- gdbserver/tdesc.h | 4 +- gdbserver/tracepoint.cc | 4 +- 8 files changed, 253 insertions(+), 38 deletions(-) diff --git a/gdb/regformats/regdef.h b/gdb/regformats/regdef.h index 09339d495209..fcf7b177f04e 100644 --- a/gdb/regformats/regdef.h +++ b/gdb/regformats/regdef.h @@ -27,6 +27,8 @@ struct reg : name (""), offset (_offset), size (0), + element_bitsize (0), + count_locexpr (nullptr), load_early (false) {} @@ -34,6 +36,8 @@ struct reg : name (_name), offset (_offset), size (_size), + element_bitsize (0), + count_locexpr (nullptr), load_early (_load_early) {} @@ -48,9 +52,20 @@ struct reg /* The offset (in bits) of the value of this register in the buffer. */ int offset; - /* The size (in bits) of the value of this register, as transmitted. */ + /* The size (in bits) of the value of this register, as transmitted. If + it's TDESC_REG_VARIABLE_SIZE then this register contains a vector with + variable number of elements given by COUNT_LOCEXPR, and each element + has a size of ELEMENT_BITSIZE. */ int size; + /* Size of each element in the vector. Only valid if + size == TDESC_REG_VARIABLE_SIZE. */ + int element_bitsize; + + /* DWARF location expression for number of elements in the vector. Only + valid if size == TDESC_REG_VARIABLE_SIZE. */ + gdb::byte_vector *count_locexpr; + /* Whether this register needs to be loaded early in the register cache, because variable-size registers depend on it to calculate their size. */ @@ -61,6 +76,8 @@ struct reg return (strcmp (name, other.name) == 0 && offset == other.offset && size == other.size + && element_bitsize == other.element_bitsize + && count_locexpr == other.count_locexpr && load_early == other.load_early); } diff --git a/gdbserver/ax.cc b/gdbserver/ax.cc index ff42795582ff..121ea6b420a3 100644 --- a/gdbserver/ax.cc +++ b/gdbserver/ax.cc @@ -1191,7 +1191,7 @@ gdb_eval_agent_expr (struct eval_agent_expr_context *ctx, int regnum = arg; struct regcache *regcache = ctx->regcache; - switch (register_size (regcache->tdesc, regnum)) + switch (regcache->register_size (regnum)) { case 8: collect_register (regcache, regnum, cnv.u64.bytes); diff --git a/gdbserver/regcache.cc b/gdbserver/regcache.cc index cd1ee2e5f145..8d491590d995 100644 --- a/gdbserver/regcache.cc +++ b/gdbserver/regcache.cc @@ -19,6 +19,7 @@ #include "regdef.h" #include "gdbthread.h" #include "tdesc.h" +#include "locexpr.h" #include "gdbsupport/rsp-low.h" #include "gdbsupport/gdb-checked-static-cast.h" @@ -56,6 +57,7 @@ get_thread_regcache (struct thread_info *thread, int fetch) /* Invalidate all registers, to prevent stale left-overs. */ memset (regcache->register_status, REG_UNAVAILABLE, regcache->tdesc->reg_defs.size ()); + regcache->variable_size_registers.reset (); fetch_inferior_registers (regcache, -1); regcache->registers_valid = 1; } @@ -127,13 +129,14 @@ init_register_cache (struct regcache *regcache, fetches. This way they'll read as zero instead of garbage. */ regcache->tdesc = tdesc; - regcache->registers - = (unsigned char *) xcalloc (1, tdesc->registers_size); + regcache->fixed_size_registers + = (unsigned char *) xcalloc (1, tdesc->fixed_registers_size); regcache->registers_owned = 1; regcache->register_status = (unsigned char *) xmalloc (tdesc->reg_defs.size ()); memset ((void *) regcache->register_status, REG_UNAVAILABLE, tdesc->reg_defs.size ()); + regcache->variable_size_registers.reset (); #else gdb_assert_not_reached ("can't allocate memory from the heap"); #endif @@ -141,10 +144,11 @@ init_register_cache (struct regcache *regcache, else { regcache->tdesc = tdesc; - regcache->registers = regbuf; + regcache->fixed_size_registers = regbuf; regcache->registers_owned = 0; #ifndef IN_PROCESS_AGENT regcache->register_status = NULL; + regcache->variable_size_registers.reset (); #endif } @@ -160,7 +164,7 @@ new_register_cache (const struct target_desc *tdesc) { struct regcache *regcache = new struct regcache; - gdb_assert (tdesc->registers_size != 0); + gdb_assert (tdesc->fixed_registers_size != 0); return init_register_cache (regcache, tdesc, NULL); } @@ -171,7 +175,7 @@ free_register_cache (struct regcache *regcache) if (regcache) { if (regcache->registers_owned) - free (regcache->registers); + free (regcache->fixed_size_registers); free (regcache->register_status); delete regcache; } @@ -186,7 +190,7 @@ regcache_cpy (struct regcache *dst, struct regcache *src) gdb_assert (src->tdesc == dst->tdesc); gdb_assert (src != dst); - memcpy (dst->registers, src->registers, src->tdesc->registers_size); + memcpy (dst->fixed_size_registers, src->fixed_size_registers, src->tdesc->fixed_registers_size); #ifndef IN_PROCESS_AGENT if (dst->register_status != NULL && src->register_status != NULL) memcpy (dst->register_status, src->register_status, @@ -255,22 +259,34 @@ register_from_string (struct regcache *regcache, int regnum, char *buf) void registers_to_string (struct regcache *regcache, char *buf) { - unsigned char *registers = regcache->registers; + unsigned char *registers = regcache->fixed_size_registers; + unsigned char *var_size_registers = regcache->variable_size_registers.get (); const struct target_desc *tdesc = regcache->tdesc; for (int i = 0; i < tdesc->reg_defs.size (); ++i) { + int reg_size = regcache->register_size (i); if (regcache->register_status[i] == REG_VALID) { - bin2hex (registers, buf, register_size (tdesc, i)); - buf += register_size (tdesc, i) * 2; + unsigned char *regs; + if (tdesc->reg_defs[i].size == TDESC_REG_VARIABLE_SIZE) + regs = var_size_registers; + else + regs = registers; + + bin2hex (regs, buf, reg_size); + buf += reg_size * 2; } else { - memset (buf, 'x', register_size (tdesc, i) * 2); - buf += register_size (tdesc, i) * 2; + memset (buf, 'x', reg_size * 2); + buf += reg_size * 2; } - registers += register_size (tdesc, i); + + if (tdesc->reg_defs[i].size == TDESC_REG_VARIABLE_SIZE) + var_size_registers += reg_size; + else + registers += reg_size; } *buf = '\0'; } @@ -279,17 +295,32 @@ void registers_from_string (struct regcache *regcache, char *buf) { int len = strlen (buf); - unsigned char *registers = regcache->registers; + unsigned char *registers = regcache->fixed_size_registers; + unsigned char *var_size_registers = regcache->variable_size_registers.get (); const struct target_desc *tdesc = regcache->tdesc; + int expected_len = (tdesc->fixed_registers_size + regcache->variable_registers_size) * 2; - if (len != tdesc->registers_size * 2) + if (len != expected_len) { warning ("Wrong sized register packet (expected %d bytes, got %d)", - 2 * tdesc->registers_size, len); - if (len > tdesc->registers_size * 2) - len = tdesc->registers_size * 2; + expected_len, len); + if (len > expected_len) + len = expected_len; + } + + for (int i = 0; i < tdesc->reg_defs.size (); ++i) + { + int reg_size = regcache->register_size (i); + unsigned char *regs; + + if (tdesc->reg_defs[i].size == TDESC_REG_VARIABLE_SIZE) + regs = var_size_registers; + else + regs = registers; + + hex2bin (buf, regs, reg_size); + buf += reg_size * 2; } - hex2bin (buf, registers, len / 2); } /* See regcache.h */ @@ -337,16 +368,56 @@ regcache_release (void) } #endif +#ifndef IN_PROCESS_AGENT +/* See regcache.h */ + +void +regcache::initialize_variable_size_registers () +{ + const unsigned int num_regs = tdesc->reg_defs.size (); + int total_size = 0; + + variable_size_sizes.resize (num_regs); + variable_size_offsets.resize (num_regs); + + for (int i = 0; i < num_regs; i++) + { + const gdb::reg ® = tdesc->reg_defs[i]; + if (reg.size != TDESC_REG_VARIABLE_SIZE) + { + variable_size_sizes[i] = -1; + variable_size_offsets[i] = -1; + continue; + } + + long size = (evaluate_locexpr (*reg.count_locexpr, this) + * reg.element_bitsize / 8); + variable_size_sizes[i] = size; + variable_size_offsets[i] = total_size; + total_size += size; + } + + variable_size_registers.reset (new unsigned char[total_size]); + variable_registers_size = total_size; +} +#endif + int register_cache_size (const struct target_desc *tdesc) { - return tdesc->registers_size; + /* Variable-size registers aren't considered here because this function is + only used for tracepoints. */ + return tdesc->fixed_registers_size; } int register_size (const struct target_desc *tdesc, int n) { - return find_register_by_number (tdesc, n).size / 8; + const gdb::reg ® = find_register_by_number (tdesc, n); + + gdb_assert (reg.size != TDESC_REG_VARIABLE_SIZE); + + return reg.size / 8; } /* See gdbsupport/common-regcache.h. */ @@ -354,15 +425,46 @@ register_size (const struct target_desc *tdesc, int n) int regcache::register_size (int regnum) const { - return ::register_size (tdesc, regnum); + const gdb::reg ® = find_register_by_number (tdesc, regnum); + + if (reg.size == TDESC_REG_VARIABLE_SIZE) + { +#ifndef IN_PROCESS_AGENT + if (!variable_size_registers) + // FIXME: Remove cast. + const_cast (this)->initialize_variable_size_registers (); + + return variable_size_sizes[regnum]; +#else + gdb_assert_not_reached ("Variable-size registers not supported."); +#endif + } + else + return reg.size / 8; } static gdb::array_view register_data (const struct regcache *regcache, int n) { const gdb::reg ® = find_register_by_number (regcache->tdesc, n); - return gdb::make_array_view (regcache->registers + reg.offset / 8, - reg.size / 8); + + if (reg.size == TDESC_REG_VARIABLE_SIZE) + { +#ifndef IN_PROCESS_AGENT + if (!regcache->variable_size_registers) + // FIXME: Remove cast. + const_cast (regcache)->initialize_variable_size_registers (); + + return gdb::make_array_view (regcache->variable_size_registers.get () + + regcache->variable_size_offsets[n], + regcache->variable_size_sizes[n]); +#else + gdb_assert_not_reached ("Variable-size registers not supported."); +#endif + } + else + return gdb::make_array_view (regcache->fixed_size_registers + reg.offset / 8, + reg.size / 8); } void @@ -396,6 +498,12 @@ regcache::raw_supply (int n, gdb::array_view src) register_status[n] = REG_UNAVAILABLE; #endif } + +#ifndef IN_PROCESS_AGENT + if (this->is_load_early_register (n)) + /* Invalidate variable-size registers. */ + this->initialize_variable_size_registers (); +#endif } /* Supply register N with value zero to REGCACHE. */ @@ -435,7 +543,7 @@ supply_regblock (struct regcache *regcache, const void *buf) { const struct target_desc *tdesc = regcache->tdesc; - memcpy (regcache->registers, buf, tdesc->registers_size); + memcpy (regcache->fixed_size_registers, buf, tdesc->fixed_registers_size); #ifndef IN_PROCESS_AGENT { int i; @@ -449,7 +557,7 @@ supply_regblock (struct regcache *regcache, const void *buf) { const struct target_desc *tdesc = regcache->tdesc; - memset (regcache->registers, 0, tdesc->registers_size); + memset (regcache->fixed_size_registers, 0, tdesc->fixed_registers_size); #ifndef IN_PROCESS_AGENT { int i; @@ -457,6 +565,8 @@ supply_regblock (struct regcache *regcache, const void *buf) for (i = 0; i < tdesc->reg_defs.size (); i++) regcache->register_status[i] = REG_UNAVAILABLE; } + + regcache->variable_size_registers.reset (); #endif } } @@ -498,7 +608,7 @@ regcache_raw_read_unsigned (reg_buffer_common *reg_buf, int regnum, gdb_assert (regcache != NULL); - size = register_size (regcache->tdesc, regnum); + size = regcache->register_size (regnum); if (size > (int) sizeof (ULONGEST)) error (_("That operation is not available on integers of more than" diff --git a/gdbserver/regcache.h b/gdbserver/regcache.h index 07e48a7432b7..e1202d708a6a 100644 --- a/gdbserver/regcache.h +++ b/gdbserver/regcache.h @@ -40,10 +40,26 @@ struct regcache : public reg_buffer_common in a traceframe. For that, check REGISTER_STATUS below. */ int registers_valid = 0; int registers_owned = 0; - unsigned char *registers = nullptr; + unsigned char *fixed_size_registers = nullptr; #ifndef IN_PROCESS_AGENT + /* The variable-size register buffers (if any). */ + std::unique_ptr variable_size_registers; + + /* Size of the variable_size_registers buffer, if there is one. */ + int variable_registers_size; + /* One of REG_UNAVAILABLE or REG_VALID. */ unsigned char *register_status = nullptr; + + /* Offsets into variable_size_registers. */ + std::vector variable_size_offsets; + + /* Size of each variable-size register. */ + std::vector variable_size_sizes; + + /* Initialize (or reset) information about variable-size registers in this + regcache. */ + void initialize_variable_size_registers (); #endif /* See gdbsupport/common-regcache.h. */ diff --git a/gdbserver/remote-utils.cc b/gdbserver/remote-utils.cc index 98c34e91220c..b4e4b6145eb4 100644 --- a/gdbserver/remote-utils.cc +++ b/gdbserver/remote-utils.cc @@ -1043,7 +1043,7 @@ outreg (struct regcache *regcache, int regno, char *buf) *buf++ = tohex (regno & 0xf); *buf++ = ':'; collect_register_as_string (regcache, regno, buf); - buf += 2 * register_size (regcache->tdesc, regno); + buf += 2 * regcache->register_size (regno); *buf++ = ';'; return buf; diff --git a/gdbserver/tdesc.cc b/gdbserver/tdesc.cc index fbaf756f5050..bf5a5c6e79a4 100644 --- a/gdbserver/tdesc.cc +++ b/gdbserver/tdesc.cc @@ -51,6 +51,69 @@ void target_desc::accept (tdesc_element_visitor &v) const #endif } +/* Return bit size of given TYPE. */ + +static int +tdesc_type_bitsize (const tdesc_type *type) +{ + switch (type->kind) { + case TDESC_TYPE_INT8: + case TDESC_TYPE_UINT8: + return 8; + case TDESC_TYPE_IEEE_HALF: + case TDESC_TYPE_INT16: + case TDESC_TYPE_UINT16: + case TDESC_TYPE_BFLOAT16: + return 16; + case TDESC_TYPE_IEEE_SINGLE: + case TDESC_TYPE_INT32: + case TDESC_TYPE_UINT32: + return 32; + case TDESC_TYPE_IEEE_DOUBLE: + case TDESC_TYPE_INT64: + case TDESC_TYPE_UINT64: + return 64; + case TDESC_TYPE_I387_EXT: + return 80; + case TDESC_TYPE_ARM_FPA_EXT: + return 96; + case TDESC_TYPE_INT128: + case TDESC_TYPE_UINT128: + return 128; + default: + /* The other types require a gdbarch to determine their size. */ + error ("Target description uses unsupported type in variable-size register."); + } +} + +/* Sets up REG size information using TYPE. */ + +static void +setup_variable_size_reg (tdesc_type *type, gdb::reg ®) +{ + /* We only support vector types or unions containing vector types as + variable-size. */ + gdb_assert (type->kind == TDESC_TYPE_UNION + || type->kind == TDESC_TYPE_VECTOR); + + if (type->kind == TDESC_TYPE_VECTOR) + { + tdesc_type_vector *vec_type = static_cast (type); + + reg.element_bitsize = tdesc_type_bitsize (vec_type->element_type); + reg.count_locexpr = &vec_type->locexpr; + } + else + { + tdesc_type_with_fields *union_type + = static_cast (type); + + /* We assume that all fields in the union have the same size, so + just get the first one. */ + setup_variable_size_reg (union_type->fields.front ().type, reg); + } +} + void init_target_desc (struct target_desc *tdesc, const char **expedite_regs) @@ -73,17 +136,26 @@ init_target_desc (struct target_desc *tdesc, tdesc->reg_defs.emplace_back (treg->name.c_str (), offset, treg->bitsize, treg->load_early); - offset += treg->bitsize; + + if (treg->bitsize == TDESC_REG_VARIABLE_SIZE) + { + tdesc_type *type + = tdesc_named_type (feature.get (), treg->type.c_str ()); + + setup_variable_size_reg (type, tdesc->reg_defs.back ()); + } + else + offset += treg->bitsize; if (treg->load_early) expedite_from_features.push_back (treg->name.c_str ()); } - tdesc->registers_size = offset / 8; + tdesc->fixed_registers_size = offset / 8; /* Make sure PBUFSIZ is large enough to hold a full register packet. */ - gdb_assert (2 * tdesc->registers_size + 32 <= PBUFSIZ); + gdb_assert (2 * tdesc->fixed_registers_size + 32 <= PBUFSIZ); #ifndef IN_PROCESS_AGENT /* Drop the contents of the previous vector, if any. */ @@ -127,7 +199,7 @@ copy_target_description (struct target_desc *dest, { dest->reg_defs = src->reg_defs; dest->expedite_regs = src->expedite_regs; - dest->registers_size = src->registers_size; + dest->fixed_registers_size = src->fixed_registers_size; dest->xmltarget = src->xmltarget; if (src->arch) diff --git a/gdbserver/tdesc.h b/gdbserver/tdesc.h index 4796b50b4d13..b7a0166c6e65 100644 --- a/gdbserver/tdesc.h +++ b/gdbserver/tdesc.h @@ -34,7 +34,7 @@ struct target_desc final : tdesc_element std::vector reg_defs; /* The register cache size, in bytes. */ - int registers_size; + int fixed_registers_size; /* XML features in this target description. */ std::vector features; @@ -61,7 +61,7 @@ struct target_desc final : tdesc_element public: target_desc () - : registers_size (0) + : fixed_registers_size (0) {} bool operator== (const target_desc &other) const; diff --git a/gdbserver/tracepoint.cc b/gdbserver/tracepoint.cc index b7d0ef2c2932..1cbf0fddc1e6 100644 --- a/gdbserver/tracepoint.cc +++ b/gdbserver/tracepoint.cc @@ -5097,7 +5097,7 @@ traceframe_walk_blocks (unsigned char *database, unsigned int datasize, { case 'R': /* Skip over the registers block. */ - dataptr += current_target_desc ()->registers_size; + dataptr += current_target_desc ()->fixed_registers_size; break; case 'M': /* Skip over the memory block. */ @@ -5776,7 +5776,7 @@ gdb_collect (struct tracepoint *tpoint, unsigned char *regs) ctx.regcache_initted = 0; /* Wrap the regblock in a register cache (in the stack, we don't want to malloc here). */ - ctx.regspace = (unsigned char *) alloca (ipa_tdesc->registers_size); + ctx.regspace = (unsigned char *) alloca (ipa_tdesc->fixed_registers_size); if (ctx.regspace == NULL) { trace_debug ("Trace buffer block allocation failed, skipping"); From patchwork Sat Nov 2 02:56:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840283 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1159170wrb; Fri, 1 Nov 2024 20:01:31 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWbeKkgWk7b+9kbLS5L0HI9xeKrZBfhCD/zjfOKJVlND53Qyqvd8G44+lir5XU+ttv4TIrJhg==@linaro.org X-Google-Smtp-Source: AGHT+IEaslXpsiO/0ynauIqAEDTLGXpXPwbpT+xTdD4txwGZ52TunoIqHa7zSWQg48y1YxUKi+LM X-Received: by 2002:a05:622a:1210:b0:461:3212:cda4 with SMTP id d75a77b69052e-4613bfc4a7dmr305091811cf.3.1730516491276; Fri, 01 Nov 2024 20:01:31 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516491; cv=pass; d=google.com; s=arc-20240605; b=hPgfzo4mj9LbVwrZlwywvThaNBkfZojllWY9Q9DsFsJUuzvJ+SRVDnwad6Xekc+NnV bB8XtwCnk/bvxqaAyHyudTOH8Zawfy5LEewmvUTz1fpLGd9qBDbJRED5zLlcmZlFnnz/ 3LUOppEDbgLGSYN7OQc1GGiQrKGN6P2Ie6O9ogIq2cqqQbJ5SzIewQQcHbEnt/sQ7mS5 t1o8y/OEMBw8O1PWc4M9/LTH1rIaDI+zEikDTJ1dDVVE3Df7TlKGzQGmWu/s2FVlvtBu RRfmsQYaqne02Lv0Ndj4eY0o1F3ke2d3h31DVn8OSaR5Z0HwSzkGdbNcF8KKruZBaFS3 qlvg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=vtIx46M2ibNPxEsW7Rx8O7t8Ib66yk8bPZlcoFbfleA=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=ZQtHfV9ySlNiIWvcYlO6PIVCB1VVUgL296JIYOhKKUgVIBWF5O6qaFXKvb9z72AZYq HRtLvFY8dATx0GDsKHTUwnns8d+2hfr19TGJvq+EniF6UCzufxvwuoBaqoXfBITeegfZ kZspWLwPLG33W1Trv/wpMRDKZggTBiwF7jtkeU9sDh95kB2C/ODYaVEsEPRclfGeI2GC s7MVzmZFhxHyku4yxJ7hWXOWmcVf7msc4GDqbJj0C/56LAODCO2upXBR0Jd7jY4QhFUK jDu+6Jld7kjK4ycaSh7tKLZ0BqRvqVu8kU2jc2BeAGG9Mrp8+naaIO52y8bPqqVpxjMO CJMg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="Wq2/sUjD"; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id d75a77b69052e-462ad1b25bdsi55257061cf.317.2024.11.01.20.01.31 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 20:01:31 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="Wq2/sUjD"; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 8265F3857C7A for ; Sat, 2 Nov 2024 03:01:30 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pl1-x629.google.com (mail-pl1-x629.google.com [IPv6:2607:f8b0:4864:20::629]) by sourceware.org (Postfix) with ESMTPS id D262B3857BA9 for ; Sat, 2 Nov 2024 02:57:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D262B3857BA9 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D262B3857BA9 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::629 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516240; cv=none; b=hFhIf7yD0MxAo22yl9r0Lr6LsYIuwkFEhPxwZbzFOVL94rRqT6zcelNFADhrVhUOtNdJq952YxS1rqMF2nV4LTGwN/UUgu7/rxc4iG8+jvoJzNrk0AFCcBv9c5ZFcvpUK5ja12lUphXeC2Z0bq6BxUyDGoQUaH0FbOdYfn2/sP0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516240; c=relaxed/simple; bh=1eq7xVd43KBe8mZrJa8qX0N2rBpkLgwyWOQJ9/ICBCc=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=SqtASlgo8eOChtzXC43cZKmNsdztsOkx/OYQK79tMsfQEfIftStZv12UvPSrJu+Jh264G0Tp0azhOS/AKzVqRlw8KPey2Vffi+egXQow0t9A204e7+JY9yB82XBXS1rQYjyVGCDY8gqBbO+PjjCMgR63s+9pswLTcYUuX4fgO08= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x629.google.com with SMTP id d9443c01a7336-20cf6eea3c0so21624025ad.0 for ; Fri, 01 Nov 2024 19:57:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516237; x=1731121037; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=vtIx46M2ibNPxEsW7Rx8O7t8Ib66yk8bPZlcoFbfleA=; b=Wq2/sUjDlZQd8xOifHHk/ul6DGcBNaiOYnEltjg2ep3+SVF8pQWk9bT592gqv4tkDo Od1yIuEMpWVkfBTSZkc3U03hdUz5cppF/fYb5rhFfdesFNK99QVDKIUMyXqiG/0AFnvz cMEf9D5CF8Z1u5qnqJ3ltnCpT3sCMf/MYvFgQW68c1ryOstF+IG4H8KB8GdhG2dzhzxV OtbustGkVq50U+ur/WRhPsKD7yMK+Tjb1rEez+I+1WLePkezVuPFf38AVtkOY6V3yIbz KPi7darend+Pe3oYlwqcJMINX4KfqxuS5YH+NnUos/GLpbnNVc3U47O0V6LqYMW7oe3r +pLw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516237; x=1731121037; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vtIx46M2ibNPxEsW7Rx8O7t8Ib66yk8bPZlcoFbfleA=; b=pA5CaB6kPEPyLeAyfCK2LKbxEOmfOTCxgyklt8iJYF4iU61rd9Mnus3dwomRoC+DvP s4cEy0r/DNi3vjBKN2ayj+6bWNFLTl46+U2l8cX6biXt6zzr9h5FapfR/rtoP66QmOUn /kOT5WaJNRskBTPmKN9aRc/TZ5LwtG1EskTwG+rGtfWdiTatUNpjGfpI5tTKuWlvJ0DT bX4IuadVqry2jTl4UB5ml9/1YUsiqb6NZOb824AvBssu99oZxbiDFmZpb2UMkV7zZB5n Llj6iIy17PtrLIF7iOf875A6CAQNvacNn54cNvnYTOrzMY6yQ2TFWg4KPLSaHGsiJ6d6 k1Hg== X-Gm-Message-State: AOJu0YwcLpAf530GEHrEC649i+ZKi3yoXGk1KtnPA/eGCvXkTtUkZUki E81xwXPTsR5g4YXMC7z/FpLXEZjbb/XrnR23K5dKOKWcrLXdSgruUulpQSKOLnQT2ynOPHm7Owy e X-Received: by 2002:a17:902:f693:b0:20b:7be8:8ecf with SMTP id d9443c01a7336-210c6c7f095mr313890405ad.53.1730516236630; Fri, 01 Nov 2024 19:57:16 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2e92fa25742sm5702491a91.19.2024.11.01.19.57.15 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:57:16 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 12/15] GDB: aarch64-linux: Load and store VG separately from other SVE registers Date: Fri, 1 Nov 2024 23:56:32 -0300 Message-ID: <20241102025635.586759-13-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org GDB currently loads and stores all SVE registers, including the VG register, at the same time. To suport variable-size SVE registers, GDB needs to be able to load and store VG separately from them so that it knows the size of the SVE vector registers in advance. So change it to fetch or store VG separately when only that register is requested. --- gdb/aarch64-linux-nat.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index 0fa5bee500b1..f1b014b5eb26 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -310,6 +310,21 @@ store_fpregs_to_thread (const struct regcache *regcache) } } +/* Fill GDB's REGCACHE with the SVE VG register value from the thread + associated with REGCACHE. + + This function handles reading data from SVE or SSVE states, depending + on which state is active at the moment. */ + +static void +fetch_sve_vg_from_thread (struct regcache *regcache) +{ + uint64_t vq = aarch64_sve_get_vq (regcache->ptid ().lwp ()); + uint64_t vg = sve_vg_from_vq (vq); + + regcache->raw_supply (AARCH64_SVE_VG_REGNUM, &vg); +} + /* Fill GDB's REGCACHE with the valid SVE register values from the thread associated with REGCACHE. @@ -323,6 +338,19 @@ fetch_sveregs_from_thread (struct regcache *regcache) aarch64_sve_regs_copy_to_reg_buf (regcache->ptid ().lwp (), regcache); } +/* Store the SVE VG register value from GDB's REGCACHE to the thread + associated with REGCACHE. + + This function handles writing data to SVE or SSVE state, depending + on which state is active at the moment. */ + +static void +store_sve_vg_to_thread (struct regcache *regcache) +{ + if (!aarch64_sve_set_vq (regcache->ptid ().lwp (), regcache)) + perror_with_name (_ ("Unable to set VG register")); +} + /* Store the valid SVE register values from GDB's REGCACHE to the thread associated with REGCACHE. @@ -583,8 +611,10 @@ aarch64_fetch_registers (struct regcache *regcache, int regno) fetch_gregs_from_thread (regcache); /* SVE register? */ else if ((tdep->has_sve () || tdep->has_sme ()) - && regno <= AARCH64_SVE_VG_REGNUM) + && regno < AARCH64_SVE_VG_REGNUM) fetch_sveregs_from_thread (regcache); + else if (tdep->has_sve () && regno == AARCH64_SVE_VG_REGNUM) + fetch_sve_vg_from_thread (regcache); /* FPSIMD register? */ else if (regno <= AARCH64_FPCR_REGNUM) fetch_fpregs_from_thread (regcache); @@ -686,8 +716,10 @@ aarch64_store_registers (struct regcache *regcache, int regno) store_gregs_to_thread (regcache); /* SVE register? */ else if ((tdep->has_sve () || tdep->has_sme ()) - && regno <= AARCH64_SVE_VG_REGNUM) + && regno < AARCH64_SVE_VG_REGNUM) store_sveregs_to_thread (regcache); + else if (tdep->has_sve () && regno == AARCH64_SVE_VG_REGNUM) + store_sve_vg_to_thread (regcache); /* FPSIMD register? */ else if (regno <= AARCH64_FPCR_REGNUM) store_fpregs_to_thread (regcache); From patchwork Sat Nov 2 02:56:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840284 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1159347wrb; Fri, 1 Nov 2024 20:01:54 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVeRsGoiqLMno5FR4L69R0FlycY8SCcNrX/e1yMwKxqH5bBEDzVClziMf+suXKZK79hL0gU4w==@linaro.org X-Google-Smtp-Source: AGHT+IG9x3CLlT+ENSlP3H9POt+1tylUQGcbbnD6+52CiGpO7k7jSzREfYxBfUyP1rx2KhZzhkIR X-Received: by 2002:a05:620a:372b:b0:7b1:5143:8da1 with SMTP id af79cd13be357-7b2fb9cc1a1mr829038185a.43.1730516514448; Fri, 01 Nov 2024 20:01:54 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516514; cv=pass; d=google.com; s=arc-20240605; b=SuNytOADVtx7aIHcISsWtzD8yLrFAWbN88K104CzwU1aducbPoYlJbuMZsD0DhmR5u TqOXVB+idQ9VOo5VNN2EOyTuxvZ2MIdlAec7OTxAidiw2yNoXZbesEuRNocIKAvkkAfh tYk4HKIRlQ3ePL7IZBS+RQzxdk8Yvd2PQpv9HvWg+d4ZBZcXQfzkL4EQvZMxWIbaTbvk qPD8gA6gwEmGmnOn8Fcrl4Gb58+kG45Vk8AhwQsDrFyZFz1PSNvbTr6TjaM7p+KruEAG ICtdwABjSzns01mGn+rAnxkfhCU47h9OypioiKOiqU/c1jZshPd/yp3UMYSYXPFGxKyo LYvQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=L0bo70u04TZg04dWHACJlBocsK5AtcL51r4yLJmc9gQ=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=knyuiaT2vEV6cV7FyeD81YsVzhUji8FMNlfMn/EPcrVaznqM1sPS/Ex/C0g463/5cV olJuYLThUTmZI6B4abOuIPfO/jd0xg2UwL5OgQglr0uH7U9VYcR4nL/VPH1Mzme69RaA w4PxifP7J2olMt988wtytfamvRTKrbA7LfZGKC9ky15IdDoSgdG6RmgkZSyq3pUbmdwF vzavXskG3G9MjCQ60aX/Jfvr6kCu1fYbYZpCqFOShuHZXN24QneC4hbuOWdJr6D9SFwA 9MQqxnonhtul/BxTuUWcnTY0NtGgAwjmonGBvG+0zciT9eKt97AgCBzZqW9q4kdv5zpc xitw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=n2jHdxzZ; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id af79cd13be357-7b2f3a833absi577805385a.368.2024.11.01.20.01.54 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 20:01:54 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=n2jHdxzZ; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 190CE3858424 for ; Sat, 2 Nov 2024 03:01:54 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by sourceware.org (Postfix) with ESMTPS id 20EFF3857719 for ; Sat, 2 Nov 2024 02:57:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 20EFF3857719 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 20EFF3857719 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::62d ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516249; cv=none; b=xoVh3iDi6xrXDjrRKbgmHGwLCVqhtcYTrzus3RQUcwiFm8r5yJ55YbJlypwtQpGrKpHOXJ3JCr9O0qMH+lMu9qv/+VOA7m97PerVogMQamShKpFaUKsmkQtm6wyJ7PPtq96amTFM1A5EL3FuqpjwAsgSEaYQ1yfv5ajnP6OqAvM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516249; c=relaxed/simple; bh=pQgMB/qRyZFNv+Osx1H/xC6w0aIgzWUhishLwuL6crk=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=nEkRLyXu00NFEmkI/VdnM6wdlDKXeHKdRdBjvFznYDxcQApAMstjbrQV4yWhfVj5YIPtjmfWq5vKmZPd76rhtNKUoIDdO3sa2VvX5fwEiZ5n/B18Hg2RAi6ucI3NIC7zyAceudtmQ1BTdWXLGN+uSUgTrXBnQ0yH7DQcjVQi1jY= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x62d.google.com with SMTP id d9443c01a7336-20c70abba48so23623805ad.0 for ; Fri, 01 Nov 2024 19:57:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516240; x=1731121040; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=L0bo70u04TZg04dWHACJlBocsK5AtcL51r4yLJmc9gQ=; b=n2jHdxzZ1KUA7JEOfYcVjTV+31kk63nM71fddD6IY/sLjusMFLU39z8i2Kx8uMij8j eRaPOphDtrcN0Gs5TbeX67ZGSJ29Z6lbgmntWIXRHNyx2vnlnG1YyMLttEtFzxhk5h7o wD10YAEddjp/96l7HafjhnEW9zOqxisRhp3J14GBX4PynNcZxBIO6+qpDsaUJRlKT1+g Po6lJeLP3OtweCoj5MBmXXBbGO1fFh8+Semk+s1Dd0WLSJLMhadzbNeY7Yxkzc9x93sh gZIvBu7X1VGhZTVVY9Sz+kau0q+N+BTKsFC6cDBA0n/xUTwpKqtGnMsfm+lJhxCBZZx2 UGWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516240; x=1731121040; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=L0bo70u04TZg04dWHACJlBocsK5AtcL51r4yLJmc9gQ=; b=KqRX3Ia18LMTYkccIfqQR7flEFl0GYf58T9aPxkimBPkjQMPctVq4hD9LkmTuckHWN CZWbGg44j9b4es5R9F5nJie1RHsx87a3WRl2jcPsFqkx1xQKSPTlYXpA8aSpb3vJGrEB yCoqt8NL6UKu7J/RcC56KQnKRJxpVhz+38ezn8a88dkbvaNAR0O5256ancfqYSnbFoCj HbohwJQeijvAXkr2jr3CUAVLCPSHOfhj1R+ifS4xjOk/dZrHdgmJ7887succrhckTkKH 6YkHQ7i0QpBjMItY2j1NtrMQ6ug9m/01XW8rSBvUKsRsbgZAl8jwUKSMK3b3xrx/B4/2 EupA== X-Gm-Message-State: AOJu0YwM27Gt+zuSOB6Vtj3a0qwDLWpSV/3rv8jb6HnuM3zVmxyznxrE ZN5DPXn/Wwdjcm2NbirHxVsEbSAbGet8vkPwP+ZCV6tkqtpB4DzmFsNE4Tt4B49DW8KMJYjExDh a X-Received: by 2002:a17:903:2449:b0:20b:6edd:e95a with SMTP id d9443c01a7336-2111af17c6bmr67240685ad.3.1730516239733; Fri, 01 Nov 2024 19:57:19 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-211057c1117sm27103745ad.224.2024.11.01.19.57.18 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:57:19 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 13/15] GDB, gdbserver: aarch64: Convert SVE feature to use variable-size registers Date: Fri, 1 Nov 2024 23:56:33 -0300 Message-ID: <20241102025635.586759-14-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org Everything needed to support describing variable-size vector registers in XML is now in place, so convert aarch64 SVE feature to XML. This commit introduces gdb/features/aarch64-sve.xml, and the corresponding aarch64-sve.c is created from it. aarch64_dwarf_reg_to_regnum () is moved to gdb/arch/aarch64.c so that it can be used by gdbserver, and an aarch64 implementation of the recently added regnum_to_dwarf2_reg () gdbarch hook is added. There's a FIXME about using max VQ in aarch64_linux_iterate_over_regset_sections () which I'm still considering how to solve. --- gdb/aarch64-linux-nat.c | 26 ++-- gdb/aarch64-linux-tdep.c | 55 +++++--- gdb/aarch64-tdep.c | 115 ++++++++-------- gdb/aarch64-tdep.h | 21 +-- gdb/arch/aarch64.c | 36 ++++- gdb/arch/aarch64.h | 25 ++-- gdb/features/Makefile | 1 + gdb/features/aarch64-sve.c | 199 +++++++++++++++------------- gdb/features/aarch64-sve.xml | 217 +++++++++++++++++++++++++++++++ gdbserver/configure.srv | 1 + gdbserver/linux-aarch64-low.cc | 6 +- gdbserver/linux-aarch64-tdesc.cc | 17 ++- 12 files changed, 494 insertions(+), 225 deletions(-) create mode 100644 gdb/features/aarch64-sve.xml diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index f1b014b5eb26..5e12a2e403f6 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -586,7 +586,7 @@ aarch64_fetch_registers (struct regcache *regcache, int regno) /* We attempt to fetch SVE registers if there is support for either SVE or SME (due to the SSVE state of SME). */ - if (tdep->has_sve () || tdep->has_sme ()) + if (tdep->has_sve || tdep->has_sme ()) fetch_sveregs_from_thread (regcache); else fetch_fpregs_from_thread (regcache); @@ -610,10 +610,9 @@ aarch64_fetch_registers (struct regcache *regcache, int regno) else if (regno < AARCH64_V0_REGNUM) fetch_gregs_from_thread (regcache); /* SVE register? */ - else if ((tdep->has_sve () || tdep->has_sme ()) - && regno < AARCH64_SVE_VG_REGNUM) + else if ((tdep->has_sve || tdep->has_sme ()) && regno < AARCH64_SVE_VG_REGNUM) fetch_sveregs_from_thread (regcache); - else if (tdep->has_sve () && regno == AARCH64_SVE_VG_REGNUM) + else if (tdep->has_sve && regno == AARCH64_SVE_VG_REGNUM) fetch_sve_vg_from_thread (regcache); /* FPSIMD register? */ else if (regno <= AARCH64_FPCR_REGNUM) @@ -694,7 +693,7 @@ aarch64_store_registers (struct regcache *regcache, int regno) /* We attempt to store SVE registers if there is support for either SVE or SME (due to the SSVE state of SME). */ - if (tdep->has_sve () || tdep->has_sme ()) + if (tdep->has_sve || tdep->has_sme ()) store_sveregs_to_thread (regcache); else store_fpregs_to_thread (regcache); @@ -715,10 +714,9 @@ aarch64_store_registers (struct regcache *regcache, int regno) else if (regno < AARCH64_V0_REGNUM) store_gregs_to_thread (regcache); /* SVE register? */ - else if ((tdep->has_sve () || tdep->has_sme ()) - && regno < AARCH64_SVE_VG_REGNUM) + else if ((tdep->has_sve || tdep->has_sme ()) && regno < AARCH64_SVE_VG_REGNUM) store_sveregs_to_thread (regcache); - else if (tdep->has_sve () && regno == AARCH64_SVE_VG_REGNUM) + else if (tdep->has_sve && regno == AARCH64_SVE_VG_REGNUM) store_sve_vg_to_thread (regcache); /* FPSIMD register? */ else if (regno <= AARCH64_FPCR_REGNUM) @@ -911,7 +909,7 @@ aarch64_linux_nat_target::read_description () /* SVE/SSVE check. Reading VQ may return either the regular vector length or the streaming vector length, depending on whether streaming mode is active or not. */ - features.vq = aarch64_sve_get_vq (tid); + features.sve = aarch64_sve_get_vq (tid) != 0; features.pauth = hwcap & AARCH64_HWCAP_PACA; features.mte = hwcap2 & HWCAP2_MTE; features.tls = aarch64_tls_register_count (tid); @@ -1025,19 +1023,19 @@ aarch64_linux_nat_target::thread_architecture (ptid_t ptid) the tdep. */ aarch64_gdbarch_tdep *tdep = gdbarch_tdep (inf->arch ()); - uint64_t vq = aarch64_sve_get_vq (ptid.lwp ()); + bool sve = aarch64_sve_get_vq (ptid.lwp ()) != 0; uint64_t svq = aarch64_za_get_svq (ptid.lwp ()); - if (vq == tdep->vq && svq == tdep->sme_svq) + if (sve == tdep->has_sve && svq == tdep->sme_svq) return inf->arch (); /* We reach here if any vector length for the thread is different from its value at process start. Lookup gdbarch via info (potentially creating a - new one) by using a target description that corresponds to the new vq/svq - value and the current architecture features. */ + new one) by using a target description that corresponds to the new + vector/matrix state and the current architecture features. */ const struct target_desc *tdesc = gdbarch_target_desc (inf->arch ()); aarch64_features features = aarch64_features_from_target_desc (tdesc); - features.vq = vq; + features.sve = sve; features.svq = svq; /* Check for the SME2 feature. */ diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index c608a84bc711..c04b693f70e7 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -275,7 +275,8 @@ read_aarch64_ctx (CORE_ADDR ctx_addr, enum bfd_endian byte_order, static void aarch64_linux_restore_vregs (struct gdbarch *gdbarch, struct trad_frame_cache *cache, - CORE_ADDR fpsimd_context) + CORE_ADDR fpsimd_context, + ULONGEST vl) { /* WARNING: SIMD state is laid out in memory in target-endian format. @@ -335,7 +336,7 @@ aarch64_linux_restore_vregs (struct gdbarch *gdbarch, num_regs + AARCH64_B0_REGNUM + i, {buf, B_REGISTER_SIZE}); - if (tdep->has_sve ()) + if (tdep->has_sve) trad_frame_set_reg_value_bytes (cache, num_regs + AARCH64_SVE_V0_REGNUM + i, {buf, V_REGISTER_SIZE}); @@ -356,22 +357,22 @@ aarch64_linux_restore_vregs (struct gdbarch *gdbarch, trad_frame_set_reg_addr (cache, num_regs + AARCH64_B0_REGNUM + i, offset); - if (tdep->has_sve ()) + if (tdep->has_sve) trad_frame_set_reg_addr (cache, num_regs + AARCH64_SVE_V0_REGNUM + i, offset); } - if (tdep->has_sve ()) + if (tdep->has_sve) { /* If SVE is supported for this target, zero out the Z registers then copy the first 16 bytes of each of the V registers to the associated Z register. Otherwise the Z registers will contain uninitialized data. */ - std::vector z_buffer (tdep->vq * 16); + std::vector z_buffer (vl); /* We have already handled the endianness swap above, so we don't need to worry about it here. */ - memcpy (z_buffer.data (), buf, V_REGISTER_SIZE); + memcpy (z_buffer.data (), buf, vl); trad_frame_set_reg_value_bytes (cache, AARCH64_SVE_Z0_REGNUM + i, z_buffer); @@ -403,8 +404,8 @@ aarch64_linux_read_signal_frame_info (const frame_info_ptr &this_frame, CORE_ADDR section_end = signal_frame.section_end; uint32_t size, magic; bool extra_found = false; - enum bfd_endian byte_order - = gdbarch_byte_order (get_frame_arch (this_frame)); + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); while ((magic = read_aarch64_ctx (section, byte_order, &size)) != 0 && size != 0) @@ -423,6 +424,11 @@ aarch64_linux_read_signal_frame_info (const frame_info_ptr &this_frame, /* Check if the section is followed by a full SVE dump, and set sve_regs if it is. */ gdb_byte buf[4]; + aarch64_gdbarch_tdep *tdep + = gdbarch_tdep (gdbarch); + + if (!tdep->has_sve) + break; /* Extract the vector length. */ if (target_read_memory (section + AARCH64_SVE_CONTEXT_VL_OFFSET, @@ -436,6 +442,10 @@ aarch64_linux_read_signal_frame_info (const frame_info_ptr &this_frame, signal_frame.vl = extract_unsigned_integer (buf, 2, byte_order); + if (signal_frame.vl == 0) + error (_ ("Invalid vector length in signal frame %" PRIu64 "."), + signal_frame.vl); + /* Extract the flags to check if we are in streaming mode. */ if (target_read_memory (section + AARCH64_SVE_CONTEXT_FLAGS_OFFSET, @@ -598,7 +608,7 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self, aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); /* Restore the SVE / FPSIMD registers. */ - if (tdep->has_sve () && signal_frame.sve_section != 0) + if (tdep->has_sve && signal_frame.sve_section != 0) { ULONGEST vq = sve_vq_from_vl (signal_frame.vl); CORE_ADDR sve_regs = signal_frame.sve_section; @@ -648,8 +658,9 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self, fpsimd + AARCH64_FPSIMD_FPCR_OFFSET); /* If there was no SVE section then set up the V registers. */ - if (!tdep->has_sve () || signal_frame.sve_section == 0) - aarch64_linux_restore_vregs (gdbarch, this_cache, fpsimd); + if (!tdep->has_sve || signal_frame.sve_section == 0) + aarch64_linux_restore_vregs (gdbarch, this_cache, fpsimd, + tdep->has_sve ? signal_frame.vl : 0); } /* Restore the SME registers. */ @@ -726,7 +737,7 @@ aarch64_linux_sigframe_prev_arch (const frame_info_ptr &this_frame, const struct target_desc *tdesc = gdbarch_target_desc (get_frame_arch (this_frame)); aarch64_features features = aarch64_features_from_target_desc (tdesc); - features.vq = sve_vq_from_vl (signal_frame.vl); + features.sve = signal_frame.vl != 0; features.svq = (uint8_t) sve_vq_from_vl (signal_frame.svl); struct gdbarch_info info; @@ -1053,9 +1064,12 @@ collect_sve_regset (const struct regset *regset, gdb_byte *header = (gdb_byte *) buf; struct gdbarch *gdbarch = regcache->arch (); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - uint64_t vq = tdep->vq; + ULONGEST vg; + // FIXME: Remove this cast. + enum register_status vg_status + = const_cast (regcache)->raw_read (AARCH64_SVE_VG_REGNUM, &vg); + gdb_assert (vg_status == REG_VALID); gdb_assert (buf != NULL); gdb_assert (size > SVE_HEADER_SIZE); @@ -1067,7 +1081,7 @@ collect_sve_regset (const struct regset *regset, store_unsigned_integer (header + SVE_HEADER_MAX_SIZE_OFFSET, SVE_HEADER_MAX_SIZE_LENGTH, byte_order, max_size); store_unsigned_integer (header + SVE_HEADER_VL_OFFSET, SVE_HEADER_VL_LENGTH, - byte_order, sve_vl_from_vq (vq)); + byte_order, sve_vl_from_vg (vg)); uint16_t max_vl = SVE_CORE_DUMMY_MAX_VL; store_unsigned_integer (header + SVE_HEADER_MAX_VL_OFFSET, SVE_HEADER_MAX_VL_LENGTH, byte_order, @@ -1437,14 +1451,15 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, cb (".reg", AARCH64_LINUX_SIZEOF_GREGSET, AARCH64_LINUX_SIZEOF_GREGSET, &aarch64_linux_gregset, NULL, cb_data); - if (tdep->has_sve ()) + if (tdep->has_sve) { /* Create this on the fly in order to handle vector register sizes. */ + // FIXME: Don't use maximum VQ. const struct regcache_map_entry sve_regmap[] = { - { 32, AARCH64_SVE_Z0_REGNUM, (int) (tdep->vq * 16) }, - { 16, AARCH64_SVE_P0_REGNUM, (int) (tdep->vq * 16 / 8) }, - { 1, AARCH64_SVE_FFR_REGNUM, (int) (tdep->vq * 16 / 8) }, + { 32, AARCH64_SVE_Z0_REGNUM, (int)(AARCH64_MAX_SVE_VQ * 16) }, + { 16, AARCH64_SVE_P0_REGNUM, (int)(AARCH64_MAX_SVE_VQ * 16 / 8) }, + { 1, AARCH64_SVE_FFR_REGNUM, (int)(AARCH64_MAX_SVE_VQ * 16 / 8) }, { 1, AARCH64_FPSR_REGNUM, 4 }, { 1, AARCH64_FPCR_REGNUM, 4 }, { 0 } @@ -1627,7 +1642,7 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch, Otherwise the SVE section is considered active. This guarantees we will have the correct target description with the correct SVE vector length. */ - features.vq = aarch64_linux_core_read_vq_from_sections (gdbarch, abfd); + features.sve = aarch64_linux_core_read_vq_from_sections (gdbarch, abfd) != 0; features.pauth = hwcap & AARCH64_HWCAP_PACA; features.mte = hwcap2 & HWCAP2_MTE; diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 04442f22ea3f..ff356b6a0ac7 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -2468,38 +2468,54 @@ aarch64_vnv_type (struct gdbarch *gdbarch) /* Implement the "dwarf2_reg_to_regnum" gdbarch method. */ static int -aarch64_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) +aarch64_tdep_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) { + int ret = aarch64_dwarf_reg_to_regnum (reg); + + if (ret != -1) + return ret; + aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + if (tdep->has_pauth () && reg == AARCH64_DWARF_RA_SIGN_STATE) + return tdep->ra_sign_state_regnum; - if (reg >= AARCH64_DWARF_X0 && reg <= AARCH64_DWARF_X0 + 30) - return AARCH64_X0_REGNUM + reg - AARCH64_DWARF_X0; + return -1; +} + +/* Implement the "regnum_to_dwarf2_reg" gdbarch method. */ + +static int +aarch64_regnum_to_dwarf_reg (struct gdbarch *gdbarch, int regnum) +{ + if (regnum >= AARCH64_X0_REGNUM && regnum <= AARCH64_X0_REGNUM + 30) + return AARCH64_DWARF_X0 + regnum - AARCH64_X0_REGNUM; - if (reg == AARCH64_DWARF_SP) - return AARCH64_SP_REGNUM; + if (regnum == AARCH64_SP_REGNUM) + return AARCH64_DWARF_SP; - if (reg == AARCH64_DWARF_PC) - return AARCH64_PC_REGNUM; + if (regnum == AARCH64_PC_REGNUM) + return AARCH64_DWARF_PC; - if (reg >= AARCH64_DWARF_V0 && reg <= AARCH64_DWARF_V0 + 31) - return AARCH64_V0_REGNUM + reg - AARCH64_DWARF_V0; + if (regnum >= AARCH64_V0_REGNUM && regnum <= AARCH64_V0_REGNUM + 31) + return AARCH64_DWARF_V0 + regnum - AARCH64_V0_REGNUM; - if (reg == AARCH64_DWARF_SVE_VG) - return AARCH64_SVE_VG_REGNUM; + if (regnum == AARCH64_SVE_VG_REGNUM) + return AARCH64_DWARF_SVE_VG; - if (reg == AARCH64_DWARF_SVE_FFR) - return AARCH64_SVE_FFR_REGNUM; + if (regnum == AARCH64_SVE_FFR_REGNUM) + return AARCH64_DWARF_SVE_FFR; - if (reg >= AARCH64_DWARF_SVE_P0 && reg <= AARCH64_DWARF_SVE_P0 + 15) - return AARCH64_SVE_P0_REGNUM + reg - AARCH64_DWARF_SVE_P0; + if (regnum >= AARCH64_SVE_P0_REGNUM && regnum <= AARCH64_SVE_P0_REGNUM + 15) + return AARCH64_DWARF_SVE_P0 + regnum - AARCH64_SVE_P0_REGNUM; - if (reg >= AARCH64_DWARF_SVE_Z0 && reg <= AARCH64_DWARF_SVE_Z0 + 15) - return AARCH64_SVE_Z0_REGNUM + reg - AARCH64_DWARF_SVE_Z0; + if (regnum >= AARCH64_SVE_Z0_REGNUM && regnum <= AARCH64_SVE_Z0_REGNUM + 15) + return AARCH64_DWARF_SVE_Z0 + regnum - AARCH64_SVE_Z0_REGNUM; + aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); if (tdep->has_pauth ()) { - if (reg == AARCH64_DWARF_RA_SIGN_STATE) - return tdep->ra_sign_state_regnum; + if (regnum == tdep->ra_sign_state_regnum) + return AARCH64_DWARF_RA_SIGN_STATE; } return -1; @@ -2994,7 +3010,7 @@ aarch64_pseudo_register_name (struct gdbarch *gdbarch, int regnum) if (is_w_pseudo_register (gdbarch, regnum)) return w_name[regnum - tdep->w_pseudo_base]; - if (tdep->has_sve ()) + if (tdep->has_sve) { static const char *const sve_v_name[] = { @@ -3050,7 +3066,7 @@ aarch64_pseudo_register_type (struct gdbarch *gdbarch, int regnum) if (p_regnum >= AARCH64_B0_REGNUM && p_regnum < AARCH64_B0_REGNUM + 32) return aarch64_vnb_type (gdbarch); - if (tdep->has_sve () && p_regnum >= AARCH64_SVE_V0_REGNUM + if (tdep->has_sve && p_regnum >= AARCH64_SVE_V0_REGNUM && p_regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM) return aarch64_vnv_type (gdbarch); @@ -3090,7 +3106,7 @@ aarch64_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum, return group == all_reggroup || group == vector_reggroup; else if (p_regnum >= AARCH64_B0_REGNUM && p_regnum < AARCH64_B0_REGNUM + 32) return group == all_reggroup || group == vector_reggroup; - else if (tdep->has_sve () && p_regnum >= AARCH64_SVE_V0_REGNUM + else if (tdep->has_sve && p_regnum >= AARCH64_SVE_V0_REGNUM && p_regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM) return group == all_reggroup || group == vector_reggroup; else if (is_sme_pseudo_register (gdbarch, regnum)) @@ -3285,7 +3301,7 @@ aarch64_pseudo_read_value (gdbarch *gdbarch, const frame_info_ptr &next_frame, 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 + 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); @@ -3425,7 +3441,7 @@ aarch64_pseudo_write (gdbarch *gdbarch, const frame_info_ptr &next_frame, return aarch64_pseudo_write_1 (gdbarch, next_frame, pseudo_offset - AARCH64_B0_REGNUM, buf); - if (tdep->has_sve () && pseudo_offset >= AARCH64_SVE_V0_REGNUM + 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); @@ -3941,10 +3957,6 @@ aarch64_displaced_step_hw_singlestep (struct gdbarch *gdbarch) const target_desc * aarch64_read_description (const aarch64_features &features) { - if (features.vq > AARCH64_MAX_SVE_VQ) - error (_("VQ is %" PRIu64 ", maximum supported value is %d"), features.vq, - AARCH64_MAX_SVE_VQ); - struct target_desc *tdesc = tdesc_aarch64_map[features]; if (tdesc == NULL) @@ -3956,27 +3968,6 @@ aarch64_read_description (const aarch64_features &features) return tdesc; } -/* Return the VQ used when creating the target description TDESC. */ - -static uint64_t -aarch64_get_tdesc_vq (const struct target_desc *tdesc) -{ - const struct tdesc_feature *feature_sve; - - if (!tdesc_has_registers (tdesc)) - return 0; - - feature_sve = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.sve"); - - if (feature_sve == nullptr) - return 0; - - uint64_t vl = tdesc_register_bitsize (feature_sve, - aarch64_sve_register_names[0]) / 8; - return sve_vq_from_vl (vl); -} - - /* Return the svq (streaming vector quotient) used when creating the target description TDESC. */ @@ -4013,7 +4004,8 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc) if (tdesc == nullptr) return features; - features.vq = aarch64_get_tdesc_vq (tdesc); + features.sve + = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.sve") != nullptr; /* We need to look for a couple pauth feature name variations. */ features.pauth @@ -4358,13 +4350,11 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) int i, num_regs = 0, num_pseudo_regs = 0; int first_pauth_regnum = -1, ra_sign_state_offset = -1; int first_mte_regnum = -1, first_tls_regnum = -1; - uint64_t vq = aarch64_get_tdesc_vq (info.target_desc); + bool has_sve = (info.target_desc == nullptr ? false + : tdesc_find_feature (info.target_desc, + "org.gnu.gdb.aarch64.sve") != nullptr); uint64_t svq = aarch64_get_tdesc_svq (info.target_desc); - if (vq > AARCH64_MAX_SVE_VQ) - internal_error (_("VQ out of bounds: %s (max %d)"), - pulongest (vq), AARCH64_MAX_SVE_VQ); - if (svq > AARCH64_MAX_SVE_VQ) internal_error (_("Streaming vector quotient (svq) out of bounds: %s" " (max %d)"), @@ -4377,18 +4367,17 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { aarch64_gdbarch_tdep *tdep = gdbarch_tdep (best_arch->gdbarch); - if (tdep && tdep->vq == vq && tdep->sme_svq == svq) + if (tdep && tdep->has_sve == has_sve && tdep->sme_svq == svq) return best_arch->gdbarch; } /* Ensure we always have a target descriptor, and that it is for the given VQ value. */ const struct target_desc *tdesc = info.target_desc; - if (!tdesc_has_registers (tdesc) || vq != aarch64_get_tdesc_vq (tdesc) - || svq != aarch64_get_tdesc_svq (tdesc)) + if (!tdesc_has_registers (tdesc)) { aarch64_features features; - features.vq = vq; + features.sve = has_sve; features.svq = svq; tdesc = aarch64_read_description (features); } @@ -4603,7 +4592,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->lowest_pc = 0x20; tdep->jb_pc = -1; /* Longjump support not enabled by default. */ tdep->jb_elt_size = 8; - tdep->vq = vq; + tdep->has_sve = feature_sve != nullptr; tdep->pauth_reg_base = first_pauth_regnum; tdep->pauth_reg_count = pauth_masks; tdep->ra_sign_state_regnum = -1; @@ -4690,7 +4679,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_stack_frame_destroyed_p (gdbarch, aarch64_stack_frame_destroyed_p); /* Internal <-> external register number maps. */ - set_gdbarch_dwarf2_reg_to_regnum (gdbarch, aarch64_dwarf_reg_to_regnum); + set_gdbarch_dwarf2_reg_to_regnum (gdbarch, aarch64_tdep_dwarf_reg_to_regnum); + set_gdbarch_regnum_to_dwarf2_reg (gdbarch, aarch64_regnum_to_dwarf_reg); /* Returning results. */ set_gdbarch_return_value_as_value (gdbarch, aarch64_return_value); @@ -4857,6 +4847,9 @@ aarch64_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file) gdb_printf (file, _("aarch64_dump_tdep: Lowest pc = 0x%s\n"), paddress (gdbarch, tdep->lowest_pc)); + gdb_printf (file, _ ("aarch64_dump_tdep: has_sve = %s\n"), + tdep->has_sve ? "true" : "false"); + /* SME fields. */ gdb_printf (file, _("aarch64_dump_tdep: sme_tile_type_q = %s\n"), host_address_to_string (tdep->sme_tile_type_q)); diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h index 50166fb4f24f..c34027c7f387 100644 --- a/gdb/aarch64-tdep.h +++ b/gdb/aarch64-tdep.h @@ -31,17 +31,6 @@ struct gdbarch; struct regset; -/* AArch64 Dwarf register numbering. */ -#define AARCH64_DWARF_X0 0 -#define AARCH64_DWARF_SP 31 -#define AARCH64_DWARF_PC 32 -#define AARCH64_DWARF_RA_SIGN_STATE 34 -#define AARCH64_DWARF_V0 64 -#define AARCH64_DWARF_SVE_VG 46 -#define AARCH64_DWARF_SVE_FFR 47 -#define AARCH64_DWARF_SVE_P0 48 -#define AARCH64_DWARF_SVE_Z0 96 - /* Size of integer registers. */ #define X_REGISTER_SIZE 8 #define B_REGISTER_SIZE 1 @@ -100,14 +89,8 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base int (*aarch64_syscall_record) (struct regcache *regcache, unsigned long svc_number) = nullptr; - /* The VQ value for SVE targets, or zero if SVE is not supported. */ - uint64_t vq = 0; - - /* Returns true if the target supports SVE. */ - bool has_sve () const - { - return vq != 0; - } + /* Whether SVE is supported. */ + bool has_sve = false; int pauth_reg_base = 0; /* Number of pauth masks. */ diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c index 5526aa1b580b..aa246857a79f 100644 --- a/gdb/arch/aarch64.c +++ b/gdb/arch/aarch64.c @@ -42,10 +42,10 @@ aarch64_create_target_description (const aarch64_features &features) regnum = create_feature_aarch64_core (tdesc.get (), regnum); - if (features.vq == 0) + if (!features.sve) regnum = create_feature_aarch64_fpu (tdesc.get (), regnum); else - regnum = create_feature_aarch64_sve (tdesc.get (), regnum, features.vq); + regnum = create_feature_aarch64_sve (tdesc.get (), regnum); if (features.pauth) regnum = create_feature_aarch64_pauth (tdesc.get (), regnum); @@ -98,3 +98,35 @@ aarch64_mask_from_pac_registers (const CORE_ADDR cmask, const CORE_ADDR dmask) return cmask; } + +/* See arch/aarch64.h. */ + +int +aarch64_dwarf_reg_to_regnum (int reg) +{ + if (reg >= AARCH64_DWARF_X0 && reg <= AARCH64_DWARF_X0 + 30) + return AARCH64_X0_REGNUM + reg - AARCH64_DWARF_X0; + + if (reg == AARCH64_DWARF_SP) + return AARCH64_SP_REGNUM; + + if (reg == AARCH64_DWARF_PC) + return AARCH64_PC_REGNUM; + + if (reg >= AARCH64_DWARF_V0 && reg <= AARCH64_DWARF_V0 + 31) + return AARCH64_V0_REGNUM + reg - AARCH64_DWARF_V0; + + if (reg == AARCH64_DWARF_SVE_VG) + return AARCH64_SVE_VG_REGNUM; + + if (reg == AARCH64_DWARF_SVE_FFR) + return AARCH64_SVE_FFR_REGNUM; + + if (reg >= AARCH64_DWARF_SVE_P0 && reg <= AARCH64_DWARF_SVE_P0 + 15) + return AARCH64_SVE_P0_REGNUM + reg - AARCH64_DWARF_SVE_P0; + + if (reg >= AARCH64_DWARF_SVE_Z0 && reg <= AARCH64_DWARF_SVE_Z0 + 15) + return AARCH64_SVE_Z0_REGNUM + reg - AARCH64_DWARF_SVE_Z0; + + return -1; +} diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h index b4c0111aeb49..1857fd4802fb 100644 --- a/gdb/arch/aarch64.h +++ b/gdb/arch/aarch64.h @@ -26,12 +26,7 @@ used to select register sets. */ struct aarch64_features { - /* A non zero VQ value indicates both the presence of SVE and the - Vector Quotient - the number of 128-bit chunks in an SVE Z - register. - - The maximum value for VQ is 16 (5 bits). */ - uint64_t vq = 0; + bool sve = false; bool pauth = false; bool mte = false; @@ -55,7 +50,7 @@ struct aarch64_features inline bool operator==(const aarch64_features &lhs, const aarch64_features &rhs) { - return lhs.vq == rhs.vq + return lhs.sve == rhs.sve && lhs.pauth == rhs.pauth && lhs.mte == rhs.mte && lhs.tls == rhs.tls @@ -72,7 +67,7 @@ namespace std { std::size_t h; - h = features.vq; + h = features.sve; h = h << 1 | features.pauth; h = h << 1 | features.mte; /* Shift by two bits for now. We may need to increase this in the future @@ -107,6 +102,9 @@ CORE_ADDR aarch64_remove_top_bits (CORE_ADDR pointer, CORE_ADDR mask); CORE_ADDR aarch64_mask_from_pac_registers (const CORE_ADDR cmask, const CORE_ADDR dmask); +/* Map DWARF reg number to GDB regnum. */ +int aarch64_dwarf_reg_to_regnum (int reg); + /* Register numbers of various important registers. Note that on SVE, the Z registers reuse the V register numbers and the V registers become pseudo registers. */ @@ -136,6 +134,17 @@ enum aarch64_regnum AARCH64_LAST_V_ARG_REGNUM = AARCH64_V0_REGNUM + 7 }; +/* AArch64 Dwarf register numbering. */ +#define AARCH64_DWARF_X0 0 +#define AARCH64_DWARF_SP 31 +#define AARCH64_DWARF_PC 32 +#define AARCH64_DWARF_RA_SIGN_STATE 34 +#define AARCH64_DWARF_V0 64 +#define AARCH64_DWARF_SVE_VG 46 +#define AARCH64_DWARF_SVE_FFR 47 +#define AARCH64_DWARF_SVE_P0 48 +#define AARCH64_DWARF_SVE_Z0 96 + /* Sizes of various AArch64 registers. */ #define AARCH64_TLS_REGISTER_SIZE 8 #define V_REGISTER_SIZE 16 diff --git a/gdb/features/Makefile b/gdb/features/Makefile index 01b327cbce1f..f84debb4f15c 100644 --- a/gdb/features/Makefile +++ b/gdb/features/Makefile @@ -202,6 +202,7 @@ FEATURE_XMLFILES = aarch64-core.xml \ aarch64-fpu.xml \ aarch64-pauth.xml \ aarch64-mte.xml \ + aarch64-sve.xml \ arc/v1-core.xml \ arc/v1-aux.xml \ arc/v2-core.xml \ diff --git a/gdb/features/aarch64-sve.c b/gdb/features/aarch64-sve.c index 67fc801ec70e..1bed5f402376 100644 --- a/gdb/features/aarch64-sve.c +++ b/gdb/features/aarch64-sve.c @@ -1,76 +1,86 @@ -/* Copyright (C) 2018-2024 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 . */ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: aarch64-sve.xml */ #include "gdbsupport/tdesc.h" - -/* This function is NOT auto generated from xml. Create the aarch64 with SVE - feature into RESULT, where SCALE is the number of 128 bit chunks in a Z - register. */ +#include "dwarf2.h" static int -create_feature_aarch64_sve (struct target_desc *result, long regnum, - uint64_t scale) +create_feature_aarch64_sve (struct target_desc *result, long regnum) { struct tdesc_feature *feature; - tdesc_type *element_type, *field_type; - tdesc_type_with_fields *type_with_fields; feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.sve"); - + tdesc_type *element_type; element_type = tdesc_named_type (feature, "uint128"); - tdesc_create_vector (feature, "svevqu", element_type, scale); + gdb_byte svevq_count_locexpr[5]; + svevq_count_locexpr[0] = DW_OP_bregx; + svevq_count_locexpr[1] = 46; + svevq_count_locexpr[2] = 0; + svevq_count_locexpr[3] = DW_OP_lit2; + svevq_count_locexpr[4] = DW_OP_div; + tdesc_create_vector (feature, "svevqu", element_type, svevq_count_locexpr); element_type = tdesc_named_type (feature, "int128"); - tdesc_create_vector (feature, "svevqs", element_type, scale); + tdesc_create_vector (feature, "svevqs", element_type, svevq_count_locexpr); element_type = tdesc_named_type (feature, "ieee_double"); - tdesc_create_vector (feature, "svevdf", element_type, 2 * scale); + gdb_byte svevd_count_locexpr[3]; + svevd_count_locexpr[0] = DW_OP_bregx; + svevd_count_locexpr[1] = 46; + svevd_count_locexpr[2] = 0; + tdesc_create_vector (feature, "svevdf", element_type, svevd_count_locexpr); element_type = tdesc_named_type (feature, "uint64"); - tdesc_create_vector (feature, "svevdu", element_type, 2 * scale); + tdesc_create_vector (feature, "svevdu", element_type, svevd_count_locexpr); element_type = tdesc_named_type (feature, "int64"); - tdesc_create_vector (feature, "svevds", element_type, 2 * scale); + tdesc_create_vector (feature, "svevds", element_type, svevd_count_locexpr); element_type = tdesc_named_type (feature, "ieee_single"); - tdesc_create_vector (feature, "svevsf", element_type, 4 * scale); + gdb_byte svevs_count_locexpr[5]; + svevs_count_locexpr[0] = DW_OP_bregx; + svevs_count_locexpr[1] = 46; + svevs_count_locexpr[2] = 0; + svevs_count_locexpr[3] = DW_OP_lit2; + svevs_count_locexpr[4] = DW_OP_mul; + tdesc_create_vector (feature, "svevsf", element_type, svevs_count_locexpr); element_type = tdesc_named_type (feature, "uint32"); - tdesc_create_vector (feature, "svevsu", element_type, 4 * scale); + tdesc_create_vector (feature, "svevsu", element_type, svevs_count_locexpr); element_type = tdesc_named_type (feature, "int32"); - tdesc_create_vector (feature, "svevss", element_type, 4 * scale); + tdesc_create_vector (feature, "svevss", element_type, svevs_count_locexpr); element_type = tdesc_named_type (feature, "ieee_half"); - tdesc_create_vector (feature, "svevhf", element_type, 8 * scale); + gdb_byte svevh_count_locexpr[5]; + svevh_count_locexpr[0] = DW_OP_bregx; + svevh_count_locexpr[1] = 46; + svevh_count_locexpr[2] = 0; + svevh_count_locexpr[3] = DW_OP_lit4; + svevh_count_locexpr[4] = DW_OP_mul; + tdesc_create_vector (feature, "svevhf", element_type, svevh_count_locexpr); element_type = tdesc_named_type (feature, "uint16"); - tdesc_create_vector (feature, "svevhu", element_type, 8 * scale); + tdesc_create_vector (feature, "svevhu", element_type, svevh_count_locexpr); element_type = tdesc_named_type (feature, "int16"); - tdesc_create_vector (feature, "svevhs", element_type, 8 * scale); + tdesc_create_vector (feature, "svevhs", element_type, svevh_count_locexpr); element_type = tdesc_named_type (feature, "uint8"); - tdesc_create_vector (feature, "svevbu", element_type, 16 * scale); + gdb_byte svevb_count_locexpr[5]; + svevb_count_locexpr[0] = DW_OP_bregx; + svevb_count_locexpr[1] = 46; + svevb_count_locexpr[2] = 0; + svevb_count_locexpr[3] = DW_OP_lit8; + svevb_count_locexpr[4] = DW_OP_mul; + tdesc_create_vector (feature, "svevbu", element_type, svevb_count_locexpr); element_type = tdesc_named_type (feature, "int8"); - tdesc_create_vector (feature, "svevbs", element_type, 16 * scale); + tdesc_create_vector (feature, "svevbs", element_type, svevb_count_locexpr); + tdesc_type_with_fields *type_with_fields; type_with_fields = tdesc_create_union (feature, "svevnq"); + tdesc_type *field_type; field_type = tdesc_named_type (feature, "svevqu"); tdesc_add_field (type_with_fields, "u", field_type); field_type = tdesc_named_type (feature, "svevqs"); @@ -118,10 +128,15 @@ create_feature_aarch64_sve (struct target_desc *result, long regnum, field_type = tdesc_named_type (feature, "svevnb"); tdesc_add_field (type_with_fields, "b", field_type); - field_type = tdesc_named_type (feature, "uint8"); - tdesc_create_vector (feature, "svep", field_type, 2 * scale); + element_type = tdesc_named_type (feature, "uint8"); + gdb_byte svep_locexpr[5]; + svep_locexpr[0] = DW_OP_bregx; + svep_locexpr[1] = 46; + svep_locexpr[2] = 0; + svep_locexpr[3] = DW_OP_lit4; + svep_locexpr[4] = DW_OP_mul; + tdesc_create_vector (feature, "svep", element_type, svep_locexpr); - /* FPSR register type */ type_with_fields = tdesc_create_flags (feature, "fpsr_flags", 4); tdesc_add_flag (type_with_fields, 0, "IOC"); tdesc_add_flag (type_with_fields, 1, "DZC"); @@ -135,7 +150,6 @@ create_feature_aarch64_sve (struct target_desc *result, long regnum, tdesc_add_flag (type_with_fields, 30, "Z"); tdesc_add_flag (type_with_fields, 31, "N"); - /* FPCR register type */ type_with_fields = tdesc_create_flags (feature, "fpcr_flags", 4); tdesc_add_flag (type_with_fields, 0, "FIZ"); tdesc_add_flag (type_with_fields, 1, "AH"); @@ -155,57 +169,58 @@ create_feature_aarch64_sve (struct target_desc *result, long regnum, tdesc_add_flag (type_with_fields, 25, "DN"); tdesc_add_flag (type_with_fields, 26, "AHP"); - tdesc_create_reg (feature, "z0", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z1", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z2", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z3", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z4", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z5", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z6", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z7", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z8", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z9", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z10", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z11", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z12", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z13", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z14", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z15", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z16", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z17", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z18", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z19", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z20", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z21", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z22", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z23", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z24", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z25", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z26", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z27", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z28", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z29", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z30", regnum++, 1, NULL, 128 * scale, "svev"); - tdesc_create_reg (feature, "z31", regnum++, 1, NULL, 128 * scale, "svev"); + regnum = 34; + tdesc_create_reg (feature, "z0", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z1", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z2", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z3", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z4", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z5", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z6", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z7", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z8", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z9", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z10", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z11", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z12", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z13", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z14", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z15", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z16", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z17", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z18", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z19", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z20", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z21", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z22", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z23", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z24", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z25", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z26", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z27", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z28", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z29", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z30", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); + tdesc_create_reg (feature, "z31", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svev"); tdesc_create_reg (feature, "fpsr", regnum++, 1, NULL, 32, "fpsr_flags"); tdesc_create_reg (feature, "fpcr", regnum++, 1, NULL, 32, "fpcr_flags"); - tdesc_create_reg (feature, "p0", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p1", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p2", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p3", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p4", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p5", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p6", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p7", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p8", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p9", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p10", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p11", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p12", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p13", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p14", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "p15", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "ffr", regnum++, 1, NULL, 16 * scale, "svep"); - tdesc_create_reg (feature, "vg", regnum++, 1, NULL, 64, "int"); + tdesc_create_reg (feature, "p0", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p1", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p2", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p3", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p4", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p5", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p6", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p7", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p8", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p9", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p10", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p11", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p12", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p13", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p14", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "p15", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "ffr", regnum++, 1, NULL, TDESC_REG_VARIABLE_SIZE, "svep"); + tdesc_create_reg (feature, "vg", regnum++, 1, NULL, 64, "int", true); return regnum; } diff --git a/gdb/features/aarch64-sve.xml b/gdb/features/aarch64-sve.xml new file mode 100644 index 000000000000..b843012b7927 --- /dev/null +++ b/gdb/features/aarch64-sve.xml @@ -0,0 +1,217 @@ + + + + + + aarch64 + + + + + + + 85 + 2 + + + + + + + + + + + + 85 + + + + + + + + + + + + + + + + 85 + 2 + + + + + + + + + + + + + + + + + 85 + 4 + + + + + + + + + + + + + + + + + 85 + 8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 85 + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdbserver/configure.srv b/gdbserver/configure.srv index 95359137f4f4..62de58d0c013 100644 --- a/gdbserver/configure.srv +++ b/gdbserver/configure.srv @@ -57,6 +57,7 @@ case "${gdbserver_host}" in srv_tgtobj="${srv_tgtobj} $srv_linux_obj" srv_linux_regsets=yes srv_linux_thread_db=yes + srv_dwarf_reg_to_regnum=yes ipa_obj="linux-aarch64-ipa.o" ipa_obj="${ipa_obj} linux-aarch64-tdesc-ipa.o" ipa_obj="${ipa_obj} arch/aarch64-ipa.o" diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc index 998ad0a9d658..13c891d282ba 100644 --- a/gdbserver/linux-aarch64-low.cc +++ b/gdbserver/linux-aarch64-low.cc @@ -884,11 +884,11 @@ aarch64_adjust_register_sets (const struct aarch64_features &features) break; case NT_FPREGSET: /* This is unavailable when SVE is present. */ - if (features.vq == 0) + if (!features.sve) regset->size = sizeof (struct user_fpsimd_state); break; case NT_ARM_SVE: - if (features.vq > 0) + if (features.sve) regset->size = SVE_PT_SIZE (AARCH64_MAX_SVE_VQ, SVE_PT_REGS_SVE); break; case NT_ARM_PAC_MASK: @@ -938,7 +938,7 @@ aarch64_target::low_arch_setup () struct aarch64_features features; int pid = current_thread->id.pid (); - features.vq = aarch64_sve_get_vq (tid); + features.sve = aarch64_sve_get_vq (tid) != 0; /* A-profile PAC is 64-bit only. */ features.pauth = linux_get_hwcap (pid, 8) & AARCH64_HWCAP_PACA; /* A-profile MTE is 64-bit only. */ diff --git a/gdbserver/linux-aarch64-tdesc.cc b/gdbserver/linux-aarch64-tdesc.cc index 31ec7854cc0b..87f2a484ac32 100644 --- a/gdbserver/linux-aarch64-tdesc.cc +++ b/gdbserver/linux-aarch64-tdesc.cc @@ -37,10 +37,6 @@ aarch64_linux_read_description (const aarch64_features &features) initialised. */ static std::unordered_map tdesc_aarch64_map; - if (features.vq > AARCH64_MAX_SVE_VQ) - error (_("VQ is %" PRIu64 ", maximum supported value is %d"), features.vq, - AARCH64_MAX_SVE_VQ); - if (features.svq > AARCH64_MAX_SVE_VQ) error (_("Streaming svq is %" PRIu8 ", maximum supported value is %d"), features.svq, @@ -60,8 +56,6 @@ aarch64_linux_read_description (const aarch64_features &features) expedited_registers.push_back ("sp"); expedited_registers.push_back ("pc"); - if (features.vq > 0) - expedited_registers.push_back ("vg"); if (features.svq > 0) expedited_registers.push_back ("svg"); @@ -74,3 +68,14 @@ aarch64_linux_read_description (const aarch64_features &features) return tdesc; } + +/* See gdbsupport/tdesc.h. */ + +int +tdesc_dwarf_reg_to_regnum (const char *arch, int dwarf_reg) +{ + if (!strcmp (arch, "aarch64")) + return aarch64_dwarf_reg_to_regnum (dwarf_reg); + + return -1; +} From patchwork Sat Nov 2 02:56:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840285 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1159443wrb; Fri, 1 Nov 2024 20:02:08 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCUPRmyw+qNFYVD/f3G36hpkr3msyNen8p9Pj14j4+U+7py85/Wuwfsj6PGErx2JobL1Nuvx0Q==@linaro.org X-Google-Smtp-Source: AGHT+IH25ZgXimUV4fbpJ20ES+ZfqLnhNCw2GB8SBR9mcRvybJ0FHYPsbHlaE9Eva0R3GL+tZJ7M X-Received: by 2002:a05:622a:20f:b0:461:1e88:595d with SMTP id d75a77b69052e-4613bffac19mr350814151cf.21.1730516528245; Fri, 01 Nov 2024 20:02:08 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516528; cv=pass; d=google.com; s=arc-20240605; b=kTCLRQDNlVYRJHcIcm8vJzwZ4meCNbTKvKfN+MlNVNwogqaCfqumt3qGbPvImTHe0L FLWudpgbHgLahOAk/nwNXExmXEEAVEv9qJbbIlmiGf9LC3FupLo4oq02ilrNQptXXw98 1dpSmRwS7BrCor5ip8wTwbXu/3TcdyUdNyLP2Pyf0t0ue3Rsl0d4WgqBMIzijkcoUrgr a9t8MtWmKOjLGmTGxqDVe5/Xzv44qNHldxsc43UJ0eA8y1U/WYJ7WTc3m7Q17Ypx6fIG KcUiPZ9jQ5/POJU2Otn/Qpewqc119zXgRUTcytiQ1NDPRRm/v4Bh9K7ROz/SWRSiZPvs neLA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=J3PHdgSJAQOK1p2geX47XXWS1yij0wyq0qY7skGwBpc=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=dow41hj3ppQLEC71XziH9+NnWanziStbxZeWjuQcN5ePkn8vgrGgmRK/j0+HOSmBCm zuOoV4EoEWvUR4gUXiskGa4NVcWbvqPxqIx1oc/cyn6jODWCJTUpQYPGx3tbukJj9ATW AvJQvbrsMNwfNoMs+neuEsw+Uky+vwZb1q+VUBOyvSiOsttEPcVL3PhVcO26sJ7bJ/zE M+fbpoWG0E6YoM6K0Jj8pP5w1MMC+Mjub3m/d/aCYiH9ZOw4jXxw6NFWzlYzFDsf6Z+F wlM0W4yb9EmQpQSWnol2lpmtlVBuvv8ri2n8RwWk21Hp5mhHEtGEYQNDvhr+EqgmfFKR BY/Q==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=uMOkag7g; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id d75a77b69052e-462ad0b2284si62917081cf.1.2024.11.01.20.02.08 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 20:02:08 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=uMOkag7g; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DE07A3858C51 for ; Sat, 2 Nov 2024 03:02:07 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pj1-x1030.google.com (mail-pj1-x1030.google.com [IPv6:2607:f8b0:4864:20::1030]) by sourceware.org (Postfix) with ESMTPS id 932293857C6A for ; Sat, 2 Nov 2024 02:57:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 932293857C6A Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 932293857C6A Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::1030 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516248; cv=none; b=GnRCxgvDQWB07vok/vg4jZZFm+p8a8zLISkScXZFtCDuKzoDGJqM6PLZ4jLufNFz1kJWYAP5tEzy5AXrNwL3FBqDiCD1TZS5qRjyYwfgOSNiw/lSXwKTn3iqwN3fiZtuvYr3/Z/uHBPVlds8rmTe9BV6N96Wf9mWXXZh6VNNCGI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516248; c=relaxed/simple; bh=ctw8nBnneZpgGOgxGgNsBuJWdZP2Y4D24Wh6Qry9X8o=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Z0WEY9lzbnCLufj0u/KOl8WQuT5oe/Z3B6dPOWMD1PZVypiN/AeRzuO1UAso1DCpytgiB6Df4vRq1P1/Wkg+OiDQ6kj0SUrUKSV6RXv6eJEedAKbHoCub+mURZsGuOhcNh8Cv3vBfx+3bl2kTrgHfbA4fFx/xaq6zE8U+/PK7vw= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pj1-x1030.google.com with SMTP id 98e67ed59e1d1-2e5a0177531so2035477a91.2 for ; Fri, 01 Nov 2024 19:57:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516243; x=1731121043; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=J3PHdgSJAQOK1p2geX47XXWS1yij0wyq0qY7skGwBpc=; b=uMOkag7gjZ9jyOXeaSUHoF5XNgG75h4WiAqIjouV3ah4KzMf2UdsFu8TzBS0OqeSBz x7c9MdVP9v+XFgdA9KZYPK087uots9dTKINtZVyBqZ2Sny2H+4AeScUbCtWqDtb5v25L wiPIdtui60Kl2M/OEKcYsz4UOkao6msayRkzqyQYrM8SHACqoHP6ggx9+Zwy4JDk9EYi IUk+q1Nxf/VBOuZC0vU9TdedRJrTcsiYxVDQA7gBBTHc3NFLQSVrRSGMPO25j1FtX13b Ibp1IlF5HuRP+nbbWHIuhJ3HlipIg5YCgz4o67DrGQih0j/z5xpnMSPTCZOovqUuDHja 4YQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516243; x=1731121043; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=J3PHdgSJAQOK1p2geX47XXWS1yij0wyq0qY7skGwBpc=; b=SFQo9C/CRhHn6VxuWlJYlbXlztDBdNIN1MvbdRE8kGcZHK3aVYF4RjWQbX8VET0pIU +F1pPg12o0JflswgfFBhIXz6Dc2cjvQrlluNjbgEhhVJwVCm6qvUJkHuXHHgQn2uuPg1 3i01DqgBANMqDje+r5bjcmpMDxLMj3km6Yn0oNlfMETzxnqyNWKE8QFxq+Wei2dbME64 0tQkbvCU8E9uxxHN2+A3IAV+4/I/XxbTOR0p6pkHHw6aFZ/MBsSHOkd1YT/MPw6CRDPF FNerMj77Cx3eby+M9t1iGqU4bWWEugjQ+2bP9J1kHDpXagfQkz0jxnA94vI2SvdD0kyQ FA1A== X-Gm-Message-State: AOJu0YxNlOlt/E4gUwNbHH6otNbXzz2rVDCfSD+hwe2YV+JDM7wCT/6P Z1XmoD1VXxyh3GdnjjyhLGmJRUfzCaSoeYs6n1ke1l+2m4k8GYGZfgaNg0WQIYVD6nd4R/kt8xW U X-Received: by 2002:a17:90a:f185:b0:2e1:682b:361a with SMTP id 98e67ed59e1d1-2e8f11bad82mr26913548a91.28.1730516243294; Fri, 01 Nov 2024 19:57:23 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2e9201b65f7sm4259172a91.0.2024.11.01.19.57.22 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:57:22 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 14/15] GDB, gdbserver: aarch64: Use VG instead of VQ Date: Fri, 1 Nov 2024 23:56:34 -0300 Message-ID: <20241102025635.586759-15-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org GDB uses VQ ("vector quotient", i.e. chunks of 128-bit values) profusely, but it's actually easier for a debugger to work in terms of VG ("vector granule", i.e. chunks of 64-bit values) because DWARF defines the VG register. The only place where we need to use VQ is with the SVE_PT_SIZE macro. --- gdb/aarch64-linux-nat.c | 9 +++---- gdb/nat/aarch64-scalable-linux-ptrace.c | 33 ++++++++++++------------- gdb/nat/aarch64-scalable-linux-ptrace.h | 12 ++++----- gdbserver/linux-aarch64-low.cc | 2 +- 4 files changed, 27 insertions(+), 29 deletions(-) diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index 5e12a2e403f6..81caffe666ea 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -319,8 +319,7 @@ store_fpregs_to_thread (const struct regcache *regcache) static void fetch_sve_vg_from_thread (struct regcache *regcache) { - uint64_t vq = aarch64_sve_get_vq (regcache->ptid ().lwp ()); - uint64_t vg = sve_vg_from_vq (vq); + uint64_t vg = aarch64_sve_get_vg (regcache->ptid ().lwp ()); regcache->raw_supply (AARCH64_SVE_VG_REGNUM, &vg); } @@ -347,7 +346,7 @@ fetch_sveregs_from_thread (struct regcache *regcache) static void store_sve_vg_to_thread (struct regcache *regcache) { - if (!aarch64_sve_set_vq (regcache->ptid ().lwp (), regcache)) + if (!aarch64_sve_set_vg (regcache->ptid ().lwp (), regcache)) perror_with_name (_ ("Unable to set VG register")); } @@ -909,7 +908,7 @@ aarch64_linux_nat_target::read_description () /* SVE/SSVE check. Reading VQ may return either the regular vector length or the streaming vector length, depending on whether streaming mode is active or not. */ - features.sve = aarch64_sve_get_vq (tid) != 0; + features.sve = aarch64_sve_get_vg (tid) != 0; features.pauth = hwcap & AARCH64_HWCAP_PACA; features.mte = hwcap2 & HWCAP2_MTE; features.tls = aarch64_tls_register_count (tid); @@ -1023,7 +1022,7 @@ aarch64_linux_nat_target::thread_architecture (ptid_t ptid) the tdep. */ aarch64_gdbarch_tdep *tdep = gdbarch_tdep (inf->arch ()); - bool sve = aarch64_sve_get_vq (ptid.lwp ()) != 0; + bool sve = aarch64_sve_get_vg (ptid.lwp ()) != 0; uint64_t svq = aarch64_za_get_svq (ptid.lwp ()); if (sve == tdep->has_sve && svq == tdep->sme_svq) return inf->arch (); diff --git a/gdb/nat/aarch64-scalable-linux-ptrace.c b/gdb/nat/aarch64-scalable-linux-ptrace.c index ac375b78541a..126cc5a29e28 100644 --- a/gdb/nat/aarch64-scalable-linux-ptrace.c +++ b/gdb/nat/aarch64-scalable-linux-ptrace.c @@ -217,7 +217,7 @@ aarch64_sve_vl_valid (const bool sve_state, size_t vl) /* See nat/aarch64-scalable-linux-ptrace.h. */ uint64_t -aarch64_sve_get_vq (int tid) +aarch64_sve_get_vg (int tid) { struct iovec iovec; struct user_sve_header header; @@ -234,10 +234,10 @@ aarch64_sve_get_vq (int tid) return 0; } - /* Ptrace gives the vector length in bytes. Convert it to VQ, the number of - 128bit chunks in a Z register. We use VQ because 128 bits is the minimum - a Z register can increase in size. */ - uint64_t vq = sve_vq_from_vl (header.vl); + /* Ptrace gives the vector length in bytes. Convert it to VG, the number + of 64-bit chunks in a Z register. We use VG because DWARF defines a VG + pseudo-register. */ + uint64_t vg = sve_vg_from_vl (header.vl); if (!aarch64_sve_vl_valid (has_sve_state, header.vl)) { @@ -245,13 +245,13 @@ aarch64_sve_get_vq (int tid) return 0; } - return vq; + return vg; } /* See nat/aarch64-scalable-linux-ptrace.h. */ bool -aarch64_sve_set_vq (int tid, uint64_t vq) +aarch64_sve_set_vg (int tid, uint64_t vg) { struct iovec iovec; struct user_sve_header header; @@ -269,7 +269,7 @@ aarch64_sve_set_vq (int tid, uint64_t vq) return false; } - header.vl = sve_vl_from_vq (vq); + header.vl = sve_vl_from_vg (vg); if (ptrace (PTRACE_SETREGSET, tid, has_sve_state? NT_ARM_SVE : NT_ARM_SSVE, &iovec) < 0) @@ -284,7 +284,7 @@ aarch64_sve_set_vq (int tid, uint64_t vq) /* See nat/aarch64-scalable-linux-ptrace.h. */ bool -aarch64_sve_set_vq (int tid, struct reg_buffer_common *reg_buf) +aarch64_sve_set_vg (int tid, struct reg_buffer_common *reg_buf) { uint64_t reg_vg = 0; @@ -296,18 +296,16 @@ aarch64_sve_set_vq (int tid, struct reg_buffer_common *reg_buf) { /* If vg is not available yet, fetch it from ptrace. The VG value from ptrace is likely the correct one. */ - uint64_t vq = aarch64_sve_get_vq (tid); + reg_vg = aarch64_sve_get_vg (tid); /* If something went wrong, just bail out. */ - if (vq == 0) + if (reg_vg == 0) return false; - - reg_vg = sve_vg_from_vq (vq); } else reg_buf->raw_collect (AARCH64_SVE_VG_REGNUM, ®_vg); - return aarch64_sve_set_vq (tid, sve_vq_from_vg (reg_vg)); + return aarch64_sve_set_vg (tid, reg_vg); } /* See nat/aarch64-scalable-linux-ptrace.h. */ @@ -410,9 +408,9 @@ aarch64_za_set_svq (int tid, const struct reg_buffer_common *reg_buf, gdb::byte_vector aarch64_fetch_sve_regset (int tid) { - uint64_t vq = aarch64_sve_get_vq (tid); + uint64_t vg = aarch64_sve_get_vg (tid); - if (vq == 0) + if (vg == 0) perror_with_name (_("Unable to fetch SVE/SSVE vector length")); /* A ptrace call with NT_ARM_SVE will return a header followed by either a @@ -420,6 +418,7 @@ aarch64_fetch_sve_regset (int tid) the one returned by NT_FPREGSET) if the kernel has not yet executed any SVE code. Make sure we allocate enough space for a full SVE dump. */ + uint64_t vq = sve_vq_from_vg (vg); gdb::byte_vector sve_state (SVE_PT_SIZE (vq, SVE_PT_REGS_SVE), 0); struct iovec iovec; @@ -709,7 +708,7 @@ aarch64_sve_regs_copy_from_reg_buf (int tid, { /* First store the vector length to the thread. This is done first to ensure the ptrace buffers read from the kernel are the correct size. */ - if (!aarch64_sve_set_vq (tid, reg_buf)) + if (!aarch64_sve_set_vg (tid, reg_buf)) perror_with_name (_("Unable to set VG register")); /* Obtain a dump of SVE registers from ptrace. */ diff --git a/gdb/nat/aarch64-scalable-linux-ptrace.h b/gdb/nat/aarch64-scalable-linux-ptrace.h index 2be45588785e..61edbdf1f864 100644 --- a/gdb/nat/aarch64-scalable-linux-ptrace.h +++ b/gdb/nat/aarch64-scalable-linux-ptrace.h @@ -80,15 +80,15 @@ bool read_za_header (int tid, struct user_za_header &header); Return true if successful, false otherwise. */ bool write_za_header (int tid, const struct user_za_header &header); -/* Read VQ for the given tid using ptrace. If SVE is not supported then zero - is returned (on a system that supports SVE, then VQ cannot be zero). */ -uint64_t aarch64_sve_get_vq (int tid); +/* Read VG for the given tid using ptrace. If SVE is not supported then zero + is returned (on a system that supports SVE, then VG cannot be zero). */ +uint64_t aarch64_sve_get_vg (int tid); -/* Set VQ in the kernel for the given tid, using either the value VQ or +/* Set VG in the kernel for the given tid, using either the value VG or reading from the register VG in the register buffer. */ -bool aarch64_sve_set_vq (int tid, uint64_t vq); -bool aarch64_sve_set_vq (int tid, struct reg_buffer_common *reg_buf); +bool aarch64_sve_set_vg (int tid, uint64_t vg); +bool aarch64_sve_set_vg (int tid, struct reg_buffer_common *reg_buf); /* Read the streaming mode vq (svq) for the given TID. If the ZA state is not supported or active, return 0. */ diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc index 13c891d282ba..c781e0246e49 100644 --- a/gdbserver/linux-aarch64-low.cc +++ b/gdbserver/linux-aarch64-low.cc @@ -938,7 +938,7 @@ aarch64_target::low_arch_setup () struct aarch64_features features; int pid = current_thread->id.pid (); - features.sve = aarch64_sve_get_vq (tid) != 0; + features.sve = aarch64_sve_get_vg (tid) != 0; /* A-profile PAC is 64-bit only. */ features.pauth = linux_get_hwcap (pid, 8) & AARCH64_HWCAP_PACA; /* A-profile MTE is 64-bit only. */ From patchwork Sat Nov 2 02:56:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840286 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1159703wrb; Fri, 1 Nov 2024 20:02:46 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVzs7/TWiRhefXkhPayJk2ZIqW8mURQHTCsFjGiqz/jQAXgT5tGbwFBDzQ+zi0Oz9uJjWQA8A==@linaro.org X-Google-Smtp-Source: AGHT+IFJ+SfzVtW1/wcuQ8CcA7A6CumT+IcCwHYcg/+0cN3cik50pbI1kZR1HQrqUqfhs0d8Up0v X-Received: by 2002:a05:6214:458f:b0:6cd:f90a:bb1b with SMTP id 6a1803df08f44-6d35c09e107mr79525636d6.4.1730516566562; Fri, 01 Nov 2024 20:02:46 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516566; cv=pass; d=google.com; s=arc-20240605; b=DzM39c1Z4mfMxtaSkDydaIMJ12avP/XX6K+rGNCc/67UHRERUzZfGWcYse10bXGR8N H0n8IxqXQp8as54vt3wgFZb8xXV/DkPCLfETnllb+hvCRpwaFaHkACyRdGxJ13n4KcQD 9jOO57xj2vqlwnlGp/oXovxoXP68a/ALYgQnhtx/VHkOOeG3ANokV76Nv2LmwmB5tHn3 LOaqExBFNajIugVRTwiYO4AQv65E5w+ln8WWX+JvSugmNQZNQNHrZAAiTT9/Y6zVkJAW CGFkFM2si8Q8QKqKSUITWPP7RPXHAJw25b6yndRPceArPbqe9VdgVcX/TRmA8AW5xgrz YQWw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=AvISyIfzlO8hVcDd+oajWMf6POF5iHimONQMZ5hyios=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=LsHuuw08Df2ntd1pvzcoupNorvByK4uX5Kew3ElDX+t5HyvXjglLIYBUXj+GdSFkn+ ad/I9hCNxeTVL4RVC31x078m+fEpAWcnpTGAdMj0Oj/NoDqE9CVgq9T6M/E4If8Uqo0q I0qJylCoePkucSNwPM22t7kPd0vl7mfJiV0eFFR4BL21IPhjbqLKsm2v+b8ken/DzHo4 O0cIvMATkEqnkeBgE8wq0+7e0G4BLeWnh75pMx5OmyKusavN/L7cSQoVN0G7HAu6TEgr ocbwv74/AypwLJ+5CbiPkNLqtikXi4lhor0NwrzGstrFIK9uC103P3OfEEYvMzV3PfEr wHRw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=xbysBmHu; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id 6a1803df08f44-6d3541a7036si56370386d6.498.2024.11.01.20.02.46 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 20:02:46 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=xbysBmHu; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 21D1F3858432 for ; Sat, 2 Nov 2024 03:02:46 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by sourceware.org (Postfix) with ESMTPS id 528F43858D37 for ; Sat, 2 Nov 2024 02:57:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 528F43858D37 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 528F43858D37 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::62d ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516250; cv=none; b=hNkrz5CSj1FkLqRaAM2mcB+yyt8+reGlMMS4/l9ooGtQjJkLNv8/QXXzGKxCXGUDY2rGlWXO3m8FTVi8jfvs49BU1YSL/Mr5vGjJDG5MwruaWDqailThDUJljSL8KBByErOFRvtY9WQkSJyYoGdL8/Dnns7jWKfdPjhvO5NHRxk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516250; c=relaxed/simple; bh=DILrWNhQY29yOuNAnI3MSUrtDs7/CxmCVYgfKnF04RQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=S61/DsREalOBEQt2itMnb6LM8k9Gcs+EuMAv9QvDoJgwfOQ0ezmH2ukJZjWaqYoxPXd7sBw5+J3i0gOtszsMjuujRgjcRuBVMZb0xaBHR5buTQx2GPF5CMjv+hV0ItG+S+Uy2HE8Cq+JaoajoTisyhlYvhaesqO2oCi9xGEby1Y= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x62d.google.com with SMTP id d9443c01a7336-20ca1b6a80aso26945805ad.2 for ; Fri, 01 Nov 2024 19:57:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516246; x=1731121046; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=AvISyIfzlO8hVcDd+oajWMf6POF5iHimONQMZ5hyios=; b=xbysBmHuoRuWTXTQr6C/Vs1v9//tLOxk1Lp7KatyqgQ5VonnC9AFpaYCZlAjoaXjZt /JgrwSBzIs+u+XhJGl4iSewcZynBy0ChIvmFHTrp3sZV9zSMikAmU1o+ABHdrGkCfTcB QZTeGtLGbucNzWKe1x7+Zdo3ef3vHoBHSq1DkxC2qaWU/oH//Ui2vsp1TiifXQnX8ZDf /E1Q5WB3bSE+bW6kTNCsxKxHwDYchSLRKOAHeL33tHI/OpnQo+mJYBhFHUqjDqKqycDE BVcyGWRfx8jY7ueKl+IK/XDw8ieAlKfntJuHTH+DXwnGU46oFKtsHVmCZohIHvzKqgMr Oafg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516246; x=1731121046; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=AvISyIfzlO8hVcDd+oajWMf6POF5iHimONQMZ5hyios=; b=gGsAiIEMo2aQ1ZVd8gE/laJShJM3XmHHFXtQeCTDn8TmWA6EKWdd0SIYiofluM94pa LWv4vGGA+q4ZxMlODU0sbvmQ3p1vTzJtsiaNydHwgDw8YPQ2Qzy1P3g20XJKkfx/xtW5 OeVC3hfcQeMEWKyLVDlKvEmrQCoirOW47aKzZ9CLlPZXpH0hBXECehyxp/qokQIxG/Vt V9obucmsmEx7ecrieB+F21Gqlue4G/YxCWSAqkjoqai6SpMmkNd9autp7+pZ3TJGNCKA eNH7Gqy85jZqB1vCCorTJz/QfQFfGuDTc8iI3NxI7pdF3vcjny0w+vf3OwfNQGvqVMo/ W8FA== X-Gm-Message-State: AOJu0Yy8cNsQ+jrkl7i/1Zr+je3x/FbWzLl4EZTJ/uYMPEFCR0d8sb8d nC0Sq0Nxq+m3AWc5Nim6PsDwsS8EKrTA5/valRuTsBexF0d4sXr0vcAnV0tfL9MVtT1VOh/9Rwz 8 X-Received: by 2002:a17:902:d2d0:b0:20c:e2ff:4a2e with SMTP id d9443c01a7336-2111b00690bmr87030075ad.53.1730516246224; Fri, 01 Nov 2024 19:57:26 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-21105709bdesm27767865ad.94.2024.11.01.19.57.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:57:25 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 15/15] gdb/testsuite: Add test to exercise multi-threaded AArch64 SVE inferiors Date: Fri, 1 Nov 2024 23:56:35 -0300 Message-ID: <20241102025635.586759-16-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org This testcase exercises two scenarios involving a multi-threaded inferior. In the first scenario, the secondary inferior thread changes its vector length and then hits a breakpoint. GDB then examines the SVE state. In the second one, the secondary inferior thread changes its vector length and then the main thread hits a breakpoint. GDB then switches to the secondary thread and examines the SVE state. --- gdb/testsuite/gdb.arch/aarch64-sve-threads.c | 125 ++++++++++++++++++ .../gdb.arch/aarch64-sve-threads.exp | 80 +++++++++++ 2 files changed, 205 insertions(+) create mode 100644 gdb/testsuite/gdb.arch/aarch64-sve-threads.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-sve-threads.exp diff --git a/gdb/testsuite/gdb.arch/aarch64-sve-threads.c b/gdb/testsuite/gdb.arch/aarch64-sve-threads.c new file mode 100644 index 000000000000..6640bd01a282 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sve-threads.c @@ -0,0 +1,125 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2024 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 . */ + +/* Exercise AArch64's Scalable Vector Extension in a multi-threaded program. */ + +#include +#include +#include +#include +#include +#include + +/* For one of the tests, the thread needs to sleep after setting the vector + length. This variable is set by GDB. */ +volatile bool should_sleep = false; + +/* Used to signal to the main thread that the additional thread's vector length + was changed. */ +sem_t vl_changed; + +/* Start routine for the additional thread. Sets a new vector length, sleeps if + requested then restores the original vector length. */ + +static void * +thread_function (void *unused) +{ + unsigned int vl; + int rc; + + rc = prctl (PR_SVE_GET_VL, 0, 0, 0, 0); + if (rc < 0) + { + perror ("FAILED to PR_SVE_GET_VL"); + sem_post (&vl_changed); + return NULL; + } + + vl = rc & PR_SVE_VL_LEN_MASK; + + /* Decrease vector length by 16 bytes. */ + vl -= 16; + + rc = prctl (PR_SVE_SET_VL, vl, 0, 0, 0, 0); + if (rc < 0) + { + perror ("FAILED to PR_SVE_SET_VL"); + sem_post (&vl_changed); + return NULL; + } + + /* Let the main thread continue. */ + rc = sem_post (&vl_changed); + if (rc != 0) + { + perror ("sem_post"); + return NULL; + } + + if (should_sleep) + sleep (10); + + /* Restore original vector length. */ + vl += 16; /* break here 1 */ + + rc = prctl (PR_SVE_SET_VL, vl, 0, 0, 0, 0); + if (rc < 0) + { + perror ("FAILED to PR_SVE_SET_VL"); + return NULL; + } + + return NULL; /* break here 2 */ +} + +int +main (int argc, char **argv) +{ + pthread_t thread; + int rc; + + rc = sem_init (&vl_changed, 0, 0); + if (rc != 0) + { + perror ("sem_init"); + return 1; + } + + rc = pthread_create (&thread, NULL, thread_function, NULL); + if (rc != 0) + { + perror ("pthread_create"); + return 1; + } + + /* Wait until the additional thread changes it's vector length. */ + rc = sem_wait (&vl_changed); + if (rc != 0) + { + perror ("sem_wait"); + return 1; + } + + rc = pthread_join (thread, NULL); /* break here 3 */ + if (rc != 0) + { + perror ("pthread_join"); + return 1; + } + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/aarch64-sve-threads.exp b/gdb/testsuite/gdb.arch/aarch64-sve-threads.exp new file mode 100644 index 000000000000..049eb24b1e6d --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sve-threads.exp @@ -0,0 +1,80 @@ +# Copyright 2024 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 . + +# Test a multi-threaded binary that uses SVE and changes the SVE vector +# length in the additional thread. + +require allow_aarch64_sve_tests + +standard_testfile +if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \ + {debug pthreads}] == -1} { + return -1 +} + +if ![runto_main] { + return -1 +} + +# Get the original VG value. +set orig_vg [get_valueof "" {$vg} "0" "get value of VG register"] +set expected_vg [expr {$orig_vg - 2}] + +# Stop after the additional thread has changed its vector length. +gdb_breakpoint [gdb_get_line_number "break here 1"] +gdb_continue_to_breakpoint "break here 1" + +# If GDB and gdbserver don't agree on the thread's vector length, this +# command will fail. +gdb_test "print \$z0" " = {q = {u = {.*}}}" "print z0 register" + +gdb_test "print \$vg" ". = ${expected_vg}" "vg was changed to ${expected_vg}" + +# Stop after the additional thread has restored its original vector length. +gdb_breakpoint [gdb_get_line_number "break here 2"] +gdb_continue_to_breakpoint "break here 2" + +# Test that going back to the original vector length doesn't confuse GDB or +# gdbserver. +gdb_test "print \$z0" " = {q = {u = {.*}}}" "print z0 register again" + +gdb_test "print \$vg" ". = ${orig_vg}" "vg was changed back to ${orig_vg}" + +# Restart GDB to test a scenario where GDB switches to a thread that +# changed its vector length but hasn't hit any breakpoints yet. +clean_restart ${binfile} + +if ![runto_main] { + return -1 +} + +# Make the thread sleep after changing its vector length. +gdb_test_no_output -nopass "set var should_sleep = 1" "make thread sleep" + +# Stop in the main thread after the additional thread has changed its +# vector length. +gdb_breakpoint [gdb_get_line_number "break here 3"] +gdb_continue_to_breakpoint "break here 3" + +# The regexp accounts for two lines of output after the "Switching to thread" +# message. +gdb_test_lines "thread 2" "switch to another thread" \ + {\[Switching to thread 2 \(.*\)\]\r\n#0 [[:print:]]+} + +# Make sure everything is still fine. +gdb_test "print \$z0" " = {q = {u = {.*}}}" "print z0 register in thread 2" + +gdb_test "print \$vg" ". = ${expected_vg}" \ + "vg was changed to ${expected_vg} in thread 2"