Re: [RFC] Register sets

Andrew Cagney
2003-08-27T03:50:41Z

> 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