Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [0/2] Inspect extra signal information
@ 2009-01-12 18:47 Pedro Alves
  2009-01-12 18:49 ` Pedro Alves
                   ` (3 more replies)
  0 siblings, 4 replies; 53+ messages in thread
From: Pedro Alves @ 2009-01-12 18:47 UTC (permalink / raw)
  To: gdb-patches

Hi!

This mini series adds support for inspecting extra signal information.

What this means is, we get a new $_siginfo convenience variable that
is typed to look like the siginfo_t object on unix-ish platforms (but
can be any other type appropriate for the target platform).

E.g., on x86_64-linux,

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400770 in main () at ../../../src/gdb/testsuite/gdb.base/siginfo-obj.c:68
68        *(int *)p = 0;
(gdb) p $_siginfo
$1 = {si_signo = 11, si_errno = 0, si_code = 2, _sifields = {_pad = {-134254592, 32767, 0, 0, 0, 0, 1, 5, 12462832,
      0, 4196201, 0, 0, 0, 4196208, 0, 12337488, 0, 12337488, 0, 4196208, 0, 12518720, 0, 12518864, 0, 12518848, 0},
    _kill = {si_pid = -134254592, si_uid = 32767}, _timer = {si_tid = -134254592, si_overrun = 32767, si_sigval = {
        sival_int = 0, sival_ptr = 0x0}}, _rt = {si_pid = -134254592, si_uid = 32767, si_sigval = {sival_int = 0,
        sival_ptr = 0x0}}, _sigchld = {si_pid = -134254592, si_uid = 32767, si_status = 0, si_utime = 0,
      si_stime = 4294967296}, _sigfault = {si_addr = 0x7ffff7ff7000}, _sigpoll = {si_band = 140737354100736,
      si_fd = 0}}}

(gdb) ptype $_siginfo
type = struct {
    int si_signo;
    int si_errno;
    int si_code;
    union {
        int _pad[28];
        struct {...} _kill;
        struct {...} _timer;
        struct {...} _rt;
        struct {...} _sigchld;
        struct {...} _sigfault;
        struct {...} _sigpoll;
    } _sifields;
}

(gdb) p $_siginfo._sifields._sigfault.si_addr
$2 = (void *) 0x7ffff7ff7000

part 1:

 - Adds some infrastracture to be able to register reader and writer
   functions that are responsible for reading and writing
   a ``struct value'''s value.  We called those lval_computed values.  We've
   been using these kinds of values for other things in our tree for a
   couple of years already --- I've piggy-backed on that, so I got to
   push it.  :-)

   This first patch applies on top of this other one:

   http://sourceware.org/ml/gdb-patches/2009-01/msg00252.html

part 2:

 - Adds a new target object ``TARGET_OBJECT_SIGNAL_INFO'', used to transfer the
   siginfo_t data from the target to GDB core.

 - Adds a way for a convenience variable's type and value be lazy.  This is because
   the actual type of the $_siginfo variable may change between archs (across runs, or
   across threads).

 - Adds a new gdbarch method (get_siginfo_type) whose job is to return a type
   suitable to print/inspect a TARGET_OBJECT_SIGNAL_INFO of a given arch.

 - Adds the $_siginfo convenience variable, whose type is lval_computed.  The read and
   writer functions of this lval_computed variable take care of transfering
   a TARGET_OBJECT_SIGINFO to/from the target.

 - Adds a generic linux implementation of get_siginfo_type, suitable for linux archs
   that use the default siginfo_t structure type, and registers it in x86, x86_64
   and arm.  Other archs that diverge from the default, will need to implement
   their own version, which will be very similar to linux_get_siginfo_type.

 - Adds linux native target and remote targets implementations of
   transfering TARGET_OBJECT_SIGNAL_INFO.

 - Adds gdbserver support for same.

 - Docs, and,

 - New test.

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-01-12 18:47 [0/2] Inspect extra signal information Pedro Alves
@ 2009-01-12 18:49 ` Pedro Alves
  2009-01-12 18:52   ` [1/2] " Pedro Alves
  2009-01-12 18:50 ` [2/2] " Pedro Alves
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-01-12 18:49 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 591 bytes --]

On Monday 12 January 2009 18:46:51, Pedro Alves wrote:
> 
> part 1:
> 
>  - Adds some infrastracture to be able to register reader and writer
>    functions that are responsible for reading and writing
>    a ``struct value'''s value.  We called those lval_computed values.  We've
>    been using these kinds of values for other things in our tree for a
>    couple of years already --- I've piggy-backed on that, so I got to
>    push it.  :-)
> 
>    This first patch applies on top of this other one:
> 
>    http://sourceware.org/ml/gdb-patches/2009-01/msg00252.html
> 

-- 
Pedro Alves

[-- Attachment #2: lval_computed.diff --]
[-- Type: text/x-diff, Size: 9719 bytes --]

2009-01-12  Jim Blandy  <jimb@codesourcery.com>
	    Daniel Jacobowitz  <dan@codesourcery.com>
	    Vladimir Prus  <vladimir@codesourcery.com>
	    Pedro Alves  <pedro@codesourcery.com>

	* defs.h (enum lval_type): New value: lval_computed.
	* value.h (struct lval_funcs): New type.
	(allocate_computed_value, value_computed_funcs)
	(value_computed_closure): New declarations.
	* value.c (struct value): Add a structure to the location union
	for computed lvalues, containing 'funcs' and 'closure' members.
	(allocate_computed_value, value_computed_funcs)
	(value_computed_closure): New functions.
	(value_free): For computed lvalues, call the closure's
	'free_closure' function before freeing the value itself.
	(value_copy): If we're copying an lval_computed value, call the
	closure's 'copy_closure' function.
	(set_value_component_location): If the original value is a
	computed lvalue, then call the closure's 'copy_closure' function.
	(value_of_internalvar): If an internal variable's value is a
	computed lvalue, make retrieving its value produce an equivalent
	computed lvalue.
	* valops.c (value_fetch_lazy): Unlazy computed lvalues by calling
	their read function.
	(value_assign): Assign to computed lvalues by calling their write
	function.

---
 gdb/defs.h   |    5 ++-
 gdb/valops.c |   12 +++++++-
 gdb/value.c  |   85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 gdb/value.h  |   54 +++++++++++++++++++++++++++++++++++++
 4 files changed, 151 insertions(+), 5 deletions(-)

Index: gdb/defs.h
===================================================================
--- gdb/defs.h.orig	2009-01-11 15:40:11.000000000 +0000
+++ gdb/defs.h	2009-01-12 16:29:28.000000000 +0000
@@ -652,7 +652,10 @@ enum lval_type
     /* In a gdb internal variable.  */
     lval_internalvar,
     /* Part of a gdb internal variable (structure field).  */
-    lval_internalvar_component
+    lval_internalvar_component,
+    /* Value's bits are fetched and stored using functions provided by
+       its creator.  */
+    lval_computed
   };
 
 /* Control types for commands */
Index: gdb/value.h
===================================================================
--- gdb/value.h.orig	2009-01-12 12:40:32.000000000 +0000
+++ gdb/value.h	2009-01-12 16:48:53.000000000 +0000
@@ -142,6 +142,60 @@ extern void set_value_pointed_to_offset 
 extern int value_embedded_offset (struct value *value);
 extern void set_value_embedded_offset (struct value *value, int val);
 
+/* For lval_computed values, this structure holds functions used to
+   retrieve and set the value (or portions of the value).
+
+   For each function, 'V' is the 'this' pointer: an lval_funcs
+   function F may always assume that the V it receives is an
+   lval_computed value, and has F in the appropriate slot of its
+   lval_funcs structure.  */
+
+struct lval_funcs
+{
+  /* Fill in VALUE's contents.  This is used to "un-lazy" values.  If
+     a problem arises in obtaining VALUE's bits, this function should
+     call 'error'.  */
+  void (*read) (struct value *v);
+
+  /* Handle an assignment TOVAL = FROMVAL by writing the value of
+     FROMVAL to TOVAL's location.  The contents of TOVAL have not yet
+     been updated.  If a problem arises in doing so, this function
+     should call 'error'.  */
+  void (*write) (struct value *toval, struct value *fromval);
+
+  /* Return a duplicate of VALUE's closure, for use in a new value.
+     This may simply return the same closure, if VALUE's is
+     reference-counted or statically allocated.
+
+     This may be NULL, in which case VALUE's closure is re-used in the
+     new value.  */
+  void *(*copy_closure) (struct value *v);
+
+  /* Drop VALUE's reference to its closure.  Maybe this frees the
+     closure; maybe this decrements a reference count; maybe the
+     closure is statically allocated and this does nothing.
+
+     This may be NULL, in which case no action is taken to free
+     VALUE's closure.  */
+  void (*free_closure) (struct value *v);
+};
+
+/* Create a computed lvalue, with type TYPE, function pointers FUNCS,
+   and closure CLOSURE.  */
+
+extern struct value *allocate_computed_value (struct type *type,
+                                              struct lval_funcs *funcs,
+                                              void *closure);
+
+/* If VALUE is lval_computed, return its lval_funcs structure.  */
+
+extern struct lval_funcs *value_computed_funcs (struct value *value);
+
+/* If VALUE is lval_computed, return its closure.  The meaning of the
+   returned value depends on the functions VALUE uses.  */
+
+extern void *value_computed_closure (struct value *value);
+
 /* If zero, contents of this value are in the contents field.  If
    nonzero, contents are in inferior.  If the lval field is lval_memory,
    the contents are in inferior memory at location.address plus offset.
Index: gdb/value.c
===================================================================
--- gdb/value.c.orig	2009-01-12 11:25:23.000000000 +0000
+++ gdb/value.c	2009-01-12 16:48:54.000000000 +0000
@@ -63,6 +63,15 @@ struct value
 
     /* Pointer to internal variable.  */
     struct internalvar *internalvar;
+
+    /* If lval == lval_computed, this is a set of function pointers
+       to use to access and describe the value, and a closure pointer
+       for them to use.  */
+    struct
+    {
+      struct lval_funcs *funcs; /* Functions to call.  */
+      void *closure;            /* Closure for those functions to use.  */
+    } computed;
   } location;
 
   /* Describes offset of a value within lval of a structure in bytes.
@@ -296,6 +305,20 @@ value_remove_from_list (struct value **h
       }
 }
 
+struct value *
+allocate_computed_value (struct type *type,
+                         struct lval_funcs *funcs,
+                         void *closure)
+{
+  struct value *v = allocate_value (type);
+  VALUE_LVAL (v) = lval_computed;
+  v->location.computed.funcs = funcs;
+  v->location.computed.closure = closure;
+  set_value_lazy (v, 1);
+
+  return v;
+}
+
 /* Accessor methods.  */
 
 struct value *
@@ -458,6 +481,22 @@ set_value_pointed_to_offset (struct valu
   value->pointed_to_offset = val;
 }
 
+struct lval_funcs *
+value_computed_funcs (struct value *v)
+{
+  gdb_assert (VALUE_LVAL (v) == lval_computed);
+
+  return v->location.computed.funcs;
+}
+
+void *
+value_computed_closure (struct value *v)
+{
+  gdb_assert (VALUE_LVAL (v) == lval_computed);
+
+  return v->location.computed.closure;
+}
+
 enum lval_type *
 deprecated_value_lval_hack (struct value *value)
 {
@@ -512,7 +551,17 @@ void
 value_free (struct value *val)
 {
   if (val)
-    xfree (val->contents);
+    {
+      if (VALUE_LVAL (val) == lval_computed)
+	{
+	  struct lval_funcs *funcs = val->location.computed.funcs;
+
+	  if (funcs->free_closure)
+	    funcs->free_closure (val);
+	}
+
+      xfree (val->contents);
+    }
   xfree (val);
 }
 
@@ -625,6 +674,13 @@ value_copy (struct value *arg)
 	      TYPE_LENGTH (value_enclosing_type (arg)));
 
     }
+  if (VALUE_LVAL (val) == lval_computed)
+    {
+      struct lval_funcs *funcs = val->location.computed.funcs;
+
+      if (funcs->copy_closure)
+        val->location.computed.closure = funcs->copy_closure (val);
+    }
   return val;
 }
 
@@ -635,7 +691,15 @@ set_value_component_location (struct val
     VALUE_LVAL (component) = lval_internalvar_component;
   else
     VALUE_LVAL (component) = VALUE_LVAL (whole);
+
   component->location = whole->location;
+  if (VALUE_LVAL (whole) == lval_computed)
+    {
+      struct lval_funcs *funcs = whole->location.computed.funcs;
+
+      if (funcs->copy_closure)
+        component->location.computed.closure = funcs->copy_closure (whole);
+    }
 }
 
 \f
@@ -872,8 +936,23 @@ value_of_internalvar (struct internalvar
   val = value_copy (var->value);
   if (value_lazy (val))
     value_fetch_lazy (val);
-  VALUE_LVAL (val) = lval_internalvar;
-  VALUE_INTERNALVAR (val) = var;
+
+  /* If the variable's value is a computed lvalue, we want references
+     to it to produce another computed lvalue, where referencces and
+     assignments actually operate through the computed value's
+     functions.
+
+     This means that internal variables with computed values behave a
+     little differently from other internal variables: assignments to
+     them don't just replace the previous value altogether.  At the
+     moment, this seems like the behavior we want.  */
+  if (var->value->lval == lval_computed)
+    VALUE_LVAL (val) = lval_computed;
+  else
+    {
+      VALUE_LVAL (val) = lval_internalvar;
+      VALUE_INTERNALVAR (val) = var;
+    }
 
   /* Values are always stored in the target's byte order.  When connected to a
      target this will most likely always be correct, so there's normally no
Index: gdb/valops.c
===================================================================
--- gdb/valops.c.orig	2009-01-12 11:25:23.000000000 +0000
+++ gdb/valops.c	2009-01-12 14:21:01.000000000 +0000
@@ -727,6 +727,8 @@ value_fetch_lazy (struct value *val)
 	 watchpoints from trying to watch the saved frame pointer.  */
       value_free_to_mark (mark);
     }
+  else if (VALUE_LVAL (val) == lval_computed)
+    value_computed_funcs (val)->read (val);
   else
     internal_error (__FILE__, __LINE__, "Unexpected lazy value type.");
 
@@ -895,7 +897,15 @@ value_assign (struct value *toval, struc
 	observer_notify_target_changed (&current_target);
 	break;
       }
-      
+
+    case lval_computed:
+      {
+	struct lval_funcs *funcs = value_computed_funcs (toval);
+
+	funcs->write (toval, fromval);
+      }
+      break;
+
     default:
       error (_("Left operand of assignment is not an lvalue."));
     }

^ permalink raw reply	[flat|nested] 53+ messages in thread

* [2/2] Inspect extra signal information
  2009-01-12 18:47 [0/2] Inspect extra signal information Pedro Alves
  2009-01-12 18:49 ` Pedro Alves
@ 2009-01-12 18:50 ` Pedro Alves
  2009-01-12 19:39   ` Eli Zaretskii
  2009-01-12 23:27 ` [0/2] " Mark Kettenis
  2009-02-03 15:02 ` Pedro Alves
  3 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-01-12 18:50 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1324 bytes --]

On Monday 12 January 2009 18:46:51, Pedro Alves wrote:

> part 2:
> 
>  - Adds a new target object ``TARGET_OBJECT_SIGNAL_INFO'', used to transfer the
>    siginfo_t data from the target to GDB core.
> 
>  - Adds a way for a convenience variable's type and value be lazy.  This is because
>    the actual type of the $_siginfo variable may change between archs (across runs, or
>    across threads).
> 
>  - Adds a new gdbarch method (get_siginfo_type) whose job is to return a type
>    suitable to print/inspect a TARGET_OBJECT_SIGNAL_INFO of a given arch.
> 
>  - Adds the $_siginfo convenience variable, whose type is lval_computed.  The read and
>    writer functions of this lval_computed variable take care of transfering
>    a TARGET_OBJECT_SIGINFO to/from the target.
> 
>  - Adds a generic linux implementation of get_siginfo_type, suitable for linux archs
>    that use the default siginfo_t structure type, and registers it in x86, x86_64
>    and arm.  Other archs that diverge from the default, will need to implement
>    their own version, which will be very similar to linux_get_siginfo_type.
> 
>  - Adds linux native target and remote targets implementations of
>    transfering TARGET_OBJECT_SIGNAL_INFO.
> 
>  - Adds gdbserver support for same.
> 
>  - Docs, and,
> 
>  - New test.
> 

-- 
Pedro Alves

[-- Attachment #2: siginfo.diff --]
[-- Type: text/x-diff, Size: 50997 bytes --]

2009-01-12  Pedro Alves  <pedro@codesourcery.com>

	* target.h (enum target_object): Add new TARGET_OBJECT_SIGNAL_INFO.
	* infrun.c (siginfo_value_read, siginfo_value_write): New.
	(siginfo_value_funcs): New.
	(siginfo_make_value): New.
	(_initialize_infrun): Create the $_siginfo convenience variable.
	* gdbtypes.h (append_composite_type_field_aligned): Declare.
	* gdbtypes.c (append_composite_type_field): Rename to...
	(append_composite_type_field_aligned): ... this.  Add ALIGNMENT
	argument.  Handle it.
	(append_composite_type_field): Rewrite on top of
	append_composite_type_field_aligned.
	* value.h (internalvar_make_value): New typedef.
	(struct internalvar) <make_value>: New field.
	(create_internalvar_type_lazy): Declare.
	* value.c (create_internalvar): Clear make_value.
	(create_internalvar_type_lazy): New.
	(value_of_internalvar): If make_value is set use it.
	(preserve_values): Skip internal variables that don't have a
	value.
	* gdbarch.sh (get_siginfo_type): New.
	* gdbarch.h, gdbarch.c: Regenerate.

	* linux-tdep.h, linux-tdep.c: New.
	* amd64-linux-tdep.c: Include "linux-tdep.h".
	(amd64_linux_init_abi): Register linux_get_siginfo_type and
	linux_get_siginfo_mapper.
	* i386-linux-tdep.c: Include "linux-tdep.h".
	(i386_linux_init_abi): Register linux_get_siginfo_type and
	linux_get_siginfo_mapper.
	* arm-linux-tdep.c: Include "linux-tdep.h".
	(i386_linux_init_abi): Register linux_get_siginfo_type and
	linux_get_siginfo_mapper.

	* linux-nat.c (linux_xfer_siginfo): New.
	(linux_nat_xfer_partial): Handle TARGET_OBJECT_SIGNAL_INFO.
	* remote.c (PACKET_qXfer_siginfo_read)
	(PACKET_qXfer_siginfo_write): New.
	(feature remote_protocol_features): Add "qXfer:siginfo:read" and
	"qXfer:siginfo:write" features.
	(remote_xfer_partial): Handle TARGET_OBJECT_SIGNAL_INFO.
	(_initialize_remote): Add "set/show remote read-siginfo-object"
	and "set/show remote write-siginfo-object" commands.

	* Makefile.in (ALL_TARGET_OBS): Add linux-tdep.o.
	(HFILES_NO_SRCDIR): Add linux-tdep.h.
	(ALLDEPFILES): Add linux-tdep.c.
	
	* configure.tgt (arm*-*-linux* | arm*-*-uclinux*)
	(i[34567]86-*-linux*, x86_64-*-linux*): Add linux-tdep.o to
	gdb_target_obs.

2009-01-12  Pedro Alves  <pedro@codesourcery.com>

	gdb/gdbserver/
	* server.c (handle_query): Reprot qXfer:siginfo:read and
	qXfer:siginfo:write as supported and handle them.
	* target.h (struct target_ops) <qxfer_siginfo>: New field.
	* linux-low.c (linux_xfer_siginfo): New.
	(linux_target_ops): Set it.

2009-01-12  Pedro Alves  <pedro@codesourcery.com>

	gdb/doc/
	* gdb.texinfo (Signals): Document $_siginfo.
	(Convenience Variables): Mention $_siginfo.
	(Remote Configuration): Document qXfer:siginfo:read,
	qXfer:siginfo:write packets, and the read-siginfo-object,
	write-siginfo-object commands.

2009-01-12  Pedro Alves  <pedro@codesourcery.com>

	gdb/testsuite/
	* gdb.base/siginfo-obj.c, gdb.base/siginfo-obj.exp: New.

---
 gdb/Makefile.in                        |    4 
 gdb/amd64-linux-tdep.c                 |    3 
 gdb/arm-linux-tdep.c                   |    3 
 gdb/configure.tgt                      |    6 -
 gdb/doc/gdb.texinfo                    |   99 +++++++++++++++++++++++
 gdb/gdbarch.c                          |   33 +++++++
 gdb/gdbarch.h                          |   10 ++
 gdb/gdbarch.sh                         |    5 +
 gdb/gdbserver/linux-low.c              |   39 +++++++++
 gdb/gdbserver/server.c                 |   74 +++++++++++++++++
 gdb/gdbserver/target.h                 |    5 +
 gdb/gdbtypes.c                         |   29 +++++-
 gdb/gdbtypes.h                         |    4 
 gdb/i386-linux-tdep.c                  |    3 
 gdb/infrun.c                           |   87 ++++++++++++++++++++
 gdb/linux-nat.c                        |   50 +++++++++++
 gdb/linux-tdep.c                       |  138 +++++++++++++++++++++++++++++++++
 gdb/linux-tdep.h                       |   25 +++++
 gdb/remote.c                           |   25 +++++
 gdb/target.h                           |    5 -
 gdb/testsuite/gdb.base/siginfo-obj.c   |   70 ++++++++++++++++
 gdb/testsuite/gdb.base/siginfo-obj.exp |  131 +++++++++++++++++++++++++++++++
 gdb/value.c                            |   62 ++++++++++----
 gdb/value.h                            |    6 +
 24 files changed, 887 insertions(+), 29 deletions(-)

Index: src/gdb/target.h
===================================================================
--- src.orig/gdb/target.h	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/target.h	2009-01-12 16:30:54.000000000 +0000
@@ -217,7 +217,10 @@ enum target_object
   TARGET_OBJECT_LIBRARIES,
   /* Get OS specific data.  The ANNEX specifies the type (running
      processes, etc.).  */
-  TARGET_OBJECT_OSDATA
+  TARGET_OBJECT_OSDATA,
+  /* Extra signal info.  Usually the contents of `siginfo_t' on unix
+     platforms.  */
+  TARGET_OBJECT_SIGNAL_INFO,
   /* Possible future objects: TARGET_OBJECT_FILE, ... */
 };
 
Index: src/gdb/infrun.c
===================================================================
--- src.orig/gdb/infrun.c	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/infrun.c	2009-01-12 16:33:32.000000000 +0000
@@ -4764,6 +4764,87 @@ signals_info (char *signum_exp, int from
 
   printf_filtered (_("\nUse the \"handle\" command to change these tables.\n"));
 }
+
+/* The $_siginfo convenience variable is a bit special.  We don't know
+   for sure the type of the value until we actually have a chance to
+   fetch the data.  The type can change depending on gdbarch, so it it
+   also dependent on which thread you have selected.
+
+     1. making $_siginfo be an internalvar that creates a new value on
+     access.
+
+     2. making the value of $_siginfo be an lval_computed value.  */
+
+/* This function implements the lval_computed support for reading a
+   $_siginfo value.  */
+
+static void
+siginfo_value_read (struct value *v)
+{
+  LONGEST transferred;
+
+  transferred =
+    target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO,
+		 NULL,
+		 value_contents_all_raw (v),
+		 value_offset (v),
+		 TYPE_LENGTH (value_type (v)));
+
+  if (transferred != TYPE_LENGTH (value_type (v)))
+    error (_("Unable to read siginfo"));
+}
+
+/* This function implements the lval_computed support for writing a
+   $_siginfo value.  */
+
+static void
+siginfo_value_write (struct value *v, struct value *fromval)
+{
+  LONGEST transferred;
+
+  transferred = target_write (&current_target,
+			      TARGET_OBJECT_SIGNAL_INFO,
+			      NULL,
+			      value_contents_all_raw (fromval),
+			      value_offset (v),
+			      TYPE_LENGTH (value_type (fromval)));
+
+  if (transferred != TYPE_LENGTH (value_type (fromval)))
+    error (_("Unable to write siginfo"));
+}
+
+static struct lval_funcs siginfo_value_funcs =
+  {
+    siginfo_value_read,
+    siginfo_value_write
+  };
+
+/* Return a new value with the correct type for the siginfo object of
+   the current thread.  Return a void value if there's no object
+   available.  */
+
+struct value *
+siginfo_make_value (struct internalvar *var)
+{
+  struct type *type;
+  struct gdbarch *gdbarch;
+
+  if (target_has_stack
+      && !ptid_equal (inferior_ptid, null_ptid))
+    {
+      gdbarch = get_frame_arch (get_current_frame ());
+
+      if (gdbarch_get_siginfo_type_p (gdbarch))
+	{
+	  type = gdbarch_get_siginfo_type (gdbarch);
+
+	  return allocate_computed_value (type, &siginfo_value_funcs, NULL);
+	}
+    }
+
+  return allocate_value (builtin_type_void);
+}
+
 \f
 struct inferior_status
 {
@@ -5378,4 +5459,10 @@ Options are 'forward' or 'reverse'."),
 
   observer_attach_thread_ptid_changed (infrun_thread_ptid_changed);
   observer_attach_thread_stop_requested (infrun_thread_stop_requested);
+
+  /* Explicitly create without lookup, since that tries to create a
+     value with a void typed value, and when we get here, gdbarch
+     isn't initialized yet.  At this point, we're quite sure there
+     isn't another convenience variable of the same name.  */
+  create_internalvar_type_lazy ("_siginfo", siginfo_make_value);
 }
Index: src/gdb/gdbtypes.h
===================================================================
--- src.orig/gdb/gdbtypes.h	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/gdbtypes.h	2009-01-12 16:30:54.000000000 +0000
@@ -1112,6 +1112,10 @@ extern struct type *init_type (enum type
 extern struct type *init_composite_type (char *name, enum type_code code);
 extern void append_composite_type_field (struct type *t, char *name,
 					 struct type *field);
+extern void append_composite_type_field_aligned (struct type *t,
+						 char *name,
+						 struct type *field,
+						 int alignment);
 
 /* Helper functions to construct a bit flags type.  An initially empty
    type is created using init_flag_type().  Flags are then added using
Index: src/gdb/gdbtypes.c
===================================================================
--- src.orig/gdb/gdbtypes.c	2009-01-12 11:20:15.000000000 +0000
+++ src/gdb/gdbtypes.c	2009-01-12 16:30:54.000000000 +0000
@@ -1840,8 +1840,8 @@ init_composite_type (char *name, enum ty
 /* Helper function.  Append a field to a composite type.  */
 
 void
-append_composite_type_field (struct type *t, char *name, 
-			     struct type *field)
+append_composite_type_field_aligned (struct type *t, char *name,
+				     struct type *field, int alignment)
 {
   struct field *f;
   TYPE_NFIELDS (t) = TYPE_NFIELDS (t) + 1;
@@ -1860,12 +1860,31 @@ append_composite_type_field (struct type
     {
       TYPE_LENGTH (t) = TYPE_LENGTH (t) + TYPE_LENGTH (field);
       if (TYPE_NFIELDS (t) > 1)
-	FIELD_BITPOS (f[0]) = (FIELD_BITPOS (f[-1])
-			       + (TYPE_LENGTH (FIELD_TYPE (f[-1]))
-				  * TARGET_CHAR_BIT));
+	{
+	  FIELD_BITPOS (f[0]) = (FIELD_BITPOS (f[-1])
+				 + (TYPE_LENGTH (FIELD_TYPE (f[-1]))
+				    * TARGET_CHAR_BIT));
+
+	  if (alignment)
+	    {
+	      int left = FIELD_BITPOS (f[0]) % (alignment * TARGET_CHAR_BIT);
+	      if (left)
+		{
+		  FIELD_BITPOS (f[0]) += left;
+		  TYPE_LENGTH (t) += left / TARGET_CHAR_BIT;
+		}
+	    }
+	}
     }
 }
 
+void
+append_composite_type_field (struct type *t, char *name,
+			     struct type *field)
+{
+  append_composite_type_field_aligned (t, name, field, 0);
+}
+
 int
 can_dereference (struct type *t)
 {
Index: src/gdb/value.h
===================================================================
--- src.orig/gdb/value.h	2009-01-12 14:28:47.000000000 +0000
+++ src/gdb/value.h	2009-01-12 16:30:54.000000000 +0000
@@ -305,11 +305,14 @@ extern struct value *coerce_array (struc
 /* Internal variables (variables for convenience of use of debugger)
    are recorded as a chain of these structures.  */
 
+typedef struct value * (*internalvar_make_value) (struct internalvar *);
+
 struct internalvar
 {
   struct internalvar *next;
   char *name;
   struct value *value;
+  internalvar_make_value make_value;
   int endian;
 };
 
@@ -535,6 +538,9 @@ extern struct internalvar *lookup_only_i
 
 extern struct internalvar *create_internalvar (char *name);
 
+extern struct internalvar *
+  create_internalvar_type_lazy (char *name, internalvar_make_value fun);
+
 extern struct internalvar *lookup_internalvar (char *name);
 
 extern int value_equal (struct value *arg1, struct value *arg2);
Index: src/gdb/value.c
===================================================================
--- src.orig/gdb/value.c	2009-01-12 16:29:57.000000000 +0000
+++ src/gdb/value.c	2009-01-12 16:30:54.000000000 +0000
@@ -901,12 +901,31 @@ create_internalvar (char *name)
   var->name = concat (name, (char *)NULL);
   var->value = allocate_value (builtin_type_void);
   var->endian = gdbarch_byte_order (current_gdbarch);
+  var->make_value = NULL;
   release_value (var->value);
   var->next = internalvars;
   internalvars = var;
   return var;
 }
 
+/* Create an internal variable with name NAME and register FUN as the
+   function that value_of_internalvar uses to create a value whenever
+   this variable is referenced.  NAME should not normally include a
+   dollar sign.  */
+
+struct internalvar *
+create_internalvar_type_lazy (char *name, internalvar_make_value fun)
+{
+  struct internalvar *var;
+  var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
+  var->name = concat (name, (char *)NULL);
+  var->value = NULL;
+  var->make_value = fun;
+  var->endian = gdbarch_byte_order (current_gdbarch);
+  var->next = internalvars;
+  internalvars = var;
+  return var;
+}
 
 /* Look up an internal variable with name NAME.  NAME should not
    normally include a dollar sign.
@@ -933,25 +952,31 @@ value_of_internalvar (struct internalvar
   int i, j;
   gdb_byte temp;
 
-  val = value_copy (var->value);
-  if (value_lazy (val))
-    value_fetch_lazy (val);
-
-  /* If the variable's value is a computed lvalue, we want references
-     to it to produce another computed lvalue, where referencces and
-     assignments actually operate through the computed value's
-     functions.
-
-     This means that internal variables with computed values behave a
-     little differently from other internal variables: assignments to
-     them don't just replace the previous value altogether.  At the
-     moment, this seems like the behavior we want.  */
-  if (var->value->lval == lval_computed)
-    VALUE_LVAL (val) = lval_computed;
+  if (var->make_value != NULL)
+    val = (*var->make_value) (var);
   else
     {
-      VALUE_LVAL (val) = lval_internalvar;
-      VALUE_INTERNALVAR (val) = var;
+      val = value_copy (var->value);
+      if (value_lazy (val))
+	value_fetch_lazy (val);
+
+      /* If the variable's value is a computed lvalue, we want
+	 references to it to produce another computed lvalue, where
+	 referencces and assignments actually operate through the
+	 computed value's functions.
+
+	 This means that internal variables with computed values
+	 behave a little differently from other internal variables:
+	 assignments to them don't just replace the previous value
+	 altogether.  At the moment, this seems like the behavior we
+	 want.  */
+      if (var->value->lval == lval_computed)
+	VALUE_LVAL (val) = lval_computed;
+      else
+	{
+	  VALUE_LVAL (val) = lval_internalvar;
+	  VALUE_INTERNALVAR (val) = var;
+	}
     }
 
   /* Values are always stored in the target's byte order.  When connected to a
@@ -1075,7 +1100,8 @@ preserve_values (struct objfile *objfile
 	preserve_one_value (cur->values[i], objfile, copied_types);
 
   for (var = internalvars; var; var = var->next)
-    preserve_one_value (var->value, objfile, copied_types);
+    if (var->value)
+      preserve_one_value (var->value, objfile, copied_types);
 
   for (val = values_in_python; val; val = val->next)
     preserve_one_value (val, objfile, copied_types);
Index: src/gdb/gdbarch.sh
===================================================================
--- src.orig/gdb/gdbarch.sh	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/gdbarch.sh	2009-01-12 16:30:54.000000000 +0000
@@ -705,6 +705,11 @@ m:enum target_signal:target_signal_from_
 # signal number.
 m:int:target_signal_to_host:enum target_signal ts:ts::default_target_signal_to_host::0
 
+# Extra signal info inspection.
+#
+# Return a type suitable to inspect extra signal information.
+M:struct type *:get_siginfo_type:void:
+
 # Record architecture-specific information from the symbol table.
 M:void:record_special_symbol:struct objfile *objfile, asymbol *sym:objfile, sym
 
Index: src/gdb/gdbarch.h
===================================================================
--- src.orig/gdb/gdbarch.h	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/gdbarch.h	2009-01-12 16:30:54.000000000 +0000
@@ -803,6 +803,16 @@ typedef int (gdbarch_target_signal_to_ho
 extern int gdbarch_target_signal_to_host (struct gdbarch *gdbarch, enum target_signal ts);
 extern void set_gdbarch_target_signal_to_host (struct gdbarch *gdbarch, gdbarch_target_signal_to_host_ftype *target_signal_to_host);
 
+/* Extra signal info inspection.
+
+   Return a type suitable to inspect extra signal information. */
+
+extern int gdbarch_get_siginfo_type_p (struct gdbarch *gdbarch);
+
+typedef struct type * (gdbarch_get_siginfo_type_ftype) (struct gdbarch *gdbarch);
+extern struct type * gdbarch_get_siginfo_type (struct gdbarch *gdbarch);
+extern void set_gdbarch_get_siginfo_type (struct gdbarch *gdbarch, gdbarch_get_siginfo_type_ftype *get_siginfo_type);
+
 /* Record architecture-specific information from the symbol table. */
 
 extern int gdbarch_record_special_symbol_p (struct gdbarch *gdbarch);
Index: src/gdb/gdbarch.c
===================================================================
--- src.orig/gdb/gdbarch.c	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/gdbarch.c	2009-01-12 16:30:54.000000000 +0000
@@ -239,6 +239,7 @@ struct gdbarch
   int sofun_address_maybe_missing;
   gdbarch_target_signal_from_host_ftype *target_signal_from_host;
   gdbarch_target_signal_to_host_ftype *target_signal_to_host;
+  gdbarch_get_siginfo_type_ftype *get_siginfo_type;
   gdbarch_record_special_symbol_ftype *record_special_symbol;
   int has_global_solist;
 };
@@ -371,6 +372,7 @@ struct gdbarch startup_gdbarch =
   0,  /* sofun_address_maybe_missing */
   default_target_signal_from_host,  /* target_signal_from_host */
   default_target_signal_to_host,  /* target_signal_to_host */
+  0,  /* get_siginfo_type */
   0,  /* record_special_symbol */
   0,  /* has_global_solist */
   /* startup_gdbarch() */
@@ -624,6 +626,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of sofun_address_maybe_missing, invalid_p == 0 */
   /* Skip verify of target_signal_from_host, invalid_p == 0 */
   /* Skip verify of target_signal_to_host, invalid_p == 0 */
+  /* Skip verify of get_siginfo_type, has predicate */
   /* Skip verify of record_special_symbol, has predicate */
   /* Skip verify of has_global_solist, invalid_p == 0 */
   buf = ui_file_xstrdup (log, &dummy);
@@ -835,6 +838,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s
                       "gdbarch_dump: get_longjmp_target = <%s>\n",
                       host_address_to_string (gdbarch->get_longjmp_target));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_get_siginfo_type_p() = %d\n",
+                      gdbarch_get_siginfo_type_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: get_siginfo_type = <0x%lx>\n",
+                      (long) gdbarch->get_siginfo_type);
+  fprintf_unfiltered (file,
                       "gdbarch_dump: has_global_solist = %s\n",
                       plongest (gdbarch->has_global_solist));
   fprintf_unfiltered (file,
@@ -3220,6 +3229,30 @@ set_gdbarch_target_signal_to_host (struc
 }
 
 int
+gdbarch_get_siginfo_type_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->get_siginfo_type != NULL;
+}
+
+struct type *
+gdbarch_get_siginfo_type (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->get_siginfo_type != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_get_siginfo_type called\n");
+  return gdbarch->get_siginfo_type (gdbarch);
+}
+
+void
+set_gdbarch_get_siginfo_type (struct gdbarch *gdbarch,
+                              gdbarch_get_siginfo_type_ftype get_siginfo_type)
+{
+  gdbarch->get_siginfo_type = get_siginfo_type;
+}
+
+int
 gdbarch_record_special_symbol_p (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
Index: src/gdb/linux-tdep.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/linux-tdep.h	2009-01-12 16:39:10.000000000 +0000
@@ -0,0 +1,25 @@
+/* Target-dependent code for GNU/Linux, architecture independent.
+
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef LINUX_TDEP_H
+#define LINUX_TDEP_H
+
+struct type *linux_get_siginfo_type (struct gdbarch *);
+
+#endif /* linux-tdep.h */
Index: src/gdb/linux-tdep.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/linux-tdep.c	2009-01-12 16:38:44.000000000 +0000
@@ -0,0 +1,138 @@
+/* Target-dependent code for GNU/Linux, architecture independent.
+
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdbtypes.h"
+
+/* This function is suitable for architectures that don't
+   extend/override the standard siginfo structure.  */
+
+struct type *
+linux_get_siginfo_type (struct gdbarch *gdbarch)
+{
+  struct type *int_type, *uint_type, *long_type, *void_ptr_type;
+  struct type *uid_type, *pid_type;
+  struct type *sigval_type, *clock_type;
+  struct type *siginfo_type, *sifields_type;
+  struct type *type;
+
+  int_type = init_type (TYPE_CODE_INT,
+			gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT,
+			0, "int", NULL);
+  uint_type = init_type (TYPE_CODE_INT,
+			 gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT,
+			 0, "unsigned int", NULL);
+  long_type = init_type (TYPE_CODE_INT,
+			 gdbarch_long_bit (gdbarch) / HOST_CHAR_BIT,
+			 0, "long", NULL);
+  void_ptr_type = lookup_pointer_type (builtin_type (gdbarch)->builtin_void);
+
+  /* sival_t */
+  sigval_type = init_composite_type (NULL, TYPE_CODE_UNION);
+  TYPE_NAME (sigval_type) = xstrdup ("sigval_t");
+  append_composite_type_field (sigval_type, "sival_int", int_type);
+  append_composite_type_field (sigval_type, "sival_ptr", void_ptr_type);
+
+  /* __pid_t */
+  pid_type = init_type (TYPE_CODE_TYPEDEF, TYPE_LENGTH (int_type),
+			TYPE_FLAG_TARGET_STUB, NULL, NULL);
+  TYPE_NAME (pid_type) = xstrdup ("__pid_t");
+  TYPE_TARGET_TYPE (pid_type) = int_type;
+
+  /* __uid_t */
+  uid_type = init_type (TYPE_CODE_TYPEDEF, TYPE_LENGTH (uint_type),
+			TYPE_FLAG_TARGET_STUB, NULL, NULL);
+  TYPE_NAME (uid_type) = xstrdup ("__uid_t");
+  TYPE_TARGET_TYPE (uid_type) = uint_type;
+
+  /* __clock_t */
+  clock_type = init_type (TYPE_CODE_TYPEDEF, TYPE_LENGTH (long_type),
+			  TYPE_FLAG_TARGET_STUB, NULL, NULL);
+  TYPE_NAME (clock_type) = xstrdup ("__clock_t");
+  TYPE_TARGET_TYPE (clock_type) = long_type;
+
+  /* _sifields */
+  sifields_type = init_composite_type (NULL, TYPE_CODE_UNION);
+
+  {
+    const int si_max_size = 128;
+    int si_pad_size;
+    int size_of_int = gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT;
+
+    /* _pad */
+    if (gdbarch_ptr_bit (gdbarch) == 64)
+      si_pad_size = (si_max_size / size_of_int) - 4;
+    else
+      si_pad_size = (si_max_size / size_of_int) - 3;
+    append_composite_type_field (sifields_type, "_pad",
+				 init_vector_type (int_type, si_pad_size));
+  }
+
+  /* _kill */
+  type = init_composite_type (NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (type, "si_pid", pid_type);
+  append_composite_type_field (type, "si_uid", uid_type);
+  append_composite_type_field (sifields_type, "_kill", type);
+
+  /* _timer */
+  type = init_composite_type (NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (type, "si_tid", int_type);
+  append_composite_type_field (type, "si_overrun", int_type);
+  append_composite_type_field (type, "si_sigval", sigval_type);
+  append_composite_type_field (sifields_type, "_timer", type);
+
+  /* _rt */
+  type = init_composite_type (NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (type, "si_pid", pid_type);
+  append_composite_type_field (type, "si_uid", uid_type);
+  append_composite_type_field (type, "si_sigval", sigval_type);
+  append_composite_type_field (sifields_type, "_rt", type);
+
+  /* _sigchld */
+  type = init_composite_type (NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (type, "si_pid", pid_type);
+  append_composite_type_field (type, "si_uid", uid_type);
+  append_composite_type_field (type, "si_status", int_type);
+  append_composite_type_field (type, "si_utime", clock_type);
+  append_composite_type_field (type, "si_stime", clock_type);
+  append_composite_type_field (sifields_type, "_sigchld", type);
+
+  /* _sigfault */
+  type = init_composite_type (NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (type, "si_addr", void_ptr_type);
+  append_composite_type_field (sifields_type, "_sigfault", type);
+
+  /* _sigpoll */
+  type = init_composite_type (NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (type, "si_band", long_type);
+  append_composite_type_field (type, "si_fd", int_type);
+  append_composite_type_field (sifields_type, "_sigpoll", type);
+
+  /* struct siginfo */
+  siginfo_type = init_composite_type (NULL, TYPE_CODE_STRUCT);
+  TYPE_NAME (siginfo_type) = xstrdup ("siginfo");
+  append_composite_type_field (siginfo_type, "si_signo", int_type);
+  append_composite_type_field (siginfo_type, "si_errno", int_type);
+  append_composite_type_field (siginfo_type, "si_code", int_type);
+  append_composite_type_field_aligned (siginfo_type,
+				       "_sifields", sifields_type,
+				       TYPE_LENGTH (long_type));
+
+  return siginfo_type;
+}
Index: src/gdb/amd64-linux-tdep.c
===================================================================
--- src.orig/gdb/amd64-linux-tdep.c	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/amd64-linux-tdep.c	2009-01-12 16:30:54.000000000 +0000
@@ -28,6 +28,7 @@
 #include "gdbtypes.h"
 #include "reggroups.h"
 #include "amd64-linux-tdep.h"
+#include "linux-tdep.h"
 
 #include "gdb_string.h"
 
@@ -286,6 +287,8 @@ amd64_linux_init_abi (struct gdbarch_inf
   /* Enable TLS support.  */
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
+
+  set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
 }
 \f
 
Index: src/gdb/i386-linux-tdep.c
===================================================================
--- src.orig/gdb/i386-linux-tdep.c	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/i386-linux-tdep.c	2009-01-12 16:30:54.000000000 +0000
@@ -31,6 +31,7 @@
 
 #include "i386-tdep.h"
 #include "i386-linux-tdep.h"
+#include "linux-tdep.h"
 #include "glibc-tdep.h"
 #include "solib-svr4.h"
 #include "symtab.h"
@@ -469,6 +470,8 @@ i386_linux_init_abi (struct gdbarch_info
                                            simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch,
                                        displaced_step_at_entry_point);
+
+  set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
Index: src/gdb/arm-linux-tdep.c
===================================================================
--- src.orig/gdb/arm-linux-tdep.c	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/arm-linux-tdep.c	2009-01-12 16:30:54.000000000 +0000
@@ -36,6 +36,7 @@
 
 #include "arm-tdep.h"
 #include "arm-linux-tdep.h"
+#include "linux-tdep.h"
 #include "glibc-tdep.h"
 
 #include "gdb_string.h"
@@ -647,6 +648,8 @@ arm_linux_init_abi (struct gdbarch_info 
   /* Core file support.  */
   set_gdbarch_regset_from_core_section (gdbarch,
 					arm_linux_regset_from_core_section);
+
+  set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
 }
 
 void
Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/linux-nat.c	2009-01-12 16:30:54.000000000 +0000
@@ -3215,14 +3215,62 @@ linux_nat_mourn_inferior (struct target_
 }
 
 static LONGEST
+linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
+                    const char *annex, gdb_byte *readbuf,
+		    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+{
+  struct lwp_info *lp;
+  LONGEST n;
+  int pid;
+  struct siginfo siginfo;
+
+  gdb_assert (object == TARGET_OBJECT_SIGNAL_INFO);
+  gdb_assert (readbuf || writebuf);
+
+  pid = GET_LWP (inferior_ptid);
+  if (pid == 0)
+    pid = GET_PID (inferior_ptid);
+
+  if (offset > sizeof (siginfo))
+    return -1;
+
+  errno = 0;
+  ptrace (PTRACE_GETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, &siginfo);
+  if (errno != 0)
+    return -1;
+
+  if (offset + len > sizeof (siginfo))
+    len = sizeof (siginfo) - offset;
+
+  if (readbuf != NULL)
+    memcpy (readbuf, (char *)&siginfo + offset, len);
+  else
+    {
+      memcpy ((char *)&siginfo + offset, writebuf, len);
+      errno = 0;
+      ptrace (PTRACE_SETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, &siginfo);
+      if (errno != 0)
+	return -1;
+    }
+
+  return len;
+}
+
+static LONGEST
 linux_nat_xfer_partial (struct target_ops *ops, enum target_object object,
 			const char *annex, gdb_byte *readbuf,
 			const gdb_byte *writebuf,
 			ULONGEST offset, LONGEST len)
 {
-  struct cleanup *old_chain = save_inferior_ptid ();
+  struct cleanup *old_chain;
   LONGEST xfer;
 
+  if (object == TARGET_OBJECT_SIGNAL_INFO)
+    return linux_xfer_siginfo (ops, object, annex, readbuf, writebuf,
+			       offset, len);
+
+  old_chain = save_inferior_ptid ();
+
   if (is_lwp (inferior_ptid))
     inferior_ptid = pid_to_ptid (GET_LWP (inferior_ptid));
 
Index: src/gdb/remote.c
===================================================================
--- src.orig/gdb/remote.c	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/remote.c	2009-01-12 16:30:54.000000000 +0000
@@ -1001,6 +1001,8 @@ enum {
   PACKET_vRun,
   PACKET_QStartNoAckMode,
   PACKET_vKill,
+  PACKET_qXfer_siginfo_read,
+  PACKET_qXfer_siginfo_write,
   PACKET_MAX
 };
 
@@ -2965,6 +2967,10 @@ static struct protocol_feature remote_pr
     PACKET_QStartNoAckMode },
   { "multiprocess", PACKET_DISABLE, remote_multi_process_feature, -1 },
   { "QNonStop", PACKET_DISABLE, remote_non_stop_feature, -1 },
+  { "qXfer:siginfo:read", PACKET_DISABLE, remote_supported_packet,
+    PACKET_qXfer_siginfo_read },
+  { "qXfer:siginfo:write", PACKET_DISABLE, remote_supported_packet,
+    PACKET_qXfer_siginfo_write },
 };
 
 static void
@@ -7300,6 +7306,19 @@ remote_xfer_partial (struct target_ops *
 				     [PACKET_qXfer_spu_write]);
     }
 
+  /* Handle extra signal info using qxfer packets.  */
+  if (object == TARGET_OBJECT_SIGNAL_INFO)
+    {
+      if (readbuf)
+	return remote_read_qxfer (ops, "siginfo", annex, readbuf, offset, len,
+				  &remote_protocol_packets
+				  [PACKET_qXfer_siginfo_read]);
+      else
+	return remote_write_qxfer (ops, "siginfo", annex, writebuf, offset, len,
+				   &remote_protocol_packets
+				   [PACKET_qXfer_siginfo_write]);
+    }
+
   /* Only handle flash writes.  */
   if (writebuf != NULL)
     {
@@ -9056,6 +9075,12 @@ Show the maximum size of the address (in
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_osdata],
                         "qXfer:osdata:read", "osdata", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_siginfo_read],
+                         "qXfer:siginfo:read", "read-siginfo-object", 0);
+
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_siginfo_write],
+                         "qXfer:siginfo:write", "write-siginfo-object", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qGetTLSAddr],
 			 "qGetTLSAddr", "get-thread-local-storage-address",
 			 0);
Index: src/gdb/Makefile.in
===================================================================
--- src.orig/gdb/Makefile.in	2009-01-12 11:21:46.000000000 +0000
+++ src/gdb/Makefile.in	2009-01-12 16:31:52.000000000 +0000
@@ -481,6 +481,7 @@ ALL_TARGET_OBS = \
 	i386-sol2-tdep.o i386-tdep.o i387-tdep.o \
 	i386-dicos-tdep.o \
 	iq2000-tdep.o \
+	linux-tdep.o \
 	m32c-tdep.o \
 	m32r-linux-tdep.o m32r-tdep.o \
 	m68hc11-tdep.o \
@@ -728,7 +729,7 @@ config/sparc/nm-sol2.h config/nm-linux.h
 config/rs6000/nm-rs6000.h top.h bsd-kvm.h gdb-stabs.h reggroups.h \
 annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h	\
 remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \
-sentinel-frame.h bcache.h symfile.h windows-tdep.h
+sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -1299,6 +1300,7 @@ ALLDEPFILES = \
 	irix5-nat.c \
 	libunwind-frame.c \
 	linux-fork.c \
+	linux-tdep.c \
 	m68hc11-tdep.c \
 	m32r-tdep.c \
 	m32r-linux-nat.c m32r-linux-tdep.c \
Index: src/gdb/configure.tgt
===================================================================
--- src.orig/gdb/configure.tgt	2009-01-12 11:21:47.000000000 +0000
+++ src/gdb/configure.tgt	2009-01-12 16:30:54.000000000 +0000
@@ -75,7 +75,7 @@ arm*-wince-pe | arm*-*-mingw32ce*)
 arm*-*-linux*)
 	# Target: ARM based machine running GNU/Linux
 	gdb_target_obs="arm-tdep.o arm-linux-tdep.o glibc-tdep.o \
-			solib.o solib-svr4.o symfile-mem.o corelow.o"
+			solib.o solib-svr4.o symfile-mem.o corelow.o linux-tdep.o"
 	build_gdbserver=yes
 	;;
 arm*-*-netbsd* | arm*-*-knetbsd*-gnu)
@@ -190,7 +190,7 @@ i[34567]86-*-solaris*)
 i[34567]86-*-linux*)
 	# Target: Intel 386 running GNU/Linux
 	gdb_target_obs="i386-tdep.o i386-linux-tdep.o glibc-tdep.o i387-tdep.o \
-			solib.o solib-svr4.o symfile-mem.o corelow.o"
+			solib.o solib-svr4.o symfile-mem.o corelow.o linux-tdep.o"
 	build_gdbserver=yes
 	;;
 i[34567]86-*-gnu*)
@@ -513,7 +513,7 @@ x86_64-*-linux*)
 	# Target: GNU/Linux x86-64
 	gdb_target_obs="amd64-tdep.o amd64-linux-tdep.o i386-tdep.o \
 			i387-tdep.o i386-linux-tdep.o glibc-tdep.o \
-			solib.o solib-svr4.o corelow.o symfile-mem.o"
+			solib.o solib-svr4.o corelow.o symfile-mem.o linux-tdep.o"
 	build_gdbserver=yes
 	;;
 x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu)
Index: src/gdb/gdbserver/server.c
===================================================================
--- src.orig/gdb/gdbserver/server.c	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/gdbserver/server.c	2009-01-12 16:30:54.000000000 +0000
@@ -800,6 +800,77 @@ handle_query (char *own_buf, int packet_
       return;
     }
 
+  if (the_target->qxfer_siginfo != NULL
+      && strncmp ("qXfer:siginfo:read:", own_buf, 19) == 0)
+    {
+      unsigned char *data;
+      int n;
+      CORE_ADDR ofs;
+      unsigned int len;
+      char *annex;
+
+      require_running (own_buf);
+
+      /* Reject any annex; grab the offset and length.  */
+      if (decode_xfer_read (own_buf + 19, &annex, &ofs, &len) < 0
+	  || annex[0] != '\0')
+	{
+	  strcpy (own_buf, "E00");
+	  return;
+	}
+
+      /* Read one extra byte, as an indicator of whether there is
+	 more.  */
+      if (len > PBUFSIZ - 2)
+	len = PBUFSIZ - 2;
+      data = malloc (len + 1);
+      if (!data)
+        return;
+      n = (*the_target->qxfer_siginfo) (annex, data, NULL, ofs, len + 1);
+      if (n < 0)
+	write_enn (own_buf);
+      else if (n > len)
+	*new_packet_len_p = write_qxfer_response (own_buf, data, len, 1);
+      else
+	*new_packet_len_p = write_qxfer_response (own_buf, data, n, 0);
+
+      free (data);
+      return;
+    }
+
+  if (the_target->qxfer_siginfo != NULL
+      && strncmp ("qXfer:siginfo:write:", own_buf, 20) == 0)
+    {
+      char *annex;
+      int n;
+      unsigned int len;
+      CORE_ADDR ofs;
+      unsigned char *data;
+
+      require_running (own_buf);
+
+      strcpy (own_buf, "E00");
+      data = malloc (packet_len - 19);
+      if (!data)
+        return;
+      if (decode_xfer_write (own_buf + 20, packet_len - 20, &annex,
+			     &ofs, &len, data) < 0)
+	{
+	  free (data);
+	  return;
+	}
+
+      n = (*the_target->qxfer_siginfo)
+	(annex, NULL, (unsigned const char *)data, ofs, len);
+      if (n < 0)
+	write_enn (own_buf);
+      else
+	sprintf (own_buf, "%x", n);
+
+      free (data);
+      return;
+    }
+
   /* Protocol features query.  */
   if (strncmp ("qSupported", own_buf, 10) == 0
       && (own_buf[10] == ':' || own_buf[10] == '\0'))
@@ -816,6 +887,9 @@ handle_query (char *own_buf, int packet_
       if (the_target->qxfer_spu != NULL)
 	strcat (own_buf, ";qXfer:spu:read+;qXfer:spu:write+");
 
+      if (the_target->qxfer_siginfo != NULL)
+	strcat (own_buf, ";qXfer:siginfo:read+;qXfer:siginfo:write+");
+
       /* We always report qXfer:features:read, as targets may
 	 install XML files on a subsequent call to arch_setup.
 	 If we reported to GDB on startup that we don't support
Index: src/gdb/gdbserver/target.h
===================================================================
--- src.orig/gdb/gdbserver/target.h	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/gdbserver/target.h	2009-01-12 16:30:54.000000000 +0000
@@ -193,6 +193,11 @@ struct target_ops
   int (*qxfer_osdata) (const char *annex, unsigned char *readbuf,
 		       unsigned const char *writebuf, CORE_ADDR offset, 
 		       int len);
+
+  /* Read/Write extra signal info.  */
+  int (*qxfer_siginfo) (const char *annex, unsigned char *readbuf,
+			unsigned const char *writebuf,
+			CORE_ADDR offset, int len);
 };
 
 extern struct target_ops *the_target;
Index: src/gdb/gdbserver/linux-low.c
===================================================================
--- src.orig/gdb/gdbserver/linux-low.c	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/gdbserver/linux-low.c	2009-01-12 16:30:54.000000000 +0000
@@ -2180,6 +2180,44 @@ linux_qxfer_osdata (const char *annex,
   return len;
 }
 
+static int
+linux_xfer_siginfo (const char *annex, unsigned char *readbuf,
+		    unsigned const char *writebuf, CORE_ADDR offset, int len)
+{
+  struct siginfo siginfo;
+  long pid = -1;
+
+  if (current_inferior == NULL)
+    return -1;
+
+  pid = pid_of (get_thread_process (current_inferior));
+
+  if (debug_threads)
+    fprintf (stderr, "%s siginfo for lwp %ld.\n",
+	     readbuf != NULL ? "Reading" : "Writing",
+	     pid);
+
+  if (offset > sizeof (siginfo))
+    return -1;
+
+  if (ptrace (PTRACE_GETSIGINFO, pid, 0, &siginfo) != 0)
+    return -1;
+
+  if (offset + len > sizeof (siginfo))
+    len = sizeof (siginfo) - offset;
+
+  if (readbuf != NULL)
+    memcpy (readbuf, (char *) &siginfo + offset, len);
+  else
+    {
+      memcpy ((char *) &siginfo + offset, writebuf, len);
+      if (ptrace (PTRACE_SETSIGINFO, pid, 0, &siginfo) != 0)
+	return -1;
+    }
+
+  return len;
+}
+
 static struct target_ops linux_target_ops = {
   linux_create_inferior,
   linux_attach,
@@ -2213,6 +2251,7 @@ static struct target_ops linux_target_op
   NULL,
   hostio_last_error_from_errno,
   linux_qxfer_osdata,
+  linux_xfer_siginfo,
 };
 
 static void
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo	2009-01-10 14:03:08.000000000 +0000
+++ src/gdb/doc/gdb.texinfo	2009-01-12 16:30:54.000000000 +0000
@@ -4473,6 +4473,55 @@ a result of the fatal signal once it saw
 you can continue with @samp{signal 0}.  @xref{Signaling, ,Giving your
 Program a Signal}.
 
+@cindex inspecting extra signal information
+@anchor{inspecting extra signal information}
+
+On some targets, @value{GDBN} can inspect extra signal information
+associated with the intercepted signal, before it is actually
+delivered to the program being debugged.  This information is exported
+by the convenience variable @code{$_siginfo}, and consists of data
+that is passed by the kernel to the signal handler at the time of the
+receipt of a signal.  The data type of the information itself is
+target dependent.  You can see the data type using the @code{ptype
+$_siginfo} command.  On Unix systems, it typically corresponds to the
+standard @code{siginfo_t} type, as defined in the @file{signal.h}
+system header.
+
+Here's an example, on a @sc{gnu}/Linux system, printing the stray
+referenced address that raised a segmentation fault.
+
+@smallexample
+@group
+(@value{GDBP}) continue
+Program received signal SIGSEGV, Segmentation fault.
+0x0000000000400766 in main ()
+69        *(int *)p = 0;
+(@value{GDBP}) ptype $_siginfo
+type = struct @{
+    int si_signo;
+    int si_errno;
+    int si_code;
+    union @{
+        int _pad[28];
+        struct @{...@} _kill;
+        struct @{...@} _timer;
+        struct @{...@} _rt;
+        struct @{...@} _sigchld;
+        struct @{...@} _sigfault;
+        struct @{...@} _sigpoll;
+    @} _sifields;
+@}
+(@value{GDBP}) ptype $_siginfo._sifields._sigfault
+type = struct @{
+    void *si_addr;
+@}
+(@value{GDBP}) p $_siginfo._sifields._sigfault.si_addr
+$1 = (void *) 0x7ffff7ff7000
+@end group
+@end smallexample
+
+Depending on target support, @code{$_siginfo} may also be writable.
+
 @node Thread Stops
 @section Stopping and Starting Multi-thread Programs
 
@@ -7345,6 +7394,11 @@ to match the format in which the data wa
 @vindex $_exitcode@r{, convenience variable}
 The variable @code{$_exitcode} is automatically set to the exit code when
 the program being debugged terminates.
+
+@item $_siginfo
+@vindex $_siginfo@r{, convenience variable}
+The variable @code{$_siginfo} is bound to extra signal information
+inspection (@pxref{inspecting extra signal information}).
 @end table
 
 On HP-UX systems, if you refer to a function or variable name that
@@ -14303,6 +14357,14 @@ are:
 @tab @code{qXfer:spu:write}
 @tab @code{info spu}
 
+@item @code{read-siginfo-object}
+@tab @code{qXfer:siginfo:read}
+@tab @code{print $_siginfo}
+
+@item @code{write-siginfo-object}
+@tab @code{qXfer:siginfo:write}
+@tab @code{set $_siginfo}
+
 @item @code{get-thread-local-@*storage-address}
 @tab @code{qGetTLSAddr}
 @tab Displaying @code{__thread} variables
@@ -26513,6 +26575,16 @@ These are the currently defined stub fea
 @tab @samp{-}
 @tab Yes
 
+@item @samp{qXfer:siginfo:read}
+@tab No
+@tab @samp{-}
+@tab Yes
+
+@item @samp{qXfer:siginfo:write}
+@tab No
+@tab @samp{-}
+@tab Yes
+
 @item @samp{QNonStop}
 @tab No
 @tab @samp{-}
@@ -26573,6 +26645,14 @@ The remote stub understands the @samp{qX
 The remote stub understands the @samp{qXfer:spu:write} packet
 (@pxref{qXfer spu write}).
 
+@item qXfer:siginfo:read
+The remote stub understands the @samp{qXfer:siginfo:read} packet
+(@pxref{qXfer spu read}).
+
+@item qXfer:siginfo:write
+The remote stub understands the @samp{qXfer:siginfo:write} packet
+(@pxref{qXfer spu write}).
+
 @item QNonStop
 The remote stub understands the @samp{QNonStop} packet
 (@pxref{QNonStop}).
@@ -26783,6 +26863,7 @@ the stub, or that the object does not su
 
 @item qXfer:@var{object}:write:@var{annex}:@var{offset}:@var{data}@dots{}
 @cindex write data into object, remote request
+@anchor{qXfer write}
 Write uninterpreted bytes into the target's special data area
 identified by the keyword @var{object}, starting at @var{offset} bytes
 into the data.  @var{data}@dots{} is the binary-encoded data
@@ -26805,6 +26886,24 @@ in that context to be accessed.
 
 This packet is not probed by default; the remote stub must request it,
 by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
+
+@item qXfer:siginfo:read:@var{annex}:@var{offset},@var{length}
+@anchor{qXfer siginfo read}
+Read contents of the extra signal information on the target
+system.  The annex part of the generic @samp{qXfer} packet must be
+empty (@pxref{qXfer read}).
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
+
+@item qXfer:@var{siginfo}:write:@var{annex}:@var{offset}:@var{data}@dots{}
+@anchor{qXfer siginfo write}
+Write @var{data} to the extra signal information on the target system.
+The annex part of the generic @samp{qXfer} packet must be
+empty (@pxref{qXfer write}).
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
 @end table
 
 Reply:
Index: src/gdb/testsuite/gdb.base/siginfo-obj.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.base/siginfo-obj.c	2009-01-12 16:30:54.000000000 +0000
@@ -0,0 +1,70 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2004, 2007, 2008 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+static void *p;
+
+static void
+handler (int sig, siginfo_t *info, void *context)
+{
+  /* Copy to local vars, as the test wants to read them, and si_addr,
+     etc. may be preprocessor defines.  */
+  int ssi_errno = info->si_errno;
+  int ssi_signo = info->si_signo;
+  int ssi_code = info->si_code;
+  void *ssi_addr = info->si_addr;
+
+  _exit (0); /* set breakpoint here */
+}
+
+int
+main (void)
+{
+  /* Set up unwritable memory.  */
+  {
+    size_t len;
+    len = sysconf(_SC_PAGESIZE);
+    p = mmap (0, len, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+    if (p == MAP_FAILED)
+      {
+	perror ("mmap");
+	return 1;
+      }
+  }
+  /* Set up the signal handler.  */
+  {
+    struct sigaction action;
+    memset (&action, 0, sizeof (action));
+    action.sa_sigaction = handler;
+    action.sa_flags |= SA_SIGINFO;
+    if (sigaction (SIGSEGV, &action, NULL))
+      {
+	perror ("sigaction");
+	return 1;
+      }
+  }
+  /* Trigger SIGSEGV.  */
+  *(int *)p = 0;
+  return 0;
+}
Index: src/gdb/testsuite/gdb.base/siginfo-obj.exp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.base/siginfo-obj.exp	2009-01-12 16:30:54.000000000 +0000
@@ -0,0 +1,131 @@
+# Copyright 2004, 2007, 2008 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+# The program siginfo-obj.c arranges for a signal handler registered
+# using sigaction's sa_sigaction / SA_SIGINFO to be called with
+# si_addr filled in.
+
+# This test confirms that we can inspect signal info using the
+# $_siginfo convenience variable.
+
+if [target_info exists gdb,nosignals] {
+    verbose "Skipping siginfo-obj.exp because of nosignals."
+    continue
+}
+
+if { ! [istarget "i?86-*-linux*"]
+     && ! [istarget "x86_64-*-linux*"]
+     && ! [istarget "arm*-*-linux*"] } {
+    verbose "Skipping siginfo-obj.exp because of lack of support."
+    return
+}
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile siginfo-obj
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+    untested "Couldn't compile ${srcfile}.c"
+    return -1
+}
+
+# get things started
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Advance to main
+if { ![runto_main] } then {
+    gdb_suppress_tests;
+}
+
+# Run to the signal.
+gdb_test "continue" ".*Program received signal SIGSEGV.*" "continue to signal"
+
+set ssi_addr ""
+set test "Extract si_addr"
+gdb_test_multiple "p \$_siginfo" "$test" {
+    -re "si_addr = ($hex).*$gdb_prompt $" {
+	set ssi_addr $expect_out(1,string)
+	pass "$test"
+    }
+}
+
+set test "Extract si_errno"
+gdb_test_multiple "p \$_siginfo" "$test" {
+    -re "si_errno = (\[0-9\]\+).*$gdb_prompt $" {
+	set ssi_errno $expect_out(1,string)
+	pass "$test"
+    }
+}
+
+set test "Extract si_code"
+gdb_test_multiple "p \$_siginfo" "$test" {
+    -re "si_code = (\[0-9\]\+).*$gdb_prompt $" {
+	set ssi_code $expect_out(1,string)
+	pass "$test"
+    }
+}
+
+set test "Extract si_signo"
+gdb_test_multiple "p \$_siginfo" "$test" {
+    -re "si_signo = (\[0-9\]\+).*$gdb_prompt $" {
+	set ssi_signo $expect_out(1,string)
+	pass "$test"
+    }
+}
+
+set bp_location [gdb_get_line_number "set breakpoint here"]
+
+gdb_test "break $bp_location"
+gdb_test "continue" ".* handler .*" "continue to handler"
+
+gdb_test "p ssi_addr" " = \\(void \\*\\) $ssi_addr"
+gdb_test "p ssi_errno" " = $ssi_errno"
+gdb_test "p ssi_code" " = $ssi_code"
+gdb_test "p ssi_signo" " = $ssi_signo"
+
+# Again, but this time, patch si_addr and check that the inferior sees
+# the changed value.
+
+# Advance to main
+if { ![runto_main] } then {
+    gdb_suppress_tests;
+}
+
+# Run to the signal.
+gdb_test "continue" ".*Program received signal SIGSEGV.*" "continue to signal"
+
+set test "Set si_addr"
+gdb_test "p \$_siginfo._sifields._sigfault.si_addr = 0x666" " = \\(void \\*\\) 0x666"
+gdb_test "p \$_siginfo.si_errno = 666" " = 666"
+gdb_test "p \$_siginfo.si_code = 999" " = 999"
+gdb_test "p \$_siginfo.si_signo = 11" " = 11"
+
+gdb_test "break $bp_location"
+gdb_test "continue" ".* handler .*" "continue to handler"
+
+gdb_test "p ssi_addr" " = \\(void \\*\\) 0x666"
+gdb_test "p ssi_errno" " = 666"
+gdb_test "p ssi_code" " = 999"
+gdb_test "p ssi_signo" " = 11"

^ permalink raw reply	[flat|nested] 53+ messages in thread

* [1/2] Inspect extra signal information
  2009-01-12 18:49 ` Pedro Alves
@ 2009-01-12 18:52   ` Pedro Alves
  2009-01-12 19:40     ` Eli Zaretskii
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-01-12 18:52 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 735 bytes --]

[ changing the all-mighty subject line this time ... ]

On Monday 12 January 2009 18:48:48, Pedro Alves wrote:
> On Monday 12 January 2009 18:46:51, Pedro Alves wrote:
> > 
> > part 1:
> > 
> >  - Adds some infrastracture to be able to register reader and writer
> >    functions that are responsible for reading and writing
> >    a ``struct value'''s value.  We called those lval_computed values.  We've
> >    been using these kinds of values for other things in our tree for a
> >    couple of years already --- I've piggy-backed on that, so I got to
> >    push it.  :-)
> > 
> >    This first patch applies on top of this other one:
> > 
> >    http://sourceware.org/ml/gdb-patches/2009-01/msg00252.html
> > 
> 

-- 
Pedro Alves

[-- Attachment #2: lval_computed.diff --]
[-- Type: text/x-diff, Size: 9719 bytes --]

2009-01-12  Jim Blandy  <jimb@codesourcery.com>
	    Daniel Jacobowitz  <dan@codesourcery.com>
	    Vladimir Prus  <vladimir@codesourcery.com>
	    Pedro Alves  <pedro@codesourcery.com>

	* defs.h (enum lval_type): New value: lval_computed.
	* value.h (struct lval_funcs): New type.
	(allocate_computed_value, value_computed_funcs)
	(value_computed_closure): New declarations.
	* value.c (struct value): Add a structure to the location union
	for computed lvalues, containing 'funcs' and 'closure' members.
	(allocate_computed_value, value_computed_funcs)
	(value_computed_closure): New functions.
	(value_free): For computed lvalues, call the closure's
	'free_closure' function before freeing the value itself.
	(value_copy): If we're copying an lval_computed value, call the
	closure's 'copy_closure' function.
	(set_value_component_location): If the original value is a
	computed lvalue, then call the closure's 'copy_closure' function.
	(value_of_internalvar): If an internal variable's value is a
	computed lvalue, make retrieving its value produce an equivalent
	computed lvalue.
	* valops.c (value_fetch_lazy): Unlazy computed lvalues by calling
	their read function.
	(value_assign): Assign to computed lvalues by calling their write
	function.

---
 gdb/defs.h   |    5 ++-
 gdb/valops.c |   12 +++++++-
 gdb/value.c  |   85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 gdb/value.h  |   54 +++++++++++++++++++++++++++++++++++++
 4 files changed, 151 insertions(+), 5 deletions(-)

Index: gdb/defs.h
===================================================================
--- gdb/defs.h.orig	2009-01-11 15:40:11.000000000 +0000
+++ gdb/defs.h	2009-01-12 16:29:28.000000000 +0000
@@ -652,7 +652,10 @@ enum lval_type
     /* In a gdb internal variable.  */
     lval_internalvar,
     /* Part of a gdb internal variable (structure field).  */
-    lval_internalvar_component
+    lval_internalvar_component,
+    /* Value's bits are fetched and stored using functions provided by
+       its creator.  */
+    lval_computed
   };
 
 /* Control types for commands */
Index: gdb/value.h
===================================================================
--- gdb/value.h.orig	2009-01-12 12:40:32.000000000 +0000
+++ gdb/value.h	2009-01-12 16:48:53.000000000 +0000
@@ -142,6 +142,60 @@ extern void set_value_pointed_to_offset 
 extern int value_embedded_offset (struct value *value);
 extern void set_value_embedded_offset (struct value *value, int val);
 
+/* For lval_computed values, this structure holds functions used to
+   retrieve and set the value (or portions of the value).
+
+   For each function, 'V' is the 'this' pointer: an lval_funcs
+   function F may always assume that the V it receives is an
+   lval_computed value, and has F in the appropriate slot of its
+   lval_funcs structure.  */
+
+struct lval_funcs
+{
+  /* Fill in VALUE's contents.  This is used to "un-lazy" values.  If
+     a problem arises in obtaining VALUE's bits, this function should
+     call 'error'.  */
+  void (*read) (struct value *v);
+
+  /* Handle an assignment TOVAL = FROMVAL by writing the value of
+     FROMVAL to TOVAL's location.  The contents of TOVAL have not yet
+     been updated.  If a problem arises in doing so, this function
+     should call 'error'.  */
+  void (*write) (struct value *toval, struct value *fromval);
+
+  /* Return a duplicate of VALUE's closure, for use in a new value.
+     This may simply return the same closure, if VALUE's is
+     reference-counted or statically allocated.
+
+     This may be NULL, in which case VALUE's closure is re-used in the
+     new value.  */
+  void *(*copy_closure) (struct value *v);
+
+  /* Drop VALUE's reference to its closure.  Maybe this frees the
+     closure; maybe this decrements a reference count; maybe the
+     closure is statically allocated and this does nothing.
+
+     This may be NULL, in which case no action is taken to free
+     VALUE's closure.  */
+  void (*free_closure) (struct value *v);
+};
+
+/* Create a computed lvalue, with type TYPE, function pointers FUNCS,
+   and closure CLOSURE.  */
+
+extern struct value *allocate_computed_value (struct type *type,
+                                              struct lval_funcs *funcs,
+                                              void *closure);
+
+/* If VALUE is lval_computed, return its lval_funcs structure.  */
+
+extern struct lval_funcs *value_computed_funcs (struct value *value);
+
+/* If VALUE is lval_computed, return its closure.  The meaning of the
+   returned value depends on the functions VALUE uses.  */
+
+extern void *value_computed_closure (struct value *value);
+
 /* If zero, contents of this value are in the contents field.  If
    nonzero, contents are in inferior.  If the lval field is lval_memory,
    the contents are in inferior memory at location.address plus offset.
Index: gdb/value.c
===================================================================
--- gdb/value.c.orig	2009-01-12 11:25:23.000000000 +0000
+++ gdb/value.c	2009-01-12 16:48:54.000000000 +0000
@@ -63,6 +63,15 @@ struct value
 
     /* Pointer to internal variable.  */
     struct internalvar *internalvar;
+
+    /* If lval == lval_computed, this is a set of function pointers
+       to use to access and describe the value, and a closure pointer
+       for them to use.  */
+    struct
+    {
+      struct lval_funcs *funcs; /* Functions to call.  */
+      void *closure;            /* Closure for those functions to use.  */
+    } computed;
   } location;
 
   /* Describes offset of a value within lval of a structure in bytes.
@@ -296,6 +305,20 @@ value_remove_from_list (struct value **h
       }
 }
 
+struct value *
+allocate_computed_value (struct type *type,
+                         struct lval_funcs *funcs,
+                         void *closure)
+{
+  struct value *v = allocate_value (type);
+  VALUE_LVAL (v) = lval_computed;
+  v->location.computed.funcs = funcs;
+  v->location.computed.closure = closure;
+  set_value_lazy (v, 1);
+
+  return v;
+}
+
 /* Accessor methods.  */
 
 struct value *
@@ -458,6 +481,22 @@ set_value_pointed_to_offset (struct valu
   value->pointed_to_offset = val;
 }
 
+struct lval_funcs *
+value_computed_funcs (struct value *v)
+{
+  gdb_assert (VALUE_LVAL (v) == lval_computed);
+
+  return v->location.computed.funcs;
+}
+
+void *
+value_computed_closure (struct value *v)
+{
+  gdb_assert (VALUE_LVAL (v) == lval_computed);
+
+  return v->location.computed.closure;
+}
+
 enum lval_type *
 deprecated_value_lval_hack (struct value *value)
 {
@@ -512,7 +551,17 @@ void
 value_free (struct value *val)
 {
   if (val)
-    xfree (val->contents);
+    {
+      if (VALUE_LVAL (val) == lval_computed)
+	{
+	  struct lval_funcs *funcs = val->location.computed.funcs;
+
+	  if (funcs->free_closure)
+	    funcs->free_closure (val);
+	}
+
+      xfree (val->contents);
+    }
   xfree (val);
 }
 
@@ -625,6 +674,13 @@ value_copy (struct value *arg)
 	      TYPE_LENGTH (value_enclosing_type (arg)));
 
     }
+  if (VALUE_LVAL (val) == lval_computed)
+    {
+      struct lval_funcs *funcs = val->location.computed.funcs;
+
+      if (funcs->copy_closure)
+        val->location.computed.closure = funcs->copy_closure (val);
+    }
   return val;
 }
 
@@ -635,7 +691,15 @@ set_value_component_location (struct val
     VALUE_LVAL (component) = lval_internalvar_component;
   else
     VALUE_LVAL (component) = VALUE_LVAL (whole);
+
   component->location = whole->location;
+  if (VALUE_LVAL (whole) == lval_computed)
+    {
+      struct lval_funcs *funcs = whole->location.computed.funcs;
+
+      if (funcs->copy_closure)
+        component->location.computed.closure = funcs->copy_closure (whole);
+    }
 }
 
 \f
@@ -872,8 +936,23 @@ value_of_internalvar (struct internalvar
   val = value_copy (var->value);
   if (value_lazy (val))
     value_fetch_lazy (val);
-  VALUE_LVAL (val) = lval_internalvar;
-  VALUE_INTERNALVAR (val) = var;
+
+  /* If the variable's value is a computed lvalue, we want references
+     to it to produce another computed lvalue, where referencces and
+     assignments actually operate through the computed value's
+     functions.
+
+     This means that internal variables with computed values behave a
+     little differently from other internal variables: assignments to
+     them don't just replace the previous value altogether.  At the
+     moment, this seems like the behavior we want.  */
+  if (var->value->lval == lval_computed)
+    VALUE_LVAL (val) = lval_computed;
+  else
+    {
+      VALUE_LVAL (val) = lval_internalvar;
+      VALUE_INTERNALVAR (val) = var;
+    }
 
   /* Values are always stored in the target's byte order.  When connected to a
      target this will most likely always be correct, so there's normally no
Index: gdb/valops.c
===================================================================
--- gdb/valops.c.orig	2009-01-12 11:25:23.000000000 +0000
+++ gdb/valops.c	2009-01-12 14:21:01.000000000 +0000
@@ -727,6 +727,8 @@ value_fetch_lazy (struct value *val)
 	 watchpoints from trying to watch the saved frame pointer.  */
       value_free_to_mark (mark);
     }
+  else if (VALUE_LVAL (val) == lval_computed)
+    value_computed_funcs (val)->read (val);
   else
     internal_error (__FILE__, __LINE__, "Unexpected lazy value type.");
 
@@ -895,7 +897,15 @@ value_assign (struct value *toval, struc
 	observer_notify_target_changed (&current_target);
 	break;
       }
-      
+
+    case lval_computed:
+      {
+	struct lval_funcs *funcs = value_computed_funcs (toval);
+
+	funcs->write (toval, fromval);
+      }
+      break;
+
     default:
       error (_("Left operand of assignment is not an lvalue."));
     }

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [2/2] Inspect extra signal information
  2009-01-12 18:50 ` [2/2] " Pedro Alves
@ 2009-01-12 19:39   ` Eli Zaretskii
  2009-01-13 12:32     ` Pedro Alves
  0 siblings, 1 reply; 53+ messages in thread
From: Eli Zaretskii @ 2009-01-12 19:39 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

> From: Pedro Alves <pedro@codesourcery.com>
> Date: Mon, 12 Jan 2009 18:49:38 +0000
> 
> 	gdb/doc/
> 	* gdb.texinfo (Signals): Document $_siginfo.
> 	(Convenience Variables): Mention $_siginfo.
> 	(Remote Configuration): Document qXfer:siginfo:read,
> 	qXfer:siginfo:write packets, and the read-siginfo-object,
> 	write-siginfo-object commands.

Thanks, this part is approved, with the following comments:

> +@cindex inspecting extra signal information

I think just "extra signal information" is enough.

> +@anchor{qXfer siginfo read}

You never reference this anchor.

> +@anchor{qXfer siginfo write}

Nor this one.


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [1/2] Inspect extra signal information
  2009-01-12 18:52   ` [1/2] " Pedro Alves
@ 2009-01-12 19:40     ` Eli Zaretskii
  2009-02-02 16:51       ` Pedro Alves
  0 siblings, 1 reply; 53+ messages in thread
From: Eli Zaretskii @ 2009-01-12 19:40 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

> From: Pedro Alves <pedro@codesourcery.com>
> Date: Mon, 12 Jan 2009 18:52:06 +0000
> 
> 	* defs.h (enum lval_type): New value: lval_computed.
> 	* value.h (struct lval_funcs): New type.
> 	(allocate_computed_value, value_computed_funcs)
> 	(value_computed_closure): New declarations.
> 	* value.c (struct value): Add a structure to the location union
> 	for computed lvalues, containing 'funcs' and 'closure' members.
> 	(allocate_computed_value, value_computed_funcs)
> 	(value_computed_closure): New functions.

I think this introduces a general-purpose infrastructure that must be
documented in gdbint.texinfo.


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-01-12 18:47 [0/2] Inspect extra signal information Pedro Alves
  2009-01-12 18:49 ` Pedro Alves
  2009-01-12 18:50 ` [2/2] " Pedro Alves
@ 2009-01-12 23:27 ` Mark Kettenis
  2009-01-13 11:05   ` Pedro Alves
  2009-02-03 15:02 ` Pedro Alves
  3 siblings, 1 reply; 53+ messages in thread
From: Mark Kettenis @ 2009-01-12 23:27 UTC (permalink / raw)
  To: pedro; +Cc: gdb-patches

> From: Pedro Alves <pedro@codesourcery.com>
> Date: Mon, 12 Jan 2009 18:46:51 +0000
> 
> Hi!
> 
> This mini series adds support for inspecting extra signal information.
> 
> What this means is, we get a new $_siginfo convenience variable that
> is typed to look like the siginfo_t object on unix-ish platforms (but
> can be any other type appropriate for the target platform).

This looks pretty cool.  I've often wished I had this information
available.  And I've also wondered about a resonable way to present it
to the user.  Your approach seems very reasonable to me.  I can't
really comment on the infrastructure to build these "computed values".
But the target-sepcific support stuff seems reasonable to me. 

One thing I wonder about is whether it really is a good idea to is the
obfuscated typenames like __uid_t instead of a straight uid_t.  I
realize that is the way the type is defined in headers, but in GDB we
don't really have to worry about namespace pollution.

The other thing I worry about is padding for these structure types
that may be necessary on some platforms.  Does your code handle that?


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-01-12 23:27 ` [0/2] " Mark Kettenis
@ 2009-01-13 11:05   ` Pedro Alves
  2009-01-13 18:42     ` Eli Zaretskii
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-01-13 11:05 UTC (permalink / raw)
  To: gdb-patches; +Cc: Mark Kettenis

Hi Mark,

Thanks for taking a look, and for your comments.

On Monday 12 January 2009 23:24:16, Mark Kettenis wrote:

> One thing I wonder about is whether it really is a good idea to is the
> obfuscated typenames like __uid_t instead of a straight uid_t.  I
> realize that is the way the type is defined in headers, but in GDB we
> don't really have to worry about namespace pollution.

I don't really have much of an opinion here.  I didn't think of a reason
to be different, so I just cloned the types from glibc's headers.  I
can change that if you think it's important.

> The other thing I worry about is padding for these structure types
> that may be necessary on some platforms.  Does your code handle that?

I think so.  That is handled on the synthesized type itself.
There's this in linux_get_siginfo_type:

+  {
+    const int si_max_size = 128;
+    int si_pad_size;
+    int size_of_int = gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT;
+
+    /* _pad */
+    if (gdbarch_ptr_bit (gdbarch) == 64)
+      si_pad_size = (si_max_size / size_of_int) - 4;
+    else
+      si_pad_size = (si_max_size / size_of_int) - 3;
+    append_composite_type_field (sifields_type, "_pad",
+                                init_vector_type (int_type, si_pad_size));
+  }

Which mimics this, in glibc's headers:

# define __SI_MAX_SIZE     128
# if __WORDSIZE == 64
#  define __SI_PAD_SIZE     ((__SI_MAX_SIZE / sizeof (int)) - 4)
# else
#  define __SI_PAD_SIZE     ((__SI_MAX_SIZE / sizeof (int)) - 3)
# endif

 struct siginfo
   {
     int si_signo;
     int si_errno;
     int si_code;
 
     union
       {
         int _pad[__SI_PAD_SIZE]; <<<


There's also this change, that allows us to add a field to
a struct with enforced alignment > 0:

 void
-append_composite_type_field (struct type *t, char *name,
-                            struct type *field)
+append_composite_type_field_aligned (struct type *t, char *name,
+                                    struct type *field, int alignment)
 {
   struct field *f;
   TYPE_NFIELDS (t) = TYPE_NFIELDS (t) + 1;
@@ -1860,12 +1860,31 @@ append_composite_type_field (struct type
     {
       TYPE_LENGTH (t) = TYPE_LENGTH (t) + TYPE_LENGTH (field);
       if (TYPE_NFIELDS (t) > 1)
-       FIELD_BITPOS (f[0]) = (FIELD_BITPOS (f[-1])
-                              + (TYPE_LENGTH (FIELD_TYPE (f[-1]))
-                                 * TARGET_CHAR_BIT));
+       {
+         FIELD_BITPOS (f[0]) = (FIELD_BITPOS (f[-1])
+                                + (TYPE_LENGTH (FIELD_TYPE (f[-1]))
+                                   * TARGET_CHAR_BIT));
+
+         if (alignment)
+           {
+             int left = FIELD_BITPOS (f[0]) % (alignment * TARGET_CHAR_BIT);
+             if (left)
+               {
+                 FIELD_BITPOS (f[0]) += left;
+                 TYPE_LENGTH (t) += left / TARGET_CHAR_BIT;
+               }
+           }
+       }
     }
 }

It is used to add the _sifields field to ``struct siginfo'' aligned to
``TYPE_LENGTH (long_type)'', with:

+  append_composite_type_field_aligned (siginfo_type,
+                                      "_sifields", sifields_type,
+                                      TYPE_LENGTH (long_type));

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [2/2] Inspect extra signal information
  2009-01-12 19:39   ` Eli Zaretskii
@ 2009-01-13 12:32     ` Pedro Alves
  2009-01-13 18:55       ` Eli Zaretskii
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-01-13 12:32 UTC (permalink / raw)
  To: gdb-patches, Eli Zaretskii

[-- Attachment #1: Type: text/plain, Size: 924 bytes --]

Thanks Eli,

On Monday 12 January 2009 19:37:13, Eli Zaretskii write:
> Thanks, this part is approved, with the following comments:
> 
> > +@cindex inspecting extra signal information
> 
> I think just "extra signal information" is enough.

I've adjusted it.

> > +@anchor{qXfer siginfo read}
> 
> You never reference this anchor.
> 
> > +@anchor{qXfer siginfo write}
> 
> Nor this one.
> 

Ooops, copypasto.  I had made references to the wrong anchors.

I now also notice that I had placed the 'qXfer siginfo read' bits
in the write table...  I've now placed the new packets in
alphabetical order as well, while I'm at it.

I've updated the docs with the attached diff.


I also noticed that the write packets have a @var{} around the
object name, but the read ones don't:

 @item qXfer:@var{spu}:write

 @item qXfer:auxv:read
 @item qXfer:libraries:read

I copied that, but which one is the correct form?

-- 
Pedro Alves

[-- Attachment #2: eli_review.diff --]
[-- Type: text/x-diff, Size: 4148 bytes --]

---
 gdb/doc/gdb.texinfo |   48 +++++++++++++++++++++++++-----------------------
 1 file changed, 25 insertions(+), 23 deletions(-)

Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo	2009-01-13 11:56:10.000000000 +0000
+++ src/gdb/doc/gdb.texinfo	2009-01-13 12:22:00.000000000 +0000
@@ -4473,8 +4473,8 @@ a result of the fatal signal once it saw
 you can continue with @samp{signal 0}.  @xref{Signaling, ,Giving your
 Program a Signal}.
 
-@cindex inspecting extra signal information
-@anchor{inspecting extra signal information}
+@cindex extra signal information
+@anchor{extra signal information}
 
 On some targets, @value{GDBN} can inspect extra signal information
 associated with the intercepted signal, before it is actually
@@ -7398,7 +7398,7 @@ the program being debugged terminates.
 @item $_siginfo
 @vindex $_siginfo@r{, convenience variable}
 The variable @code{$_siginfo} is bound to extra signal information
-inspection (@pxref{inspecting extra signal information}).
+inspection (@pxref{extra signal information}).
 @end table
 
 On HP-UX systems, if you refer to a function or variable name that
@@ -26647,11 +26647,11 @@ The remote stub understands the @samp{qX
 
 @item qXfer:siginfo:read
 The remote stub understands the @samp{qXfer:siginfo:read} packet
-(@pxref{qXfer spu read}).
+(@pxref{qXfer siginfo read}).
 
 @item qXfer:siginfo:write
 The remote stub understands the @samp{qXfer:siginfo:write} packet
-(@pxref{qXfer spu write}).
+(@pxref{qXfer siginfo write}).
 
 @item QNonStop
 The remote stub understands the @samp{QNonStop} packet
@@ -26811,6 +26811,16 @@ annex part of the generic @samp{qXfer} p
 This packet is not probed by default; the remote stub must request it,
 by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
 
+@item qXfer:siginfo:read::@var{offset},@var{length}
+@anchor{qXfer siginfo read}
+Read contents of the extra signal information on the target
+system.  The annex part of the generic @samp{qXfer} packet must be
+empty (@pxref{qXfer read}).
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response
+(@pxref{qSupported}).
+
 @item qXfer:spu:read:@var{annex}:@var{offset},@var{length}
 @anchor{qXfer spu read}
 Read contents of an @code{spufs} file on the target system.  The
@@ -26876,6 +26886,16 @@ Here are the specific requests of this f
 formats, listed below.
 
 @table @samp
+@item qXfer:@var{siginfo}:write::@var{offset}:@var{data}@dots{}
+@anchor{qXfer siginfo write}
+Write @var{data} to the extra signal information on the target system.
+The annex part of the generic @samp{qXfer} packet must be
+empty (@pxref{qXfer write}).
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response
+(@pxref{qSupported}).
+
 @item qXfer:@var{spu}:write:@var{annex}:@var{offset}:@var{data}@dots{}
 @anchor{qXfer spu write}
 Write @var{data} to an @code{spufs} file on the target system.  The
@@ -26886,24 +26906,6 @@ in that context to be accessed.
 
 This packet is not probed by default; the remote stub must request it,
 by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
-
-@item qXfer:siginfo:read:@var{annex}:@var{offset},@var{length}
-@anchor{qXfer siginfo read}
-Read contents of the extra signal information on the target
-system.  The annex part of the generic @samp{qXfer} packet must be
-empty (@pxref{qXfer read}).
-
-This packet is not probed by default; the remote stub must request it,
-by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
-
-@item qXfer:@var{siginfo}:write:@var{annex}:@var{offset}:@var{data}@dots{}
-@anchor{qXfer siginfo write}
-Write @var{data} to the extra signal information on the target system.
-The annex part of the generic @samp{qXfer} packet must be
-empty (@pxref{qXfer write}).
-
-This packet is not probed by default; the remote stub must request it,
-by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
 @end table
 
 Reply:

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-01-13 11:05   ` Pedro Alves
@ 2009-01-13 18:42     ` Eli Zaretskii
  2009-01-13 18:50       ` Pedro Alves
  0 siblings, 1 reply; 53+ messages in thread
From: Eli Zaretskii @ 2009-01-13 18:42 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches, mark.kettenis

> From: Pedro Alves <pedro@codesourcery.com>
> Date: Tue, 13 Jan 2009 11:05:34 +0000
> Cc: Mark Kettenis <mark.kettenis@xs4all.nl>
> 
> On Monday 12 January 2009 23:24:16, Mark Kettenis wrote:
> 
> > One thing I wonder about is whether it really is a good idea to is the
> > obfuscated typenames like __uid_t instead of a straight uid_t.  I
> > realize that is the way the type is defined in headers, but in GDB we
> > don't really have to worry about namespace pollution.
> 
> I don't really have much of an opinion here.  I didn't think of a reason
> to be different, so I just cloned the types from glibc's headers.  I
> can change that if you think it's important.

I happen to agree with Mark.  Not only we don't need to use symbols
with leading underscores, it's actually forbidden by the C Standard
(AFAIK).  Such names are "reserved for the implementation" of the C
language, which we aren't.


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-01-13 18:42     ` Eli Zaretskii
@ 2009-01-13 18:50       ` Pedro Alves
  2009-01-13 19:19         ` Eli Zaretskii
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-01-13 18:50 UTC (permalink / raw)
  To: gdb-patches, Eli Zaretskii; +Cc: mark.kettenis

On Tuesday 13 January 2009 18:41:28, Eli Zaretskii wrote:
> > From: Pedro Alves <pedro@codesourcery.com>
> > Date: Tue, 13 Jan 2009 11:05:34 +0000
> > Cc: Mark Kettenis <mark.kettenis@xs4all.nl>
> > 
> > On Monday 12 January 2009 23:24:16, Mark Kettenis wrote:
> > 
> > > One thing I wonder about is whether it really is a good idea to is the
> > > obfuscated typenames like __uid_t instead of a straight uid_t.  I
> > > realize that is the way the type is defined in headers, but in GDB we
> > > don't really have to worry about namespace pollution.
> > 
> > I don't really have much of an opinion here.  I didn't think of a reason
> > to be different, so I just cloned the types from glibc's headers.  I
> > can change that if you think it's important.
> 
> I happen to agree with Mark.  Not only we don't need to use symbols
> with leading underscores, it's actually forbidden by the C Standard
> (AFAIK).  Such names are "reserved for the implementation" of the C
> language, which we aren't.
> 

I don't think that argument fits this case, because, well, this
is really a kernel data type, which can use it's own rules.  There's no
way for this $_siginfo type to collide with anything in the user code.  Also, these
are also the types you'd see if I wasn't synthesizing it, but using the debug
info instead, in case it is available  --- I was actually doing that in a previous
version of the patch, and synthesized the type only as a fallback, but, then considered
that if we're synthesizing sometimes, might as well make it simpler and
always synthesize -- less cases, less bugs, less maintenance.

Do you not agree in the light of this perpective?

I can change it, but I just want to make sure we're seeing
the whole picture.

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [2/2] Inspect extra signal information
  2009-01-13 12:32     ` Pedro Alves
@ 2009-01-13 18:55       ` Eli Zaretskii
  2009-01-13 19:08         ` Pedro Alves
  2009-02-06 23:35         ` Pedro Alves
  0 siblings, 2 replies; 53+ messages in thread
From: Eli Zaretskii @ 2009-01-13 18:55 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

> From: Pedro Alves <pedro@codesourcery.com>
> Date: Tue, 13 Jan 2009 12:31:59 +0000
> 
> I've updated the docs with the attached diff.

Thanks.  This version is OK.

> I also noticed that the write packets have a @var{} around the
> object name, but the read ones don't:
> 
>  @item qXfer:@var{spu}:write
> 
>  @item qXfer:auxv:read
>  @item qXfer:libraries:read
> 
> I copied that, but which one is the correct form?

@var{spu} is incorrect, since "spu" is a literal string, it does not
stand for something else.  Please remove those extra @var if you have
a moment to spare.


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [2/2] Inspect extra signal information
  2009-01-13 18:55       ` Eli Zaretskii
@ 2009-01-13 19:08         ` Pedro Alves
  2009-01-13 19:15           ` Eli Zaretskii
  2009-02-06 23:35         ` Pedro Alves
  1 sibling, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-01-13 19:08 UTC (permalink / raw)
  To: gdb-patches, Eli Zaretskii

[-- Attachment #1: Type: text/plain, Size: 265 bytes --]

On Tuesday 13 January 2009 18:54:24, Eli Zaretskii wrote:

> @var{spu} is incorrect, since "spu" is a literal string, it does not
> stand for something else.  Please remove those extra @var if you have
> a moment to spare.

I checked in the below.

-- 
Pedro Alves

[-- Attachment #2: spu.diff --]
[-- Type: text/x-diff, Size: 1231 bytes --]

Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/doc/ChangeLog,v
retrieving revision 1.847
diff -u -p -r1.847 ChangeLog
--- ChangeLog	7 Jan 2009 21:42:50 -0000	1.847
+++ ChangeLog	13 Jan 2009 19:04:46 -0000
@@ -1,3 +1,8 @@
+2009-01-13  Pedro Alves  <pedro@codesourcery.com>
+
+	* gdb.texinfo (General Query Packets): Remove @var{} around the
+	"spu" literal string.
+
 2009-01-07  Pedro Alves  <pedro@codesourcery.com>
 
 	* gdb.texinfo (Error in Breakpoints): Delete mention of "The same
Index: gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.543
diff -u -p -r1.543 gdb.texinfo
--- gdb.texinfo	7 Jan 2009 21:42:50 -0000	1.543
+++ gdb.texinfo	13 Jan 2009 19:04:52 -0000
@@ -26795,7 +26795,7 @@ Here are the specific requests of this f
 formats, listed below.
 
 @table @samp
-@item qXfer:@var{spu}:write:@var{annex}:@var{offset}:@var{data}@dots{}
+@item qXfer:spu:write:@var{annex}:@var{offset}:@var{data}@dots{}
 @anchor{qXfer spu write}
 Write @var{data} to an @code{spufs} file on the target system.  The
 annex specifies which file to write; it must be of the form

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [2/2] Inspect extra signal information
  2009-01-13 19:08         ` Pedro Alves
@ 2009-01-13 19:15           ` Eli Zaretskii
  0 siblings, 0 replies; 53+ messages in thread
From: Eli Zaretskii @ 2009-01-13 19:15 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

> From: Pedro Alves <pedro@codesourcery.com>
> Date: Tue, 13 Jan 2009 19:07:59 +0000
> 
> On Tuesday 13 January 2009 18:54:24, Eli Zaretskii wrote:
> 
> > @var{spu} is incorrect, since "spu" is a literal string, it does not
> > stand for something else.  Please remove those extra @var if you have
> > a moment to spare.
> 
> I checked in the below.

Thank you.


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-01-13 18:50       ` Pedro Alves
@ 2009-01-13 19:19         ` Eli Zaretskii
  2009-01-13 19:37           ` Pedro Alves
  0 siblings, 1 reply; 53+ messages in thread
From: Eli Zaretskii @ 2009-01-13 19:19 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches, mark.kettenis

> From: Pedro Alves <pedro@codesourcery.com>
> Date: Tue, 13 Jan 2009 18:50:01 +0000
> Cc: mark.kettenis@xs4all.nl
> 
> > I happen to agree with Mark.  Not only we don't need to use symbols
> > with leading underscores, it's actually forbidden by the C Standard
> > (AFAIK).  Such names are "reserved for the implementation" of the C
> > language, which we aren't.
> > 
> 
> I don't think that argument fits this case, because, well, this
> is really a kernel data type, which can use it's own rules.  There's no
> way for this $_siginfo type to collide with anything in the user code.

The problem is not to clash with GDB code elsewhere, the problem is
the possibility of a clash with the library.  A library implementation
is free to change the symbol it uses for this any time, and use the
__uid_t one for something utterly incompatible.  Since the name begins
with 2 underscores, the library implementation doesn't need to bother
being back-compatible, because such names are off-limits for user code.

> Also, these are also the types you'd see if I wasn't synthesizing
> it, but using the debug info instead, in case it is available --- I
> was actually doing that in a previous version of the patch, and
> synthesized the type only as a fallback, but, then considered that
> if we're synthesizing sometimes, might as well make it simpler and
> always synthesize -- less cases, less bugs, less maintenance.

Sorry, I don't follow: what do you mean by ``synthesizing''?


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-01-13 19:19         ` Eli Zaretskii
@ 2009-01-13 19:37           ` Pedro Alves
  2009-01-13 19:47             ` Pedro Alves
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-01-13 19:37 UTC (permalink / raw)
  To: gdb-patches, Eli Zaretskii; +Cc: mark.kettenis

On Tuesday 13 January 2009 19:18:05, Eli Zaretskii wrote:

> The problem is not to clash with GDB code elsewhere, the problem is
> the possibility of a clash with the library.  A library implementation

When I meant user code, I didn't mean *GDB* code, which of course it can't
collide with, because I wrote literal strings, not identifiers.  I meant code
that isn't part of the C (library) implementation.

> is free to change the symbol it uses for this any time, and use the
> __uid_t one for something utterly incompatible.  Since the name begins
> with 2 underscores, the library implementation doesn't need to bother
> being back-compatible, because such names are off-limits for user code.

No, it is allowed to assume that the type name will not collide with
any user defined type.  It's only about namespace, that's all.  Things will
surelly break if the type changes to something else incompatible.

In any case, user code will want to be using the si_pid, si_uid, si_status,
si_addr, etc, X/Open macros.  I'm *really exposing* C library internals.
> 
> > Also, these are also the types you'd see if I wasn't synthesizing
> > it, but using the debug info instead, in case it is available --- I
> > was actually doing that in a previous version of the patch, and
> > synthesized the type only as a fallback, but, then considered that
> > if we're synthesizing sometimes, might as well make it simpler and
> > always synthesize -- less cases, less bugs, less maintenance.
> 

> Sorry, I don't follow: what do you mean by ``synthesizing''?

It means that I'm building the ``struct type'' that represents
this siginfo_t type "manually", instead of relying on debug info
for it being available.

What I was aiming for, is to see the same you see when you do this
(this is from the already in tree siginfo-addr.exp BTW):

static void
handler (int sig, siginfo_t *info, void *context)
{
  if (info->si_addr == p)
    printf ("Correct si_addr value.\n");
  else
    printf ("Got si_addr = %p, expected %p.\n", info->si_addr, p);
  _exit (0);
}

static void *p;

int
main (void)
{
(...)
  /* Trigger SIGSEGV.  */
  *(int *)p = 0;
  return 0;
}

(gdb) b handler
Breakpoint 1 at 0x40070b: file ../../../src/gdb/testsuite/gdb.base/siginfo-addr.c, line 32.
(gdb) r
Starting program: /home/pedro/gdb/siginfo/build/gdb/testsuite/gdb.base/siginfo-addr

Program received signal SIGSEGV, Segmentation fault.
0x000000000040081b in main () at ../../../src/gdb/testsuite/gdb.base/siginfo-addr.c:66
66        *(int *)p = 0;
(gdb) c
Continuing.

Breakpoint 1, handler (sig=11, info=0x7fffffffe130, context=0x7fffffffe000) at ../../../src/gdb/testsuite/gdb.base/siginfo-addr.c:32
32        if (info->si_addr == p)
(gdb)

(gdb) ptype info->_sifields
type = union {
    int _pad[28];
    struct {
        __pid_t si_pid;
        __uid_t si_uid;
    } _kill;
    struct {
        int si_tid;
        int si_overrun;
        sigval_t si_sigval;
    } _timer;
    struct {
        __pid_t si_pid;
        __uid_t si_uid;
        sigval_t si_sigval;
    } _rt;
    struct {
        __pid_t si_pid;
        __uid_t si_uid;
        int si_status;
        __clock_t si_utime;
        __clock_t si_stime;
    } _sigchld;
    struct {
        void *si_addr;
    } _sigfault;
    struct {
        long int si_band;
        int si_fd;
    } _sigpoll;
}
(gdb)                      

Notice that these types came from debug info (but only because I
siginfo_t, which will not be the common case).

Versus the synthesized:

(gdb) r
Starting program: /home/pedro/gdb/siginfo/build/gdb/testsuite/gdb.base/siginfo-addr
During symbol reading, DW_AT_name missing from DW_TAG_base_type.

Program received signal SIGSEGV, Segmentation fault.
0x000000000040081b in main () at ../../../src/gdb/testsuite/gdb.base/siginfo-addr.c:66
66        *(int *)p = 0;

(gdb) ptype $_siginfo._sifields
type = union {
    int _pad[28];
    struct {
        __pid_t si_pid;
        __uid_t si_uid;
    } _kill;
    struct {
        int si_tid;
        int si_overrun;
        sigval_t si_sigval;
    } _timer;
    struct {
        __pid_t si_pid;
        __uid_t si_uid;
        sigval_t si_sigval;
    } _rt;
    struct {
        __pid_t si_pid;
        __uid_t si_uid;
        int si_status;
        __clock_t si_utime;
        __clock_t si_stime;
    } _sigchld;
    struct {
        void *si_addr;
    } _sigfault;
    struct {
        long si_band;
        int si_fd;
    } _sigpoll;
}

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-01-13 19:37           ` Pedro Alves
@ 2009-01-13 19:47             ` Pedro Alves
  2009-02-02 14:40               ` Pedro Alves
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-01-13 19:47 UTC (permalink / raw)
  To: gdb-patches; +Cc: Eli Zaretskii, mark.kettenis

On Tuesday 13 January 2009 19:37:25, Pedro Alves wrote:
> > is free to change the symbol it uses for this any time, and use the
> > __uid_t one for something utterly incompatible.  Since the name begins
> > with 2 underscores, the library implementation doesn't need to bother
> > being back-compatible, because such names are off-limits for user code.
> 
> No, it is allowed to assume that the type name will not collide with
> any user defined type.  It's only about namespace, that's all.  Things will
> surelly break if the type changes to something else incompatible.

Oh well, I think I said the same thing you did anyway.  :-)

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-01-13 19:47             ` Pedro Alves
@ 2009-02-02 14:40               ` Pedro Alves
  2009-02-02 20:49                 ` Mark Kettenis
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-02-02 14:40 UTC (permalink / raw)
  To: gdb-patches; +Cc: Eli Zaretskii, mark.kettenis

Hi guys, I'm looking at this again.

Given the argument that with this patch, the siginfo_t type before the signal
is delivered is the the same as what is seen on the signal handler, when
the signal is delivered to the inferior inferior, do you still think I
should change the type, or are you OK with how things are?

Is there anything else I should do to make this good to go?

Thanks,

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [1/2] Inspect extra signal information
  2009-01-12 19:40     ` Eli Zaretskii
@ 2009-02-02 16:51       ` Pedro Alves
  2009-02-02 21:04         ` Eli Zaretskii
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-02-02 16:51 UTC (permalink / raw)
  To: gdb-patches, Eli Zaretskii

On Monday 12 January 2009 19:39:09, Eli Zaretskii wrote:
> > From: Pedro Alves <pedro@codesourcery.com>
> > Date: Mon, 12 Jan 2009 18:52:06 +0000
> > 
> > 	* defs.h (enum lval_type): New value: lval_computed.
> > 	* value.h (struct lval_funcs): New type.
> > 	(allocate_computed_value, value_computed_funcs)
> > 	(value_computed_closure): New declarations.
> > 	* value.c (struct value): Add a structure to the location union
> > 	for computed lvalues, containing 'funcs' and 'closure' members.
> > 	(allocate_computed_value, value_computed_funcs)
> > 	(value_computed_closure): New functions.
> 
> I think this introduces a general-purpose infrastructure that must be
> documented in gdbint.texinfo.
> 

I'm taking a stab at this.  I don't see struct value documented in
the internals manual though.  What kind of detail do you require here?

I'm thinking of adding a "Values" section somewhere, don't know
where yet.

@section Values

@value{GDBN} uses @code{struct value}, or simply named a @dfn{value}, as an
internal abstraction for the representation of a variety of inferior
objects and @value{GDBN} convenience objects.

Values have an associated @code{struct type}, that describes a virtual
view of the data stored in or accessed through the value.

A value is in addition descriminated by its lvalue-ness, given its
@code{enum lval_type} enumeration:

@table @code
@item @code{not_lval}
This value is not an lval.  It can't be assigned to.

@item @code{lval_memory}
This value represents an object in memory.

@item @code{lval_register}
This value represents an object that lives in a register.

@item @code{lval_internalvar}
Represents the value of an internal variable.

@item @code{lval_internalvar_component}
Represents part of a gdb internal variable.  E.g., a structure field.

@item @code{lval_computed}

These are values with arbitrary functions to handle reads and writes,
and "copy operators" and "destructors".  They allow creating
specialized value objects for specific purposes, all abstracted way
from the the core value support code.  The creator of such a value
specifies specialized read, write, copy and release callbacks,
described by the @code{struct lval_funcs} struture declared in
@file{value.h} to the @code{allocate_computed_value} function.  An
example use is the implementations of the @code{$_siginfo} convenience
variable in @file{infrun.c}.

@end table

@subsection Lazy values

...

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-02-02 14:40               ` Pedro Alves
@ 2009-02-02 20:49                 ` Mark Kettenis
  0 siblings, 0 replies; 53+ messages in thread
From: Mark Kettenis @ 2009-02-02 20:49 UTC (permalink / raw)
  To: pedro; +Cc: gdb-patches, eliz, mark.kettenis

> From: Pedro Alves <pedro@codesourcery.com>
> Date: Mon, 2 Feb 2009 14:42:00 +0000
> 
> Hi guys, I'm looking at this again.
> 
> Given the argument that with this patch, the siginfo_t type before the signal
> is delivered is the the same as what is seen on the signal handler, when
> the signal is delivered to the inferior inferior, do you still think I
> should change the type, or are you OK with how things are?

I have no real issues with using the obfuscated type names.  Just
thought it was a bit ugly and thought users might prefer the
unobfuscated names.  But since I don't use Linux all that much, I
don't really care.


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [1/2] Inspect extra signal information
  2009-02-02 16:51       ` Pedro Alves
@ 2009-02-02 21:04         ` Eli Zaretskii
  2009-02-05  1:14           ` Pedro Alves
  0 siblings, 1 reply; 53+ messages in thread
From: Eli Zaretskii @ 2009-02-02 21:04 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

> From: Pedro Alves <pedro@codesourcery.com>
> Date: Mon, 2 Feb 2009 16:52:27 +0000
> 
> > I think this introduces a general-purpose infrastructure that must be
> > documented in gdbint.texinfo.
> > 
> 
> I'm taking a stab at this.

Thanks!

> I don't see struct value documented in
> the internals manual though.  What kind of detail do you require here?

Exactly the kind you described.

> I'm thinking of adding a "Values" section somewhere, don't know
> where yet.

The place doesn't matter much, since the internals manual is "work in
progress", and looks more like a car crash than a concise document.

> @item @code{lval_computed}
> 
> These are values with arbitrary functions to handle reads and writes,

Please lose the empty line between the @item and its description.

> and "copy operators" and "destructors".  They allow creating

Please use ``this kind of quoting'' in Texinfo, not "this kind".

> described by the @code{struct lval_funcs} struture declared in
                                            ^^^^^^^^
A typo.

> @file{value.h} to the @code{allocate_computed_value} function.  An

What does it mean "declared in value.h to the allocate_computed_value
function"?

Perhaps add a few words describing `struct lval_funcs', or maybe just
showing a simple example would be enough.

A couple of index entries for this section will also help.

Thanks again for working on this.


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-01-12 18:47 [0/2] Inspect extra signal information Pedro Alves
                   ` (2 preceding siblings ...)
  2009-01-12 23:27 ` [0/2] " Mark Kettenis
@ 2009-02-03 15:02 ` Pedro Alves
  2009-02-03 16:42   ` Ulrich Weigand
  3 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-02-03 15:02 UTC (permalink / raw)
  To: gdb-patches

On Monday 12 January 2009 18:46:51, Pedro Alves wrote:
>  - Adds a new gdbarch method (get_siginfo_type) whose job is to return a type
>    suitable to print/inspect a TARGET_OBJECT_SIGNAL_INFO of a given arch.

Boo, turns out that I had tested on x86-64:

 - 64-bit gdb x 64-bit inferior, 64-bit kernel

   siginfo comes out with the 64-bit layout.

 - 32-bit gdb x 32-bit inferior, 64-bit kernel

   siginfo comes out with the 32-bit layout.


But, I thought I had, but I clearly didn't test before:

 - 64-bit gdb x 32-bit inferior, 64-bit kernel

   siginfo comes out with the 64-bit layout.
                              ^^^^^^

The current patch assumed that PTRACE_GETSIGINFO would return
an object with the layout of the 32-bit inferior, but, we actually
get a 64-bit object.  In sum, the data/type returned by PTRACE_GETSIGINFO
is dependent on the arch of the *superior* (gdb).
The current patch was using the gdbarch of the current frame, but,
it is clear now that that is not the gdbarch we want.

I was looking at target_gdbarch, and it doesn't seem to fit the
bill either.  E.g., a biarch ppc64 gdbserver returns a 32-bit
target_arch if the inferior is 32-bit.

(now that I'm looking at it, can't an inferior that started
out as 32-bit call 64-bit code?  If so, it seems that gdbserver and 
target_gdbarch does not cope with that.)

The options I'm seeing are either:

 - come up with a new target/host *interface* gdbarch, and
   pass that along in the target description.  Use that gdbarch
   to build up the siginfo type, on the gdb side.

 - extend the xml type description support to be rich enough
   to describe the siginfo_t type (structs, typedefs, etc), and
   pass that along in the target description.

Any suggestions?  Other alternatives?

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-02-03 15:02 ` Pedro Alves
@ 2009-02-03 16:42   ` Ulrich Weigand
  2009-02-03 18:06     ` Daniel Jacobowitz
  2009-02-03 18:23     ` [0/2] Inspect extra signal information Pedro Alves
  0 siblings, 2 replies; 53+ messages in thread
From: Ulrich Weigand @ 2009-02-03 16:42 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves wrote:

> Boo, turns out that I had tested on x86-64:
> 
>  - 64-bit gdb x 64-bit inferior, 64-bit kernel
> 
>    siginfo comes out with the 64-bit layout.
> 
>  - 32-bit gdb x 32-bit inferior, 64-bit kernel
> 
>    siginfo comes out with the 32-bit layout.
> 
> 
> But, I thought I had, but I clearly didn't test before:
> 
>  - 64-bit gdb x 32-bit inferior, 64-bit kernel
> 
>    siginfo comes out with the 64-bit layout.
>                               ^^^^^^

Huh.  With bi-arch setups, I understand everything is currently
supposed to be set up so that debugging a 32-bit program
with a 64-bit GDB looks just the same as debugging it
with a 32-bit GDB.

The above would break that assumption: you see different
types of siginfo depending on your host GDB.  I'm not sure
if that is really what we want ...

On the other hand, it's going to be difficult to avoid.  One
way would be for the Linux native target to always return
the 32-bit layout when debugging a 32-bit inferior; if necessary
it would have to convert the data in-place before returning it
(similar to how the native target today converts register contents
to 32 bit even though the ptrace interface returns 64 bit values).

> I was looking at target_gdbarch, and it doesn't seem to fit the
> bill either.  E.g., a biarch ppc64 gdbserver returns a 32-bit
> target_arch if the inferior is 32-bit.

That's actually an interesting question.  The idea behind
"target_gdbarch" is "the architecture implemented by the
target debugger interface".  In a bi-arch setup, the target
today emulates a 32-bit target interface when debugging a 32-bit
inferior, even when GDB itself is 64-bit.  This is done by 
explicit conversion in the native target (see above).

Before real multi-architecture support, there really was to
other way to do it.  However, once we get to full multi-arch,
it might in fact be a more natural fit to model the bi-arch
setup by having "target_gdbarch" indicate the actual bitness
of the ptrace interface (i.e. 64-bit), while still setting
the per-frame architecture of all frames to the appropriate
32-bit architecture ...  This might allow us to get rid of
some of the bi-arch special hacks in native target code.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-02-03 16:42   ` Ulrich Weigand
@ 2009-02-03 18:06     ` Daniel Jacobowitz
  2009-02-03 18:24       ` Pedro Alves
  2009-02-03 18:23     ` [0/2] Inspect extra signal information Pedro Alves
  1 sibling, 1 reply; 53+ messages in thread
From: Daniel Jacobowitz @ 2009-02-03 18:06 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Pedro Alves, gdb-patches

On Tue, Feb 03, 2009 at 05:42:21PM +0100, Ulrich Weigand wrote:
> On the other hand, it's going to be difficult to avoid.  One
> way would be for the Linux native target to always return
> the 32-bit layout when debugging a 32-bit inferior; if necessary
> it would have to convert the data in-place before returning it
> (similar to how the native target today converts register contents
> to 32 bit even though the ptrace interface returns 64 bit values).

I like this idea.  We'd just need a "native siginfo to gdb siginfo"
routine, which could probably live in one common native-only file.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-02-03 16:42   ` Ulrich Weigand
  2009-02-03 18:06     ` Daniel Jacobowitz
@ 2009-02-03 18:23     ` Pedro Alves
  1 sibling, 0 replies; 53+ messages in thread
From: Pedro Alves @ 2009-02-03 18:23 UTC (permalink / raw)
  To: gdb-patches; +Cc: Ulrich Weigand

On Tuesday 03 February 2009 16:42:21, Ulrich Weigand wrote:
> Pedro Alves wrote:

> > But, I thought I had, but I clearly didn't test before:
> > 
> >  - 64-bit gdb x 32-bit inferior, 64-bit kernel
> > 
> >    siginfo comes out with the 64-bit layout.
> >                               ^^^^^^
> 
> Huh.  With bi-arch setups, I understand everything is currently
> supposed to be set up so that debugging a 32-bit program
> with a 64-bit GDB looks just the same as debugging it
> with a 32-bit GDB.
> 
> The above would break that assumption: you see different
> types of siginfo depending on your host GDB.  I'm not sure
> if that is really what we want ...

Right, I'm not sure either.

> On the other hand, it's going to be difficult to avoid.  One
> way would be for the Linux native target to always return
> the 32-bit layout when debugging a 32-bit inferior; if necessary
> it would have to convert the data in-place before returning it
> (similar to how the native target today converts register contents
> to 32 bit even though the ptrace interface returns 64 bit values).

I guess I should try this.

> > I was looking at target_gdbarch, and it doesn't seem to fit the
> > bill either.  E.g., a biarch ppc64 gdbserver returns a 32-bit
> > target_arch if the inferior is 32-bit.
> 
> That's actually an interesting question.  The idea behind
> "target_gdbarch" is "the architecture implemented by the
> target debugger interface".  In a bi-arch setup, the target
> today emulates a 32-bit target interface when debugging a 32-bit
> inferior, even when GDB itself is 64-bit.  This is done by 
> explicit conversion in the native target (see above).

The only weird case I can think of, if when you have an
inferior that can do mode switching, and the siginfo_t type
is different in different modes.  In this case, there'd better
be a single siginfo_t layout for all modes, otherwise you get
funny cases.  Say, a signal handler installed in code that runs
mode x-bit, but the signal was raised while running code
in mode y-bit.  Without kernel help, GDB can't know the correct
layout of the siginfo_t object the inferior will see in the
signal handler.

I don't think we can see that happen on linux, though, so on
the fly conversion out of ptrace sounds like a good option.

Let's see if it doesn't come out looking too ugly.  If I make
use of struct type/struct value if may not be bad, but, gdbserver
can't use those...

> Before real multi-architecture support, there really was to
> other way to do it.  However, once we get to full multi-arch,
> it might in fact be a more natural fit to model the bi-arch
> setup by having "target_gdbarch" indicate the actual bitness
> of the ptrace interface (i.e. 64-bit), while still setting
> the per-frame architecture of all frames to the appropriate
> 32-bit architecture ...  This might allow us to get rid of
> some of the bi-arch special hacks in native target code.

That's actually what I initially thought target_gdbarch was
reporting.  Full multi-arch is something that is also interesting
for multi-process.  E.g, a bi-arch gdbserver, that supports
multi-process has issues, when trying to debug simultaneously
32-bit and 64-bit inferiors.  In this case, we have one
target interface active (remote) and one target_gdbarch.  Since
the register layouts in the protocol aren't dynamic depending
on the inferior (after the first inferior), on the multi-process
branch, gdbserver only allows debugging multiple inferiors if
they're of the same arch.
current_gdbarch of course bites back in this scenario as well.

BTW, what is the status of your per-frame gdbarch patches
submitted a while ago?

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-02-03 18:06     ` Daniel Jacobowitz
@ 2009-02-03 18:24       ` Pedro Alves
  2009-02-03 19:04         ` Daniel Jacobowitz
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-02-03 18:24 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: Ulrich Weigand, gdb-patches

On Tuesday 03 February 2009 18:06:17, Daniel Jacobowitz wrote:
> I like this idea.  We'd just need a "native siginfo to gdb siginfo"
> routine, which could probably live in one common native-only file.

Hmmm, what do you mean exactly by "gdb siginfo" here?

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-02-03 18:24       ` Pedro Alves
@ 2009-02-03 19:04         ` Daniel Jacobowitz
  2009-02-03 19:51           ` Pedro Alves
  0 siblings, 1 reply; 53+ messages in thread
From: Daniel Jacobowitz @ 2009-02-03 19:04 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Ulrich Weigand, gdb-patches

On Tue, Feb 03, 2009 at 06:24:21PM +0000, Pedro Alves wrote:
> On Tuesday 03 February 2009 18:06:17, Daniel Jacobowitz wrote:
> > I like this idea.  We'd just need a "native siginfo to gdb siginfo"
> > routine, which could probably live in one common native-only file.
> 
> Hmmm, what do you mean exactly by "gdb siginfo" here?

Whatever type you've constructed via the gdbarch.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-02-03 19:04         ` Daniel Jacobowitz
@ 2009-02-03 19:51           ` Pedro Alves
  2009-02-03 23:18             ` Doug Evans
  2009-02-04  0:24             ` Daniel Jacobowitz
  0 siblings, 2 replies; 53+ messages in thread
From: Pedro Alves @ 2009-02-03 19:51 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: Ulrich Weigand, gdb-patches

On Tuesday 03 February 2009 19:04:32, Daniel Jacobowitz wrote:
> On Tue, Feb 03, 2009 at 06:24:21PM +0000, Pedro Alves wrote:
> > On Tuesday 03 February 2009 18:06:17, Daniel Jacobowitz wrote:
> > > I like this idea.  We'd just need a "native siginfo to gdb siginfo"
> > > routine, which could probably live in one common native-only file.
> > 
> > Hmmm, what do you mean exactly by "gdb siginfo" here?
> 
> Whatever type you've constructed via the gdbarch.
> 

There are two points of information here.  First, the raw data of
the siginfo_t object, passed around with TARGET_OBJECT_SIGNAL_INFO,
which is implemented by both native linux target, and gdbserver.
This transfers a block of raw data.  Then, there's the the gdbarch
built type, which is used to interpret the data.  So, we're talking about
making sure the TARGET_OBJECT_SIGNAL_INFO object is converted to a
a 32-bit layout before reaching the core of gdb, to match what the type
contructed by gdbarch will expect.

I'd like to come up with something that works equally well and
is simple, in both native gdb and gdbserver implementation sides.

I hacked the below into linux-nat.c, which works OK for i386/amd64
just to see it work.

The siginfo layout is different depending on the architecture, so
although this layout works for some archs, it doesn't for others,
e.g, mips, has this:

typedef struct siginfo
  {
    int si_signo;               /* Signal number.  */
    int si_code;                /* Signal code.  */
    int si_errno;               /* If non-zero, an errno value associated with
                                   this signal, as defined in <errno.h>.  */
    int __pad0[__SI_MAX_SIZE / sizeof (int) - __SI_PAD_SIZE - 3];

        ^^^^^^
    union
      {


I was thinking on doing this in the arch specific native files, e.g,
gdb/amd64-linux-nat.c, gdb/ppc-linux-nat.c, etc., and something similar in
gdbserver too.

Just to make sure, where you perhaps thinking of something
entirely different?  I don't see how to make this in a common native
file.

--- src.orig/gdb/linux-nat.c    2009-02-03 19:20:49.000000000 +0000
+++ src/gdb/linux-nat.c 2009-02-03 19:26:33.000000000 +0000
@@ -3214,6 +3214,26 @@ linux_nat_mourn_inferior (struct target_
     linux_fork_mourn_inferior ();
 }

+struct gdb_siginfo32
+  {
+    int si_signo;
+    int si_errno;
+    int si_code;
+
+    union
+      {
+       int _pad[29];
+       struct
+         {
+           int _si_pid;
+           unsigned int _si_uid;
+           int _si_status;
+           int _si_utime;
+           int _si_stime;
+         } _sigchld;
+      } _sifields;
+  };
+

 static LONGEST
 linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
                     const char *annex, gdb_byte *readbuf,
@@ -3239,6 +3259,25 @@ linux_xfer_siginfo (struct target_ops *o
   if (errno != 0)
     return -1;

+  if (gdbarch_addr_bit (current_gdbarch) == 32)
+    {
+      struct gdb_siginfo32 siginfo32;
+      struct siginfo sigi;
+
+      gdb_assert (sizeof (siginfo32) == sizeof (siginfo));
+
+      siginfo32.si_signo = siginfo.si_signo;
+      siginfo32.si_errno = siginfo.si_errno;
+      siginfo32.si_code = siginfo.si_code;
+      siginfo32._sifields._sigchld._si_pid = siginfo.si_pid;
+      siginfo32._sifields._sigchld._si_uid = siginfo.si_uid;
+      siginfo32._sifields._sigchld._si_status = siginfo.si_status;
+      siginfo32._sifields._sigchld._si_utime = siginfo.si_utime;
+      siginfo32._sifields._sigchld._si_stime = siginfo.si_stime;
+
+      memcpy (&siginfo, &siginfo32, sizeof (siginfo));
+    }
+


-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-02-03 19:51           ` Pedro Alves
@ 2009-02-03 23:18             ` Doug Evans
  2009-02-03 23:50               ` Pedro Alves
  2009-02-04  0:24             ` Daniel Jacobowitz
  1 sibling, 1 reply; 53+ messages in thread
From: Doug Evans @ 2009-02-03 23:18 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Daniel Jacobowitz, Ulrich Weigand, gdb-patches

On Tue, Feb 3, 2009 at 11:51 AM, Pedro Alves <pedro@codesourcery.com> wrote:
> On Tuesday 03 February 2009 19:04:32, Daniel Jacobowitz wrote:
>> On Tue, Feb 03, 2009 at 06:24:21PM +0000, Pedro Alves wrote:
>> > On Tuesday 03 February 2009 18:06:17, Daniel Jacobowitz wrote:
>> > > I like this idea.  We'd just need a "native siginfo to gdb siginfo"
>> > > routine, which could probably live in one common native-only file.
>> >
>> > Hmmm, what do you mean exactly by "gdb siginfo" here?
>>
>> Whatever type you've constructed via the gdbarch.
>>
>
> There are two points of information here.  First, the raw data of
> the siginfo_t object, passed around with TARGET_OBJECT_SIGNAL_INFO,
> which is implemented by both native linux target, and gdbserver.
> This transfers a block of raw data.  Then, there's the the gdbarch
> built type, which is used to interpret the data.  So, we're talking about
> making sure the TARGET_OBJECT_SIGNAL_INFO object is converted to a
> a 32-bit layout before reaching the core of gdb, to match what the type
> contructed by gdbarch will expect.
>
> I'd like to come up with something that works equally well and
> is simple, in both native gdb and gdbserver implementation sides.
>
> I hacked the below into linux-nat.c, which works OK for i386/amd64
> just to see it work.
>
> The siginfo layout is different depending on the architecture, so
> although this layout works for some archs, it doesn't for others,
> e.g, mips, has this:
>
> typedef struct siginfo
>  {
>    int si_signo;               /* Signal number.  */
>    int si_code;                /* Signal code.  */
>    int si_errno;               /* If non-zero, an errno value associated with
>                                   this signal, as defined in <errno.h>.  */
>    int __pad0[__SI_MAX_SIZE / sizeof (int) - __SI_PAD_SIZE - 3];
>
>        ^^^^^^
>    union
>      {
>
>
> I was thinking on doing this in the arch specific native files, e.g,
> gdb/amd64-linux-nat.c, gdb/ppc-linux-nat.c, etc., and something similar in
> gdbserver too.
>
> Just to make sure, where you perhaps thinking of something
> entirely different?  I don't see how to make this in a common native
> file.
>
> --- src.orig/gdb/linux-nat.c    2009-02-03 19:20:49.000000000 +0000
> +++ src/gdb/linux-nat.c 2009-02-03 19:26:33.000000000 +0000
> @@ -3214,6 +3214,26 @@ linux_nat_mourn_inferior (struct target_
>     linux_fork_mourn_inferior ();
>  }
>
> +struct gdb_siginfo32
> +  {
> +    int si_signo;
> +    int si_errno;
> +    int si_code;
> +
> +    union
> +      {
> +       int _pad[29];
> +       struct
> +         {
> +           int _si_pid;
> +           unsigned int _si_uid;
> +           int _si_status;
> +           int _si_utime;
> +           int _si_stime;
> +         } _sigchld;
> +      } _sifields;
> +  };
> +
>
>  static LONGEST
>  linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
>                     const char *annex, gdb_byte *readbuf,
> @@ -3239,6 +3259,25 @@ linux_xfer_siginfo (struct target_ops *o
>   if (errno != 0)
>     return -1;
>
> +  if (gdbarch_addr_bit (current_gdbarch) == 32)
> +    {
> +      struct gdb_siginfo32 siginfo32;
> +      struct siginfo sigi;
> +
> +      gdb_assert (sizeof (siginfo32) == sizeof (siginfo));
> +
> +      siginfo32.si_signo = siginfo.si_signo;
> +      siginfo32.si_errno = siginfo.si_errno;
> +      siginfo32.si_code = siginfo.si_code;
> +      siginfo32._sifields._sigchld._si_pid = siginfo.si_pid;
> +      siginfo32._sifields._sigchld._si_uid = siginfo.si_uid;
> +      siginfo32._sifields._sigchld._si_status = siginfo.si_status;
> +      siginfo32._sifields._sigchld._si_utime = siginfo.si_utime;
> +      siginfo32._sifields._sigchld._si_stime = siginfo.si_stime;
> +
> +      memcpy (&siginfo, &siginfo32, sizeof (siginfo));
> +    }
> +

One can either read the struct info buffer returned by ptrace directly
(as in the above "mumble = siginfo.si_signo;") or one can use a
constructed gdbarch siginfo type that maps directly to a struct
siginfo buffer returned by ptrace and use that to access it.  Then one
could write a routine that given either of those (pick one), and a
pointer to the desired siginfo type, and returns a new value in the
desired type.

With this gdbserver can continue to just pass the raw buffer back to
gdb.  Otherwise I guess you'd have to switch to passing back a
semi-formatted buffer of values from gdbserver that gdb can then
parse.


Does that make sense?


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-02-03 23:18             ` Doug Evans
@ 2009-02-03 23:50               ` Pedro Alves
  2009-02-04  0:17                 ` Doug Evans
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-02-03 23:50 UTC (permalink / raw)
  To: Doug Evans; +Cc: Daniel Jacobowitz, Ulrich Weigand, gdb-patches

On Tuesday 03 February 2009 23:18:40, Doug Evans wrote:

> One can either read the struct info buffer returned by ptrace directly
> (as in the above "mumble = siginfo.si_signo;") 

Right, this is something similar to what the kernel does
in its conversion routines for 32-bit userspace support.

> or one can use a 
> constructed gdbarch siginfo type that maps directly to a struct
> siginfo buffer returned by ptrace and use that to access it.  Then one
> could write a routine that given either of those (pick one), and a
> pointer to the desired siginfo type, and returns a new value in the
> desired type.

When connected to a 64-bit gdbserver that is debugging a 32-bit
inferior, how would gdb know that the binary blob that is coming out
of TARGET_OBJECT_SIGNAL_INFO has the 64-bit layout, and that it
needs to be converted?  All gdbarchs that we have accessible tell us
about the inferior arch, which is 32-bit.  gdb has no idea that the
gdbserver is running a 64-bit ptrace.

> 
> With this gdbserver can continue to just pass the raw buffer back to
> gdb.  

I don't see how given that missing link.

> Otherwise I guess you'd have to switch to passing back a 
> semi-formatted buffer of values from gdbserver that gdb can then
> parse.
> 
> 
> Does that make sense?

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-02-03 23:50               ` Pedro Alves
@ 2009-02-04  0:17                 ` Doug Evans
  0 siblings, 0 replies; 53+ messages in thread
From: Doug Evans @ 2009-02-04  0:17 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Daniel Jacobowitz, Ulrich Weigand, gdb-patches

On Tue, Feb 3, 2009 at 3:50 PM, Pedro Alves <pedro@codesourcery.com> wrote:
> When connected to a 64-bit gdbserver that is debugging a 32-bit
> inferior, how would gdb know that the binary blob that is coming out
> of TARGET_OBJECT_SIGNAL_INFO has the 64-bit layout, and that it
> needs to be converted?  All gdbarchs that we have accessible tell us
> about the inferior arch, which is 32-bit.  gdb has no idea that the
> gdbserver is running a 64-bit ptrace.

Hmmm, I'd forgotten the "using gdb compiled for amd64 talking to a
gdbserver compiled for i386" case.  Blech. GDB could send a query
request for the necessary info.

OOC, are there other reasons why gdb would want to know which host
gdbserver was compiled for?


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-02-03 19:51           ` Pedro Alves
  2009-02-03 23:18             ` Doug Evans
@ 2009-02-04  0:24             ` Daniel Jacobowitz
  2009-02-04  0:49               ` Pedro Alves
  1 sibling, 1 reply; 53+ messages in thread
From: Daniel Jacobowitz @ 2009-02-04  0:24 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Ulrich Weigand, gdb-patches

On Tue, Feb 03, 2009 at 07:51:44PM +0000, Pedro Alves wrote:
> I was thinking on doing this in the arch specific native files, e.g,
> gdb/amd64-linux-nat.c, gdb/ppc-linux-nat.c, etc., and something similar in
> gdbserver too.
> 
> Just to make sure, where you perhaps thinking of something
> entirely different?  I don't see how to make this in a common native
> file.

What Doug described is pretty similar to what I had in mind; it does
not fix the issue for gdbserver, but does for gdb.  Read each field of
the ptrace buffer, then use gdbarch to retrieve the type this would be
expected to have in the inferior.  Use gdb's type/value machinery to
store the raw fields into the new value.  Pass that value's contents
back through the target layer to gdb, which will see the right values
because it uses the same gdbarch to interpret them.

Now, whether those hoops are worth it is another question.  If we have
to do this in gdbserver anyway, we could use the same method in gdb.
I vaguely remember having to do something similar for Solaris's
procfs.

Only biarch platforms would have this problem, and fortunately there
aren't too many.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [0/2] Inspect extra signal information
  2009-02-04  0:24             ` Daniel Jacobowitz
@ 2009-02-04  0:49               ` Pedro Alves
  2009-02-04 21:02                 ` [3/2] Inspect extra signal information, handle amd64 bi-arch gdb Pedro Alves
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-02-04  0:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Daniel Jacobowitz, Ulrich Weigand

On Wednesday 04 February 2009 00:24:38, Daniel Jacobowitz wrote:

> What Doug described is pretty similar to what I had in mind; it does
> not fix the issue for gdbserver, but does for gdb.  Read each field of
> the ptrace buffer, then use gdbarch to retrieve the type this would be
> expected to have in the inferior.  Use gdb's type/value machinery to
> store the raw fields into the new value.  Pass that value's contents
> back through the target layer to gdb, which will see the right values
> because it uses the same gdbarch to interpret them.

A few emails ago I mentioned "if I make use of struct type/struct value
if may not be bad, but, gdbserver can't use those..."  :-), and I was
also thinking of something similar, but simpler.  I was thinking
of building up a value with the 64-bit type (gdb knows how to
build it already), and pass it the raw 64-bit data.  Then build
a new value with the 32-bit data, and iterate simulatenously in both
values through each field and copy/convert each field to the 32-bit
value, as appropriate.  But as you say below, I don't like having
two ways to do the same thing, given that something has to be done
on the gdbserver side.

> Now, whether those hoops are worth it is another question.  If we have
> to do this in gdbserver anyway, we could use the same method in gdb.

That's my thinking too.  I'm half through, let's see what comes out...

> I vaguely remember having to do something similar for Solaris's
> procfs.

Yep.  I remember that.  It was related to that fact that auxv data
in procfs is presented with a 64-bit layout to a 64-bit gdb, even
if the inferior is 32-bit.  If I'm not mistaken:

2008-05-04  Vladimir Prus ...

	* target.h (struct target_ops): New field to_auxv_parse.
	* auxv.c (default_auxv_parse): New, renamed from previous
	target_auxv_parse.
	(target_auxv_parse): Try to call target method.  Fallback to
	default_auxv_parse if not found.
	* procfs.c (procfs_auxv_parse): New.
	(init_procfs_ops): On Solaris, in 64-bit mode, install
	procfs_auxv_parse.

> Only biarch platforms would have this problem, and fortunately there
> aren't too many.

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

* [3/2] Inspect extra signal information, handle amd64 bi-arch gdb
  2009-02-04  0:49               ` Pedro Alves
@ 2009-02-04 21:02                 ` Pedro Alves
  2009-02-04 21:17                   ` Daniel Jacobowitz
  2009-02-04 22:07                   ` Doug Evans
  0 siblings, 2 replies; 53+ messages in thread
From: Pedro Alves @ 2009-02-04 21:02 UTC (permalink / raw)
  To: gdb-patches; +Cc: Daniel Jacobowitz, Ulrich Weigand

[-- Attachment #1: Type: text/plain, Size: 706 bytes --]

Here's a patch that applies on top of the other two.  I think
it's easy to read it split out from the other patches.

This handles the layout conversion for x86/amd64, near the
PTRACE_[G|S]ETSIGINFO calls, like we discussed yesterday.

I'm not adjusting gdbserver here yet, since the original series
added $_siginfo support for ARM, and x86/amd64 only, and, gdbserver
on x86/amd64 isn't biarch aware yet.  We can handle doing something
like this there when we add $_siginfo gdbarch type support for ppc, or
when we add biarch support for x86/amd64.

What do you think?  I've tried to make it as pretty as I could.  :-)

Please, don't hesitate pointing me at anything bogus I may
be doing.

-- 
Pedro Alves

[-- Attachment #2: siginfo_convrt.diff --]
[-- Type: text/x-diff, Size: 11864 bytes --]

2009-02-04  Pedro Alves  <pedro@codesourcery.com>

	* amd64-linux-nat.c (compat_int_t, compat_uptr_t, compat_time_t)
	(compat_timer_t, compat_clock_t, struct compat_timeval)
	(compat_sigval_t, compat_siginfo_t): New types.
	(cpt_si_pid, cpt_si_uid, cpt_si_timerid, cpt_si_overrun)
	(cpt_si_status, cpt_si_utime, cpt_si_stime, cpt_si_ptr)
	(cpt_si_addr, cpt_si_band, cpt_si_fd): New defines.
	(compat_siginfo_from_siginfo, siginfo_from_compat_siginfo)
	(amd64_linux_siginfo_fixup): New.
	* linux-nat.c (linux_nat_siginfo_fixup): New.
	(siginfo_fixup): New.
	(linux_xfer_siginfo): Use siginfo_fixup to convert between the
	siginfo layout expected by ptrace and the siginfo layout of the
	inferior.
	(linux_nat_set_siginfo_fixup): New.
	* linux-nat.h (linux_nat_set_siginfo_fixup): Declare.

---
 gdb/amd64-linux-nat.c |  232 ++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/linux-nat.c       |   59 ++++++++++++
 gdb/linux-nat.h       |    8 +
 3 files changed, 297 insertions(+), 2 deletions(-)

Index: src/gdb/amd64-linux-nat.c
===================================================================
--- src.orig/gdb/amd64-linux-nat.c	2009-02-03 19:20:38.000000000 +0000
+++ src/gdb/amd64-linux-nat.c	2009-02-04 20:11:59.000000000 +0000
@@ -400,6 +400,237 @@ amd64_linux_child_post_startup_inferior 
 }
 \f
 
+/* When GDB is built as a 64-bit application on linux, the
+   PTRACE_GETSIGINFO data is always presented in 64-bit layout.  Since
+   debugging a 32-bit inferior with a 64-bit GDB should look the same
+   as debugging it with a 32-bit GDB, we do the 32-bit <-> 64-bit
+   conversion in-place ourselves.  */
+
+/* These types below (compat_*) define a siginfo type that is layout
+   compatible with the siginfo type exported by the 32-bit userspace
+   support.  */
+
+typedef int compat_int_t;
+typedef unsigned int compat_uptr_t;
+
+typedef int compat_time_t;
+typedef int compat_timer_t;
+typedef int compat_clock_t;
+
+struct compat_timeval
+{
+  compat_time_t tv_sec;
+  int tv_usec;
+};
+
+typedef union compat_sigval
+{
+  compat_int_t sival_int;
+  compat_uptr_t sival_ptr;
+} compat_sigval_t;
+
+typedef struct compat_siginfo
+{
+  int si_signo;
+  int si_errno;
+  int si_code;
+
+  union
+  {
+    int _pad[((128 / sizeof (int)) - 3)];
+
+    /* kill() */
+    struct
+    {
+      unsigned int _pid;
+      unsigned int _uid;
+    } _kill;
+
+    /* POSIX.1b timers */
+    struct
+    {
+      compat_timer_t _tid;
+      int _overrun;
+      compat_sigval_t _sigval;
+    } _timer;
+
+    /* POSIX.1b signals */
+    struct
+    {
+      unsigned int _pid;
+      unsigned int _uid;
+      compat_sigval_t _sigval;
+    } _rt;
+
+    /* SIGCHLD */
+    struct
+    {
+      unsigned int _pid;
+      unsigned int _uid;
+      int _status;
+      compat_clock_t _utime;
+      compat_clock_t _stime;
+    } _sigchld;
+
+    /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+    struct
+    {
+      unsigned int _addr;
+    } _sigfault;
+
+    /* SIGPOLL */
+    struct
+    {
+      int _band;
+      int _fd;
+    } _sigpoll;
+  } _sifields;
+} compat_siginfo_t;
+
+#define cpt_si_pid _sifields._kill._pid
+#define cpt_si_uid _sifields._kill._uid
+#define cpt_si_timerid _sifields._timer._tid
+#define cpt_si_overrun _sifields._timer._overrun
+#define cpt_si_status _sifields._sigchld._status
+#define cpt_si_utime _sifields._sigchld._utime
+#define cpt_si_stime _sifields._sigchld._stime
+#define cpt_si_ptr _sifields._rt._sigval.sival_ptr
+#define cpt_si_addr _sifields._sigfault._addr
+#define cpt_si_band _sifields._sigpoll._band
+#define cpt_si_fd _sifields._sigpoll._fd
+
+static void
+compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
+{
+  memset (to, 0, sizeof (*to));
+
+  to->si_signo = from->si_signo;
+  to->si_errno = from->si_errno;
+  to->si_code = from->si_code;
+
+  if (to->si_code < 0)
+    {
+      to->cpt_si_ptr = (intptr_t) from->si_ptr;
+    }
+  else if (to->si_code == SI_USER)
+    {
+      to->cpt_si_pid = from->si_pid;
+      to->cpt_si_uid = from->si_uid;
+    }
+  else if (to->si_code == SI_TIMER)
+    {
+      to->cpt_si_timerid = from->si_timerid;
+      to->cpt_si_overrun = from->si_overrun;
+      to->cpt_si_ptr = (intptr_t) from->si_ptr;
+    }
+  else
+    {
+      switch (to->si_signo)
+	{
+	case SIGCHLD:
+	  to->cpt_si_pid = from->si_pid;
+	  to->cpt_si_uid = from->si_uid;
+	  to->cpt_si_status = from->si_status;
+	  to->cpt_si_utime = from->si_utime;
+	  to->cpt_si_stime = from->si_stime;
+	  break;
+	case SIGILL:
+	case SIGFPE:
+	case SIGSEGV:
+	case SIGBUS:
+	  to->cpt_si_addr = (intptr_t) from->si_addr;
+	  break;
+	case SIGPOLL:
+	  to->cpt_si_band = from->si_band;
+	  to->cpt_si_fd = from->si_fd;
+	  break;
+	default:
+	  to->cpt_si_pid = from->si_pid;
+	  to->cpt_si_uid = from->si_uid;
+	  to->cpt_si_ptr = (intptr_t) from->si_ptr;
+	}
+    }
+}
+
+static void
+siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
+{
+  memset (to, 0, sizeof (*to));
+
+  to->si_signo = from->si_signo;
+  to->si_errno = from->si_errno;
+  to->si_code = from->si_code;
+
+  if (to->si_code < 0)
+    {
+      to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
+    }
+  else if (to->si_code == SI_USER)
+    {
+      to->si_pid = from->cpt_si_pid;
+      to->si_uid = from->cpt_si_uid;
+    }
+  else if (to->si_code == SI_TIMER)
+    {
+      to->si_timerid = from->cpt_si_timerid;
+      to->si_overrun = from->cpt_si_overrun;
+      to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
+    }
+  else
+    {
+      switch (to->si_signo)
+	{
+	case SIGCHLD:
+	  to->si_pid = from->cpt_si_pid;
+	  to->si_uid = from->cpt_si_uid;
+	  to->si_status = from->cpt_si_status;
+	  to->si_utime = from->cpt_si_utime;
+	  to->si_stime = from->cpt_si_stime;
+	  break;
+	case SIGILL:
+	case SIGFPE:
+	case SIGSEGV:
+	case SIGBUS:
+	  to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
+	  break;
+	case SIGPOLL:
+	  to->si_band = from->cpt_si_band;
+	  to->si_fd = from->cpt_si_fd;
+	  break;
+	default:
+	  to->si_pid = from->cpt_si_pid;
+	  to->si_uid = from->cpt_si_uid;
+	  to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
+	}
+    }
+}
+
+/* Convert a native/host siginfo object, into/from the siginfo in the
+   layout of the inferiors' architecture.  Returns true if any
+   conversion was done; false otherwise.  If DIRECTION is 1, then copy
+   from INF to NATIVE.  If DIRECTION is 0, copy from NATIVE to
+   INF.  */
+
+static int
+amd64_linux_siginfo_fixup (struct siginfo *native, gdb_byte *inf, int direction)
+{
+  /* Is the inferior 32-bit?  If so, then do fixup the siginfo
+     object.  */
+  if (gdbarch_addr_bit (get_frame_arch (get_current_frame ())) == 32)
+    {
+      gdb_assert (sizeof (struct siginfo) == sizeof (compat_siginfo_t));
+
+      if (direction == 0)
+	compat_siginfo_from_siginfo ((struct compat_siginfo *) inf, native);
+      else
+	siginfo_from_compat_siginfo (native, (struct compat_siginfo *) inf);
+
+      return 1;
+    }
+  else
+    return 0;
+}
+
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 void _initialize_amd64_linux_nat (void);
 
@@ -434,4 +665,5 @@ _initialize_amd64_linux_nat (void)
   /* Register the target.  */
   linux_nat_add_target (t);
   linux_nat_set_new_thread (t, amd64_linux_new_thread);
+  linux_nat_set_siginfo_fixup (t, amd64_linux_siginfo_fixup);
 }
Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c	2009-02-03 19:20:49.000000000 +0000
+++ src/gdb/linux-nat.c	2009-02-04 20:23:46.000000000 +0000
@@ -205,6 +205,13 @@ static struct target_ops linux_ops_saved
 /* The method to call, if any, when a new thread is attached.  */
 static void (*linux_nat_new_thread) (ptid_t);
 
+/* The method to call, if any, when the siginfo object needs to be
+   converted between the layout returned by ptrace, and the layout in
+   the architecture of the inferior.  */
+static int (*linux_nat_siginfo_fixup) (struct siginfo *,
+				       gdb_byte *,
+				       int);
+
 /* The saved to_xfer_partial method, inherited from inf-ptrace.c.
    Called by our to_xfer_partial.  */
 static LONGEST (*super_xfer_partial) (struct target_ops *, 
@@ -3214,6 +3221,28 @@ linux_nat_mourn_inferior (struct target_
     linux_fork_mourn_inferior ();
 }
 
+/* Convert a native/host siginfo object, into/from the siginfo in the
+   layout of the inferiors' architecture.  */
+
+static void
+siginfo_fixup (struct siginfo *siginfo, gdb_byte *inf_siginfo, int direction)
+{
+  int done = 0;
+
+  if (linux_nat_siginfo_fixup != NULL)
+    done = linux_nat_siginfo_fixup (siginfo, inf_siginfo, direction);
+
+  /* If there was no callback, or the callback didn't do anything,
+     then just do a straight memcpy.  */
+  if (!done)
+    {
+      if (direction == 1)
+	memcpy (siginfo, inf_siginfo, sizeof (struct siginfo));
+      else
+	memcpy (inf_siginfo, siginfo, sizeof (struct siginfo));
+    }
+}
+
 static LONGEST
 linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
                     const char *annex, gdb_byte *readbuf,
@@ -3223,6 +3252,7 @@ linux_xfer_siginfo (struct target_ops *o
   LONGEST n;
   int pid;
   struct siginfo siginfo;
+  gdb_byte inf_siginfo[sizeof (struct siginfo)];
 
   gdb_assert (object == TARGET_OBJECT_SIGNAL_INFO);
   gdb_assert (readbuf || writebuf);
@@ -3239,14 +3269,26 @@ linux_xfer_siginfo (struct target_ops *o
   if (errno != 0)
     return -1;
 
+  /* When GDB is built as a 64-bit application, ptrace writes into
+     SIGINFO an object with 64-bit layout.  Since debugging a 32-bit
+     inferior with a 64-bit GDB should look the same as debugging it
+     with a 32-bit GDB, we need to convert it.  GDB core always sees
+     the converted layout, so any read/write will have to be done
+     post-conversion.  */
+  siginfo_fixup (&siginfo, inf_siginfo, 0);
+
   if (offset + len > sizeof (siginfo))
     len = sizeof (siginfo) - offset;
 
   if (readbuf != NULL)
-    memcpy (readbuf, (char *)&siginfo + offset, len);
+    memcpy (readbuf, inf_siginfo + offset, len);
   else
     {
-      memcpy ((char *)&siginfo + offset, writebuf, len);
+      memcpy (inf_siginfo + offset, writebuf, len);
+
+      /* Convert back to ptrace layout before flushing it out.  */
+      siginfo_fixup (&siginfo, inf_siginfo, 1);
+
       errno = 0;
       ptrace (PTRACE_SETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, &siginfo);
       if (errno != 0)
@@ -4715,6 +4757,19 @@ linux_nat_set_new_thread (struct target_
   linux_nat_new_thread = new_thread;
 }
 
+/* Register a method that converts a siginfo object between the layout
+   that ptrace returns, and the layout in the architecture of the
+   inferior.  */
+void
+linux_nat_set_siginfo_fixup (struct target_ops *t,
+			     int (*siginfo_fixup) (struct siginfo *,
+						   gdb_byte *,
+						   int))
+{
+  /* Save the pointer.  */
+  linux_nat_siginfo_fixup = siginfo_fixup;
+}
+
 /* Return the saved siginfo associated with PTID.  */
 struct siginfo *
 linux_nat_get_siginfo (ptid_t ptid)
Index: src/gdb/linux-nat.h
===================================================================
--- src.orig/gdb/linux-nat.h	2009-02-03 20:09:44.000000000 +0000
+++ src/gdb/linux-nat.h	2009-02-04 19:57:44.000000000 +0000
@@ -128,6 +128,14 @@ void linux_nat_add_target (struct target
 /* Register a method to call whenever a new thread is attached.  */
 void linux_nat_set_new_thread (struct target_ops *, void (*) (ptid_t));
 
+/* Register a method that converts a siginfo object between the layout
+   that ptrace returns, and the layout in the architecture of the
+   inferior.  */
+void linux_nat_set_siginfo_fixup (struct target_ops *,
+				  int (*) (struct siginfo *,
+					   gdb_byte *,
+					   int));
+
 /* Update linux-nat internal state when changing from one fork
    to another.  */
 void linux_nat_switch_fork (ptid_t new_ptid);

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [3/2] Inspect extra signal information, handle amd64 bi-arch  gdb
  2009-02-04 21:02                 ` [3/2] Inspect extra signal information, handle amd64 bi-arch gdb Pedro Alves
@ 2009-02-04 21:17                   ` Daniel Jacobowitz
  2009-02-06 23:37                     ` Pedro Alves
  2009-02-04 22:07                   ` Doug Evans
  1 sibling, 1 reply; 53+ messages in thread
From: Daniel Jacobowitz @ 2009-02-04 21:17 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches, Ulrich Weigand

On Wed, Feb 04, 2009 at 09:02:10PM +0000, Pedro Alves wrote:
> Here's a patch that applies on top of the other two.  I think
> it's easy to read it split out from the other patches.
> 
> This handles the layout conversion for x86/amd64, near the
> PTRACE_[G|S]ETSIGINFO calls, like we discussed yesterday.
> 
> I'm not adjusting gdbserver here yet, since the original series
> added $_siginfo support for ARM, and x86/amd64 only, and, gdbserver
> on x86/amd64 isn't biarch aware yet.  We can handle doing something
> like this there when we add $_siginfo gdbarch type support for ppc, or
> when we add biarch support for x86/amd64.
> 
> What do you think?  I've tried to make it as pretty as I could.  :-)

Seems fine to me.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [3/2] Inspect extra signal information, handle amd64 bi-arch gdb
  2009-02-04 21:02                 ` [3/2] Inspect extra signal information, handle amd64 bi-arch gdb Pedro Alves
  2009-02-04 21:17                   ` Daniel Jacobowitz
@ 2009-02-04 22:07                   ` Doug Evans
  1 sibling, 0 replies; 53+ messages in thread
From: Doug Evans @ 2009-02-04 22:07 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches, Daniel Jacobowitz, Ulrich Weigand

On Wed, Feb 4, 2009 at 1:02 PM, Pedro Alves <pedro@codesourcery.com> wrote:
> Here's a patch that applies on top of the other two.  I think
> it's easy to read it split out from the other patches.
>
> This handles the layout conversion for x86/amd64, near the
> PTRACE_[G|S]ETSIGINFO calls, like we discussed yesterday.
>
> I'm not adjusting gdbserver here yet, since the original series
> added $_siginfo support for ARM, and x86/amd64 only, and, gdbserver
> on x86/amd64 isn't biarch aware yet.  We can handle doing something
> like this there when we add $_siginfo gdbarch type support for ppc, or
> when we add biarch support for x86/amd64.
>
> What do you think?  I've tried to make it as pretty as I could.  :-)
>
> Please, don't hesitate pointing me at anything bogus I may
> be doing.

Another way to go, for reference sake, is to write a routine that
converts a struct siginfo to a string, and another that converts a
string to a struct siginfo, and have both gdb and gdbserver use those
routines.  Then bi-arch gdbserver support would pretty much come for
free.

Over time it seems like a growing amount of code would be useful to
share between gdb and gdbserver.  Do we have a plan for that?


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [1/2] Inspect extra signal information
  2009-02-02 21:04         ` Eli Zaretskii
@ 2009-02-05  1:14           ` Pedro Alves
  2009-02-05 20:30             ` Eli Zaretskii
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-02-05  1:14 UTC (permalink / raw)
  To: gdb-patches, Eli Zaretskii

[-- Attachment #1: Type: text/plain, Size: 2002 bytes --]

On Monday 02 February 2009 21:04:34, Eli Zaretskii wrote:
> > From: Pedro Alves <pedro@codesourcery.com>
> > I don't see struct value documented in
> > the internals manual though.  What kind of detail do you require here?
> 
> Exactly the kind you described.

Great.

> > I'm thinking of adding a "Values" section somewhere, don't know
> > where yet.
> 
> The place doesn't matter much, since the internals manual is "work in
> progress", and looks more like a car crash than a concise document.
> 

:-)

There doesn't seem there's a good way to place it, since values
are used for many things, so I made it a new chapter.  I placed
it even before Stack Frames, because frame handling uses struct value.

> > @item @code{lval_computed}
> > 
> > These are values with arbitrary functions to handle reads and writes,
> 
> Please lose the empty line between the @item and its description.
> 

Done.

> > and "copy operators" and "destructors".  They allow creating
> 
> Please use ``this kind of quoting'' in Texinfo, not "this kind".
> 

Done.  ( it shows I didn't write that in emacs :-) )

> > described by the @code{struct lval_funcs} struture declared in
>                                             ^^^^^^^^
> A typo.
> 

Fixed.

> > @file{value.h} to the @code{allocate_computed_value} function.  An
> 
> What does it mean "declared in value.h to the allocate_computed_value
> function"?

It means I wrote a too long sentence, and lost sense somewhere along the
way.  :-)

"The creator of such a value specifies specialized read (...) callbacks (...)
to the @code{allocate_computed_value} function."

I've rewriten this.  I think it's clearer now.

> Perhaps add a few words describing `struct lval_funcs', or maybe just
> showing a simple example would be enough.

I've added an example.

> A couple of index entries for this section will also help.

I've added them.

> Thanks again for working on this.

Thanks for the speedy review.

Here's a proper patch.

Does it look OK?

-- 
Pedro Alves

[-- Attachment #2: lval_computed_docs.diff --]
[-- Type: text/x-diff, Size: 3614 bytes --]

2009-02-04  Pedro Alves  <pedro@codesourcery.com>

	* gdbint.texinfo (Values): New chapter.

---
 gdb/doc/gdbint.texinfo |   95 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 95 insertions(+)

Index: src/gdb/doc/gdbint.texinfo
===================================================================
--- src.orig/gdb/doc/gdbint.texinfo	2009-02-03 19:20:40.000000000 +0000
+++ src/gdb/doc/gdbint.texinfo	2009-02-05 01:11:31.000000000 +0000
@@ -76,6 +76,7 @@ as the mechanisms that adapt @value{GDBN
 * Algorithms::
 * User Interface::
 * libgdb::
+* Values::
 * Stack Frames::
 * Symbol Handling::
 * Language Support::
@@ -1834,6 +1835,100 @@ the query interface.  Each function is p
 builder.  The result of the query is constructed using that builder
 before the query function returns.
 
+@node Values
+@chapter Values
+@section Values
+
+@cindex values
+@cindex @code{value} structure
+@value{GDBN} uses @code{struct value}, or @dfn{values}, as an internal
+abstraction for the representation of a variety of inferior objects
+and @value{GDBN} convenience objects.
+
+Values have an associated @code{struct type}, that describes a virtual
+view of the raw data or object stored in or accessed through the
+value.
+
+A value is in addition descriminated by its lvalue-ness, given its
+@code{enum lval_type} enumeration type:
+
+@cindex @code{lval_type} enumeration, for values.
+@table @code
+@item @code{not_lval}
+This value is not an lval.  It can't be assigned to.
+
+@item @code{lval_memory}
+This value represents an object in memory.
+
+@item @code{lval_register}
+This value represents an object that lives in a register.
+
+@item @code{lval_internalvar}
+Represents the value of an internal variable.
+
+@item @code{lval_internalvar_component}
+Represents part of a gdb internal variable.  E.g., a structure field.
+
+@cindex computed values
+@item @code{lval_computed}
+These are ``computed'' values.  They allow creating specialized value
+objects for specific purposes, all abstracted way from the the core
+value support code.  The creator of such a value writes specialized
+functions to handle the reading and writing to/from the value's
+backend data, and optionally, a ``copy operator'' and a
+``destructor''.
+
+Pointers to these functions are stored in a @code{struct lval_funcs}
+instance (declared in @file{value.h}), and passed to the
+@code{allocate_computed_value} function, as in the example below.
+
+@smallexample
+static void
+nil_value_read (struct value *v)
+@{
+  /* This callback reads data from some backend, and stores it in V.
+     In this case, we always read null data.  You'll want to fill in
+     something more interesting.  */
+
+  memset (value_contents_all_raw (v),
+          value_offset (v),
+          TYPE_LENGTH (value_type (v)));
+@}
+
+static void
+nil_value_write (struct value *v, struct value *fromval)
+@{
+  /* Takes the data from FROMVAL and stores it in the backend of V.  */
+
+  to_oblivion (value_contents_all_raw (fromval),
+               value_offset (v),
+               TYPE_LENGTH (value_type (fromval)));
+@}
+
+static struct lval_funcs nil_value_funcs =
+  @{
+    nil_value_read,
+    nil_value_write
+  @};
+
+struct value *
+make_nil_value (void)
+@{
+   struct type *type;
+   struct value *v;
+
+   type = make_nils_type ();
+   v = allocate_computed_value (type, &nil_value_funcs, NULL);
+
+   return v;
+@}
+@end smallexample
+
+See the implementation of the @code{$_siginfo} convenience variable in
+@file{infrun.c} as a real example use of lval_computed.
+
+@end table
+
 @node Stack Frames
 @chapter Stack Frames
 

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [1/2] Inspect extra signal information
  2009-02-05  1:14           ` Pedro Alves
@ 2009-02-05 20:30             ` Eli Zaretskii
  2009-02-06 23:31               ` Pedro Alves
  0 siblings, 1 reply; 53+ messages in thread
From: Eli Zaretskii @ 2009-02-05 20:30 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

> From: Pedro Alves <pedro@codesourcery.com>
> Date: Thu, 5 Feb 2009 01:14:04 +0000
> 
> Here's a proper patch.
> 
> Does it look OK?

Yes, but I have a couple of nits:

> +A value is in addition descriminated by its lvalue-ness, given its
                          ^^^^^^^^^^^^^
"discriminated"

> +Represents part of a gdb internal variable.  E.g., a structure field.
                        ^^^
@value{GDBN}

> +objects for specific purposes, all abstracted way from the the core
                                                 ^^^      ^^^^^^^
"way" or "away"?  Also, lose the extra "the".

Thanks.


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [1/2] Inspect extra signal information
  2009-02-05 20:30             ` Eli Zaretskii
@ 2009-02-06 23:31               ` Pedro Alves
  0 siblings, 0 replies; 53+ messages in thread
From: Pedro Alves @ 2009-02-06 23:31 UTC (permalink / raw)
  To: gdb-patches, Eli Zaretskii

On Thursday 05 February 2009 20:30:36, Eli Zaretskii wrote:
> > From: Pedro Alves <pedro@codesourcery.com>
> > Date: Thu, 5 Feb 2009 01:14:04 +0000
> > 
> > Does it look OK?
> 
> Yes, but I have a couple of nits:

[...]

Thanks a lot Eli.  I've fixed the nits, and checked this in.

-- 
Pedro Alves

gdb/
2009-02-06  Jim Blandy  <jimb@codesourcery.com>
	    Daniel Jacobowitz  <dan@codesourcery.com>
	    Vladimir Prus  <vladimir@codesourcery.com>
	    Pedro Alves  <pedro@codesourcery.com>

	* defs.h (enum lval_type): New value: lval_computed.
	* value.h (struct lval_funcs): New type.
	(allocate_computed_value, value_computed_funcs)
	(value_computed_closure): New declarations.
	* value.c (struct value): Add a structure to the location union
	for computed lvalues, containing 'funcs' and 'closure' members.
	(allocate_computed_value, value_computed_funcs)
	(value_computed_closure): New functions.
	(value_free): For computed lvalues, call the closure's
	'free_closure' function before freeing the value itself.
	(value_copy): If we're copying an lval_computed value, call the
	closure's 'copy_closure' function.
	(set_value_component_location): If the original value is a
	computed lvalue, then call the closure's 'copy_closure' function.
	(value_of_internalvar): If an internal variable's value is a
	computed lvalue, make retrieving its value produce an equivalent
	computed lvalue.
	* valops.c (value_fetch_lazy): Unlazy computed lvalues by calling
	their read function.
	(value_assign): Assign to computed lvalues by calling their write
	function.

gdb/doc/
2009-02-06  Pedro Alves  <pedro@codesourcery.com>

	* gdbint.texinfo (Values): New chapter.

---
 gdb/defs.h             |    5 ++
 gdb/doc/gdbint.texinfo |   96 +++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/valops.c           |   12 +++++-
 gdb/value.c            |   85 +++++++++++++++++++++++++++++++++++++++++--
 gdb/value.h            |   54 +++++++++++++++++++++++++++
 5 files changed, 247 insertions(+), 5 deletions(-)

Index: src/gdb/defs.h
===================================================================
--- src.orig/gdb/defs.h	2009-02-06 20:31:15.000000000 +0000
+++ src/gdb/defs.h	2009-02-06 20:40:16.000000000 +0000
@@ -652,7 +652,10 @@ enum lval_type
     /* In a gdb internal variable.  */
     lval_internalvar,
     /* Part of a gdb internal variable (structure field).  */
-    lval_internalvar_component
+    lval_internalvar_component,
+    /* Value's bits are fetched and stored using functions provided by
+       its creator.  */
+    lval_computed
   };
 
 /* Control types for commands */
Index: src/gdb/value.h
===================================================================
--- src.orig/gdb/value.h	2009-02-06 20:39:43.000000000 +0000
+++ src/gdb/value.h	2009-02-06 20:40:16.000000000 +0000
@@ -142,6 +142,60 @@ extern void set_value_pointed_to_offset 
 extern int value_embedded_offset (struct value *value);
 extern void set_value_embedded_offset (struct value *value, int val);
 
+/* For lval_computed values, this structure holds functions used to
+   retrieve and set the value (or portions of the value).
+
+   For each function, 'V' is the 'this' pointer: an lval_funcs
+   function F may always assume that the V it receives is an
+   lval_computed value, and has F in the appropriate slot of its
+   lval_funcs structure.  */
+
+struct lval_funcs
+{
+  /* Fill in VALUE's contents.  This is used to "un-lazy" values.  If
+     a problem arises in obtaining VALUE's bits, this function should
+     call 'error'.  */
+  void (*read) (struct value *v);
+
+  /* Handle an assignment TOVAL = FROMVAL by writing the value of
+     FROMVAL to TOVAL's location.  The contents of TOVAL have not yet
+     been updated.  If a problem arises in doing so, this function
+     should call 'error'.  */
+  void (*write) (struct value *toval, struct value *fromval);
+
+  /* Return a duplicate of VALUE's closure, for use in a new value.
+     This may simply return the same closure, if VALUE's is
+     reference-counted or statically allocated.
+
+     This may be NULL, in which case VALUE's closure is re-used in the
+     new value.  */
+  void *(*copy_closure) (struct value *v);
+
+  /* Drop VALUE's reference to its closure.  Maybe this frees the
+     closure; maybe this decrements a reference count; maybe the
+     closure is statically allocated and this does nothing.
+
+     This may be NULL, in which case no action is taken to free
+     VALUE's closure.  */
+  void (*free_closure) (struct value *v);
+};
+
+/* Create a computed lvalue, with type TYPE, function pointers FUNCS,
+   and closure CLOSURE.  */
+
+extern struct value *allocate_computed_value (struct type *type,
+                                              struct lval_funcs *funcs,
+                                              void *closure);
+
+/* If VALUE is lval_computed, return its lval_funcs structure.  */
+
+extern struct lval_funcs *value_computed_funcs (struct value *value);
+
+/* If VALUE is lval_computed, return its closure.  The meaning of the
+   returned value depends on the functions VALUE uses.  */
+
+extern void *value_computed_closure (struct value *value);
+
 /* If zero, contents of this value are in the contents field.  If
    nonzero, contents are in inferior.  If the lval field is lval_memory,
    the contents are in inferior memory at location.address plus offset.
Index: src/gdb/value.c
===================================================================
--- src.orig/gdb/value.c	2009-02-06 20:39:43.000000000 +0000
+++ src/gdb/value.c	2009-02-06 20:40:16.000000000 +0000
@@ -63,6 +63,15 @@ struct value
 
     /* Pointer to internal variable.  */
     struct internalvar *internalvar;
+
+    /* If lval == lval_computed, this is a set of function pointers
+       to use to access and describe the value, and a closure pointer
+       for them to use.  */
+    struct
+    {
+      struct lval_funcs *funcs; /* Functions to call.  */
+      void *closure;            /* Closure for those functions to use.  */
+    } computed;
   } location;
 
   /* Describes offset of a value within lval of a structure in bytes.
@@ -296,6 +305,20 @@ value_remove_from_list (struct value **h
       }
 }
 
+struct value *
+allocate_computed_value (struct type *type,
+                         struct lval_funcs *funcs,
+                         void *closure)
+{
+  struct value *v = allocate_value (type);
+  VALUE_LVAL (v) = lval_computed;
+  v->location.computed.funcs = funcs;
+  v->location.computed.closure = closure;
+  set_value_lazy (v, 1);
+
+  return v;
+}
+
 /* Accessor methods.  */
 
 struct value *
@@ -458,6 +481,22 @@ set_value_pointed_to_offset (struct valu
   value->pointed_to_offset = val;
 }
 
+struct lval_funcs *
+value_computed_funcs (struct value *v)
+{
+  gdb_assert (VALUE_LVAL (v) == lval_computed);
+
+  return v->location.computed.funcs;
+}
+
+void *
+value_computed_closure (struct value *v)
+{
+  gdb_assert (VALUE_LVAL (v) == lval_computed);
+
+  return v->location.computed.closure;
+}
+
 enum lval_type *
 deprecated_value_lval_hack (struct value *value)
 {
@@ -512,7 +551,17 @@ void
 value_free (struct value *val)
 {
   if (val)
-    xfree (val->contents);
+    {
+      if (VALUE_LVAL (val) == lval_computed)
+	{
+	  struct lval_funcs *funcs = val->location.computed.funcs;
+
+	  if (funcs->free_closure)
+	    funcs->free_closure (val);
+	}
+
+      xfree (val->contents);
+    }
   xfree (val);
 }
 
@@ -625,6 +674,13 @@ value_copy (struct value *arg)
 	      TYPE_LENGTH (value_enclosing_type (arg)));
 
     }
+  if (VALUE_LVAL (val) == lval_computed)
+    {
+      struct lval_funcs *funcs = val->location.computed.funcs;
+
+      if (funcs->copy_closure)
+        val->location.computed.closure = funcs->copy_closure (val);
+    }
   return val;
 }
 
@@ -635,7 +691,15 @@ set_value_component_location (struct val
     VALUE_LVAL (component) = lval_internalvar_component;
   else
     VALUE_LVAL (component) = VALUE_LVAL (whole);
+
   component->location = whole->location;
+  if (VALUE_LVAL (whole) == lval_computed)
+    {
+      struct lval_funcs *funcs = whole->location.computed.funcs;
+
+      if (funcs->copy_closure)
+        component->location.computed.closure = funcs->copy_closure (whole);
+    }
 }
 
 \f
@@ -872,8 +936,23 @@ value_of_internalvar (struct internalvar
   val = value_copy (var->value);
   if (value_lazy (val))
     value_fetch_lazy (val);
-  VALUE_LVAL (val) = lval_internalvar;
-  VALUE_INTERNALVAR (val) = var;
+
+  /* If the variable's value is a computed lvalue, we want references
+     to it to produce another computed lvalue, where referencces and
+     assignments actually operate through the computed value's
+     functions.
+
+     This means that internal variables with computed values behave a
+     little differently from other internal variables: assignments to
+     them don't just replace the previous value altogether.  At the
+     moment, this seems like the behavior we want.  */
+  if (var->value->lval == lval_computed)
+    VALUE_LVAL (val) = lval_computed;
+  else
+    {
+      VALUE_LVAL (val) = lval_internalvar;
+      VALUE_INTERNALVAR (val) = var;
+    }
 
   /* Values are always stored in the target's byte order.  When connected to a
      target this will most likely always be correct, so there's normally no
Index: src/gdb/valops.c
===================================================================
--- src.orig/gdb/valops.c	2009-02-06 20:39:43.000000000 +0000
+++ src/gdb/valops.c	2009-02-06 20:40:16.000000000 +0000
@@ -727,6 +727,8 @@ value_fetch_lazy (struct value *val)
 	 watchpoints from trying to watch the saved frame pointer.  */
       value_free_to_mark (mark);
     }
+  else if (VALUE_LVAL (val) == lval_computed)
+    value_computed_funcs (val)->read (val);
   else
     internal_error (__FILE__, __LINE__, "Unexpected lazy value type.");
 
@@ -895,7 +897,15 @@ value_assign (struct value *toval, struc
 	observer_notify_target_changed (&current_target);
 	break;
       }
-      
+
+    case lval_computed:
+      {
+	struct lval_funcs *funcs = value_computed_funcs (toval);
+
+	funcs->write (toval, fromval);
+      }
+      break;
+
     default:
       error (_("Left operand of assignment is not an lvalue."));
     }
Index: src/gdb/doc/gdbint.texinfo
===================================================================
--- src.orig/gdb/doc/gdbint.texinfo	2009-02-06 20:39:45.000000000 +0000
+++ src/gdb/doc/gdbint.texinfo	2009-02-06 20:40:16.000000000 +0000
@@ -73,6 +73,7 @@ as the mechanisms that adapt @value{GDBN
 * Algorithms::
 * User Interface::
 * libgdb::
+* Values::
 * Stack Frames::
 * Symbol Handling::
 * Language Support::
@@ -1831,6 +1832,101 @@ the query interface.  Each function is p
 builder.  The result of the query is constructed using that builder
 before the query function returns.
 
+@node Values
+@chapter Values
+@section Values
+
+@cindex values
+@cindex @code{value} structure
+@value{GDBN} uses @code{struct value}, or @dfn{values}, as an internal
+abstraction for the representation of a variety of inferior objects
+and @value{GDBN} convenience objects.
+
+Values have an associated @code{struct type}, that describes a virtual
+view of the raw data or object stored in or accessed through the
+value.
+
+A value is in addition discriminated by its lvalue-ness, given its
+@code{enum lval_type} enumeration type:
+
+@cindex @code{lval_type} enumeration, for values.
+@table @code
+@item @code{not_lval}
+This value is not an lval.  It can't be assigned to.
+
+@item @code{lval_memory}
+This value represents an object in memory.
+
+@item @code{lval_register}
+This value represents an object that lives in a register.
+
+@item @code{lval_internalvar}
+Represents the value of an internal variable.
+
+@item @code{lval_internalvar_component}
+Represents part of a @value{GDBN} internal variable.  E.g., a
+structure field.
+
+@cindex computed values
+@item @code{lval_computed}
+These are ``computed'' values.  They allow creating specialized value
+objects for specific purposes, all abstracted away from the core value
+support code.  The creator of such a value writes specialized
+functions to handle the reading and writing to/from the value's
+backend data, and optionally, a ``copy operator'' and a
+``destructor''.
+
+Pointers to these functions are stored in a @code{struct lval_funcs}
+instance (declared in @file{value.h}), and passed to the
+@code{allocate_computed_value} function, as in the example below.
+
+@smallexample
+static void
+nil_value_read (struct value *v)
+@{
+  /* This callback reads data from some backend, and stores it in V.
+     In this case, we always read null data.  You'll want to fill in
+     something more interesting.  */
+
+  memset (value_contents_all_raw (v),
+          value_offset (v),
+          TYPE_LENGTH (value_type (v)));
+@}
+
+static void
+nil_value_write (struct value *v, struct value *fromval)
+@{
+  /* Takes the data from FROMVAL and stores it in the backend of V.  */
+
+  to_oblivion (value_contents_all_raw (fromval),
+               value_offset (v),
+               TYPE_LENGTH (value_type (fromval)));
+@}
+
+static struct lval_funcs nil_value_funcs =
+  @{
+    nil_value_read,
+    nil_value_write
+  @};
+
+struct value *
+make_nil_value (void)
+@{
+   struct type *type;
+   struct value *v;
+
+   type = make_nils_type ();
+   v = allocate_computed_value (type, &nil_value_funcs, NULL);
+
+   return v;
+@}
+@end smallexample
+
+See the implementation of the @code{$_siginfo} convenience variable in
+@file{infrun.c} as a real example use of lval_computed.
+
+@end table
+
 @node Stack Frames
 @chapter Stack Frames
 


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [2/2] Inspect extra signal information
  2009-01-13 18:55       ` Eli Zaretskii
  2009-01-13 19:08         ` Pedro Alves
@ 2009-02-06 23:35         ` Pedro Alves
  2009-02-09  6:23           ` Paul Pluzhnikov
  1 sibling, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-02-06 23:35 UTC (permalink / raw)
  To: gdb-patches

Here's the version of this patch that went in.

-- 
Pedro Alves

2009-02-06  Pedro Alves  <pedro@codesourcery.com>

	* target.h (enum target_object): Add new TARGET_OBJECT_SIGNAL_INFO.
	* infrun.c (siginfo_value_read, siginfo_value_write): New.
	(siginfo_value_funcs): New.
	(siginfo_make_value): New.
	(_initialize_infrun): Create the $_siginfo convenience variable.
	* gdbtypes.h (append_composite_type_field_aligned): Declare.
	* gdbtypes.c (append_composite_type_field): Rename to...
	(append_composite_type_field_aligned): ... this.  Add ALIGNMENT
	argument.  Handle it.
	(append_composite_type_field): Rewrite on top of
	append_composite_type_field_aligned.
	* value.h (internalvar_make_value): New typedef.
	(struct internalvar) <make_value>: New field.
	(create_internalvar_type_lazy): Declare.
	* value.c (create_internalvar): Clear make_value.
	(create_internalvar_type_lazy): New.
	(value_of_internalvar): If make_value is set use it.
	(preserve_values): Skip internal variables that don't have a
	value.
	* gdbarch.sh (get_siginfo_type): New.
	* gdbarch.h, gdbarch.c: Regenerate.

	* linux-tdep.h, linux-tdep.c: New.
	* amd64-linux-tdep.c: Include "linux-tdep.h".
	(amd64_linux_init_abi): Register linux_get_siginfo_type and
	linux_get_siginfo_mapper.
	* i386-linux-tdep.c: Include "linux-tdep.h".
	(i386_linux_init_abi): Register linux_get_siginfo_type and
	linux_get_siginfo_mapper.
	* arm-linux-tdep.c: Include "linux-tdep.h".
	(i386_linux_init_abi): Register linux_get_siginfo_type and
	linux_get_siginfo_mapper.

	* linux-nat.c (linux_xfer_siginfo): New.
	(linux_nat_xfer_partial): Handle TARGET_OBJECT_SIGNAL_INFO.
	* remote.c (PACKET_qXfer_siginfo_read)
	(PACKET_qXfer_siginfo_write): New.
	(feature remote_protocol_features): Add "qXfer:siginfo:read" and
	"qXfer:siginfo:write" features.
	(remote_xfer_partial): Handle TARGET_OBJECT_SIGNAL_INFO.
	(_initialize_remote): Add "set/show remote read-siginfo-object"
	and "set/show remote write-siginfo-object" commands.

	* Makefile.in (ALL_TARGET_OBS): Add linux-tdep.o.
	(HFILES_NO_SRCDIR): Add linux-tdep.h.
	(ALLDEPFILES): Add linux-tdep.c.
	
	* configure.tgt (arm*-*-linux* | arm*-*-uclinux*)
	(i[34567]86-*-linux*, x86_64-*-linux*): Add linux-tdep.o to
	gdb_target_obs.

2009-02-06  Pedro Alves  <pedro@codesourcery.com>

	gdb/gdbserver/
	* server.c (handle_query): Report qXfer:siginfo:read and
	qXfer:siginfo:write as supported and handle them.
	* target.h (struct target_ops) <qxfer_siginfo>: New field.
	* linux-low.c (linux_xfer_siginfo): New.
	(linux_target_ops): Set it.

2009-02-06  Pedro Alves  <pedro@codesourcery.com>

	gdb/doc/
	* gdb.texinfo (Signals): Document $_siginfo.
	(Convenience Variables): Mention $_siginfo.
	(Remote Configuration): Document qXfer:siginfo:read,
	qXfer:siginfo:write packets, and the read-siginfo-object,
	write-siginfo-object commands.

2009-02-06  Pedro Alves  <pedro@codesourcery.com>

	gdb/testsuite/
	* gdb.base/siginfo-obj.c, gdb.base/siginfo-obj.exp: New.

---
 gdb/Makefile.in                        |    4 
 gdb/amd64-linux-tdep.c                 |    3 
 gdb/arm-linux-tdep.c                   |    3 
 gdb/configure.tgt                      |    6 -
 gdb/doc/gdb.texinfo                    |  101 ++++++++++++++++++++++++
 gdb/gdbarch.c                          |   33 +++++++
 gdb/gdbarch.h                          |   10 ++
 gdb/gdbarch.sh                         |    5 +
 gdb/gdbserver/linux-low.c              |   39 +++++++++
 gdb/gdbserver/server.c                 |   74 +++++++++++++++++
 gdb/gdbserver/target.h                 |    5 +
 gdb/gdbtypes.c                         |   29 +++++-
 gdb/gdbtypes.h                         |    4 
 gdb/i386-linux-tdep.c                  |    3 
 gdb/infrun.c                           |   87 ++++++++++++++++++++
 gdb/linux-nat.c                        |   50 +++++++++++
 gdb/linux-tdep.c                       |  138 +++++++++++++++++++++++++++++++++
 gdb/linux-tdep.h                       |   25 +++++
 gdb/remote.c                           |   25 +++++
 gdb/target.h                           |    5 -
 gdb/testsuite/gdb.base/siginfo-obj.c   |   70 ++++++++++++++++
 gdb/testsuite/gdb.base/siginfo-obj.exp |  131 +++++++++++++++++++++++++++++++
 gdb/value.c                            |   62 ++++++++++----
 gdb/value.h                            |    6 +
 24 files changed, 889 insertions(+), 29 deletions(-)

Index: src/gdb/target.h
===================================================================
--- src.orig/gdb/target.h	2009-02-06 22:36:44.000000000 +0000
+++ src/gdb/target.h	2009-02-06 22:42:34.000000000 +0000
@@ -221,7 +221,10 @@ enum target_object
   TARGET_OBJECT_LIBRARIES,
   /* Get OS specific data.  The ANNEX specifies the type (running
      processes, etc.).  */
-  TARGET_OBJECT_OSDATA
+  TARGET_OBJECT_OSDATA,
+  /* Extra signal info.  Usually the contents of `siginfo_t' on unix
+     platforms.  */
+  TARGET_OBJECT_SIGNAL_INFO,
   /* Possible future objects: TARGET_OBJECT_FILE, ... */
 };
 
Index: src/gdb/infrun.c
===================================================================
--- src.orig/gdb/infrun.c	2009-02-06 22:28:26.000000000 +0000
+++ src/gdb/infrun.c	2009-02-06 22:42:34.000000000 +0000
@@ -4804,6 +4804,87 @@ signals_info (char *signum_exp, int from
 
   printf_filtered (_("\nUse the \"handle\" command to change these tables.\n"));
 }
+
+/* The $_siginfo convenience variable is a bit special.  We don't know
+   for sure the type of the value until we actually have a chance to
+   fetch the data.  The type can change depending on gdbarch, so it it
+   also dependent on which thread you have selected.
+
+     1. making $_siginfo be an internalvar that creates a new value on
+     access.
+
+     2. making the value of $_siginfo be an lval_computed value.  */
+
+/* This function implements the lval_computed support for reading a
+   $_siginfo value.  */
+
+static void
+siginfo_value_read (struct value *v)
+{
+  LONGEST transferred;
+
+  transferred =
+    target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO,
+		 NULL,
+		 value_contents_all_raw (v),
+		 value_offset (v),
+		 TYPE_LENGTH (value_type (v)));
+
+  if (transferred != TYPE_LENGTH (value_type (v)))
+    error (_("Unable to read siginfo"));
+}
+
+/* This function implements the lval_computed support for writing a
+   $_siginfo value.  */
+
+static void
+siginfo_value_write (struct value *v, struct value *fromval)
+{
+  LONGEST transferred;
+
+  transferred = target_write (&current_target,
+			      TARGET_OBJECT_SIGNAL_INFO,
+			      NULL,
+			      value_contents_all_raw (fromval),
+			      value_offset (v),
+			      TYPE_LENGTH (value_type (fromval)));
+
+  if (transferred != TYPE_LENGTH (value_type (fromval)))
+    error (_("Unable to write siginfo"));
+}
+
+static struct lval_funcs siginfo_value_funcs =
+  {
+    siginfo_value_read,
+    siginfo_value_write
+  };
+
+/* Return a new value with the correct type for the siginfo object of
+   the current thread.  Return a void value if there's no object
+   available.  */
+
+struct value *
+siginfo_make_value (struct internalvar *var)
+{
+  struct type *type;
+  struct gdbarch *gdbarch;
+
+  if (target_has_stack
+      && !ptid_equal (inferior_ptid, null_ptid))
+    {
+      gdbarch = get_frame_arch (get_current_frame ());
+
+      if (gdbarch_get_siginfo_type_p (gdbarch))
+	{
+	  type = gdbarch_get_siginfo_type (gdbarch);
+
+	  return allocate_computed_value (type, &siginfo_value_funcs, NULL);
+	}
+    }
+
+  return allocate_value (builtin_type_void);
+}
+
 \f
 /* Inferior thread state.
    These are details related to the inferior itself, and don't include
@@ -5467,4 +5548,10 @@ Options are 'forward' or 'reverse'."),
 
   observer_attach_thread_ptid_changed (infrun_thread_ptid_changed);
   observer_attach_thread_stop_requested (infrun_thread_stop_requested);
+
+  /* Explicitly create without lookup, since that tries to create a
+     value with a void typed value, and when we get here, gdbarch
+     isn't initialized yet.  At this point, we're quite sure there
+     isn't another convenience variable of the same name.  */
+  create_internalvar_type_lazy ("_siginfo", siginfo_make_value);
 }
Index: src/gdb/gdbtypes.h
===================================================================
--- src.orig/gdb/gdbtypes.h	2009-02-06 22:28:25.000000000 +0000
+++ src/gdb/gdbtypes.h	2009-02-06 22:42:34.000000000 +0000
@@ -1112,6 +1112,10 @@ extern struct type *init_type (enum type
 extern struct type *init_composite_type (char *name, enum type_code code);
 extern void append_composite_type_field (struct type *t, char *name,
 					 struct type *field);
+extern void append_composite_type_field_aligned (struct type *t,
+						 char *name,
+						 struct type *field,
+						 int alignment);
 
 /* Helper functions to construct a bit flags type.  An initially empty
    type is created using init_flag_type().  Flags are then added using
Index: src/gdb/gdbtypes.c
===================================================================
--- src.orig/gdb/gdbtypes.c	2009-02-06 22:28:25.000000000 +0000
+++ src/gdb/gdbtypes.c	2009-02-06 22:42:34.000000000 +0000
@@ -1822,8 +1822,8 @@ init_composite_type (char *name, enum ty
 /* Helper function.  Append a field to a composite type.  */
 
 void
-append_composite_type_field (struct type *t, char *name, 
-			     struct type *field)
+append_composite_type_field_aligned (struct type *t, char *name,
+				     struct type *field, int alignment)
 {
   struct field *f;
   TYPE_NFIELDS (t) = TYPE_NFIELDS (t) + 1;
@@ -1842,12 +1842,31 @@ append_composite_type_field (struct type
     {
       TYPE_LENGTH (t) = TYPE_LENGTH (t) + TYPE_LENGTH (field);
       if (TYPE_NFIELDS (t) > 1)
-	FIELD_BITPOS (f[0]) = (FIELD_BITPOS (f[-1])
-			       + (TYPE_LENGTH (FIELD_TYPE (f[-1]))
-				  * TARGET_CHAR_BIT));
+	{
+	  FIELD_BITPOS (f[0]) = (FIELD_BITPOS (f[-1])
+				 + (TYPE_LENGTH (FIELD_TYPE (f[-1]))
+				    * TARGET_CHAR_BIT));
+
+	  if (alignment)
+	    {
+	      int left = FIELD_BITPOS (f[0]) % (alignment * TARGET_CHAR_BIT);
+	      if (left)
+		{
+		  FIELD_BITPOS (f[0]) += left;
+		  TYPE_LENGTH (t) += left / TARGET_CHAR_BIT;
+		}
+	    }
+	}
     }
 }
 
+void
+append_composite_type_field (struct type *t, char *name,
+			     struct type *field)
+{
+  append_composite_type_field_aligned (t, name, field, 0);
+}
+
 int
 can_dereference (struct type *t)
 {
Index: src/gdb/value.h
===================================================================
--- src.orig/gdb/value.h	2009-02-06 22:42:33.000000000 +0000
+++ src/gdb/value.h	2009-02-06 22:42:34.000000000 +0000
@@ -305,11 +305,14 @@ extern struct value *coerce_array (struc
 /* Internal variables (variables for convenience of use of debugger)
    are recorded as a chain of these structures.  */
 
+typedef struct value * (*internalvar_make_value) (struct internalvar *);
+
 struct internalvar
 {
   struct internalvar *next;
   char *name;
   struct value *value;
+  internalvar_make_value make_value;
   int endian;
 };
 
@@ -534,6 +537,9 @@ extern struct internalvar *lookup_only_i
 
 extern struct internalvar *create_internalvar (char *name);
 
+extern struct internalvar *
+  create_internalvar_type_lazy (char *name, internalvar_make_value fun);
+
 extern struct internalvar *lookup_internalvar (char *name);
 
 extern int value_equal (struct value *arg1, struct value *arg2);
Index: src/gdb/value.c
===================================================================
--- src.orig/gdb/value.c	2009-02-06 22:42:33.000000000 +0000
+++ src/gdb/value.c	2009-02-06 22:42:34.000000000 +0000
@@ -901,12 +901,31 @@ create_internalvar (char *name)
   var->name = concat (name, (char *)NULL);
   var->value = allocate_value (builtin_type_void);
   var->endian = gdbarch_byte_order (current_gdbarch);
+  var->make_value = NULL;
   release_value (var->value);
   var->next = internalvars;
   internalvars = var;
   return var;
 }
 
+/* Create an internal variable with name NAME and register FUN as the
+   function that value_of_internalvar uses to create a value whenever
+   this variable is referenced.  NAME should not normally include a
+   dollar sign.  */
+
+struct internalvar *
+create_internalvar_type_lazy (char *name, internalvar_make_value fun)
+{
+  struct internalvar *var;
+  var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
+  var->name = concat (name, (char *)NULL);
+  var->value = NULL;
+  var->make_value = fun;
+  var->endian = gdbarch_byte_order (current_gdbarch);
+  var->next = internalvars;
+  internalvars = var;
+  return var;
+}
 
 /* Look up an internal variable with name NAME.  NAME should not
    normally include a dollar sign.
@@ -933,25 +952,31 @@ value_of_internalvar (struct internalvar
   int i, j;
   gdb_byte temp;
 
-  val = value_copy (var->value);
-  if (value_lazy (val))
-    value_fetch_lazy (val);
-
-  /* If the variable's value is a computed lvalue, we want references
-     to it to produce another computed lvalue, where referencces and
-     assignments actually operate through the computed value's
-     functions.
-
-     This means that internal variables with computed values behave a
-     little differently from other internal variables: assignments to
-     them don't just replace the previous value altogether.  At the
-     moment, this seems like the behavior we want.  */
-  if (var->value->lval == lval_computed)
-    VALUE_LVAL (val) = lval_computed;
+  if (var->make_value != NULL)
+    val = (*var->make_value) (var);
   else
     {
-      VALUE_LVAL (val) = lval_internalvar;
-      VALUE_INTERNALVAR (val) = var;
+      val = value_copy (var->value);
+      if (value_lazy (val))
+	value_fetch_lazy (val);
+
+      /* If the variable's value is a computed lvalue, we want
+	 references to it to produce another computed lvalue, where
+	 referencces and assignments actually operate through the
+	 computed value's functions.
+
+	 This means that internal variables with computed values
+	 behave a little differently from other internal variables:
+	 assignments to them don't just replace the previous value
+	 altogether.  At the moment, this seems like the behavior we
+	 want.  */
+      if (var->value->lval == lval_computed)
+	VALUE_LVAL (val) = lval_computed;
+      else
+	{
+	  VALUE_LVAL (val) = lval_internalvar;
+	  VALUE_INTERNALVAR (val) = var;
+	}
     }
 
   /* Values are always stored in the target's byte order.  When connected to a
@@ -1075,7 +1100,8 @@ preserve_values (struct objfile *objfile
 	preserve_one_value (cur->values[i], objfile, copied_types);
 
   for (var = internalvars; var; var = var->next)
-    preserve_one_value (var->value, objfile, copied_types);
+    if (var->value)
+      preserve_one_value (var->value, objfile, copied_types);
 
   for (val = values_in_python; val; val = val->next)
     preserve_one_value (val, objfile, copied_types);
Index: src/gdb/gdbarch.sh
===================================================================
--- src.orig/gdb/gdbarch.sh	2009-02-06 22:28:25.000000000 +0000
+++ src/gdb/gdbarch.sh	2009-02-06 22:42:34.000000000 +0000
@@ -705,6 +705,11 @@ m:enum target_signal:target_signal_from_
 # signal number.
 m:int:target_signal_to_host:enum target_signal ts:ts::default_target_signal_to_host::0
 
+# Extra signal info inspection.
+#
+# Return a type suitable to inspect extra signal information.
+M:struct type *:get_siginfo_type:void:
+
 # Record architecture-specific information from the symbol table.
 M:void:record_special_symbol:struct objfile *objfile, asymbol *sym:objfile, sym
 
Index: src/gdb/gdbarch.h
===================================================================
--- src.orig/gdb/gdbarch.h	2009-02-06 22:28:25.000000000 +0000
+++ src/gdb/gdbarch.h	2009-02-06 22:42:34.000000000 +0000
@@ -803,6 +803,16 @@ typedef int (gdbarch_target_signal_to_ho
 extern int gdbarch_target_signal_to_host (struct gdbarch *gdbarch, enum target_signal ts);
 extern void set_gdbarch_target_signal_to_host (struct gdbarch *gdbarch, gdbarch_target_signal_to_host_ftype *target_signal_to_host);
 
+/* Extra signal info inspection.
+
+   Return a type suitable to inspect extra signal information. */
+
+extern int gdbarch_get_siginfo_type_p (struct gdbarch *gdbarch);
+
+typedef struct type * (gdbarch_get_siginfo_type_ftype) (struct gdbarch *gdbarch);
+extern struct type * gdbarch_get_siginfo_type (struct gdbarch *gdbarch);
+extern void set_gdbarch_get_siginfo_type (struct gdbarch *gdbarch, gdbarch_get_siginfo_type_ftype *get_siginfo_type);
+
 /* Record architecture-specific information from the symbol table. */
 
 extern int gdbarch_record_special_symbol_p (struct gdbarch *gdbarch);
Index: src/gdb/gdbarch.c
===================================================================
--- src.orig/gdb/gdbarch.c	2009-02-06 22:28:25.000000000 +0000
+++ src/gdb/gdbarch.c	2009-02-06 22:42:34.000000000 +0000
@@ -239,6 +239,7 @@ struct gdbarch
   int sofun_address_maybe_missing;
   gdbarch_target_signal_from_host_ftype *target_signal_from_host;
   gdbarch_target_signal_to_host_ftype *target_signal_to_host;
+  gdbarch_get_siginfo_type_ftype *get_siginfo_type;
   gdbarch_record_special_symbol_ftype *record_special_symbol;
   int has_global_solist;
 };
@@ -371,6 +372,7 @@ struct gdbarch startup_gdbarch =
   0,  /* sofun_address_maybe_missing */
   default_target_signal_from_host,  /* target_signal_from_host */
   default_target_signal_to_host,  /* target_signal_to_host */
+  0,  /* get_siginfo_type */
   0,  /* record_special_symbol */
   0,  /* has_global_solist */
   /* startup_gdbarch() */
@@ -624,6 +626,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of sofun_address_maybe_missing, invalid_p == 0 */
   /* Skip verify of target_signal_from_host, invalid_p == 0 */
   /* Skip verify of target_signal_to_host, invalid_p == 0 */
+  /* Skip verify of get_siginfo_type, has predicate */
   /* Skip verify of record_special_symbol, has predicate */
   /* Skip verify of has_global_solist, invalid_p == 0 */
   buf = ui_file_xstrdup (log, &dummy);
@@ -835,6 +838,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s
                       "gdbarch_dump: get_longjmp_target = <%s>\n",
                       host_address_to_string (gdbarch->get_longjmp_target));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_get_siginfo_type_p() = %d\n",
+                      gdbarch_get_siginfo_type_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: get_siginfo_type = <0x%lx>\n",
+                      (long) gdbarch->get_siginfo_type);
+  fprintf_unfiltered (file,
                       "gdbarch_dump: has_global_solist = %s\n",
                       plongest (gdbarch->has_global_solist));
   fprintf_unfiltered (file,
@@ -3220,6 +3229,30 @@ set_gdbarch_target_signal_to_host (struc
 }
 
 int
+gdbarch_get_siginfo_type_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->get_siginfo_type != NULL;
+}
+
+struct type *
+gdbarch_get_siginfo_type (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->get_siginfo_type != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_get_siginfo_type called\n");
+  return gdbarch->get_siginfo_type (gdbarch);
+}
+
+void
+set_gdbarch_get_siginfo_type (struct gdbarch *gdbarch,
+                              gdbarch_get_siginfo_type_ftype get_siginfo_type)
+{
+  gdbarch->get_siginfo_type = get_siginfo_type;
+}
+
+int
 gdbarch_record_special_symbol_p (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
Index: src/gdb/linux-tdep.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/linux-tdep.h	2009-02-06 22:42:35.000000000 +0000
@@ -0,0 +1,25 @@
+/* Target-dependent code for GNU/Linux, architecture independent.
+
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef LINUX_TDEP_H
+#define LINUX_TDEP_H
+
+struct type *linux_get_siginfo_type (struct gdbarch *);
+
+#endif /* linux-tdep.h */
Index: src/gdb/linux-tdep.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/linux-tdep.c	2009-02-06 22:42:35.000000000 +0000
@@ -0,0 +1,138 @@
+/* Target-dependent code for GNU/Linux, architecture independent.
+
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdbtypes.h"
+
+/* This function is suitable for architectures that don't
+   extend/override the standard siginfo structure.  */
+
+struct type *
+linux_get_siginfo_type (struct gdbarch *gdbarch)
+{
+  struct type *int_type, *uint_type, *long_type, *void_ptr_type;
+  struct type *uid_type, *pid_type;
+  struct type *sigval_type, *clock_type;
+  struct type *siginfo_type, *sifields_type;
+  struct type *type;
+
+  int_type = init_type (TYPE_CODE_INT,
+			gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT,
+			0, "int", NULL);
+  uint_type = init_type (TYPE_CODE_INT,
+			 gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT,
+			 0, "unsigned int", NULL);
+  long_type = init_type (TYPE_CODE_INT,
+			 gdbarch_long_bit (gdbarch) / HOST_CHAR_BIT,
+			 0, "long", NULL);
+  void_ptr_type = lookup_pointer_type (builtin_type (gdbarch)->builtin_void);
+
+  /* sival_t */
+  sigval_type = init_composite_type (NULL, TYPE_CODE_UNION);
+  TYPE_NAME (sigval_type) = xstrdup ("sigval_t");
+  append_composite_type_field (sigval_type, "sival_int", int_type);
+  append_composite_type_field (sigval_type, "sival_ptr", void_ptr_type);
+
+  /* __pid_t */
+  pid_type = init_type (TYPE_CODE_TYPEDEF, TYPE_LENGTH (int_type),
+			TYPE_FLAG_TARGET_STUB, NULL, NULL);
+  TYPE_NAME (pid_type) = xstrdup ("__pid_t");
+  TYPE_TARGET_TYPE (pid_type) = int_type;
+
+  /* __uid_t */
+  uid_type = init_type (TYPE_CODE_TYPEDEF, TYPE_LENGTH (uint_type),
+			TYPE_FLAG_TARGET_STUB, NULL, NULL);
+  TYPE_NAME (uid_type) = xstrdup ("__uid_t");
+  TYPE_TARGET_TYPE (uid_type) = uint_type;
+
+  /* __clock_t */
+  clock_type = init_type (TYPE_CODE_TYPEDEF, TYPE_LENGTH (long_type),
+			  TYPE_FLAG_TARGET_STUB, NULL, NULL);
+  TYPE_NAME (clock_type) = xstrdup ("__clock_t");
+  TYPE_TARGET_TYPE (clock_type) = long_type;
+
+  /* _sifields */
+  sifields_type = init_composite_type (NULL, TYPE_CODE_UNION);
+
+  {
+    const int si_max_size = 128;
+    int si_pad_size;
+    int size_of_int = gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT;
+
+    /* _pad */
+    if (gdbarch_ptr_bit (gdbarch) == 64)
+      si_pad_size = (si_max_size / size_of_int) - 4;
+    else
+      si_pad_size = (si_max_size / size_of_int) - 3;
+    append_composite_type_field (sifields_type, "_pad",
+				 init_vector_type (int_type, si_pad_size));
+  }
+
+  /* _kill */
+  type = init_composite_type (NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (type, "si_pid", pid_type);
+  append_composite_type_field (type, "si_uid", uid_type);
+  append_composite_type_field (sifields_type, "_kill", type);
+
+  /* _timer */
+  type = init_composite_type (NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (type, "si_tid", int_type);
+  append_composite_type_field (type, "si_overrun", int_type);
+  append_composite_type_field (type, "si_sigval", sigval_type);
+  append_composite_type_field (sifields_type, "_timer", type);
+
+  /* _rt */
+  type = init_composite_type (NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (type, "si_pid", pid_type);
+  append_composite_type_field (type, "si_uid", uid_type);
+  append_composite_type_field (type, "si_sigval", sigval_type);
+  append_composite_type_field (sifields_type, "_rt", type);
+
+  /* _sigchld */
+  type = init_composite_type (NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (type, "si_pid", pid_type);
+  append_composite_type_field (type, "si_uid", uid_type);
+  append_composite_type_field (type, "si_status", int_type);
+  append_composite_type_field (type, "si_utime", clock_type);
+  append_composite_type_field (type, "si_stime", clock_type);
+  append_composite_type_field (sifields_type, "_sigchld", type);
+
+  /* _sigfault */
+  type = init_composite_type (NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (type, "si_addr", void_ptr_type);
+  append_composite_type_field (sifields_type, "_sigfault", type);
+
+  /* _sigpoll */
+  type = init_composite_type (NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (type, "si_band", long_type);
+  append_composite_type_field (type, "si_fd", int_type);
+  append_composite_type_field (sifields_type, "_sigpoll", type);
+
+  /* struct siginfo */
+  siginfo_type = init_composite_type (NULL, TYPE_CODE_STRUCT);
+  TYPE_NAME (siginfo_type) = xstrdup ("siginfo");
+  append_composite_type_field (siginfo_type, "si_signo", int_type);
+  append_composite_type_field (siginfo_type, "si_errno", int_type);
+  append_composite_type_field (siginfo_type, "si_code", int_type);
+  append_composite_type_field_aligned (siginfo_type,
+				       "_sifields", sifields_type,
+				       TYPE_LENGTH (long_type));
+
+  return siginfo_type;
+}
Index: src/gdb/amd64-linux-tdep.c
===================================================================
--- src.orig/gdb/amd64-linux-tdep.c	2009-02-06 22:28:26.000000000 +0000
+++ src/gdb/amd64-linux-tdep.c	2009-02-06 22:42:35.000000000 +0000
@@ -29,6 +29,7 @@
 #include "gdbtypes.h"
 #include "reggroups.h"
 #include "amd64-linux-tdep.h"
+#include "linux-tdep.h"
 
 #include "gdb_string.h"
 
@@ -296,6 +297,8 @@ amd64_linux_init_abi (struct gdbarch_inf
                                            simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch,
                                        displaced_step_at_entry_point);
+
+  set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
 }
 \f
 
Index: src/gdb/i386-linux-tdep.c
===================================================================
--- src.orig/gdb/i386-linux-tdep.c	2009-02-06 22:28:25.000000000 +0000
+++ src/gdb/i386-linux-tdep.c	2009-02-06 22:42:35.000000000 +0000
@@ -31,6 +31,7 @@
 
 #include "i386-tdep.h"
 #include "i386-linux-tdep.h"
+#include "linux-tdep.h"
 #include "glibc-tdep.h"
 #include "solib-svr4.h"
 #include "symtab.h"
@@ -469,6 +470,8 @@ i386_linux_init_abi (struct gdbarch_info
                                            simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch,
                                        displaced_step_at_entry_point);
+
+  set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
Index: src/gdb/arm-linux-tdep.c
===================================================================
--- src.orig/gdb/arm-linux-tdep.c	2009-02-06 22:28:26.000000000 +0000
+++ src/gdb/arm-linux-tdep.c	2009-02-06 22:42:35.000000000 +0000
@@ -36,6 +36,7 @@
 
 #include "arm-tdep.h"
 #include "arm-linux-tdep.h"
+#include "linux-tdep.h"
 #include "glibc-tdep.h"
 
 #include "gdb_string.h"
@@ -647,6 +648,8 @@ arm_linux_init_abi (struct gdbarch_info 
   /* Core file support.  */
   set_gdbarch_regset_from_core_section (gdbarch,
 					arm_linux_regset_from_core_section);
+
+  set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
 }
 
 void
Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c	2009-02-06 22:36:43.000000000 +0000
+++ src/gdb/linux-nat.c	2009-02-06 22:42:35.000000000 +0000
@@ -3224,14 +3224,62 @@ linux_nat_mourn_inferior (struct target_
 }
 
 static LONGEST
+linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
+                    const char *annex, gdb_byte *readbuf,
+		    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+{
+  struct lwp_info *lp;
+  LONGEST n;
+  int pid;
+  struct siginfo siginfo;
+
+  gdb_assert (object == TARGET_OBJECT_SIGNAL_INFO);
+  gdb_assert (readbuf || writebuf);
+
+  pid = GET_LWP (inferior_ptid);
+  if (pid == 0)
+    pid = GET_PID (inferior_ptid);
+
+  if (offset > sizeof (siginfo))
+    return -1;
+
+  errno = 0;
+  ptrace (PTRACE_GETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, &siginfo);
+  if (errno != 0)
+    return -1;
+
+  if (offset + len > sizeof (siginfo))
+    len = sizeof (siginfo) - offset;
+
+  if (readbuf != NULL)
+    memcpy (readbuf, (char *)&siginfo + offset, len);
+  else
+    {
+      memcpy ((char *)&siginfo + offset, writebuf, len);
+      errno = 0;
+      ptrace (PTRACE_SETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, &siginfo);
+      if (errno != 0)
+	return -1;
+    }
+
+  return len;
+}
+
+static LONGEST
 linux_nat_xfer_partial (struct target_ops *ops, enum target_object object,
 			const char *annex, gdb_byte *readbuf,
 			const gdb_byte *writebuf,
 			ULONGEST offset, LONGEST len)
 {
-  struct cleanup *old_chain = save_inferior_ptid ();
+  struct cleanup *old_chain;
   LONGEST xfer;
 
+  if (object == TARGET_OBJECT_SIGNAL_INFO)
+    return linux_xfer_siginfo (ops, object, annex, readbuf, writebuf,
+			       offset, len);
+
+  old_chain = save_inferior_ptid ();
+
   if (is_lwp (inferior_ptid))
     inferior_ptid = pid_to_ptid (GET_LWP (inferior_ptid));
 
Index: src/gdb/remote.c
===================================================================
--- src.orig/gdb/remote.c	2009-02-06 22:36:43.000000000 +0000
+++ src/gdb/remote.c	2009-02-06 22:42:35.000000000 +0000
@@ -998,6 +998,8 @@ enum {
   PACKET_vRun,
   PACKET_QStartNoAckMode,
   PACKET_vKill,
+  PACKET_qXfer_siginfo_read,
+  PACKET_qXfer_siginfo_write,
   PACKET_MAX
 };
 
@@ -2962,6 +2964,10 @@ static struct protocol_feature remote_pr
     PACKET_QStartNoAckMode },
   { "multiprocess", PACKET_DISABLE, remote_multi_process_feature, -1 },
   { "QNonStop", PACKET_DISABLE, remote_non_stop_feature, -1 },
+  { "qXfer:siginfo:read", PACKET_DISABLE, remote_supported_packet,
+    PACKET_qXfer_siginfo_read },
+  { "qXfer:siginfo:write", PACKET_DISABLE, remote_supported_packet,
+    PACKET_qXfer_siginfo_write },
 };
 
 static void
@@ -7323,6 +7329,19 @@ remote_xfer_partial (struct target_ops *
 				     [PACKET_qXfer_spu_write]);
     }
 
+  /* Handle extra signal info using qxfer packets.  */
+  if (object == TARGET_OBJECT_SIGNAL_INFO)
+    {
+      if (readbuf)
+	return remote_read_qxfer (ops, "siginfo", annex, readbuf, offset, len,
+				  &remote_protocol_packets
+				  [PACKET_qXfer_siginfo_read]);
+      else
+	return remote_write_qxfer (ops, "siginfo", annex, writebuf, offset, len,
+				   &remote_protocol_packets
+				   [PACKET_qXfer_siginfo_write]);
+    }
+
   /* Only handle flash writes.  */
   if (writebuf != NULL)
     {
@@ -9070,6 +9089,12 @@ Show the maximum size of the address (in
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_osdata],
                         "qXfer:osdata:read", "osdata", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_siginfo_read],
+                         "qXfer:siginfo:read", "read-siginfo-object", 0);
+
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_siginfo_write],
+                         "qXfer:siginfo:write", "write-siginfo-object", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qGetTLSAddr],
 			 "qGetTLSAddr", "get-thread-local-storage-address",
 			 0);
Index: src/gdb/Makefile.in
===================================================================
--- src.orig/gdb/Makefile.in	2009-02-06 22:36:42.000000000 +0000
+++ src/gdb/Makefile.in	2009-02-06 22:42:35.000000000 +0000
@@ -483,6 +483,7 @@ ALL_TARGET_OBS = \
 	i386-sol2-tdep.o i386-tdep.o i387-tdep.o \
 	i386-dicos-tdep.o \
 	iq2000-tdep.o \
+	linux-tdep.o \
 	m32c-tdep.o \
 	m32r-linux-tdep.o m32r-tdep.o \
 	m68hc11-tdep.o \
@@ -730,7 +731,7 @@ config/sparc/nm-sol2.h config/nm-linux.h
 config/rs6000/nm-rs6000.h top.h bsd-kvm.h gdb-stabs.h reggroups.h \
 annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h	\
 remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \
-sentinel-frame.h bcache.h symfile.h windows-tdep.h
+sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -1301,6 +1302,7 @@ ALLDEPFILES = \
 	irix5-nat.c \
 	libunwind-frame.c \
 	linux-fork.c \
+	linux-tdep.c \
 	m68hc11-tdep.c \
 	m32r-tdep.c \
 	m32r-linux-nat.c m32r-linux-tdep.c \
Index: src/gdb/configure.tgt
===================================================================
--- src.orig/gdb/configure.tgt	2009-02-06 22:28:26.000000000 +0000
+++ src/gdb/configure.tgt	2009-02-06 22:42:35.000000000 +0000
@@ -75,7 +75,7 @@ arm*-wince-pe | arm*-*-mingw32ce*)
 arm*-*-linux*)
 	# Target: ARM based machine running GNU/Linux
 	gdb_target_obs="arm-tdep.o arm-linux-tdep.o glibc-tdep.o \
-			solib.o solib-svr4.o symfile-mem.o corelow.o"
+			solib.o solib-svr4.o symfile-mem.o corelow.o linux-tdep.o"
 	build_gdbserver=yes
 	;;
 arm*-*-netbsd* | arm*-*-knetbsd*-gnu)
@@ -190,7 +190,7 @@ i[34567]86-*-solaris*)
 i[34567]86-*-linux*)
 	# Target: Intel 386 running GNU/Linux
 	gdb_target_obs="i386-tdep.o i386-linux-tdep.o glibc-tdep.o i387-tdep.o \
-			solib.o solib-svr4.o symfile-mem.o corelow.o"
+			solib.o solib-svr4.o symfile-mem.o corelow.o linux-tdep.o"
 	build_gdbserver=yes
 	;;
 i[34567]86-*-gnu*)
@@ -513,7 +513,7 @@ x86_64-*-linux*)
 	# Target: GNU/Linux x86-64
 	gdb_target_obs="amd64-tdep.o amd64-linux-tdep.o i386-tdep.o \
 			i387-tdep.o i386-linux-tdep.o glibc-tdep.o \
-			solib.o solib-svr4.o corelow.o symfile-mem.o"
+			solib.o solib-svr4.o corelow.o symfile-mem.o linux-tdep.o"
 	build_gdbserver=yes
 	;;
 x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu)
Index: src/gdb/gdbserver/server.c
===================================================================
--- src.orig/gdb/gdbserver/server.c	2009-02-06 22:28:25.000000000 +0000
+++ src/gdb/gdbserver/server.c	2009-02-06 22:42:35.000000000 +0000
@@ -810,6 +810,77 @@ handle_query (char *own_buf, int packet_
       return;
     }
 
+  if (the_target->qxfer_siginfo != NULL
+      && strncmp ("qXfer:siginfo:read:", own_buf, 19) == 0)
+    {
+      unsigned char *data;
+      int n;
+      CORE_ADDR ofs;
+      unsigned int len;
+      char *annex;
+
+      require_running (own_buf);
+
+      /* Reject any annex; grab the offset and length.  */
+      if (decode_xfer_read (own_buf + 19, &annex, &ofs, &len) < 0
+	  || annex[0] != '\0')
+	{
+	  strcpy (own_buf, "E00");
+	  return;
+	}
+
+      /* Read one extra byte, as an indicator of whether there is
+	 more.  */
+      if (len > PBUFSIZ - 2)
+	len = PBUFSIZ - 2;
+      data = malloc (len + 1);
+      if (!data)
+        return;
+      n = (*the_target->qxfer_siginfo) (annex, data, NULL, ofs, len + 1);
+      if (n < 0)
+	write_enn (own_buf);
+      else if (n > len)
+	*new_packet_len_p = write_qxfer_response (own_buf, data, len, 1);
+      else
+	*new_packet_len_p = write_qxfer_response (own_buf, data, n, 0);
+
+      free (data);
+      return;
+    }
+
+  if (the_target->qxfer_siginfo != NULL
+      && strncmp ("qXfer:siginfo:write:", own_buf, 20) == 0)
+    {
+      char *annex;
+      int n;
+      unsigned int len;
+      CORE_ADDR ofs;
+      unsigned char *data;
+
+      require_running (own_buf);
+
+      strcpy (own_buf, "E00");
+      data = malloc (packet_len - 19);
+      if (!data)
+        return;
+      if (decode_xfer_write (own_buf + 20, packet_len - 20, &annex,
+			     &ofs, &len, data) < 0)
+	{
+	  free (data);
+	  return;
+	}
+
+      n = (*the_target->qxfer_siginfo)
+	(annex, NULL, (unsigned const char *)data, ofs, len);
+      if (n < 0)
+	write_enn (own_buf);
+      else
+	sprintf (own_buf, "%x", n);
+
+      free (data);
+      return;
+    }
+
   /* Protocol features query.  */
   if (strncmp ("qSupported", own_buf, 10) == 0
       && (own_buf[10] == ':' || own_buf[10] == '\0'))
@@ -826,6 +897,9 @@ handle_query (char *own_buf, int packet_
       if (the_target->qxfer_spu != NULL)
 	strcat (own_buf, ";qXfer:spu:read+;qXfer:spu:write+");
 
+      if (the_target->qxfer_siginfo != NULL)
+	strcat (own_buf, ";qXfer:siginfo:read+;qXfer:siginfo:write+");
+
       /* We always report qXfer:features:read, as targets may
 	 install XML files on a subsequent call to arch_setup.
 	 If we reported to GDB on startup that we don't support
Index: src/gdb/gdbserver/target.h
===================================================================
--- src.orig/gdb/gdbserver/target.h	2009-02-06 22:28:25.000000000 +0000
+++ src/gdb/gdbserver/target.h	2009-02-06 22:42:35.000000000 +0000
@@ -193,6 +193,11 @@ struct target_ops
   int (*qxfer_osdata) (const char *annex, unsigned char *readbuf,
 		       unsigned const char *writebuf, CORE_ADDR offset, 
 		       int len);
+
+  /* Read/Write extra signal info.  */
+  int (*qxfer_siginfo) (const char *annex, unsigned char *readbuf,
+			unsigned const char *writebuf,
+			CORE_ADDR offset, int len);
 };
 
 extern struct target_ops *the_target;
Index: src/gdb/gdbserver/linux-low.c
===================================================================
--- src.orig/gdb/gdbserver/linux-low.c	2009-02-06 22:28:25.000000000 +0000
+++ src/gdb/gdbserver/linux-low.c	2009-02-06 22:42:35.000000000 +0000
@@ -2180,6 +2180,44 @@ linux_qxfer_osdata (const char *annex,
   return len;
 }
 
+static int
+linux_xfer_siginfo (const char *annex, unsigned char *readbuf,
+		    unsigned const char *writebuf, CORE_ADDR offset, int len)
+{
+  struct siginfo siginfo;
+  long pid = -1;
+
+  if (current_inferior == NULL)
+    return -1;
+
+  pid = pid_of (get_thread_process (current_inferior));
+
+  if (debug_threads)
+    fprintf (stderr, "%s siginfo for lwp %ld.\n",
+	     readbuf != NULL ? "Reading" : "Writing",
+	     pid);
+
+  if (offset > sizeof (siginfo))
+    return -1;
+
+  if (ptrace (PTRACE_GETSIGINFO, pid, 0, &siginfo) != 0)
+    return -1;
+
+  if (offset + len > sizeof (siginfo))
+    len = sizeof (siginfo) - offset;
+
+  if (readbuf != NULL)
+    memcpy (readbuf, (char *) &siginfo + offset, len);
+  else
+    {
+      memcpy ((char *) &siginfo + offset, writebuf, len);
+      if (ptrace (PTRACE_SETSIGINFO, pid, 0, &siginfo) != 0)
+	return -1;
+    }
+
+  return len;
+}
+
 static struct target_ops linux_target_ops = {
   linux_create_inferior,
   linux_attach,
@@ -2213,6 +2251,7 @@ static struct target_ops linux_target_op
   NULL,
   hostio_last_error_from_errno,
   linux_qxfer_osdata,
+  linux_xfer_siginfo,
 };
 
 static void
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo	2009-02-06 22:36:45.000000000 +0000
+++ src/gdb/doc/gdb.texinfo	2009-02-06 22:42:35.000000000 +0000
@@ -4472,6 +4472,55 @@ a result of the fatal signal once it saw
 you can continue with @samp{signal 0}.  @xref{Signaling, ,Giving your
 Program a Signal}.
 
+@cindex extra signal information
+@anchor{extra signal information}
+
+On some targets, @value{GDBN} can inspect extra signal information
+associated with the intercepted signal, before it is actually
+delivered to the program being debugged.  This information is exported
+by the convenience variable @code{$_siginfo}, and consists of data
+that is passed by the kernel to the signal handler at the time of the
+receipt of a signal.  The data type of the information itself is
+target dependent.  You can see the data type using the @code{ptype
+$_siginfo} command.  On Unix systems, it typically corresponds to the
+standard @code{siginfo_t} type, as defined in the @file{signal.h}
+system header.
+
+Here's an example, on a @sc{gnu}/Linux system, printing the stray
+referenced address that raised a segmentation fault.
+
+@smallexample
+@group
+(@value{GDBP}) continue
+Program received signal SIGSEGV, Segmentation fault.
+0x0000000000400766 in main ()
+69        *(int *)p = 0;
+(@value{GDBP}) ptype $_siginfo
+type = struct @{
+    int si_signo;
+    int si_errno;
+    int si_code;
+    union @{
+        int _pad[28];
+        struct @{...@} _kill;
+        struct @{...@} _timer;
+        struct @{...@} _rt;
+        struct @{...@} _sigchld;
+        struct @{...@} _sigfault;
+        struct @{...@} _sigpoll;
+    @} _sifields;
+@}
+(@value{GDBP}) ptype $_siginfo._sifields._sigfault
+type = struct @{
+    void *si_addr;
+@}
+(@value{GDBP}) p $_siginfo._sifields._sigfault.si_addr
+$1 = (void *) 0x7ffff7ff7000
+@end group
+@end smallexample
+
+Depending on target support, @code{$_siginfo} may also be writable.
+
 @node Thread Stops
 @section Stopping and Starting Multi-thread Programs
 
@@ -7348,6 +7397,11 @@ to match the format in which the data wa
 @vindex $_exitcode@r{, convenience variable}
 The variable @code{$_exitcode} is automatically set to the exit code when
 the program being debugged terminates.
+
+@item $_siginfo
+@vindex $_siginfo@r{, convenience variable}
+The variable @code{$_siginfo} is bound to extra signal information
+inspection (@pxref{extra signal information}).
 @end table
 
 On HP-UX systems, if you refer to a function or variable name that
@@ -14307,6 +14361,14 @@ are:
 @tab @code{qXfer:spu:write}
 @tab @code{info spu}
 
+@item @code{read-siginfo-object}
+@tab @code{qXfer:siginfo:read}
+@tab @code{print $_siginfo}
+
+@item @code{write-siginfo-object}
+@tab @code{qXfer:siginfo:write}
+@tab @code{set $_siginfo}
+
 @item @code{get-thread-local-@*storage-address}
 @tab @code{qGetTLSAddr}
 @tab Displaying @code{__thread} variables
@@ -26879,6 +26941,16 @@ These are the currently defined stub fea
 @tab @samp{-}
 @tab Yes
 
+@item @samp{qXfer:siginfo:read}
+@tab No
+@tab @samp{-}
+@tab Yes
+
+@item @samp{qXfer:siginfo:write}
+@tab No
+@tab @samp{-}
+@tab Yes
+
 @item @samp{QNonStop}
 @tab No
 @tab @samp{-}
@@ -26939,6 +27011,14 @@ The remote stub understands the @samp{qX
 The remote stub understands the @samp{qXfer:spu:write} packet
 (@pxref{qXfer spu write}).
 
+@item qXfer:siginfo:read
+The remote stub understands the @samp{qXfer:siginfo:read} packet
+(@pxref{qXfer siginfo read}).
+
+@item qXfer:siginfo:write
+The remote stub understands the @samp{qXfer:siginfo:write} packet
+(@pxref{qXfer siginfo write}).
+
 @item QNonStop
 The remote stub understands the @samp{QNonStop} packet
 (@pxref{QNonStop}).
@@ -27097,6 +27177,16 @@ annex part of the generic @samp{qXfer} p
 This packet is not probed by default; the remote stub must request it,
 by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
 
+@item qXfer:siginfo:read::@var{offset},@var{length}
+@anchor{qXfer siginfo read}
+Read contents of the extra signal information on the target
+system.  The annex part of the generic @samp{qXfer} packet must be
+empty (@pxref{qXfer read}).
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response
+(@pxref{qSupported}).
+
 @item qXfer:spu:read:@var{annex}:@var{offset},@var{length}
 @anchor{qXfer spu read}
 Read contents of an @code{spufs} file on the target system.  The
@@ -27149,6 +27239,7 @@ the stub, or that the object does not su
 
 @item qXfer:@var{object}:write:@var{annex}:@var{offset}:@var{data}@dots{}
 @cindex write data into object, remote request
+@anchor{qXfer write}
 Write uninterpreted bytes into the target's special data area
 identified by the keyword @var{object}, starting at @var{offset} bytes
 into the data.  @var{data}@dots{} is the binary-encoded data
@@ -27161,6 +27252,16 @@ Here are the specific requests of this f
 formats, listed below.
 
 @table @samp
+@item qXfer:siginfo:write::@var{offset}:@var{data}@dots{}
+@anchor{qXfer siginfo write}
+Write @var{data} to the extra signal information on the target system.
+The annex part of the generic @samp{qXfer} packet must be
+empty (@pxref{qXfer write}).
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response
+(@pxref{qSupported}).
+
 @item qXfer:spu:write:@var{annex}:@var{offset}:@var{data}@dots{}
 @anchor{qXfer spu write}
 Write @var{data} to an @code{spufs} file on the target system.  The
Index: src/gdb/testsuite/gdb.base/siginfo-obj.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.base/siginfo-obj.c	2009-02-06 22:42:35.000000000 +0000
@@ -0,0 +1,70 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2004, 2007, 2008 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+static void *p;
+
+static void
+handler (int sig, siginfo_t *info, void *context)
+{
+  /* Copy to local vars, as the test wants to read them, and si_addr,
+     etc. may be preprocessor defines.  */
+  int ssi_errno = info->si_errno;
+  int ssi_signo = info->si_signo;
+  int ssi_code = info->si_code;
+  void *ssi_addr = info->si_addr;
+
+  _exit (0); /* set breakpoint here */
+}
+
+int
+main (void)
+{
+  /* Set up unwritable memory.  */
+  {
+    size_t len;
+    len = sysconf(_SC_PAGESIZE);
+    p = mmap (0, len, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+    if (p == MAP_FAILED)
+      {
+	perror ("mmap");
+	return 1;
+      }
+  }
+  /* Set up the signal handler.  */
+  {
+    struct sigaction action;
+    memset (&action, 0, sizeof (action));
+    action.sa_sigaction = handler;
+    action.sa_flags |= SA_SIGINFO;
+    if (sigaction (SIGSEGV, &action, NULL))
+      {
+	perror ("sigaction");
+	return 1;
+      }
+  }
+  /* Trigger SIGSEGV.  */
+  *(int *)p = 0;
+  return 0;
+}
Index: src/gdb/testsuite/gdb.base/siginfo-obj.exp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.base/siginfo-obj.exp	2009-02-06 22:42:35.000000000 +0000
@@ -0,0 +1,131 @@
+# Copyright 2004, 2007, 2008 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+# The program siginfo-obj.c arranges for a signal handler registered
+# using sigaction's sa_sigaction / SA_SIGINFO to be called with
+# si_addr filled in.
+
+# This test confirms that we can inspect signal info using the
+# $_siginfo convenience variable.
+
+if [target_info exists gdb,nosignals] {
+    verbose "Skipping siginfo-obj.exp because of nosignals."
+    continue
+}
+
+if { ! [istarget "i?86-*-linux*"]
+     && ! [istarget "x86_64-*-linux*"]
+     && ! [istarget "arm*-*-linux*"] } {
+    verbose "Skipping siginfo-obj.exp because of lack of support."
+    return
+}
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile siginfo-obj
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+    untested "Couldn't compile ${srcfile}.c"
+    return -1
+}
+
+# get things started
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Advance to main
+if { ![runto_main] } then {
+    gdb_suppress_tests;
+}
+
+# Run to the signal.
+gdb_test "continue" ".*Program received signal SIGSEGV.*" "continue to signal"
+
+set ssi_addr ""
+set test "Extract si_addr"
+gdb_test_multiple "p \$_siginfo" "$test" {
+    -re "si_addr = ($hex).*$gdb_prompt $" {
+	set ssi_addr $expect_out(1,string)
+	pass "$test"
+    }
+}
+
+set test "Extract si_errno"
+gdb_test_multiple "p \$_siginfo" "$test" {
+    -re "si_errno = (\[0-9\]\+).*$gdb_prompt $" {
+	set ssi_errno $expect_out(1,string)
+	pass "$test"
+    }
+}
+
+set test "Extract si_code"
+gdb_test_multiple "p \$_siginfo" "$test" {
+    -re "si_code = (\[0-9\]\+).*$gdb_prompt $" {
+	set ssi_code $expect_out(1,string)
+	pass "$test"
+    }
+}
+
+set test "Extract si_signo"
+gdb_test_multiple "p \$_siginfo" "$test" {
+    -re "si_signo = (\[0-9\]\+).*$gdb_prompt $" {
+	set ssi_signo $expect_out(1,string)
+	pass "$test"
+    }
+}
+
+set bp_location [gdb_get_line_number "set breakpoint here"]
+
+gdb_test "break $bp_location"
+gdb_test "continue" ".* handler .*" "continue to handler"
+
+gdb_test "p ssi_addr" " = \\(void \\*\\) $ssi_addr"
+gdb_test "p ssi_errno" " = $ssi_errno"
+gdb_test "p ssi_code" " = $ssi_code"
+gdb_test "p ssi_signo" " = $ssi_signo"
+
+# Again, but this time, patch si_addr and check that the inferior sees
+# the changed value.
+
+# Advance to main
+if { ![runto_main] } then {
+    gdb_suppress_tests;
+}
+
+# Run to the signal.
+gdb_test "continue" ".*Program received signal SIGSEGV.*" "continue to signal"
+
+set test "Set si_addr"
+gdb_test "p \$_siginfo._sifields._sigfault.si_addr = 0x666" " = \\(void \\*\\) 0x666"
+gdb_test "p \$_siginfo.si_errno = 666" " = 666"
+gdb_test "p \$_siginfo.si_code = 999" " = 999"
+gdb_test "p \$_siginfo.si_signo = 11" " = 11"
+
+gdb_test "break $bp_location"
+gdb_test "continue" ".* handler .*" "continue to handler"
+
+gdb_test "p ssi_addr" " = \\(void \\*\\) 0x666"
+gdb_test "p ssi_errno" " = 666"
+gdb_test "p ssi_code" " = 999"
+gdb_test "p ssi_signo" " = 11"


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [3/2] Inspect extra signal information, handle amd64 bi-arch gdb
  2009-02-04 21:17                   ` Daniel Jacobowitz
@ 2009-02-06 23:37                     ` Pedro Alves
  2009-02-07  2:28                       ` Paul Pluzhnikov
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-02-06 23:37 UTC (permalink / raw)
  To: gdb-patches

On Wednesday 04 February 2009 21:17:12, Daniel Jacobowitz wrote:
> Seems fine to me.

Thanks Daniel.  Here's the version I just checked in.

-- 
Pedro Alves

2009-02-06  Pedro Alves  <pedro@codesourcery.com>

	* amd64-linux-nat.c (compat_int_t, compat_uptr_t, compat_time_t)
	(compat_timer_t, compat_clock_t, struct compat_timeval)
	(compat_sigval_t, compat_siginfo_t): New types.
	(cpt_si_pid, cpt_si_uid, cpt_si_timerid, cpt_si_overrun)
	(cpt_si_status, cpt_si_utime, cpt_si_stime, cpt_si_ptr)
	(cpt_si_addr, cpt_si_band, cpt_si_fd): New defines.
	(compat_siginfo_from_siginfo, siginfo_from_compat_siginfo)
	(amd64_linux_siginfo_fixup): New.
	* linux-nat.c (linux_nat_siginfo_fixup): New.
	(siginfo_fixup): New.
	(linux_xfer_siginfo): Use siginfo_fixup to convert between the
	siginfo layout expected by ptrace and the siginfo layout of the
	inferior.
	(linux_nat_set_siginfo_fixup): New.
	* linux-nat.h (linux_nat_set_siginfo_fixup): Declare.

---
 gdb/amd64-linux-nat.c |  234 ++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/linux-nat.c       |   59 ++++++++++++
 gdb/linux-nat.h       |    8 +
 3 files changed, 299 insertions(+), 2 deletions(-)

Index: src/gdb/amd64-linux-nat.c
===================================================================
--- src.orig/gdb/amd64-linux-nat.c	2009-02-06 23:02:14.000000000 +0000
+++ src/gdb/amd64-linux-nat.c	2009-02-06 23:04:07.000000000 +0000
@@ -400,6 +400,239 @@ amd64_linux_child_post_startup_inferior 
 }
 \f
 
+/* When GDB is built as a 64-bit application on linux, the
+   PTRACE_GETSIGINFO data is always presented in 64-bit layout.  Since
+   debugging a 32-bit inferior with a 64-bit GDB should look the same
+   as debugging it with a 32-bit GDB, we do the 32-bit <-> 64-bit
+   conversion in-place ourselves.  */
+
+/* These types below (compat_*) define a siginfo type that is layout
+   compatible with the siginfo type exported by the 32-bit userspace
+   support.  */
+
+typedef int compat_int_t;
+typedef unsigned int compat_uptr_t;
+
+typedef int compat_time_t;
+typedef int compat_timer_t;
+typedef int compat_clock_t;
+
+struct compat_timeval
+{
+  compat_time_t tv_sec;
+  int tv_usec;
+};
+
+typedef union compat_sigval
+{
+  compat_int_t sival_int;
+  compat_uptr_t sival_ptr;
+} compat_sigval_t;
+
+typedef struct compat_siginfo
+{
+  int si_signo;
+  int si_errno;
+  int si_code;
+
+  union
+  {
+    int _pad[((128 / sizeof (int)) - 3)];
+
+    /* kill() */
+    struct
+    {
+      unsigned int _pid;
+      unsigned int _uid;
+    } _kill;
+
+    /* POSIX.1b timers */
+    struct
+    {
+      compat_timer_t _tid;
+      int _overrun;
+      compat_sigval_t _sigval;
+    } _timer;
+
+    /* POSIX.1b signals */
+    struct
+    {
+      unsigned int _pid;
+      unsigned int _uid;
+      compat_sigval_t _sigval;
+    } _rt;
+
+    /* SIGCHLD */
+    struct
+    {
+      unsigned int _pid;
+      unsigned int _uid;
+      int _status;
+      compat_clock_t _utime;
+      compat_clock_t _stime;
+    } _sigchld;
+
+    /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+    struct
+    {
+      unsigned int _addr;
+    } _sigfault;
+
+    /* SIGPOLL */
+    struct
+    {
+      int _band;
+      int _fd;
+    } _sigpoll;
+  } _sifields;
+} compat_siginfo_t;
+
+#define cpt_si_pid _sifields._kill._pid
+#define cpt_si_uid _sifields._kill._uid
+#define cpt_si_timerid _sifields._timer._tid
+#define cpt_si_overrun _sifields._timer._overrun
+#define cpt_si_status _sifields._sigchld._status
+#define cpt_si_utime _sifields._sigchld._utime
+#define cpt_si_stime _sifields._sigchld._stime
+#define cpt_si_ptr _sifields._rt._sigval.sival_ptr
+#define cpt_si_addr _sifields._sigfault._addr
+#define cpt_si_band _sifields._sigpoll._band
+#define cpt_si_fd _sifields._sigpoll._fd
+
+static void
+compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
+{
+  memset (to, 0, sizeof (*to));
+
+  to->si_signo = from->si_signo;
+  to->si_errno = from->si_errno;
+  to->si_code = from->si_code;
+
+  if (to->si_code < 0)
+    {
+      to->cpt_si_ptr = (intptr_t) from->si_ptr;
+    }
+  else if (to->si_code == SI_USER)
+    {
+      to->cpt_si_pid = from->si_pid;
+      to->cpt_si_uid = from->si_uid;
+    }
+  else if (to->si_code == SI_TIMER)
+    {
+      to->cpt_si_timerid = from->si_timerid;
+      to->cpt_si_overrun = from->si_overrun;
+      to->cpt_si_ptr = (intptr_t) from->si_ptr;
+    }
+  else
+    {
+      switch (to->si_signo)
+	{
+	case SIGCHLD:
+	  to->cpt_si_pid = from->si_pid;
+	  to->cpt_si_uid = from->si_uid;
+	  to->cpt_si_status = from->si_status;
+	  to->cpt_si_utime = from->si_utime;
+	  to->cpt_si_stime = from->si_stime;
+	  break;
+	case SIGILL:
+	case SIGFPE:
+	case SIGSEGV:
+	case SIGBUS:
+	  to->cpt_si_addr = (intptr_t) from->si_addr;
+	  break;
+	case SIGPOLL:
+	  to->cpt_si_band = from->si_band;
+	  to->cpt_si_fd = from->si_fd;
+	  break;
+	default:
+	  to->cpt_si_pid = from->si_pid;
+	  to->cpt_si_uid = from->si_uid;
+	  to->cpt_si_ptr = (intptr_t) from->si_ptr;
+	  break;
+	}
+    }
+}
+
+static void
+siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
+{
+  memset (to, 0, sizeof (*to));
+
+  to->si_signo = from->si_signo;
+  to->si_errno = from->si_errno;
+  to->si_code = from->si_code;
+
+  if (to->si_code < 0)
+    {
+      to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
+    }
+  else if (to->si_code == SI_USER)
+    {
+      to->si_pid = from->cpt_si_pid;
+      to->si_uid = from->cpt_si_uid;
+    }
+  else if (to->si_code == SI_TIMER)
+    {
+      to->si_timerid = from->cpt_si_timerid;
+      to->si_overrun = from->cpt_si_overrun;
+      to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
+    }
+  else
+    {
+      switch (to->si_signo)
+	{
+	case SIGCHLD:
+	  to->si_pid = from->cpt_si_pid;
+	  to->si_uid = from->cpt_si_uid;
+	  to->si_status = from->cpt_si_status;
+	  to->si_utime = from->cpt_si_utime;
+	  to->si_stime = from->cpt_si_stime;
+	  break;
+	case SIGILL:
+	case SIGFPE:
+	case SIGSEGV:
+	case SIGBUS:
+	  to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
+	  break;
+	case SIGPOLL:
+	  to->si_band = from->cpt_si_band;
+	  to->si_fd = from->cpt_si_fd;
+	  break;
+	default:
+	  to->si_pid = from->cpt_si_pid;
+	  to->si_uid = from->cpt_si_uid;
+	  to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
+	  break;
+	}
+    }
+}
+
+/* Convert a native/host siginfo object, into/from the siginfo in the
+   layout of the inferiors' architecture.  Returns true if any
+   conversion was done; false otherwise.  If DIRECTION is 1, then copy
+   from INF to NATIVE.  If DIRECTION is 0, copy from NATIVE to
+   INF.  */
+
+static int
+amd64_linux_siginfo_fixup (struct siginfo *native, gdb_byte *inf, int direction)
+{
+  /* Is the inferior 32-bit?  If so, then do fixup the siginfo
+     object.  */
+  if (gdbarch_addr_bit (get_frame_arch (get_current_frame ())) == 32)
+    {
+      gdb_assert (sizeof (struct siginfo) == sizeof (compat_siginfo_t));
+
+      if (direction == 0)
+	compat_siginfo_from_siginfo ((struct compat_siginfo *) inf, native);
+      else
+	siginfo_from_compat_siginfo (native, (struct compat_siginfo *) inf);
+
+      return 1;
+    }
+  else
+    return 0;
+}
+
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 void _initialize_amd64_linux_nat (void);
 
@@ -434,4 +667,5 @@ _initialize_amd64_linux_nat (void)
   /* Register the target.  */
   linux_nat_add_target (t);
   linux_nat_set_new_thread (t, amd64_linux_new_thread);
+  linux_nat_set_siginfo_fixup (t, amd64_linux_siginfo_fixup);
 }
Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c	2009-02-06 23:02:15.000000000 +0000
+++ src/gdb/linux-nat.c	2009-02-06 23:04:07.000000000 +0000
@@ -205,6 +205,13 @@ static struct target_ops linux_ops_saved
 /* The method to call, if any, when a new thread is attached.  */
 static void (*linux_nat_new_thread) (ptid_t);
 
+/* The method to call, if any, when the siginfo object needs to be
+   converted between the layout returned by ptrace, and the layout in
+   the architecture of the inferior.  */
+static int (*linux_nat_siginfo_fixup) (struct siginfo *,
+				       gdb_byte *,
+				       int);
+
 /* The saved to_xfer_partial method, inherited from inf-ptrace.c.
    Called by our to_xfer_partial.  */
 static LONGEST (*super_xfer_partial) (struct target_ops *, 
@@ -3223,6 +3230,28 @@ linux_nat_mourn_inferior (struct target_
     linux_fork_mourn_inferior ();
 }
 
+/* Convert a native/host siginfo object, into/from the siginfo in the
+   layout of the inferiors' architecture.  */
+
+static void
+siginfo_fixup (struct siginfo *siginfo, gdb_byte *inf_siginfo, int direction)
+{
+  int done = 0;
+
+  if (linux_nat_siginfo_fixup != NULL)
+    done = linux_nat_siginfo_fixup (siginfo, inf_siginfo, direction);
+
+  /* If there was no callback, or the callback didn't do anything,
+     then just do a straight memcpy.  */
+  if (!done)
+    {
+      if (direction == 1)
+	memcpy (siginfo, inf_siginfo, sizeof (struct siginfo));
+      else
+	memcpy (inf_siginfo, siginfo, sizeof (struct siginfo));
+    }
+}
+
 static LONGEST
 linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
                     const char *annex, gdb_byte *readbuf,
@@ -3232,6 +3261,7 @@ linux_xfer_siginfo (struct target_ops *o
   LONGEST n;
   int pid;
   struct siginfo siginfo;
+  gdb_byte inf_siginfo[sizeof (struct siginfo)];
 
   gdb_assert (object == TARGET_OBJECT_SIGNAL_INFO);
   gdb_assert (readbuf || writebuf);
@@ -3248,14 +3278,26 @@ linux_xfer_siginfo (struct target_ops *o
   if (errno != 0)
     return -1;
 
+  /* When GDB is built as a 64-bit application, ptrace writes into
+     SIGINFO an object with 64-bit layout.  Since debugging a 32-bit
+     inferior with a 64-bit GDB should look the same as debugging it
+     with a 32-bit GDB, we need to convert it.  GDB core always sees
+     the converted layout, so any read/write will have to be done
+     post-conversion.  */
+  siginfo_fixup (&siginfo, inf_siginfo, 0);
+
   if (offset + len > sizeof (siginfo))
     len = sizeof (siginfo) - offset;
 
   if (readbuf != NULL)
-    memcpy (readbuf, (char *)&siginfo + offset, len);
+    memcpy (readbuf, inf_siginfo + offset, len);
   else
     {
-      memcpy ((char *)&siginfo + offset, writebuf, len);
+      memcpy (inf_siginfo + offset, writebuf, len);
+
+      /* Convert back to ptrace layout before flushing it out.  */
+      siginfo_fixup (&siginfo, inf_siginfo, 1);
+
       errno = 0;
       ptrace (PTRACE_SETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, &siginfo);
       if (errno != 0)
@@ -4720,6 +4762,19 @@ linux_nat_set_new_thread (struct target_
   linux_nat_new_thread = new_thread;
 }
 
+/* Register a method that converts a siginfo object between the layout
+   that ptrace returns, and the layout in the architecture of the
+   inferior.  */
+void
+linux_nat_set_siginfo_fixup (struct target_ops *t,
+			     int (*siginfo_fixup) (struct siginfo *,
+						   gdb_byte *,
+						   int))
+{
+  /* Save the pointer.  */
+  linux_nat_siginfo_fixup = siginfo_fixup;
+}
+
 /* Return the saved siginfo associated with PTID.  */
 struct siginfo *
 linux_nat_get_siginfo (ptid_t ptid)
Index: src/gdb/linux-nat.h
===================================================================
--- src.orig/gdb/linux-nat.h	2009-02-06 23:02:15.000000000 +0000
+++ src/gdb/linux-nat.h	2009-02-06 23:04:07.000000000 +0000
@@ -125,6 +125,14 @@ void linux_nat_add_target (struct target
 /* Register a method to call whenever a new thread is attached.  */
 void linux_nat_set_new_thread (struct target_ops *, void (*) (ptid_t));
 
+/* Register a method that converts a siginfo object between the layout
+   that ptrace returns, and the layout in the architecture of the
+   inferior.  */
+void linux_nat_set_siginfo_fixup (struct target_ops *,
+				  int (*) (struct siginfo *,
+					   gdb_byte *,
+					   int));
+
 /* Update linux-nat internal state when changing from one fork
    to another.  */
 void linux_nat_switch_fork (ptid_t new_ptid);


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [3/2] Inspect extra signal information, handle amd64 bi-arch gdb
  2009-02-06 23:37                     ` Pedro Alves
@ 2009-02-07  2:28                       ` Paul Pluzhnikov
  2009-02-07 14:56                         ` Pedro Alves
  0 siblings, 1 reply; 53+ messages in thread
From: Paul Pluzhnikov @ 2009-02-07  2:28 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Fri, Feb 6, 2009 at 3:37 PM, Pedro Alves <pedro@codesourcery.com> wrote:
> On Wednesday 04 February 2009 21:17:12, Daniel Jacobowitz wrote:
>> Seems fine to me.
>
> Thanks Daniel.  Here's the version I just checked in.

This just broke my build :-(

../../src/gdb/linux-nat.c: In function 'linux_xfer_siginfo':
../../src/gdb/linux-nat.c:3302: error: 'PTRACE_SETSIGINFO' undeclared
(first use in this function)
../../src/gdb/linux-nat.c:3302: error: (Each undeclared identifier is
reported only once
../../src/gdb/linux-nat.c:3302: error: for each function it appears in.)
make: *** [linux-nat.o] Error 1

I am targeting glibc-2.3.6, and that doesn't appear to have
PTRACE_SETSIGINFO

-- 
Paul Pluzhnikov


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [3/2] Inspect extra signal information, handle amd64 bi-arch gdb
  2009-02-07  2:28                       ` Paul Pluzhnikov
@ 2009-02-07 14:56                         ` Pedro Alves
  2009-02-07 16:14                           ` Paul Pluzhnikov
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-02-07 14:56 UTC (permalink / raw)
  To: Paul Pluzhnikov; +Cc: gdb-patches

On Saturday 07 February 2009 02:28:44, Paul Pluzhnikov wrote:
> On Fri, Feb 6, 2009 at 3:37 PM, Pedro Alves <pedro@codesourcery.com> wrote:
> This just broke my build :-(
> 
> ../../src/gdb/linux-nat.c: In function 'linux_xfer_siginfo':
> ../../src/gdb/linux-nat.c:3302: error: 'PTRACE_SETSIGINFO' undeclared
> (first use in this function)
> ../../src/gdb/linux-nat.c:3302: error: (Each undeclared identifier is
> reported only once
> ../../src/gdb/linux-nat.c:3302: error: for each function it appears in.)
> make: *** [linux-nat.o] Error 1
> 
> I am targeting glibc-2.3.6, and that doesn't appear to have
> PTRACE_SETSIGINFO
> 

I've committed the below to fix it.  gdbserver doesn't need fixing, as
it's already doing this.  According to grep over glibc 2.9, this value
is good for all archs.

-- 
Pedro Alves

2009-02-07  Pedro Alves  <pedro@codesourcery.com>

	* linux-nat.c (PTRACE_SETSIGINFO): Define if PTRACE_GETSIGINFO
	isn't defined.

---
 gdb/linux-nat.c |    1 +
 1 file changed, 1 insertion(+)

Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c	2009-02-07 14:34:40.000000000 +0000
+++ src/gdb/linux-nat.c	2009-02-07 14:43:32.000000000 +0000
@@ -195,6 +195,7 @@ blocked.  */
 
 #ifndef PTRACE_GETSIGINFO
 #define PTRACE_GETSIGINFO    0x4202
+#define PTRACE_SETSIGINFO    0x4203
 #endif
 
 /* The single-threaded native GNU/Linux target_ops.  We save a pointer for


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [3/2] Inspect extra signal information, handle amd64 bi-arch gdb
  2009-02-07 14:56                         ` Pedro Alves
@ 2009-02-07 16:14                           ` Paul Pluzhnikov
  0 siblings, 0 replies; 53+ messages in thread
From: Paul Pluzhnikov @ 2009-02-07 16:14 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Sat, Feb 7, 2009 at 6:56 AM, Pedro Alves <pedro@codesourcery.com> wrote:

> I've committed the below to fix it.  gdbserver doesn't need fixing, as
> it's already doing this.  According to grep over glibc 2.9, this value
> is good for all archs.

Thanks, it builds again for me :-)

-- 
Paul Pluzhnikov


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [2/2] Inspect extra signal information
  2009-02-06 23:35         ` Pedro Alves
@ 2009-02-09  6:23           ` Paul Pluzhnikov
  2009-02-09 22:17             ` Pedro Alves
  0 siblings, 1 reply; 53+ messages in thread
From: Paul Pluzhnikov @ 2009-02-09  6:23 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Fri, Feb 6, 2009 at 3:35 PM, Pedro Alves <pedro@codesourcery.com> wrote:
> Here's the version of this patch that went in.

AFAICT, this broke 'gdb.base/default.exp' show convenience,
which expects "No debugger convenience variables ..."

Instead, it gets:

$ ./gdb -nx
GNU gdb (GDB) 6.8.50.20090207-cvs
...
This GDB was configured as "x86_64-unknown-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) show convenience
$_siginfo = void
(gdb)

I find it weird to have a "void" $_siginfo ...

-- 
Paul Pluzhnikov


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [2/2] Inspect extra signal information
  2009-02-09  6:23           ` Paul Pluzhnikov
@ 2009-02-09 22:17             ` Pedro Alves
  2009-04-06 19:00               ` Paul Pluzhnikov
  0 siblings, 1 reply; 53+ messages in thread
From: Pedro Alves @ 2009-02-09 22:17 UTC (permalink / raw)
  To: Paul Pluzhnikov; +Cc: gdb-patches

On Monday 09 February 2009 06:23:36, Paul Pluzhnikov wrote:
> On Fri, Feb 6, 2009 at 3:35 PM, Pedro Alves <pedro@codesourcery.com> wrote:
> > Here's the version of this patch that went in.
> 
> AFAICT, this broke 'gdb.base/default.exp' show convenience,
> which expects "No debugger convenience variables ..."
> 

Sigh. I don't know how, but I somehow missed this one all
along.  I suspect I was comparing testresults with a log that
already had the problem.  I'll try to make sure it doesn't
happen again.

> Instead, it gets:
> 
> $ ./gdb -nx
> GNU gdb (GDB) 6.8.50.20090207-cvs
> ...
> This GDB was configured as "x86_64-unknown-linux-gnu".
> For bug reporting instructions, please see:
> <http://www.gnu.org/software/gdb/bugs/>.
> (gdb) show convenience
> $_siginfo = void
> (gdb)
> 
> I find it weird to have a "void" $_siginfo ...
> 

That's what you get for all other convenience variables when
they are empty:

E.g.:

 >gdb-6.8
 (gdb) p $_siginfo
 $1 = void

Or:

 >gdb-6.8
 (gdb) p $randomvar
 $1 = void
 (gdb) show convenience
 $randomvar = void

I'm not 100% sure if we want to fix this, or if we want to
adjust the testsuite instead, and making clear in the docs
that the variable can be empty.

We could try delaying creating the convenience variable a bit,
but, how much?  First stop? --- there's targets that could in
principle show extra signal information without a stop (opening
a core, or, opening a remote-ish target (ignore start_remote, please)).
First target push (not the exec target though) ? --- sounds like
a bit of a hack.

Grumble.

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [2/2] Inspect extra signal information
  2009-02-09 22:17             ` Pedro Alves
@ 2009-04-06 19:00               ` Paul Pluzhnikov
  2009-04-06 19:18                 ` relying on testsuite results Thiago Jung Bauermann
  2009-04-07 14:57                 ` [2/2] Inspect extra signal information Pedro Alves
  0 siblings, 2 replies; 53+ messages in thread
From: Paul Pluzhnikov @ 2009-04-06 19:00 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 619 bytes --]

On Mon, Feb 9, 2009 at 3:16 PM, Pedro Alves <pedro@codesourcery.com> wrote:

> I'm not 100% sure if we want to fix this, or if we want to
> adjust the testsuite instead, and making clear in the docs
> that the variable can be empty.

Meanwhile the test continues to fail :-(

Attached is a proposed cleanup.

Thanks,
-- 
Paul Pluzhnikov


testsuite/ChangeLog
2009-04-06  Paul Pluzhnikov  <ppluzhnikov@google.com>

	    * gdb.base/default.exp: Fix "show convenience".

doc/ChangeLog
2009-04-06  Paul Pluzhnikov  <ppluzhnikov@google.com>

	    * gdb.texinfo (convenince variables): Mention
	    $_siginfo could be empty.

[-- Attachment #2: gdb-convenience.20090406.txt --]
[-- Type: text/plain, Size: 1796 bytes --]

Index: testsuite/gdb.base/default.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/default.exp,v
retrieving revision 1.29
diff -u -p -u -r1.29 default.exp
--- testsuite/gdb.base/default.exp	3 Jan 2009 05:58:03 -0000	1.29
+++ testsuite/gdb.base/default.exp	6 Apr 2009 18:43:46 -0000
@@ -598,7 +598,7 @@ gdb_test "show complaints" "Max number o
 #test show confirm
 gdb_test "show confirm" "Whether to confirm potentially dangerous operations is o\[a-z\]*." "show confirm"
 #test show convenience
-gdb_test "show convenience" "No debugger convenience variables now defined.(\[^\r\n\]*\[\r\n\])+Convenience variables have names starting with \".\";(\[^\r\n\]*\[\r\n\])+use \"set\" as in \"set .foo = 5\" to define them." "show convenience"
+gdb_test "show convenience" "\\\$_siginfo = void" "show convenience"
 #test show directories
 gdb_test "show directories" "Source directories searched: .cdir\[:;\].cwd" "show directories"
 #test show editing
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.578
diff -u -p -u -r1.578 gdb.texinfo
--- doc/gdb.texinfo	2 Apr 2009 15:56:08 -0000	1.578
+++ doc/gdb.texinfo	6 Apr 2009 18:43:47 -0000
@@ -7445,7 +7448,9 @@ the program being debugged terminates.
 @item $_siginfo
 @vindex $_siginfo@r{, convenience variable}
 The variable @code{$_siginfo} is bound to extra signal information
-inspection (@pxref{extra signal information}).
+inspection (@pxref{extra signal information}). Note that @code{$_siginfo}
+could be empty. For example, it will be empty before you execute the
+@code{run} command.
 @end table
 
 On HP-UX systems, if you refer to a function or variable name that

^ permalink raw reply	[flat|nested] 53+ messages in thread

* relying on testsuite results
  2009-04-06 19:00               ` Paul Pluzhnikov
@ 2009-04-06 19:18                 ` Thiago Jung Bauermann
  2009-04-06 19:33                   ` Paul Pluzhnikov
  2009-04-06 19:51                   ` Tom Tromey
  2009-04-07 14:57                 ` [2/2] Inspect extra signal information Pedro Alves
  1 sibling, 2 replies; 53+ messages in thread
From: Thiago Jung Bauermann @ 2009-04-06 19:18 UTC (permalink / raw)
  To: Paul Pluzhnikov; +Cc: gdb-patches

Hi Paul,

[ Hijacking thread, changing subject. ]

El lun, 06-04-2009 a las 11:59 -0700, Paul Pluzhnikov escribió:
> On Mon, Feb 9, 2009 at 3:16 PM, Pedro Alves <pedro@codesourcery.com> wrote:
> 
> > I'm not 100% sure if we want to fix this, or if we want to
> > adjust the testsuite instead, and making clear in the docs
> > that the variable can be empty.
> 
> Meanwhile the test continues to fail :-(

I'm sincerely curious about why this bothers you to the point of
remembering this discussion from one month ago and fixing it.

I'd love to rely on testsuite results like this, but unfortunately there
are too many "non-deterministic testcases" (as I call them) and they add
a great deal of noise.

So the most use I get from the testsuite is to run regression tests on
each patch I submit, and tediously eyeball the diff looking to see if
any of the PASS<->FAIL flips actuallly mean something.

Do you have a way out of this except going through each of the
unreliable tests and staring at them long enough to see why they flip
(and that can be tricky)?
-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: relying on testsuite results
  2009-04-06 19:18                 ` relying on testsuite results Thiago Jung Bauermann
@ 2009-04-06 19:33                   ` Paul Pluzhnikov
  2009-04-06 19:57                     ` Daniel Jacobowitz
  2009-04-06 19:51                   ` Tom Tromey
  1 sibling, 1 reply; 53+ messages in thread
From: Paul Pluzhnikov @ 2009-04-06 19:33 UTC (permalink / raw)
  To: Thiago Jung Bauermann; +Cc: gdb-patches

On Mon, Apr 6, 2009 at 12:18 PM, Thiago Jung Bauermann
<bauerman@br.ibm.com> wrote:

>> Meanwhile the test continues to fail :-(
>
> I'm sincerely curious about why this bothers you to the point of
> remembering this discussion from one month ago and fixing it.

My previous experience maintaining a product with extensive test suite on
multiple platforms has taught me that there are really only two states:
"no failures" and "some failures". Once you enter "some failures" state,
it tends to deteriorate to the point where you get new bug reports,
check your testsuite, and discover that they are already catching the
failure :-(

> I'd love to rely on testsuite results like this, but unfortunately there
> are too many "non-deterministic testcases" (as I call them) and they add
> a great deal of noise.

Yes, they do.
I think we should have a "fixit day", when everybody cleans them up.

> So the most use I get from the testsuite is to run regression tests on
> each patch I submit, and tediously eyeball the diff looking to see if
> any of the PASS<->FAIL flips actuallly mean something.

Yes, I do the same.

But I don't maintain/test the "before" tree. Instead I compare with
gdb.sum-20090309, and so this failure continues to "stick out".

> Do you have a way out of this except going through each of the
> unreliable tests and staring at them long enough to see why they flip
> (and that can be tricky)?

No, I don't :-(

-- 
Paul Pluzhnikov


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: relying on testsuite results
  2009-04-06 19:18                 ` relying on testsuite results Thiago Jung Bauermann
  2009-04-06 19:33                   ` Paul Pluzhnikov
@ 2009-04-06 19:51                   ` Tom Tromey
  2009-04-06 20:22                     ` Mark Kettenis
  1 sibling, 1 reply; 53+ messages in thread
From: Tom Tromey @ 2009-04-06 19:51 UTC (permalink / raw)
  To: Thiago Jung Bauermann; +Cc: Paul Pluzhnikov, gdb-patches

>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:

Thiago> So the most use I get from the testsuite is to run regression
Thiago> tests on each patch I submit, and tediously eyeball the diff
Thiago> looking to see if any of the PASS<->FAIL flips actuallly mean
Thiago> something.

Yeah, me too.

These non-deterministic tests may add something, in one scenario: if
they start failing consistently, and somebody notices that, then they
may provide information about a real regression.

I'm sure I won't notice if they start failing consistently, though.
I already ignore them.

I generally do full regression tests for each patch.  ("Generally"
because I occasionally forget, or something goes wrong and I don't
notice.)  This is nice, although slow, and unfortunately also open to
some kinds of major failure (e.g., a change of compiler negatively
affecting baseline results).

Tom


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: relying on testsuite results
  2009-04-06 19:33                   ` Paul Pluzhnikov
@ 2009-04-06 19:57                     ` Daniel Jacobowitz
  0 siblings, 0 replies; 53+ messages in thread
From: Daniel Jacobowitz @ 2009-04-06 19:57 UTC (permalink / raw)
  To: Paul Pluzhnikov; +Cc: Thiago Jung Bauermann, gdb-patches

On Mon, Apr 06, 2009 at 12:32:51PM -0700, Paul Pluzhnikov wrote:
> > I'd love to rely on testsuite results like this, but unfortunately there
> > are too many "non-deterministic testcases" (as I call them) and they add
> > a great deal of noise.
> 
> Yes, they do.
> I think we should have a "fixit day", when everybody cleans them up.

I used to regularly do this, but it's basically impossible to keep up.
There are too many configurations and the testsuite is too
disorganized.  I encourage other folks to try though...

The non-deterministic testcases can often be throttled down to the
point where they are reasonably likely to pass.  I've fixed some of
the worst offenders.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: relying on testsuite results
  2009-04-06 19:51                   ` Tom Tromey
@ 2009-04-06 20:22                     ` Mark Kettenis
  0 siblings, 0 replies; 53+ messages in thread
From: Mark Kettenis @ 2009-04-06 20:22 UTC (permalink / raw)
  To: tromey; +Cc: bauerman, ppluzhnikov, gdb-patches

> From: Tom Tromey <tromey@redhat.com>
> Reply-To: tromey@redhat.com
> 
> I generally do full regression tests for each patch.  ("Generally"
> because I occasionally forget, or something goes wrong and I don't
> notice.)  This is nice, although slow, and unfortunately also open to
> some kinds of major failure (e.g., a change of compiler negatively
> affecting baseline results).

And there you touch upon an important reason why it is so hard to make
all tests PASS.  In many cases our testsuite isn't just testing GDB in
isolation, but also the compiler, kernel or threads library.
Unfortunately the developers of those components don't run the GDB
testsuite as part of their regression testing.  So things are
sometimes broken and take a while to get fixed again.

That said, on my preferred platform (OpenBSD) the testsuite produces
fairly consistent results.  We use a stable toolchain (GCC 3.3.5,
binutils 2.15) which helps.  And a fair number of the threads-related
tests FAIL because of some Linuxisms that crept, which means they
often dom't even get to the racy bits.  But it is also because in the
past I spent time on actually fixing broken tests.


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [2/2] Inspect extra signal information
  2009-04-06 19:00               ` Paul Pluzhnikov
  2009-04-06 19:18                 ` relying on testsuite results Thiago Jung Bauermann
@ 2009-04-07 14:57                 ` Pedro Alves
  1 sibling, 0 replies; 53+ messages in thread
From: Pedro Alves @ 2009-04-07 14:57 UTC (permalink / raw)
  To: Paul Pluzhnikov; +Cc: gdb-patches

On Monday 06 April 2009 19:59:49, Paul Pluzhnikov wrote:
> testsuite/ChangeLog
> 2009-04-06  Paul Pluzhnikov  <ppluzhnikov@google.com>
> 
>             * gdb.base/default.exp: Fix "show convenience".

If nobody yells, this part is OK with me.  Thank you.

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 53+ messages in thread

end of thread, other threads:[~2009-04-07 14:57 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-01-12 18:47 [0/2] Inspect extra signal information Pedro Alves
2009-01-12 18:49 ` Pedro Alves
2009-01-12 18:52   ` [1/2] " Pedro Alves
2009-01-12 19:40     ` Eli Zaretskii
2009-02-02 16:51       ` Pedro Alves
2009-02-02 21:04         ` Eli Zaretskii
2009-02-05  1:14           ` Pedro Alves
2009-02-05 20:30             ` Eli Zaretskii
2009-02-06 23:31               ` Pedro Alves
2009-01-12 18:50 ` [2/2] " Pedro Alves
2009-01-12 19:39   ` Eli Zaretskii
2009-01-13 12:32     ` Pedro Alves
2009-01-13 18:55       ` Eli Zaretskii
2009-01-13 19:08         ` Pedro Alves
2009-01-13 19:15           ` Eli Zaretskii
2009-02-06 23:35         ` Pedro Alves
2009-02-09  6:23           ` Paul Pluzhnikov
2009-02-09 22:17             ` Pedro Alves
2009-04-06 19:00               ` Paul Pluzhnikov
2009-04-06 19:18                 ` relying on testsuite results Thiago Jung Bauermann
2009-04-06 19:33                   ` Paul Pluzhnikov
2009-04-06 19:57                     ` Daniel Jacobowitz
2009-04-06 19:51                   ` Tom Tromey
2009-04-06 20:22                     ` Mark Kettenis
2009-04-07 14:57                 ` [2/2] Inspect extra signal information Pedro Alves
2009-01-12 23:27 ` [0/2] " Mark Kettenis
2009-01-13 11:05   ` Pedro Alves
2009-01-13 18:42     ` Eli Zaretskii
2009-01-13 18:50       ` Pedro Alves
2009-01-13 19:19         ` Eli Zaretskii
2009-01-13 19:37           ` Pedro Alves
2009-01-13 19:47             ` Pedro Alves
2009-02-02 14:40               ` Pedro Alves
2009-02-02 20:49                 ` Mark Kettenis
2009-02-03 15:02 ` Pedro Alves
2009-02-03 16:42   ` Ulrich Weigand
2009-02-03 18:06     ` Daniel Jacobowitz
2009-02-03 18:24       ` Pedro Alves
2009-02-03 19:04         ` Daniel Jacobowitz
2009-02-03 19:51           ` Pedro Alves
2009-02-03 23:18             ` Doug Evans
2009-02-03 23:50               ` Pedro Alves
2009-02-04  0:17                 ` Doug Evans
2009-02-04  0:24             ` Daniel Jacobowitz
2009-02-04  0:49               ` Pedro Alves
2009-02-04 21:02                 ` [3/2] Inspect extra signal information, handle amd64 bi-arch gdb Pedro Alves
2009-02-04 21:17                   ` Daniel Jacobowitz
2009-02-06 23:37                     ` Pedro Alves
2009-02-07  2:28                       ` Paul Pluzhnikov
2009-02-07 14:56                         ` Pedro Alves
2009-02-07 16:14                           ` Paul Pluzhnikov
2009-02-04 22:07                   ` Doug Evans
2009-02-03 18:23     ` [0/2] Inspect extra signal information Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox