From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21262 invoked by alias); 24 Aug 2003 16:43:51 -0000 Mailing-List: contact gdb-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sources.redhat.com Received: (qmail 21255 invoked from network); 24 Aug 2003 16:43:50 -0000 Received: from unknown (HELO nevyn.them.org) (66.93.172.17) by sources.redhat.com with SMTP; 24 Aug 2003 16:43:50 -0000 Received: from drow by nevyn.them.org with local (Exim 4.20 #1 (Debian)) id 19qxxz-0004bx-UO; Sun, 24 Aug 2003 12:43:47 -0400 Date: Sun, 24 Aug 2003 16:43:00 -0000 From: Daniel Jacobowitz To: Mark Kettenis Cc: gdb@sources.redhat.com Subject: Re: [RFC] Register sets Message-ID: <20030824164347.GA17520@nevyn.them.org> Mail-Followup-To: Mark Kettenis , gdb@sources.redhat.com References: <200308232249.h7NMnvhh090154@elgar.kettenis.dyndns.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <200308232249.h7NMnvhh090154@elgar.kettenis.dyndns.org> User-Agent: Mutt/1.5.1i X-SW-Source: 2003-08/txt/msg00277.txt.bz2 On Sun, Aug 24, 2003 at 12:49:57AM +0200, Mark Kettenis wrote: > Folks (and especially Andrew), > > A while back, Andrew submitted a patch that made it possible to read > Linux/i386 corefiles on Linux/x86-64. He tricked me into fixing the > "gcore" command for this case, which forced me to think a bit more > about how we can solve this cleanly. Here's what I think is the > solution. Hi Mark, I've been thinking about the same problem for a while now. I have a slightly different mental picture; let's see if we can put them together. > Registers sets > -------------- > > In most hosted environments, the underlying OS devides the ISA's > registers in groups. Typically there is a set of general-purpose > (which usually includes all integer register)s and a set of > floating-point registers. That's one of the reasons why we have > reggroups in GDB. > > Most OS'es define data structures for dealing with these groups of > registers: > > * Modern BSD's have `struct reg' and `struct fpreg'. > > * System V has `gregset_t' and `fpregset_t'. Solaris (as an > SVR4-derivative) has `prgregset_t' and `fpregset_t' and the > provision for an `xregset'. > > * QNX has `procfs_greg', `procfs_fpreg' and `procfs_altreg'. > > * Linux is a bit messy, but tries to mimic SVR4/Solaris. > > These data structures are used in several interfaces: > > * ptrace(2) (for systems that have PT_GETREGS/PTRACE_GETREGS and > friends, e.g. modern BSD's and most Linuxen). > > * proc(4) filesystem (a.k.a. procfs on e.g. SVR4/Solaris and QNX). > > * libthread_db(3)/proc_service(3) debugging interface (on Solaris and > Linux). > > * core(5) memory dumps (on ELF systems, but also in some cases, > traditional a.out systems). > > As a result, we use these data structures all over the place in GDB, > usually in ways that make it difficult to re-use code and/or > multi-arch things. I'd like to introduce a more unified approach to > handling these data structures, which I propose to call register sets, > or regsets for short. Basically a register set is just a block of > memory of a certain size. We may want to put these register sets (or > a single register from them) into GDB's register cache. We also need > to be able to grab these register sets (or a single register in them) > from the register cache. > > It seems that we need a maximum of three of these sets. I propose to > name these register sets as follows: > > * `gregset' for the general-purpose registers. > > * `fpregset' for the floating-point registers. > > * `xregset' for any "extra" registers. I don't think this is a good assumption. There are two problems with it: - It assumes that everything relating to a particular target uses the same register set format. In general (there are exceptions where libthread_db will zero the regset instead of calling ps_*getregs) we can pass regsets through libthread_db as opaque objects; we might wish to include registers that are not available in a core dump. Then we've got two different "general" regsets. There are some other examples. - It assumes that there is one possible xregset for a target. Suppose that you have two ARM targets with different vector extensions; I'll pick Cirrus/Maverick and iWMMXt, since there happen to be two ARM targets with different vector extensions. We may not know right away which regset is available. I'm not sure this is a problem; we could just define the architecture appropriately; but another example is the embedded x86 architecture registers, which a remote stub might want to transfer. (Choice of iWMMXt isn't just an example. I need to add gdbserver support for iWMMXt, and I want to do it without changing the g/G packet. See below...) > For each register set we have to provide a function that takes apart > the register set and stores it in GDB's register cache, and a > functions that puts together a register set from GDB's register set. > For these functions I propose the functions: > > void _supply_ (struct regcache *regcache, > const void *regs, int regnum); > > for supplying register REGNUM from register set REGS into the cache > REGCACHE, and > > void _collect_ (const struct regcache *regcache, > void *regs, int regnum) > > for collecting register REGNUM from the cache REGCACHE into register > set REGS. > > If REGNUM is -1, these function operate on all registers within the set. Can we define the REGNUM != -1 case a little more clearly? Is the regnum a hint, what registers must be valid in the regcache when collecting, what registers must be valid in the regset when supplying, et cetera. Right now we're a bit inconsistent between targets. > For each architecture we will have a structure that contains all > information about the register sets: > > struct regset_info > { > size_t sizeof_gregset; > void (*supply_gregset)(struct regcache *, const void *, int); > void (*collect_gregset)(const struct regcache *, void *, int); > size_t sizeof_fpregset; > void (*supply_fpregset)(struct regcache *, const void *, int); > void (*collect_fpregset)(const struct regcache *, void *, int); > size_t sizeof_xregset; > void (*supply_xregset)(const struct regcache *, void *, int); > void (*collect_xregset)(const struct regcache *, void *, int); > }; > > A pointer to this structure will be stored in the architecture vector, > such that we can use this from various places in GDB. > > Thoughts? I was thinking of something like this, very roughly: struct regset { size_t size; mapping_of_registers_and_sizes_and_offsets mapping; }; struct native_regsets { struct regset *gregset, *fpregset, *xregset; }; struct regset * gdbarch_core_section_to_regset (int which, int sizeof); This would replace lots of identical copies of fetch_core_registers all over GDB. And then: struct regset * gdbarch_remote_name_to_regset (int which, int sizeof); The companion to this would be some remote protocol work: -> qRegsets:: <- qRegsets:General,FP,iWMMXt [Local GDB calls gdbarch_remote_name_to_regset on each of these] -> g <- 0000102109210831973987etc [This would be the General set.] -> qFetchRegset:FP <- 000000831092831098201923etc -> qSetRegset:FP:100000831092831098201923etc <- OK [This would be the FP set.] Also available might be: -> qDescribeRegset:General <- a0:8;a1:8;a2:8;a3:8;v0:8;sp:8;pc:8 which could be used before trying the gdbarch_remote_name_to_regset as a fallback. And this logically extends to a CLI command to specify the format of the G packet, which I think there's a PR requesting? How does that sound? I'll implement it if folks like it. Open to any/all suggestions. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer