[v2] Implement xfer_partial TARGET_OBJECT_SIGNAL_INFO for NetBSD

Message ID 20200728150418.19720-1-n54@gmx.com
State Superseded
Headers show
Series
  • [v2] Implement xfer_partial TARGET_OBJECT_SIGNAL_INFO for NetBSD
Related show

Commit Message

Kamil Rytarowski July 28, 2020, 3:04 p.m.
NetBSD implements reading and overwriting siginfo_t received by the
tracee. With TARGET_OBJECT_SIGNAL_INFO signal information can be
examined and modified through the special variable $_siginfo.

Implement the "get_siginfo_type" gdbarch method for NetBSD architectures.

As with Linux architectures, cache the created type in the gdbarch when it
is first created.  Currently NetBSD uses an identical siginfo type on
all architectures, so there is no support for architecture-specific fields.

gdb/ChangeLog:

	* nbsd-nat.h (nbsd_nat_target::xfer_partial): New declaration.
	* nbsd-nat.c (nbsd_nat_target::xfer_partial): New function.
	* nbsd-tdep.c (nbsd_gdbarch_data_handle, struct nbsd_gdbarch_data)
	(init_nbsd_gdbarch_data, get_nbsd_gdbarch_data)
	(nbsd_get_siginfo_type): New.
	(nbsd_init_abi): Install gdbarch "get_siginfo_type" method.
	(_initialize_nbsd_tdep): New
---
 gdb/ChangeLog   |  10 ++++
 gdb/nbsd-nat.c  |  45 ++++++++++++++
 gdb/nbsd-nat.h  |   6 ++
 gdb/nbsd-tdep.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 217 insertions(+)

--
2.26.2

Comments

Simon Marchi July 28, 2020, 3:17 p.m. | #1
On 2020-07-28 11:04 a.m., Kamil Rytarowski wrote:
> diff --git a/gdb/nbsd-nat.c b/gdb/nbsd-nat.c

> index a9405ebf862..bdf3388de0b 100644

> --- a/gdb/nbsd-nat.c

> +++ b/gdb/nbsd-nat.c

> @@ -845,3 +845,48 @@ nbsd_nat_target::supports_multi_process ()

>  {

>    return true;

>  }

> +

> +/* Implement the "xfer_partial" target_ops method.  */

> +

> +enum target_xfer_status

> +nbsd_nat_target::xfer_partial (enum target_object object,

> +                               const char *annex, gdb_byte *readbuf,

> +                               const gdb_byte *writebuf,

> +                               ULONGEST offset, ULONGEST len,

> +                               ULONGEST *xfered_len)


Spaces here.

Just search for "        " (8 spaces) in the files, it's quite easy to find.

If there are pre-existing offenders, you can push obvious fixes to fix them.

Simon

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index defca83c263..c12eda04285 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,13 @@ 
+2020-07-28  Kamil Rytarowski  <n54@gmx.com>
+
+	* nbsd-nat.h (nbsd_nat_target::xfer_partial): New declaration.
+	* nbsd-nat.c (nbsd_nat_target::xfer_partial): New function.
+	* nbsd-tdep.c (nbsd_gdbarch_data_handle, struct nbsd_gdbarch_data)
+	(init_nbsd_gdbarch_data, get_nbsd_gdbarch_data)
+	(nbsd_get_siginfo_type): New.
+	(nbsd_init_abi): Install gdbarch "get_siginfo_type" method.
+	(_initialize_nbsd_tdep): New.
+
 2020-07-28  H.J. Lu  <hongjiu.lu@intel.com>

 	PR binutils/26301
diff --git a/gdb/nbsd-nat.c b/gdb/nbsd-nat.c
index a9405ebf862..bdf3388de0b 100644
--- a/gdb/nbsd-nat.c
+++ b/gdb/nbsd-nat.c
@@ -845,3 +845,48 @@  nbsd_nat_target::supports_multi_process ()
 {
   return true;
 }
+
+/* Implement the "xfer_partial" target_ops method.  */
+
+enum target_xfer_status
+nbsd_nat_target::xfer_partial (enum target_object object,
+                               const char *annex, gdb_byte *readbuf,
+                               const gdb_byte *writebuf,
+                               ULONGEST offset, ULONGEST len,
+                               ULONGEST *xfered_len)
+{
+  pid_t pid = inferior_ptid.pid ();
+
+  switch (object)
+    {
+    case TARGET_OBJECT_SIGNAL_INFO:
+      {
+	ptrace_siginfo_t psi;
+
+	if (offset > sizeof (siginfo_t))
+	  return TARGET_XFER_E_IO;
+
+	if (ptrace (PT_GET_SIGINFO, pid, &psi, sizeof (psi)) == -1)
+	  return TARGET_XFER_E_IO;
+
+	if (offset + len > sizeof (siginfo_t))
+          len = sizeof (siginfo_t) - offset;
+
+	if (readbuf != NULL)
+	  memcpy (readbuf, ((gdb_byte *) &psi.psi_siginfo) + offset, len);
+	else
+	  {
+	    memcpy (((gdb_byte *) &psi.psi_siginfo) + offset, writebuf, len);
+
+	    if (ptrace (PT_SET_SIGINFO, pid, &psi, sizeof (psi)) == -1)
+	      return TARGET_XFER_E_IO;
+	  }
+        *xfered_len = len;
+        return TARGET_XFER_OK;
+      }
+    default:
+      return inf_ptrace_target::xfer_partial (object, annex,
+                                              readbuf, writebuf, offset,
+                                              len, xfered_len);
+    }
+}
diff --git a/gdb/nbsd-nat.h b/gdb/nbsd-nat.h
index 0a7048ecf35..59210ad1d03 100644
--- a/gdb/nbsd-nat.h
+++ b/gdb/nbsd-nat.h
@@ -49,6 +49,12 @@  struct nbsd_nat_target : public inf_ptrace_target
     override;

   bool supports_multi_process () override;
+  enum target_xfer_status xfer_partial (enum target_object object,
+                                        const char *annex,
+                                        gdb_byte *readbuf,
+                                        const gdb_byte *writebuf,
+                                        ULONGEST offset, ULONGEST len,
+                                        ULONGEST *xfered_len) override;
 };

 #endif /* nbsd-nat.h */
diff --git a/gdb/nbsd-tdep.c b/gdb/nbsd-tdep.c
index 4fdfe476b59..ecbcbcfe163 100644
--- a/gdb/nbsd-tdep.c
+++ b/gdb/nbsd-tdep.c
@@ -373,6 +373,153 @@  nbsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
     return find_solib_trampoline_target (get_current_frame (), pc);
 }

+static struct gdbarch_data *nbsd_gdbarch_data_handle;
+
+struct nbsd_gdbarch_data
+{
+  struct type *siginfo_type;
+};
+
+static void *
+init_nbsd_gdbarch_data (struct gdbarch *gdbarch)
+{
+  return GDBARCH_OBSTACK_ZALLOC (gdbarch, struct nbsd_gdbarch_data);
+}
+
+static struct nbsd_gdbarch_data *
+get_nbsd_gdbarch_data (struct gdbarch *gdbarch)
+{
+  return ((struct nbsd_gdbarch_data *)
+          gdbarch_data (gdbarch, nbsd_gdbarch_data_handle));
+}
+
+/* Implement the "get_siginfo_type" gdbarch method.  */
+
+static struct type *
+nbsd_get_siginfo_type (struct gdbarch *gdbarch)
+{
+  nbsd_gdbarch_data *nbsd_gdbarch_data = get_nbsd_gdbarch_data (gdbarch);
+  if (nbsd_gdbarch_data->siginfo_type != NULL)
+    return nbsd_gdbarch_data->siginfo_type;
+
+  type *char_type = builtin_type (gdbarch)->builtin_char;
+  type *int_type = builtin_type (gdbarch)->builtin_int;
+  type *long_type = builtin_type (gdbarch)->builtin_long;
+
+  type *void_ptr_type
+    = lookup_pointer_type (builtin_type (gdbarch)->builtin_void);
+
+  type *int32_type = builtin_type (gdbarch)->builtin_int32;
+  type *uint32_type = builtin_type (gdbarch)->builtin_uint32;
+  type *uint64_type = builtin_type (gdbarch)->builtin_uint64;
+
+  bool lp64 = TYPE_LENGTH (void_ptr_type) == 8;
+  size_t char_bits = gdbarch_addressable_memory_unit_size (gdbarch) * 8;
+
+  /* pid_t */
+  type *pid_type = arch_type (gdbarch, TYPE_CODE_TYPEDEF,
+			      TYPE_LENGTH (int32_type) * char_bits, "pid_t");
+  TYPE_TARGET_TYPE (pid_type) = int32_type;
+
+  /* uid_t */
+  type *uid_type = arch_type (gdbarch, TYPE_CODE_TYPEDEF,
+			      TYPE_LENGTH (uint32_type) * char_bits, "uid_t");
+  TYPE_TARGET_TYPE (uid_type) = uint32_type;
+
+  /* clock_t */
+  type *clock_type = arch_type (gdbarch, TYPE_CODE_TYPEDEF,
+				TYPE_LENGTH (int_type) * char_bits, "clock_t");
+  TYPE_TARGET_TYPE (clock_type) = int_type;
+
+  /* lwpid_t */
+  type *lwpid_type = arch_type (gdbarch, TYPE_CODE_TYPEDEF,
+				TYPE_LENGTH (int32_type) * char_bits,
+				"lwpid_t");
+  TYPE_TARGET_TYPE (lwpid_type) = int32_type;
+
+  /* union sigval */
+  type *sigval_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION);
+  sigval_type->set_name (gdbarch_obstack_strdup (gdbarch, "sigval"));
+  append_composite_type_field (sigval_type, "sival_int", int_type);
+  append_composite_type_field (sigval_type, "sival_ptr", void_ptr_type);
+
+  /* union _option */
+  type *option_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION);
+  option_type->set_name (gdbarch_obstack_strdup (gdbarch, "_option"));
+  append_composite_type_field (option_type, "_pe_other_pid", pid_type);
+  append_composite_type_field (option_type, "_pe_lwp", lwpid_type);
+
+  /* union _reason */
+  type *reason_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION);
+
+  /* _rt */
+  type *t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (t, "_pid", pid_type);
+  append_composite_type_field (t, "_uid", uid_type);
+  append_composite_type_field (t, "_value", sigval_type);
+  append_composite_type_field (reason_type, "_rt", t);
+
+  /* _child */
+  t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (t, "_pid", pid_type);
+  append_composite_type_field (t, "_uid", uid_type);
+  append_composite_type_field (t, "_status", int_type);
+  append_composite_type_field (t, "_utime", clock_type);
+  append_composite_type_field (t, "_stime", clock_type);
+  append_composite_type_field (reason_type, "_child", t);
+
+  /* _fault */
+  t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (t, "_addr", void_ptr_type);
+  append_composite_type_field (t, "_trap", int_type);
+  append_composite_type_field (t, "_trap2", int_type);
+  append_composite_type_field (t, "_trap3", int_type);
+  append_composite_type_field (reason_type, "_fault", t);
+
+  /* _poll */
+  t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (t, "_band", long_type);
+  append_composite_type_field (t, "_fd", int_type);
+  append_composite_type_field (reason_type, "_poll", t);
+
+  /* _syscall */
+  t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (t, "_sysnum", int_type);
+  append_composite_type_field (t, "_retval",
+			       init_vector_type (int_type, 2));
+  append_composite_type_field (t, "_error", int_type);
+  append_composite_type_field (t, "_args",
+			       init_vector_type (uint64_type, 8));
+  append_composite_type_field (reason_type, "_syscall", t);
+
+  /* _ptrace_state */
+  t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (t, "_pe_report_event", int_type);
+  append_composite_type_field (t, "_option", option_type);
+  append_composite_type_field (reason_type, "_ptrace_state", t);
+
+  /* struct _ksiginfo */
+  type *ksiginfo_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  ksiginfo_type->set_name (gdbarch_obstack_strdup (gdbarch, "_ksiginfo"));
+  append_composite_type_field (ksiginfo_type, "_signo", int_type);
+  append_composite_type_field (ksiginfo_type, "_code", int_type);
+  append_composite_type_field (ksiginfo_type, "_errno", int_type);
+  if (lp64)
+    append_composite_type_field (ksiginfo_type, "_pad", int_type);
+  append_composite_type_field (ksiginfo_type, "_reason", reason_type);
+
+  /* union siginfo */
+  type *siginfo_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION);
+  siginfo_type->set_name (gdbarch_obstack_strdup (gdbarch, "siginfo"));
+  append_composite_type_field (siginfo_type, "si_pad",
+			       init_vector_type (char_type, 128));
+  append_composite_type_field (siginfo_type, "_info", ksiginfo_type);
+
+  nbsd_gdbarch_data->siginfo_type = siginfo_type;
+
+  return siginfo_type;
+}
+
 /* See nbsd-tdep.h.  */

 void
@@ -469,8 +616,17 @@  nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_gdb_signal_to_target (gdbarch, nbsd_gdb_signal_to_target);
   set_gdbarch_skip_solib_resolver (gdbarch, nbsd_skip_solib_resolver);
   set_gdbarch_auxv_parse (gdbarch, svr4_auxv_parse);
+  set_gdbarch_get_siginfo_type (gdbarch, nbsd_get_siginfo_type);

   /* `catch syscall' */
   set_xml_syscall_file_name (gdbarch, "syscalls/netbsd.xml");
   set_gdbarch_get_syscall_number (gdbarch, nbsd_get_syscall_number);
 }
+
+void _initialize_nbsd_tdep ();
+void
+_initialize_nbsd_tdep ()
+{
+  nbsd_gdbarch_data_handle
+    = gdbarch_data_register_post_init (init_nbsd_gdbarch_data);
+}