This is the mail archive of the libc-hacker@sourceware.cygnus.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

prgregset_t & prfpregset_t


Hi Ulrich,

I think the current definitions of prgregset_t & prfpregset_t in
sysdeps/unix/sysv/linux/i386/sys/procfs.h are somewhat misleading:

   /* Register sets.  Linux has different names.  */
   typedef gregset_t prgregset_t;
   typedef fpregset_t prfpregset_t;

This suggests that the register layout for prgregset_t is identical to
the register layout used for the gregset_t type.  However, in the
current implementation of the thread_db support for Linuxthreads in
GDB, this is not the case.  GDB uses ptrace() to get the registers of
a particular thread, and ptrace() returns the registers in `struct
user' format (struct user_regs_struct, defined in sys/user.h), which
is AKA elf_gregset_t (defined in sys/elf.h).

So the question is, did you really mean to use gregset_t for passing
around register values in the thread_db interface?  I suspect you did
not and in that case, the definition:

  typedef elf_gregset_t prgregset_t;
  typedef elf_fpregset_t prfregset_t;

would make more sense.  

Note that there might be some real danger here too, since:

  sizeof (elf_gregset_t) < sizeof (gregset_t)

Also look at the following fragment from
linuxthreads_db/td_thr_getfpregs.c:

  td_err_e
  td_thr_getfpregs (const td_thrhandle_t *th, prfpregset_t *regset)
  {
    struct _pthread_descr_struct pds;

    LOG (__FUNCTION__);

    /* We have to get the state and the PID for this thread.  */
    if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds,
		   sizeof (struct _pthread_descr_struct)) != PS_OK)
      return TD_ERR;

    /* If the thread already terminated we return all zeroes.  */
    if (pds.p_terminated)
      memset (regset, '\0', sizeof (*regset));

In the current situation (due to the weird definition of fpregset_t),
we have effectively:

  struct _fpstate **regset;

So sizeof (*regset) == 4, and only the first part of the structure is
zeroed out.

The source of this mess is obvious: GDB uses the gregset_t type where
it actually should use `struct user_regs_struct'.  Remember HJ's
complaint about GDB compilation problems?  You told him to use
elf_gregset_t (which is allright since that is just another way of
viewing `struct user_regs_struct').  So you see that GDB is really
using the `struct user' layout instead of the sigcontext layout.

Mark

PS I'm working on getting this fixed in GDB (the official one, not
HJ's hacked version).

PPS sys/{elf.h, procfs.h, user.h} contain some really misleading
comments.  I'll try to come up with something better.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]