[RFC] Register sets

Andrew Cagney ac131313@redhat.com
Wed Aug 27 03:50:00 GMT 2003


> 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.

Here data is moving moving from the regset buffer to the regcache.  The 
problems you mention don't occure.

> 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.

I agree that the target_fetch_registers call shouldn't be needed.  I 
think the correct way to avoid it though is to have the "gcore" code 
pull register values from the high (regcache_raw_read) and not the low 
(collect_register) side of the regcache.  That way the target gets a 
chance to on-demand pull in the registers it needs.

> 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?

I think transforming something like:

> void
> mipsnbsd_supply_reg (char *regs, int regno)
> {
>   int i;
> 
>   for (i = 0; i <= PC_REGNUM; i++)
>     {
>       if (regno == i || regno == -1)
>         {
>           if (CANNOT_FETCH_REGISTER (i))
>             supply_register (i, NULL);
>           else
>             supply_register (i, regs + (i * MIPS_REGSIZE));
>         }
>     }
> }

into an equivalent function like:

 > void
 > mipsnbsd_xfer_reg (void *cache, int regno, void (xfer*) (void *cache, 
int regnum, int offset))
 > {
 >   int i;
 >
 >   for (i = 0; i <= PC_REGNUM; i++)
 >     {
 >       if (regno == i || regno == -1)
 >         {
 >           if (CANNOT_FETCH_REGISTER (i))
 >             xfer (cache, i, -1);
 >           else
 >             xfer (cache, i, (i * MIPS_REGSIZE));
 >         }
 >     }
 > }

is far lower risk and less complex then trying to replace this with a table.

The key thing to remember is that the code is write once, fix, forget. 
Any duplication isn't an issue as, once working, it won't be touched.
> 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 }
> };

Right.  It needs a method to perform an arbitrary map from a REGNUM to a 
regset descriptor vis:
	REGNUM -> regset descriptor
But what does a regset descriptor consist of?
	- the buffer <-> cache method[s]
	- the ptrace number (is this constant for an OS?)
	- the /proc field (is this constant for an OS?)
	- the size of the buffer

Recall an earlier suggestion that GDB be given access to /proc in the 
remote target?  This would let GDB initiate remote ptrace and remote 
/proc requests.

Andrew



More information about the Gdb mailing list