Re: [RFC] Register sets

Mark Kettenis
2003-09-04T21:58:06Z

Date: Thu, 4 Sep 2003 08:55:15 -0400
From: Daniel Jacobowitz <drow@mvista.com>

Hi Mark,

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

[Doesn't really matter. I've been away from home for most of the 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.

Hmm, so you're proposing to drop the GDBARCH argument. You might be
right in that we don't need it. It's clear that its only useful in
the case where we're having what I'd call a cross-core situation,
i.e. when we're reading a corefile whose architecture doesn't match
the architecture of the executable, but that was nevertheless produced
by running that executable. Let's take as an example a FreeBSD/amd64
corefile produced by a FreeBSD/i386 executable.

My idea was to invoke the supply_regset method from the FreeBSD/i386
architecture. This method can only make sense out of the data if we
somehow tell it that it was really generated by FreeBSD/amd64, since
that can't be inferred from the REGCACHE. Hence the GDBARCH argument.

The alternative is to invoke the supply_regset method from the
FreeBSD/amd64 architecture. This method can infer that it is
supplying data to a FreeBSD/i386 target since it can get the proper
architecture from the REGCACHE. Therefore it doesn't need the GDBARCH
argument.

I think that the alternative is actually more correct. Let's consider
the case where we have a FreeBSD/i386 corefile produced by a
Linux/i386 executable running (crashing) on FreeBSD. In the first
case we'd have to teach the Linux architecture about reading FreeBSD
core files, which doesn't make sense, since you can't run FreeBSD
stuff on Linux AFAIK. The alternative implies we'd have to teach the
FreeBSD architecture about Linux's register cache, which makes a lot
more sense since we know that we can run Linux executables on FreeBSD.

I like your core_section_to_regset function too. That's the function
we should add to the architecture function.

I'm a bit agnostic about the remote_name_to_regset, since I can't see
the context in which it would be used. A method for fetching regsets
for the libthread_db case makes sense though. The great thing about
your function-interface is that it makes it very easy to re-use the
register set definitions if the definitions (core-file, remote,
libthread_db) are similar enough.

Mark