From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp.polymtl.ca (smtp.polymtl.ca [132.207.4.11]) by sourceware.org (Postfix) with ESMTPS id 2DEFD3858430 for ; Wed, 2 Feb 2022 01:27:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 2DEFD3858430 Received: from simark.ca (simark.ca [158.69.221.121]) (authenticated bits=0) by smtp.polymtl.ca (8.14.7/8.14.7) with ESMTP id 2121REDW023971 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 1 Feb 2022 20:27:20 -0500 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp.polymtl.ca 2121REDW023971 Received: from [10.0.0.11] (192-222-157-6.qc.cable.ebox.net [192.222.157.6]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPSA id 579B91EDEE; Tue, 1 Feb 2022 20:27:13 -0500 (EST) Message-ID: <97c1f02b-498c-ce70-07a9-4b22aa0f1733@polymtl.ca> Date: Tue, 1 Feb 2022 20:27:12 -0500 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.5.0 Subject: Re: RFC gdbserver and tdesc and powerpc (stuck on a gdbserver assert) Content-Language: en-US To: will schmidt , gdb-patches@sourceware.org Cc: rogerio , Ulrich Weigand References: <0f8ec5130c4f798083a52129138241e130f1ee7e.camel@vnet.ibm.com> From: Simon Marchi In-Reply-To: <0f8ec5130c4f798083a52129138241e130f1ee7e.camel@vnet.ibm.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Poly-FromMTA: (simark.ca [158.69.221.121]) at Wed, 2 Feb 2022 01:27:14 +0000 X-Spam-Status: No, score=-3033.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, NICE_REPLY_A, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: Wed, 02 Feb 2022 01:27:23 -0000 On 2022-02-01 16:48, will schmidt via Gdb-patches wrote: > > Hi, > I've been working on a target-description rework for powerpc, this is > a continuation of work that Rogerio has posted rfc patches for sometime last year. > > I've run into a stumbling block with the init_target_desc code in gdbserver, > and am not sure how to best proceed. > > gdbserver/tdesc.cc: init_target_desc(...) iterates through the provided > features and populates the reg_defs structure. The code currently has an assert > with a comment: > > /* Register number will increase (possibly with gaps) or be zero. */ > gdb_assert (regnum == 0 || regnum >= tdesc->reg_defs.size ()); > > This trips on powerpc (with the WIP tdesc patch set), potentially in several > locations, since our features contain registers that are intermixed across the > ranges, so we end up with regnos that numerically belong earlier in the > tdesc->reg_defs structure, but they belong in the features where they are. > In particular; > The Powerpc "core" features includes regnums 0-31 (gprs r0..r31), > a gap, then 64-69 (PC,MSR,CR,LR,CTR,XER). > The subsequent "fpu" feature fills in that gap as it includes regnums > 32-63 (f0..f31), and 70 (fpscr). >From a quick look at the code, my understanding is: - The order in which the registers appear in the target description defines the order of the registers in the regcache buffer. See how `offset` gets incremented for each register in that loop you were looking at? - When handling the 'g' packet (read registers), there is currently the assumption that the order of the registers in the reg_defs vector (that is, sorted by register number, as reg_defs is indexed by register number) matches the order of the registers in the regcache buffer. Look in registers_to_string, how we grab a pointer to the beginning of the regcache buffer and only advance it as we iterate on reg_defs. So, if you were to fill reg_defs in a non-sorted order: - regnum 0, name=A, size=4 - regnum 2, name=C, size=4 - regnum 1, name=B, size=4 such that you ended up with this reg_defs: [0] name=A, offset=0 [1] name=B, offset=8 [2] name=C, offset=4 Then registers_to_string would get it wrong, as it would mix up B and C. I think what you are trying to do is possible, it's just a matter of either respecting the existing assumptions the code is based on, or adjust the code to not assume these things anymore. For this specific problem, I see two possible solutions: - When filling reg_defs, do a first pass to create all elements. Then do a second pass, iterating on reg_defs, to fill in the offset fields. - Remove the assumption that the order of the registers in the regcache is the same as in reg_defs. In registers_to_string, that would mean not advancing a pointer in the regcache buffer, but using each register's offset to grab the data at the right place in the regcache buffer. registers_from_string would need to be adapted too, which seems harder, as it's currently implemented as one big hex2bin, which assumes the regcache has registers sorted by number. I would lean towards the first solution, it seems easier. > There may or may not be an issue with the subsequent altivec and vsx register sets, > since we have some overlapping ranges there. Can a single tdesc actually contain two registers with the same number? > I could split apart the features into smaller bits, but this would scramble the > documented powerpc features descriptions (as seen in gdb.texinfo). > I've tried just disabling the assert, but I'm not certain that is sufficient, I currently > also see some partial transfer errors between gdb and gdbserver that i've not sorted out. Right after that assert, we have: /* Register number will increase (possibly with gaps) or be zero. */ gdb_assert (regnum == 0 || regnum >= tdesc->reg_defs.size ()); if (regnum != 0) tdesc->reg_defs.resize (regnum, gdb::reg (offset)); So if you handle registers 0, then 100, then 1, the resize will make it so the reg_defs vector ends up with a size of 1 (and subsequently 2 when we emplace_back). Whereas what you want is a vector of size 101 with all undefined registers except at indices 0, 1 and 100. So to implement the idea described above, you'd need to change that code to make sure you only grow the vector. Simon