From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-io1-xd2e.google.com (mail-io1-xd2e.google.com [IPv6:2607:f8b0:4864:20::d2e]) by sourceware.org (Postfix) with ESMTPS id 2AD7C3856DF4 for ; Tue, 31 May 2022 12:57:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 2AD7C3856DF4 Received: by mail-io1-xd2e.google.com with SMTP id y12so13982210ior.7 for ; Tue, 31 May 2022 05:57:36 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Ue4yKb5Yl+x7lOluU4WA4TZWWkyJY8idlG23+WE/Ucs=; b=OIUsWw/fGTIXwZBn48+JGL05b4ZM4n6571Q2NGFlQr7XGyjCtuNZzzEhXljuLCdaco +1eD3RnL0gRXzchQs8vI7S6w3maRhuFYoWP1PfShp+q0HNi2bS7Rxqq+JBtVVs+u2Uqq 21awiQLaJ29tX3niNrQgn8uF3/Xu+0AC0fLPuBB82+lDV7OoUbAmRPvB5RFTY3clZXSF ptTF++UojxYTB42zFn6AXwZ49n3+/LAkfLzoYheP7PnhIbkmbhz8JLN9Glgo+Z7zWtbw V/jLxIQzXls7SezT6+abdNn4Jj1NZy6RQiEXHqS8jS221elKqQ6FIPVm+7ewg/B+T0fT 0vXQ== X-Gm-Message-State: AOAM530XEfaZKvUv+Jtbox/WG60/K/S9WabYmPFzjZburDf/6yQX7tV1 AXBMQ4xUntGyL1WvnZcH21LXpbzf/XKtjQ== X-Google-Smtp-Source: ABdhPJzkdlW+YFT58yipSHZxszrwrMJ18JQwJVKSvK0DjU5N2x69LZgLkLhxZygaJLAsfgczr5kvjg== X-Received: by 2002:a5d:81cb:0:b0:653:7cec:64aa with SMTP id t11-20020a5d81cb000000b006537cec64aamr26931817iol.208.1654001855111; Tue, 31 May 2022 05:57:35 -0700 (PDT) Received: from murgatroyd.Home (71-211-167-178.hlrn.qwest.net. [71.211.167.178]) by smtp.gmail.com with ESMTPSA id q16-20020a5d8510000000b0065a47e16f5asm3834829ion.44.2022.05.31.05.57.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 31 May 2022 05:57:34 -0700 (PDT) From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH 2/3] Reimplement ravenscar registers using tables Date: Tue, 31 May 2022 06:57:30 -0600 Message-Id: <20220531125731.1280943-3-tromey@adacore.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220531125731.1280943-1-tromey@adacore.com> References: <20220531125731.1280943-1-tromey@adacore.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 31 May 2022 12:57:41 -0000 Currently, the ravenscar-thread implementation for each architecture is written by hand. However, these are actually written by copy-paste. It seems better to switch to a table-driven approach. The previous code also fetched all registers whenever any register was requested. This is corrected in the new implementation. --- gdb/aarch64-ravenscar-thread.c | 121 +------------------------- gdb/amd64-ravenscar-thread.c | 112 ++++-------------------- gdb/ppc-ravenscar-thread.c | 154 +-------------------------------- gdb/ravenscar-thread.c | 113 +++++++++++++++++++++++- gdb/ravenscar-thread.h | 42 ++++++++- gdb/riscv-ravenscar-thread.c | 120 ++++++------------------- gdb/sparc-ravenscar-thread.c | 124 +------------------------- 7 files changed, 206 insertions(+), 580 deletions(-) diff --git a/gdb/aarch64-ravenscar-thread.c b/gdb/aarch64-ravenscar-thread.c index dc35537e3d5..045d022fc23 100644 --- a/gdb/aarch64-ravenscar-thread.c +++ b/gdb/aarch64-ravenscar-thread.c @@ -61,127 +61,10 @@ static const int aarch64_context_offsets[] = 112, 116, }; -/* The register layout info. */ - -struct ravenscar_reg_info -{ - /* A table providing the offset relative to the context structure - where each register is saved. */ - const int *context_offsets; - - /* The number of elements in the context_offsets table above. */ - int context_offsets_size; -}; - -/* supply register REGNUM, which has been saved on REGISTER_ADDR, to the - regcache. */ - -static void -supply_register_at_address (struct regcache *regcache, int regnum, - CORE_ADDR register_addr) -{ - struct gdbarch *gdbarch = regcache->arch (); - int buf_size = register_size (gdbarch, regnum); - gdb_byte *buf; - - buf = (gdb_byte *) alloca (buf_size); - read_memory (register_addr, buf, buf_size); - regcache->raw_supply (regnum, buf); -} - -/* Return true if, for a non-running thread, REGNUM has been saved on the - Thread_Descriptor. */ - -static int -register_in_thread_descriptor_p (const struct ravenscar_reg_info *reg_info, - int regnum) -{ - /* Check FPU registers */ - return (regnum < reg_info->context_offsets_size - && reg_info->context_offsets[regnum] != NO_OFFSET); -} - -/* to_fetch_registers when inferior_ptid is different from the running - thread. */ - -static void -aarch64_ravenscar_generic_fetch_registers - (const struct ravenscar_reg_info *reg_info, - struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = regcache->arch (); - const int num_regs = gdbarch_num_regs (gdbarch); - int current_regnum; - CORE_ADDR current_address; - CORE_ADDR thread_descriptor_address; - - /* The tid is the thread_id field, which is a pointer to the thread. */ - thread_descriptor_address = (CORE_ADDR) inferior_ptid.tid (); - - /* Read registers. */ - for (current_regnum = 0; current_regnum < num_regs; current_regnum++) - { - if (register_in_thread_descriptor_p (reg_info, current_regnum)) - { - current_address = thread_descriptor_address - + reg_info->context_offsets[current_regnum]; - supply_register_at_address (regcache, current_regnum, - current_address); - } - } -} - -/* to_store_registers when inferior_ptid is different from the running - thread. */ - -static void -aarch64_ravenscar_generic_store_registers - (const struct ravenscar_reg_info *reg_info, - struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = regcache->arch (); - int buf_size = register_size (gdbarch, regnum); - gdb_byte buf[buf_size]; - ULONGEST register_address; - - if (register_in_thread_descriptor_p (reg_info, regnum)) - register_address - = inferior_ptid.tid () + reg_info->context_offsets [regnum]; - else - return; - - regcache->raw_collect (regnum, buf); - write_memory (register_address, - buf, - buf_size); -} - -/* The ravenscar_reg_info for most Aarch64 targets. */ - -static const struct ravenscar_reg_info aarch64_reg_info = -{ - aarch64_context_offsets, - ARRAY_SIZE (aarch64_context_offsets), -}; - -struct aarch64_ravenscar_ops : public ravenscar_arch_ops -{ - void fetch_registers (struct regcache *regcache, int regnum) override - { - aarch64_ravenscar_generic_fetch_registers - (&aarch64_reg_info, regcache, regnum); - } - - void store_registers (struct regcache *regcache, int regnum) override - { - aarch64_ravenscar_generic_store_registers - (&aarch64_reg_info, regcache, regnum); - } -}; - /* The ravenscar_arch_ops vector for most Aarch64 targets. */ -static struct aarch64_ravenscar_ops aarch64_ravenscar_ops; +static struct ravenscar_arch_ops aarch64_ravenscar_ops + (aarch64_context_offsets); /* Register aarch64_ravenscar_ops in GDBARCH. */ diff --git a/gdb/amd64-ravenscar-thread.c b/gdb/amd64-ravenscar-thread.c index d06cdf8b7a2..18c000dc988 100644 --- a/gdb/amd64-ravenscar-thread.c +++ b/gdb/amd64-ravenscar-thread.c @@ -26,17 +26,6 @@ #include "ravenscar-thread.h" #include "amd64-ravenscar-thread.h" -struct amd64_ravenscar_ops : public ravenscar_arch_ops -{ - void fetch_registers (struct regcache *regcache, int regnum) override; - void store_registers (struct regcache *regcache, int regnum) override; - -private: - - /* Return the offset of the register in the context buffer. */ - int register_offset (struct gdbarch *arch, int regnum); -}; - /* x86-64 Ravenscar stores registers as: type Context_Buffer is record @@ -54,92 +43,29 @@ struct amd64_ravenscar_ops : public ravenscar_arch_ops */ static const int register_layout[] = { - AMD64_RIP_REGNUM, - AMD64_EFLAGS_REGNUM, - AMD64_RSP_REGNUM, - AMD64_RBX_REGNUM, - AMD64_RBP_REGNUM, - AMD64_R12_REGNUM, - AMD64_R13_REGNUM, - AMD64_R14_REGNUM, - AMD64_R15_REGNUM, + /* RAX */ -1, + /* RBX */ 3 * 8, + /* RCX */ -1, + /* RDX */ -1, + /* RSI */ -1, + /* RDI */ -1, + /* RBP */ 4 * 8, + /* RSP */ 2 * 8, + /* R8 */ -1, + /* R9 */ -1, + /* R10 */ -1, + /* R11 */ -1, + /* R12 */ 5 * 8, + /* R13 */ 6 * 8, + /* R14 */ 7 * 8, + /* R15 */ 8 * 8, + /* RIP */ 0 * 8, + /* EFLAGS */ 1 * 8, }; -int -amd64_ravenscar_ops::register_offset (struct gdbarch *arch, int regnum) -{ - for (int i = 0; i < ARRAY_SIZE (register_layout); ++i) - if (register_layout[i] == regnum) - return i * 8; - /* Not saved. */ - return -1; -} - -/* Supply register REGNUM, which has been saved at REGISTER_ADDR, to - the regcache. */ - -static void -supply_register_at_address (struct regcache *regcache, int regnum, - CORE_ADDR register_addr) -{ - struct gdbarch *gdbarch = regcache->arch (); - int buf_size = register_size (gdbarch, regnum); - gdb_byte *buf; - - buf = (gdb_byte *) alloca (buf_size); - read_memory (register_addr, buf, buf_size); - regcache->raw_supply (regnum, buf); -} - -void -amd64_ravenscar_ops::fetch_registers (struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = regcache->arch (); - const int num_regs = gdbarch_num_regs (gdbarch); - int current_regnum; - CORE_ADDR current_address; - CORE_ADDR thread_descriptor_address; - - /* The tid is the thread_id field, which is a pointer to the thread. */ - thread_descriptor_address = (CORE_ADDR) inferior_ptid.tid (); - - /* Read registers. */ - for (current_regnum = 0; current_regnum < num_regs; current_regnum++) - { - int offset = register_offset (gdbarch, current_regnum); - - if (offset != -1) - { - current_address = thread_descriptor_address + offset; - supply_register_at_address (regcache, current_regnum, - current_address); - } - } -} - -void -amd64_ravenscar_ops::store_registers (struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = regcache->arch (); - int buf_size = register_size (gdbarch, regnum); - gdb_byte buf[buf_size]; - CORE_ADDR register_address; - - int offset = register_offset (gdbarch, regnum); - if (offset != -1) - { - register_address = inferior_ptid.tid () + offset; - - regcache->raw_collect (regnum, buf); - write_memory (register_address, - buf, - buf_size); - } -} - /* The ravenscar_arch_ops vector for AMD64 targets. */ -static struct amd64_ravenscar_ops amd64_ravenscar_ops; +static struct ravenscar_arch_ops amd64_ravenscar_ops (register_layout); /* Register amd64_ravenscar_ops in GDBARCH. */ diff --git a/gdb/ppc-ravenscar-thread.c b/gdb/ppc-ravenscar-thread.c index 42d7334b93f..0691a6317d5 100644 --- a/gdb/ppc-ravenscar-thread.c +++ b/gdb/ppc-ravenscar-thread.c @@ -100,129 +100,10 @@ static const int e500_context_offsets[] = NO_OFFSET, 176 }; -/* The register layout info. */ - -struct ravenscar_reg_info -{ - /* A table providing the offset relative to the context structure - where each register is saved. */ - const int *context_offsets; - - /* The number of elements in the context_offsets table above. */ - int context_offsets_size; -}; - -/* supply register REGNUM, which has been saved on REGISTER_ADDR, to the - regcache. */ - -static void -supply_register_at_address (struct regcache *regcache, int regnum, - CORE_ADDR register_addr) -{ - struct gdbarch *gdbarch = regcache->arch (); - int buf_size = register_size (gdbarch, regnum); - gdb_byte *buf; - - buf = (gdb_byte *) alloca (buf_size); - read_memory (register_addr, buf, buf_size); - regcache->raw_supply (regnum, buf); -} - -/* Return true if, for a non-running thread, REGNUM has been saved on the - Thread_Descriptor. */ - -static int -register_in_thread_descriptor_p (const struct ravenscar_reg_info *reg_info, - int regnum) -{ - return (regnum < reg_info->context_offsets_size - && reg_info->context_offsets[regnum] != NO_OFFSET); -} - -/* to_fetch_registers when inferior_ptid is different from the running - thread. */ - -static void -ppc_ravenscar_generic_fetch_registers - (const struct ravenscar_reg_info *reg_info, - struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = regcache->arch (); - const int num_regs = gdbarch_num_regs (gdbarch); - int current_regnum; - CORE_ADDR current_address; - CORE_ADDR thread_descriptor_address; - - /* The tid is the thread_id field, which is a pointer to the thread. */ - thread_descriptor_address = (CORE_ADDR) inferior_ptid.tid (); - - /* Read registers. */ - for (current_regnum = 0; current_regnum < num_regs; current_regnum++) - { - if (register_in_thread_descriptor_p (reg_info, current_regnum)) - { - current_address = thread_descriptor_address - + reg_info->context_offsets[current_regnum]; - supply_register_at_address (regcache, current_regnum, - current_address); - } - } -} - -/* to_store_registers when inferior_ptid is different from the running - thread. */ - -static void -ppc_ravenscar_generic_store_registers - (const struct ravenscar_reg_info *reg_info, - struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = regcache->arch (); - int buf_size = register_size (gdbarch, regnum); - gdb_byte buf[buf_size]; - ULONGEST register_address; - - if (register_in_thread_descriptor_p (reg_info, regnum)) - register_address - = inferior_ptid.tid () + reg_info->context_offsets [regnum]; - else - return; - - regcache->raw_collect (regnum, buf); - write_memory (register_address, - buf, - buf_size); -} - -/* The ravenscar_reg_info for most PowerPC targets. */ - -static const struct ravenscar_reg_info ppc_reg_info = -{ - powerpc_context_offsets, - ARRAY_SIZE (powerpc_context_offsets), -}; - -struct ppc_ravenscar_powerpc_ops : public ravenscar_arch_ops -{ - void fetch_registers (struct regcache *, int) override; - void store_registers (struct regcache *, int) override; -}; - -void -ppc_ravenscar_powerpc_ops::fetch_registers (struct regcache *regcache, int regnum) -{ - ppc_ravenscar_generic_fetch_registers (&ppc_reg_info, regcache, regnum); -} - -void -ppc_ravenscar_powerpc_ops::store_registers (struct regcache *regcache, int regnum) -{ - ppc_ravenscar_generic_store_registers (&ppc_reg_info, regcache, regnum); -} - /* The ravenscar_arch_ops vector for most PowerPC targets. */ -static struct ppc_ravenscar_powerpc_ops ppc_ravenscar_powerpc_ops; +static struct ravenscar_arch_ops ppc_ravenscar_powerpc_ops + (powerpc_context_offsets); /* Register ppc_ravenscar_powerpc_ops in GDBARCH. */ @@ -232,38 +113,9 @@ register_ppc_ravenscar_ops (struct gdbarch *gdbarch) set_gdbarch_ravenscar_ops (gdbarch, &ppc_ravenscar_powerpc_ops); } -/* The ravenscar_reg_info for E500 targets. */ - -static const struct ravenscar_reg_info e500_reg_info = -{ - e500_context_offsets, - ARRAY_SIZE (e500_context_offsets), -}; - -struct ppc_ravenscar_e500_ops : public ravenscar_arch_ops -{ - void fetch_registers (struct regcache *, int) override; - void store_registers (struct regcache *, int) override; -}; - -void -ppc_ravenscar_e500_ops::fetch_registers (struct regcache *regcache, int regnum) -{ - ppc_ravenscar_generic_fetch_registers (&e500_reg_info, regcache, regnum); -} - -/* Implement the to_store_registers ravenscar_arch_ops method - for E500 targets. */ - -void -ppc_ravenscar_e500_ops::store_registers (struct regcache *regcache, int regnum) -{ - ppc_ravenscar_generic_store_registers (&e500_reg_info, regcache, regnum); -} - /* The ravenscar_arch_ops vector for E500 targets. */ -static struct ppc_ravenscar_e500_ops ppc_ravenscar_e500_ops; +static struct ravenscar_arch_ops ppc_ravenscar_e500_ops (e500_context_offsets); /* Register ppc_ravenscar_e500_ops in GDBARCH. */ diff --git a/gdb/ravenscar-thread.c b/gdb/ravenscar-thread.c index aae6e397327..e300095b53f 100644 --- a/gdb/ravenscar-thread.c +++ b/gdb/ravenscar-thread.c @@ -477,6 +477,116 @@ ravenscar_thread_target::pid_to_str (ptid_t ptid) phex_nz (ptid.tid (), sizeof (ULONGEST))); } +CORE_ADDR +ravenscar_arch_ops::get_stack_base (struct regcache *regcache) const +{ + struct gdbarch *gdbarch = regcache->arch (); + const int sp_regnum = gdbarch_sp_regnum (gdbarch); + ULONGEST stack_address; + regcache_cooked_read_unsigned (regcache, sp_regnum, &stack_address); + return (CORE_ADDR) stack_address; +} + +void +ravenscar_arch_ops::supply_one_register (struct regcache *regcache, + int regnum, + CORE_ADDR descriptor, + CORE_ADDR stack_base) const +{ + CORE_ADDR addr; + if (regnum >= first_stack_register && regnum <= last_stack_register) + addr = stack_base; + else + addr = descriptor; + addr += offsets[regnum]; + + struct gdbarch *gdbarch = regcache->arch (); + int size = register_size (gdbarch, regnum); + gdb_byte *buf = (gdb_byte *) alloca (size); + read_memory (addr, buf, size); + regcache->raw_supply (regnum, buf); +} + +void +ravenscar_arch_ops::fetch_registers (struct regcache *regcache, + int regnum) const +{ + struct gdbarch *gdbarch = regcache->arch (); + /* The tid is the thread_id field, which is a pointer to the thread. */ + CORE_ADDR thread_descriptor_address + = (CORE_ADDR) regcache->ptid ().tid (); + + int sp_regno = -1; + CORE_ADDR stack_address = 0; + if (regnum == -1 + || (regnum >= first_stack_register && regnum <= last_stack_register)) + { + /* We must supply SP for get_stack_base, so recurse. */ + sp_regno = gdbarch_sp_regnum (gdbarch); + gdb_assert (!(sp_regno >= first_stack_register + && sp_regno <= last_stack_register)); + fetch_registers (regcache, sp_regno); + stack_address = get_stack_base (regcache); + } + + if (regnum == -1) + { + /* Fetch all registers. */ + for (int reg = 0; reg < offsets.size (); ++reg) + if (reg != sp_regno && offsets[reg] != -1) + supply_one_register (regcache, reg, thread_descriptor_address, + stack_address); + } + else if (regnum < offsets.size () && offsets[regnum] != -1) + supply_one_register (regcache, regnum, thread_descriptor_address, + stack_address); +} + +void +ravenscar_arch_ops::store_one_register (struct regcache *regcache, int regnum, + CORE_ADDR descriptor, + CORE_ADDR stack_base) const +{ + CORE_ADDR addr; + if (regnum >= first_stack_register && regnum <= last_stack_register) + addr = stack_base; + else + addr = descriptor; + addr += offsets[regnum]; + + struct gdbarch *gdbarch = regcache->arch (); + int size = register_size (gdbarch, regnum); + gdb_byte *buf = (gdb_byte *) alloca (size); + regcache->raw_collect (regnum, buf); + write_memory (addr, buf, size); +} + +void +ravenscar_arch_ops::store_registers (struct regcache *regcache, + int regnum) const +{ + /* The tid is the thread_id field, which is a pointer to the thread. */ + CORE_ADDR thread_descriptor_address + = (CORE_ADDR) regcache->ptid ().tid (); + + CORE_ADDR stack_address = 0; + if (regnum == -1 + || (regnum >= first_stack_register && regnum <= last_stack_register)) + stack_address = get_stack_base (regcache); + + if (regnum == -1) + { + /* Store all registers. */ + for (int reg = 0; reg < offsets.size (); ++reg) + if (offsets[reg] != -1) + store_one_register (regcache, reg, thread_descriptor_address, + stack_address); + } + else if (regnum < offsets.size () && offsets[regnum] != -1) + store_one_register (regcache, regnum, thread_descriptor_address, + stack_address); +} + /* Temporarily set the ptid of a regcache to some other value. When this object is destroyed, the regcache's original ptid is restored. */ @@ -506,7 +616,8 @@ class temporarily_change_regcache_ptid }; void -ravenscar_thread_target::fetch_registers (struct regcache *regcache, int regnum) +ravenscar_thread_target::fetch_registers (struct regcache *regcache, + int regnum) { ptid_t ptid = regcache->ptid (); diff --git a/gdb/ravenscar-thread.h b/gdb/ravenscar-thread.h index df750667ab9..5d5661f48df 100644 --- a/gdb/ravenscar-thread.h +++ b/gdb/ravenscar-thread.h @@ -24,12 +24,48 @@ struct ravenscar_arch_ops { - virtual ~ravenscar_arch_ops () + ravenscar_arch_ops (gdb::array_view offsets_, + int first_stack = -1, + int last_stack = -1) + : offsets (offsets_), + first_stack_register (first_stack), + last_stack_register (last_stack) { + /* These must either both be -1 or both be valid. */ + gdb_assert ((first_stack_register == -1) == (last_stack_register == -1)); + /* They must also be ordered. */ + gdb_assert (last_stack_register >= first_stack_register); } - virtual void fetch_registers (struct regcache *, int) = 0; - virtual void store_registers (struct regcache *, int) = 0; + void fetch_registers (struct regcache *, int) const; + void store_registers (struct regcache *, int) const; + +private: + + /* An array where the indices are register numbers and the contents + are offsets. The offsets are either in the thread descriptor or + the stack, depending on the other fields. An offset of -1 means + that the corresponding register is not stored. */ + const gdb::array_view offsets; + + /* If these are -1, then all registers for this architecture are + stored in the thread descriptor. Otherwise, these mark a range + of registers that are stored on the stack. */ + const int first_stack_register; + const int last_stack_register; + + /* Helper function to supply one register. */ + void supply_one_register (struct regcache *regcache, int regnum, + CORE_ADDR descriptor, + CORE_ADDR stack_base) const; + /* Helper function to store one register. */ + void store_one_register (struct regcache *regcache, int regnum, + CORE_ADDR descriptor, + CORE_ADDR stack_base) const; + /* Helper function to find stack address where registers are stored. + This must be called with the stack pointer already supplied in + the register cache. */ + CORE_ADDR get_stack_base (struct regcache *) const; }; #endif /* !defined (RAVENSCAR_THREAD_H) */ diff --git a/gdb/riscv-ravenscar-thread.c b/gdb/riscv-ravenscar-thread.c index b2a7b6e0096..e28e17878c3 100644 --- a/gdb/riscv-ravenscar-thread.c +++ b/gdb/riscv-ravenscar-thread.c @@ -26,115 +26,51 @@ #include "ravenscar-thread.h" #include "riscv-ravenscar-thread.h" +#define LAST_REGISTER (RISCV_FIRST_FP_REGNUM + 14) + struct riscv_ravenscar_ops : public ravenscar_arch_ops { - void fetch_registers (struct regcache *regcache, int regnum) override; - void store_registers (struct regcache *regcache, int regnum) override; - -private: + int reg_offsets[LAST_REGISTER + 1]; - /* Return the offset of the register in the context buffer. */ - int register_offset (struct gdbarch *arch, int regnum); + riscv_ravenscar_ops (struct gdbarch *arch); }; -int -riscv_ravenscar_ops::register_offset (struct gdbarch *arch, int regnum) -{ - int offset; - if (regnum == RISCV_RA_REGNUM || regnum == RISCV_PC_REGNUM) - offset = 0; - else if (regnum == RISCV_SP_REGNUM) - offset = 1; - else if (regnum == RISCV_ZERO_REGNUM + 8) /* S0 */ - offset = 2; - else if (regnum == RISCV_ZERO_REGNUM + 9) /* S1 */ - offset = 3; - else if (regnum >= RISCV_ZERO_REGNUM + 19 - && regnum <= RISCV_ZERO_REGNUM + 27) /* S2..S11 */ - offset = regnum - (RISCV_ZERO_REGNUM + 19) + 4; - else if (regnum >= RISCV_FIRST_FP_REGNUM - && regnum <= RISCV_FIRST_FP_REGNUM + 11) - offset = regnum - RISCV_FIRST_FP_REGNUM + 14; /* FS0..FS11 */ - else - { - /* Not saved. */ - return -1; - } - - int size = register_size (arch, regnum); - return offset * size; -} - -/* Supply register REGNUM, which has been saved on REGISTER_ADDR, to the - regcache. */ - -static void -supply_register_at_address (struct regcache *regcache, int regnum, - CORE_ADDR register_addr) -{ - struct gdbarch *gdbarch = regcache->arch (); - int buf_size = register_size (gdbarch, regnum); - gdb_byte *buf; - - buf = (gdb_byte *) alloca (buf_size); - read_memory (register_addr, buf, buf_size); - regcache->raw_supply (regnum, buf); -} - -void -riscv_ravenscar_ops::fetch_registers (struct regcache *regcache, int regnum) +riscv_ravenscar_ops::riscv_ravenscar_ops (struct gdbarch *arch) + : ravenscar_arch_ops (gdb::make_array_view (reg_offsets, LAST_REGISTER + 1)) { - struct gdbarch *gdbarch = regcache->arch (); - const int num_regs = gdbarch_num_regs (gdbarch); - int current_regnum; - CORE_ADDR current_address; - CORE_ADDR thread_descriptor_address; - - /* The tid is the thread_id field, which is a pointer to the thread. */ - thread_descriptor_address = (CORE_ADDR) inferior_ptid.tid (); + int reg_size = riscv_isa_xlen (arch); - /* Read registers. */ - for (current_regnum = 0; current_regnum < num_regs; current_regnum++) + for (int regnum = 0; regnum <= LAST_REGISTER; ++regnum) { - int offset = register_offset (gdbarch, current_regnum); + int offset; + if (regnum == RISCV_RA_REGNUM || regnum == RISCV_PC_REGNUM) + offset = 0; + else if (regnum == RISCV_SP_REGNUM) + offset = 1; + else if (regnum == RISCV_ZERO_REGNUM + 8) /* S0 */ + offset = 2; + else if (regnum == RISCV_ZERO_REGNUM + 9) /* S1 */ + offset = 3; + else if (regnum >= RISCV_ZERO_REGNUM + 19 + && regnum <= RISCV_ZERO_REGNUM + 27) /* S2..S11 */ + offset = regnum - (RISCV_ZERO_REGNUM + 19) + 4; + else if (regnum >= RISCV_FIRST_FP_REGNUM + && regnum <= RISCV_FIRST_FP_REGNUM + 11) + offset = regnum - RISCV_FIRST_FP_REGNUM + 14; /* FS0..FS11 */ + else + offset = -1; if (offset != -1) - { - current_address = thread_descriptor_address + offset; - supply_register_at_address (regcache, current_regnum, - current_address); - } - } -} - -void -riscv_ravenscar_ops::store_registers (struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = regcache->arch (); - int buf_size = register_size (gdbarch, regnum); - gdb_byte buf[buf_size]; - CORE_ADDR register_address; - - int offset = register_offset (gdbarch, regnum); - if (offset != -1) - { - register_address = inferior_ptid.tid () + offset; + offset *= reg_size; - regcache->raw_collect (regnum, buf); - write_memory (register_address, - buf, - buf_size); + reg_offsets[regnum] = offset; } } -/* The ravenscar_arch_ops vector for most RISC-V targets. */ - -static struct riscv_ravenscar_ops riscv_ravenscar_ops; - /* Register riscv_ravenscar_ops in GDBARCH. */ void register_riscv_ravenscar_ops (struct gdbarch *gdbarch) { - set_gdbarch_ravenscar_ops (gdbarch, &riscv_ravenscar_ops); + set_gdbarch_ravenscar_ops (gdbarch, new riscv_ravenscar_ops (gdbarch)); } diff --git a/gdb/sparc-ravenscar-thread.c b/gdb/sparc-ravenscar-thread.c index 014d8981d7b..b199afb99c0 100644 --- a/gdb/sparc-ravenscar-thread.c +++ b/gdb/sparc-ravenscar-thread.c @@ -26,12 +26,6 @@ #include "sparc-ravenscar-thread.h" #include "gdbarch.h" -struct sparc_ravenscar_ops : public ravenscar_arch_ops -{ - void fetch_registers (struct regcache *, int) override; - void store_registers (struct regcache *, int) override; -}; - /* Register offsets from a referenced address (exempli gratia the Thread_Descriptor). The referenced address depends on the register number. The Thread_Descriptor layout and the stack layout are documented @@ -56,121 +50,9 @@ static const int sparc_register_offsets[] = 0x40, 0x20, 0x44, -1, 0x1C, -1, 0x4C, -1 }; -/* supply register REGNUM, which has been saved on REGISTER_ADDR, to the - regcache. */ - -static void -supply_register_at_address (struct regcache *regcache, int regnum, - CORE_ADDR register_addr) -{ - struct gdbarch *gdbarch = regcache->arch (); - int buf_size = register_size (gdbarch, regnum); - gdb_byte *buf; - - buf = (gdb_byte *) alloca (buf_size); - read_memory (register_addr, buf, buf_size); - regcache->raw_supply (regnum, buf); -} - -/* Return true if, for a non-running thread, REGNUM has been saved on the - stack. */ - -static int -register_on_stack_p (int regnum) -{ - return (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM) - || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM); -} - -/* Return true if, for a non-running thread, REGNUM has been saved on the - Thread_Descriptor. */ - -static int -register_in_thread_descriptor_p (int regnum) -{ - return (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM) - || (regnum == SPARC32_PSR_REGNUM) - || (regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM) - || (regnum == SPARC32_Y_REGNUM) - || (regnum == SPARC32_WIM_REGNUM) - || (regnum == SPARC32_FSR_REGNUM) - || (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F0_REGNUM + 31) - || (regnum == SPARC32_PC_REGNUM); -} - -/* to_fetch_registers when inferior_ptid is different from the running - thread. */ - -void -sparc_ravenscar_ops::fetch_registers (struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = regcache->arch (); - const int sp_regnum = gdbarch_sp_regnum (gdbarch); - const int num_regs = gdbarch_num_regs (gdbarch); - int current_regnum; - CORE_ADDR current_address; - CORE_ADDR thread_descriptor_address; - ULONGEST stack_address; - - /* The tid is the thread_id field, which is a pointer to the thread. */ - thread_descriptor_address = (CORE_ADDR) inferior_ptid.tid (); - - /* Read the saved SP in the context buffer. */ - current_address = thread_descriptor_address - + sparc_register_offsets [sp_regnum]; - supply_register_at_address (regcache, sp_regnum, current_address); - regcache_cooked_read_unsigned (regcache, sp_regnum, &stack_address); - - /* Read registers. */ - for (current_regnum = 0; current_regnum < num_regs; current_regnum ++) - { - if (register_in_thread_descriptor_p (current_regnum)) - { - current_address = thread_descriptor_address - + sparc_register_offsets [current_regnum]; - supply_register_at_address (regcache, current_regnum, - current_address); - } - else if (register_on_stack_p (current_regnum)) - { - current_address = stack_address - + sparc_register_offsets [current_regnum]; - supply_register_at_address (regcache, current_regnum, - current_address); - } - } -} - -/* to_store_registers when inferior_ptid is different from the running - thread. */ - -void -sparc_ravenscar_ops::store_registers (struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = regcache->arch (); - int buf_size = register_size (gdbarch, regnum); - gdb_byte buf[buf_size]; - ULONGEST register_address; - - if (register_in_thread_descriptor_p (regnum)) - register_address = - inferior_ptid.tid () + sparc_register_offsets [regnum]; - else if (register_on_stack_p (regnum)) - { - regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, - ®ister_address); - register_address += sparc_register_offsets [regnum]; - } - else - return; - - regcache->raw_collect (regnum, buf); - write_memory (register_address, - buf, - buf_size); -} - -static struct sparc_ravenscar_ops sparc_ravenscar_ops; +static struct ravenscar_arch_ops sparc_ravenscar_ops (sparc_register_offsets, + SPARC_L0_REGNUM, + SPARC_I7_REGNUM); /* Register ravenscar_arch_ops in GDBARCH. */ -- 2.34.1