Re: [RFC] Register sets

Daniel Jacobowitz
2003-09-04T12:55:17Z

Hi Mark,

[Sorry about the delay in responding - busy week.]

On Sun, Aug 31, 2003 at 04:03:52PM +0200, Mark Kettenis wrote:
> 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);
> };

Hmm, yes and no. That definition of regset is only useful for core
files; I would like something more generally useful, for remote and
native use. I also don't really like passing the core gdbarch around,
for the same reason. How about this instead?

struct regset
{
void (*supply_regset)(struct regcache *, const void *, size_t, int);
void (*read_regset)(struct regcache *, void *, size_t, int);
};

const struct regset *
core_section_to_regset (struct gdbarch *core_gdbarch,
const char *sec_name, size_t sec_size);

which would then allow:

const struct regset *
remote_name_to_regset (const char *name);

And perhaps some method to fetch the regset descriptor for each of the
named regsets used by libthread_db.

Otherwise, I like all the below very much.

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

--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer