prgregset_t vs gdb_gregset_t on Linux: not the same!

Daniel Jacobowitz dmj+@andrew.cmu.edu
Sat Jun 9 15:42:00 GMT 2001


On Sat, Jun 09, 2001 at 09:01:49PM +0200, Mark Kettenis wrote:
> Daniel Jacobowitz <dmj+@andrew.cmu.edu> writes:
> 
> > On Fri, Jun 08, 2001 at 01:27:30PM -0700, Daniel Jacobowitz wrote:
> > > In proc-service.c, we call fill_gregset and supply_gregset with a
> > > prgregset_t cast to a gdb_gregset_t *.  The problem is, they really are
> > > different.  We can mostly get away with this, because in almost all cases
> > > glibc won't do anything with the gregset except pass it back to gdb again
> > > (if the process has terminated, it will memset something the size of a
> > > prgregset_t, though...).
> > 
> > The matching question here is that core-regset.c's fetch_core_registers
> > calls supply_gregset with a gregset_t, but supply_gregset is prototyped
> > with a gdb_gregset_t.  That doesn't work very well either.
> 
> It's a mess.  Linux should have three different regset types:
> 
>  * elf_gregset_t: The type used for register sets in ELF core dumps.
>    Should be defined by <sys/procfs.h>.
> 
>  * prgregset_t: The type used for register sets in the
>    <proc_service.h> debugging interface.
> 
>  * gregset_t: The type used for register sets in machine contexts.
>    Should be defined in <sys/ucontext.h>.
> 
> On many Linux ports the elf_gregset_t and gregset_t types differ, and
> apparently the MIPS port is one of them.  The type prgregset_t is
> equivalent to one of them, but which one?  To make matters worse
> <linux/elfcore.h> has a
> 
>    typedef elf_gregset_t gregset_t;
> 
> which means that there might be two different types bearing the same
> name.  Which type you get depends on what headers you include.

Right.  Nothing in GDB that I can find and nothing in sys/, bits/, or
straight usr/include/ gets <linux/elfcore.h>, fortunately.

> The first thing you'll need to do is cleanup up the glibc headers for
> MIPS.  The important headers are <sys/procfs.h>, <sys/ucontext.h> and
> <sys/user.h>.  Avoid including Linux kernel headers and copy the few
> definitions that you really need.  Avoid cross-includes.  I cleaned up
> the i386 headers some time ago.  Take a look at those to see what I
> mean.

The only two kernel headers we get right now in the relevant portions
are <asm/elf.h> and <asm/user.h>; asm/elf.h gives us the reasonable
definition of elf_gregset_t, and asm/user.h gives us struct user, which
gives us the offsets into an elf_gregset_t for particular registers.

> Then for GDB you need to make sure that gdb_gregset_t is equivalent to
> elf_gregset_t.  The file config/nm-linux.h makes sure it is by
> defining GDB_GREGSET_T.  You should include this file from
> config/mips/nm-linux (or whatever your native configuration header is
> called).

Yep, already got that.

> The proc-service.c module assumes that gdb_gregset_t and prgregset_t
> are equivalent types.  Preferably, you should fix glibc such that that
> is the case.  You might need to change the version of the
> libthread_db.so library if you're worried about backward compatibility.

Do you think I could get away with this?  I can't (as much as I'm
tempted) change the actual gregset_t, since it is used in things like
ucontext_t.  But since nothing uses a prgregset_t outside of thread_db,
that might be possible.

libc people?  Is something like this reasonable for
sysdeps/unix/sysv/linux/mips/sys/procfs.h, possibly with a libthread_db
version bump (although since I doubt anything successfully uses
thread_db on mips yet...):

- typedef gregset_t prgregset_t;
- typedef fpregset_t prfpregset_t;
+ typedef elf_gregset_t prgregset_t;
+ typedef elf_fpregset_t prfpregset_t;

I notice that a lot of platforms have these two as separate types.

prgregset_t is elf_gregset_t: i386, hppa, s390, sparc
prgregset_t is gregset_t: powerpc, alpha, mips, ia64, and all others
	(linux/sys/procfs.h - I guess that's m68k and sh)

Since we only use prgregset_t for thread_db, I think elf_gregset_t is
more appropriate.  I don't entirely understand why gregset_t and
elf_gregset_t are different, though.  What we really want to return
is what we get from ptrace, which seems to be closer to elf_gregset_t
on most platforms.


> We could add conversion routines for prgregset_t in GDB, but I'd like
> to avoid that.

I'm not sure we could, though - a prgegset_t is too small to hold what
we want to put in a gdb_gregset_t!

-- 
Daniel Jacobowitz                           Debian GNU/Linux Developer
Monta Vista Software                              Debian Security Team



More information about the Gdb mailing list