Re: [patch 1/9]#2 Rename `enum target_signal' to target_signal_t

Jan Kratochvil
2010-09-07T17:58:50Z

On Thu, 02 Sep 2010 21:33:11 +0200, Jan Kratochvil wrote:
> On Thu, 02 Sep 2010 19:27:52 +0200, Pedro Alves wrote:
> > I don't think it is a good idea to associate the siginfo with a signal
> > and think of it as a single entity. For many cases, you don't need the
> > siginfo. Carrying it around would be extra burden, especially for the remote
> > target.
>
> For the remote part I was thinking about making it lazy, requesting it only
> when retrieved for a different kind of processing than a target resume.

While trying to implement it I found it cannot be done (without C++).

If target_signal_t as returned by remote_wait (=to_wait implementation) is
lazy it can either be passed to remote_resume (=to_resume implementation) or
saved by infrun.c save_inferior_thread_state. But remote.c can no longer
track where that target_signal_t has been copied without C++.

On Mon, 30 Aug 2010 09:09:55 +0200, Jan Kratochvil wrote:
# I tried to make target_signal a pointer with reference counter. I have the
# unfinished patch here but I really do not find it viable. All the assignments
# and passing by value to functions make it difficult to catch all the cases.
# With C++ GDB this patchset could be greatly simplified with fixed performance.
+
Even if the implementation would get finished I find target_signal_t a too
basic type to require explicit reference counting while having no compiler
checks of it. It could become a large problem similar to all the effort to
manage the GObject reference counting in Gnome/C.

remote.c PASSes with FSF gdbserver even for gdb.base/siginfo-infcall.exp but
without C++ it has to have the back-and-forth siginfo_t transfer overhead.
[attached as a preview]

Therefore going to implement explicit carrying of associated siginfo_t
together with siginfo-less target_signal_t in the middle-end (infrun.c&co.).

Regards,
Jan

--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -176,6 +176,18 @@ static void print_packet (char *);

static void compare_sections_command (char *, int);

+struct packet_config;
+
+static LONGEST remote_read_qxfer (struct target_ops *ops,
+ const char *object_name, const char *annex,
+ gdb_byte *readbuf, ULONGEST offset,
+ LONGEST len, struct packet_config *packet);
+
+static LONGEST remote_write_qxfer (struct target_ops *ops,
+ const char *object_name, const char *annex,
+ const gdb_byte *writebuf, ULONGEST offset,
+ LONGEST len, struct packet_config *packet);
+
static void packet_command (char *, int);

static int stub_unpack_int (char *buff, int fieldlength);
@@ -196,8 +208,6 @@ static int putpkt_binary (char *buf, int cnt);

static void check_binary_download (CORE_ADDR addr);

-struct packet_config;
-
static void show_packet_config_cmd (struct packet_config *config);

static void update_packet_config (struct packet_config *config);
@@ -4446,6 +4456,32 @@ remote_vcont_resume (ptid_t ptid, int step, target_signal_t siggnal)
if (remote_protocol_packets[PACKET_vCont].support == PACKET_DISABLE)
return 0;

+ if (target_signal_siginfo_p (&siggnal))
+ {
+ ptid_t siggnal_ptid;
+ struct gdbarch *siggnal_ptid_gdbarch;
+ size_t len;
+ gdb_byte *siginfop;
+ LONGEST got;
+
+ if (ptid_equal (ptid, magic_null_ptid)
+ || ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
+ siggnal_ptid = inferior_ptid;
+ else
+ siggnal_ptid = ptid;
+
+ set_general_thread (siggnal_ptid);
+
+ siggnal_ptid_gdbarch = target_thread_architecture (siggnal_ptid);
+ len = target_signal_siginfo_len (siggnal_ptid_gdbarch);
+ siginfop = target_signal_siginfo_get (&siggnal, siggnal_ptid_gdbarch);
+
+ got = remote_write_qxfer (NULL /* unused */, "siginfo", NULL, siginfop,
+ 0, len, &remote_protocol_packets
+ [PACKET_qXfer_siginfo_read]);
+ /* FIXME: Real len. */
+ }
+
p = rs->buf;
endp = rs->buf + get_remote_packet_size ();

@@ -4554,6 +4590,34 @@ remote_resume (struct target_ops *ops,
{
int siggnal_number = TARGET_SIGNAL_NUMBER (siggnal);

+ if (target_signal_siginfo_p (&siggnal))
+ {
+ ptid_t siggnal_ptid;
+ struct gdbarch *siggnal_ptid_gdbarch;
+ size_t len;
+ gdb_byte *siginfop;
+ LONGEST got;
+
+ if (ptid_equal (ptid, magic_null_ptid)
+ || ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
+ siggnal_ptid = inferior_ptid;
+ else
+ siggnal_ptid = ptid;
+
+ set_general_thread (siggnal_ptid);
+
+ siggnal_ptid_gdbarch = target_thread_architecture (siggnal_ptid);
+ len = target_signal_siginfo_len (siggnal_ptid_gdbarch);
+ siginfop = target_signal_siginfo_get (&siggnal,
+ siggnal_ptid_gdbarch);
+
+ got = remote_write_qxfer (NULL /* unused */, "siginfo", NULL,
+ siginfop, 0, len,
+ &remote_protocol_packets
+ [PACKET_qXfer_siginfo_read]);
+ /* FIXME: Real len. */
+ }
+
buf[0] = step ? 'S' : 'C';
buf[1] = tohex ((siggnal_number >> 4) & 0xf);
buf[2] = tohex (siggnal_number & 0xf);
@@ -5575,6 +5639,37 @@ remote_wait (struct target_ops *ops,
else
event_ptid = remote_wait_as (ptid, status, options);

+ if (TARGET_WAITKIND_USES_SIG (status->kind))
+ {
+ ptid_t siggnal_ptid;
+ struct gdbarch *siggnal_ptid_gdbarch;
+ size_t len;
+ gdb_byte siginfo[MAX_SIGINFO_SIZE];
+ LONGEST got;
+
+ if (ptid_equal (event_ptid, magic_null_ptid)
+ || ptid_equal (event_ptid, minus_one_ptid)
+ || ptid_is_pid (event_ptid))
+ siggnal_ptid = inferior_ptid;
+ else
+ siggnal_ptid = event_ptid;
+
+ siggnal_ptid_gdbarch = target_thread_architecture (siggnal_ptid);
+ len = target_signal_siginfo_len (siggnal_ptid_gdbarch);
+
+ got = remote_read_qxfer (ops, "siginfo", NULL, siginfo, 0, len,
+ &remote_protocol_packets
+ [PACKET_qXfer_siginfo_read]);
+ if (got >= 0)
+ {
+ set_general_thread (siggnal_ptid);
+
+ memset (&siginfo[got], 0, len - got);
+ target_signal_siginfo_set (&status->value.sig, siggnal_ptid_gdbarch,
+ siginfo);
+ }
+ }
+
if (target_can_async_p ())
{
/* If there are are events left in the queue tell the event loop