From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31136 invoked by alias); 31 Aug 2003 14:04:01 -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 31124 invoked from network); 31 Aug 2003 14:03:59 -0000 Received: from unknown (HELO walton.kettenis.dyndns.org) (213.93.115.144) by sources.redhat.com with SMTP; 31 Aug 2003 14:03:59 -0000 Received: from elgar.kettenis.dyndns.org (elgar.kettenis.dyndns.org [192.168.0.2]) by walton.kettenis.dyndns.org (8.12.6p2/8.12.5) with ESMTP id h7VE3rFd012836; Sun, 31 Aug 2003 16:03:53 +0200 (CEST) (envelope-from kettenis@elgar.kettenis.dyndns.org) Received: from elgar.kettenis.dyndns.org (localhost [127.0.0.1]) by elgar.kettenis.dyndns.org (8.12.6p2/8.12.6) with ESMTP id h7VE3qSr011854; Sun, 31 Aug 2003 16:03:52 +0200 (CEST) (envelope-from kettenis@elgar.kettenis.dyndns.org) Received: (from kettenis@localhost) by elgar.kettenis.dyndns.org (8.12.6p2/8.12.6/Submit) id h7VE3qrm011851; Sun, 31 Aug 2003 16:03:52 +0200 (CEST) To: Daniel Jacobowitz Cc: gdb@sources.redhat.com Subject: Re: [RFC] Register sets References: <200308232249.h7NMnvhh090154@elgar.kettenis.dyndns.org> <20030824164347.GA17520@nevyn.them.org> <200308252234.h7PMYqFu001245@elgar.kettenis.dyndns.org> <3F4B8173.1000302@redhat.com> <20030826165547.GA22836@nevyn.them.org> From: Mark Kettenis Date: Sun, 31 Aug 2003 14:04:00 -0000 In-Reply-To: Daniel Jacobowitz's message of "Tue, 26 Aug 2003 12:55:47 -0400" Message-ID: <86he3xrkjb.fsf@elgar.kettenis.dyndns.org> X-SW-Source: 2003-08/txt/msg00335.txt.bz2 Daniel Jacobowitz writes: > On Tue, Aug 26, 2003 at 11:49:07AM -0400, Andrew Cagney wrote: > > Need to figure out how to relate these regsets back to ptrace/proc > > requests in some sort of generic way. Doing the same for remote would > > hopefully then fall out. > > I'm not sure that it's possible to relate them back in any generic way; > ptrace is just too quirky. The closest I can picture is the way I did > it in gdbserver, which is really more of a common-code thing than a > generic-interface thing: > > struct regset_info target_regsets[] = { > { PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t), > GENERAL_REGS, > i386_fill_gregset, i386_store_gregset }, > { PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (elf_fpregset_t), > FP_REGS, > i386_fill_fpregset, i386_store_fpregset }, > { 0, 0, -1, -1, NULL, NULL } > }; I agree with Daniel here. Trying to have some sort of generic interface for ptrace(2)/proc(4) isn't worth the trouble, since there are too many quirks. We should still try to use common code where appropriate though (I'm usually able to share the ptrace(2) code between the various BSD's). Daniel's post put me on the right track on what to do about core files though. If we look at how BFD munges core files, we see that it puts registers in sections. Generally speaking it puts the general-purpose registers in a section named ".reg" and the floating-point registers (if any, and if they're not included in ".reg") in ".reg2". On the i386, the SSE registers end up in ".reg-xfp". Currently we have these strings hard-coded into GDB and convert them to a number, which we then use in the various fetch_core_registers functions to identify the register. However, why do we need this extra conversion step? If we just include the BFD sectionname in the definition of the register set GDB will be able to match things up. That way, it's easy to add new register sets if they arise. I'm not going to make the necessary changes to GDB to recognize section names instead of numbers right now. However, I'll propose an interface that will make this possible in the future. For now, I'd like to propose the following definition of a `struct regset': struct regset { /* Section name for core files as used by BFD. */ const char *name; void (*supply_regset)(struct gdbarch *, struct regcache *, const void *, size_t, int); void (*read_regset)(struct gdbarch *, struct regcache *, void *, size_t, int); }; The supply_regset function will be used to supply registers from a core file to GDB's register cache. It's signature is as follows: void supply_regset (struct gdbarch *gdbarch, struct regcache *regcache, const void *regs, size_t len, int regnum); Here, GDBARCH is the architecture of the core file, REGCACHE the register cache to store the information, REGS the (raw) buffer containing the registers in the OS/ABI-dependent format, LEN the size of this buffer, and REGNUM the register to supply. The latter can be -1 to indicate that all registers in REGS are to be supplied to the register cache. I think with those arguments, the function has all information available that it will need. I hope it is clear why we need the REGCACHE, REGS and REGNUM arguments. Let me explain why we need the GDBARCH and LEN arguments. Andrew already suggested we need the latter to avoid buffer overruns. The supply_regset function should check whether the buffer has the appropriate size. Having LEN as argument also makes it easier to support different releases of an OS since sometimes extra registers get included in a register set with a new OS release. We can't detect simple layout changes that don't change the size though. Including GDBARCH has its purpose too. There are several cases where the architecture of the core file and the executable don't match, even though the core file in question was generated by that particular executable: * When a Linux binary running on FreeBSD dumps core, it will produce a FreeBSD core dump. * When a 32-bit binary running on FreeBSD/amd64 or Linux x86-64 dumps core, it will produce a 64-bit coredump. Now, if we supply the GDBARCH associated with the core file architecture to supply_regset, it can do something intelligent with it. And yes, it is possible to detect this case since we can get the architecture associated with the register cache from its `struct regcache_descr'. The read_regset function is necessary to support the `gcore' command. It should use regcache_raw_read to fetch all relevant registers from the running target, such that we don't need target_fetch_registers(-1) first. How does this sound? Mark