Re: [0/2] Inspect extra signal information

Doug Evans
2009-02-03T23:18:51Z

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?