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]

*regset_t mess


Ulrich,

This is a rather longish message, but please read it.  We cannot
release 2.1.3 in its current state!

Look at the following change:

2000-02-19  Ulrich Drepper  <drepper@redhat.com>

	* sysdeps/unix/sysv/linux/i386/sys/ucontext.h: Include
	<sys/user.h>.  Make fpregset_t definition compatible with
	definition in 2.1.2 and before.
	(struct ucontext): Use fpregset_t.
	* sysdeps/unix/sysv/linux/i386/sys/procfs.h (prfpregset_t): Define
	as pointer to fpregset_t.

This cannot be correct!  Now `struct ucontext' in <sys/ucontext.h> is
no longer equivalent with the definition in <asm/ucontext.h>.  The
`mcontext_t' type should be equivalent to `struct sigcontext' (in fact
we could get away with simply `typedef struct sigcontext mcontext_t'
if we didn't care about the SVR4-ish naming of the members of the
mcontext_t type[1]).  So the `fpregs' member should be of type
`fpregset_t *' after your redefinition of fpregset_t.

However I really believe all these problems are caused by a
misunderstanding how the register set types and the headers are used.

The header <sys/ucontext.h> (or rather <ucontext.h>) is for user-level
contexts (ucontext_t).  A user context is passed as the third argument
to signal handlers for signals installed with the SA_SIGINFO flag set.
It is also used for the user-level context switching facilities made
available by the getcontext(), makecontext() and swapcontext() calls,
but those are currently unimplemented.  The user-level context
includes the machine context (mcontext_t).  On SVR4 systems, this
machine context is defined in terms of register sets, whose names are
gregset_t (for the general-purpose registers) and fpregset_t (for the
floating-point registers).  On Linux, the machine context has the same
layout as a `struct sigcontext', which has the unfortunate consequence
that only a pointer to the floating-point register set is included (in
a signal handler this points to some data on the stack, the location
of which will no-doubt change in the future).  When you created this
header file for Linux/i386 you tried to model the machine context from
SVR4 and provided a gregset_t and fpregset_t type.  That's why the
fpregset_t type ended up as a pointer to a struct.

The header files <sys/user.h>, <sys/reg.h> and <sys/procfs.h> exist
primarly for the debugger.

The header <sys/user.h> defines `struct user', the area of
process-specific data that can be accessed using `ptrace', which is
also dumped into a.out core-dumps.

The header <sys/reg.h> defines the offset into `struct user' where the
registers representing the process can be found.

The header <sys/procfs.h> defines some data structures for use in
conjuction with the SVR4 /proc filesystem (these are irrelevant for
the Linux /proc filesystem).  Some of these data types are also used
in ELF core dumps (in the special note sections), which is why we also
have this header on Linux.  These data types include register set data
types.  On SVR4 systems the layout for register sets used in
conjunction with the /proc filesystem and ELF core dumps is identical
to the layout used in the machine context that is part of a user-level
context.  So again, the same gregset_t and fpregset_t types are used.
On Solaris the layout of the register sets used in conjunction with
the /proc system was changed, and became different from the layout
used in the machine context part of the user-level context.  Hence the
new prgregset_t and prfpregset_t types.  On Linux, the types are
different too.  For the register sets in ELF core-dumps, the same
layout is used as in a.out core-dumps (the `struct user' layout),
which contains less "registers" as `struct sigcontext' (TRAPNO and ERR
are absent).  The Linux types were named elf_gregset_t and
elf_fpregset_t, and gregset_t and fpregset_t aliases were provided for
user-space, probably to make it easier to re-use some of the SVR4 code
in GDB.  So we ended up with two different definitions of gregset_t
and fpregset_t.  Please note that the second fpregset is *not* a
pointer to a struct.  Nobody noticed the problem, since nobody
included both <sys/ucontext.h> and <sys/procfs.h> together.

Things got really messy when you introduced the prgregset_t and
prfpregset_t types in the Linux/i386 <sys/procfs.h>.  You typedef-ed them
to gregset_t and fpregset_t.  Nothing wrong with that, except that we
have two sets of those and it might become unclear which of the two
you mean.  Which happened when you decided that <sys/ucontext.h>
should be included from <sys/procfs.h>.  I don't understand why.  What
is the relation between user-level contexts and the information stored
in ELF core-dumps?  You're ChangeLog entries seem to suggest that you
think that the prgregset_t and prfpregset_t types should be equivalent
to the register set types as defined in <sys/ucontext.h>, but this
makes no sense.  The prgregset_t and prfpregset_t are used to pass
information around about the register state of a program that is being
debugged.  On Solaris this information is read from the /proc
filesystem.  On Linux this information is read using `ptrace', which
uses the `struct user' layout which is equivalent with the
elf_gregset_t and elf_fpregset_t types.  If this doesn't convince you
please look at the prfpregset_t type.  Right now, on Linux, it's a
pointer to a struct.  This isn't the case on Solaris, and if you look
at `linuxthreads_db/td_thr_getfpregs.c' this makes no sense at all!

The bottom-line is that we should clean up the header files mentioned
in this message eventually, to make them less confusing.  Since this
involves removing one of the two gregset_t and fpregset_t types,
breaking source compatibility is inevitable.  I suggest we postpone
this for the 2.2 release.

For 2.1.3 I suggest we restart from the 2.1.2 headers, and simply add
the following types to <sys/procfs.h>:

   /* Addresses.  */
   typedef void *psaddr_t;

   /* Register sets.  Linux has different names.  */
   typedef elf_gregset_t prgregset_t;
   typedef elf_fpregset_t prfpregset_t;

   /* We don't have any differences between processes and threads,
      therefore habe only ine PID type.  */
   typedef __pid_t lwpid_t;

   typedef struct elf_prstatus prstatus_t;
   typedef struct elf_prpsinfo prpsinfo_t;

Mark


[1] Do we really care about the SVR4-ish naming of these members,
including the gregset_t and fpregset_t types?  The contents of
mcontext_t and these types aren't specified in any standard I know
of, and since `struct sigcontext' does only provide a pointer to where
the floating-point registers are stored a real SVR4-ish definition
isn't really possible.

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