Re: [RFC] Register sets

Daniel Jacobowitz
2003-08-26T16:55:51Z

On Tue, Aug 26, 2003 at 11:49:07AM -0400, Andrew Cagney wrote:
>
> > > * `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.
>
> FYI, the table will definitly need to be generalized.
>
> The i386 GNU/Linux (glibc and the kernel collued on this one :-)
> PTRACE_GET_THREAD_AREA is really an additional register set and should
> be implemented as such.

Oh, good point. We could also use a regset for the debug registers,
if we switch to managing them through the regcache - would make
thread-specific use of them a little simpler I expect.

> > > 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.
> >
> >It's pretty clear. If REGNUM is not -1, only that particular register
> >is transferred between the register cache and the buffer. If REGNUM
> >is -1, all registers (within the set) are transferred. When
> >collecting, this doesn't pay attention to the validity of the data.
>
> FYI, given a request for REGNUM (>= 0) the code must supply at least
> that register (but is free to supply others).

That's where I'd like things more clearly specified. The difference
between Mark's statement and Andrew's is whether the other register
data in the regset is considered precious, or is clobbered from the
copy in the regcache. I believe not all our architectures agree on
that now.

> The fun starts when trying to interpret target_fetch_registers(-1). I
> guess it really does fetch all register sets.
>
> There's a more general problem here (JeffJ pointed it out to me). At
> present "gcore" obtains the registers being saved using regcache
> collect. Unfortunatly, there's a missing target_fetch_registers(-1)
> call, and, as a consequence, the registers written out can be invalid
> :-( There are several issues here: should "gcore" use regcache collect
> directly (bypassing the register fetch mechanism); if not, should this
> regset methods be parameterized with the function that should be used
> when collecting the registers (see regcache_cooked_read_ftype)?

I've run into this problem also. There's a target_fetch_registers in
linux-proc.c with a FIXME; that's in the threaded case. In the
non-threaded case the call is missing. Personally, I believe that the
call shouldn't be necessary, and that fill_gregset should use the
collect mechanism (which implicitly calls fetch). But I'm not sure if
that will work.

In the meantime, shall I submit the additional target_fetch_registers
with the matching FIXME?

> > > 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.
> >
> >That's exactly what I'm aiming at :-). The "mapping" needs to be a
> >function though, since in some cases it might need to do some
> >arithmetic on the buffer contents in order to convert them to the
> >format used by GDB's register cache.
>
> Yes. Functions will work better.

OK. I'd like to add a function in common code which does the mapping
based on a table though, since for many cases that's enough - cuts down
on duplication. What do you think?

> > How does that sound? I'll implement it if folks like it. Open to
> > any/all suggestions.
> >
> >I have to think about this a bit more...
>
> Yes.
>
> 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 }
};

--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer