gdbserver: start turning the target ops vector into a class
authorTankut Baris Aktemur <tankut.baris.aktemur@intel.com>
Mon, 17 Feb 2020 15:11:50 +0000 (16:11 +0100)
committerTankut Baris Aktemur <tankut.baris.aktemur@intel.com>
Thu, 20 Feb 2020 16:35:01 +0000 (17:35 +0100)
This is the beginning of a series of patches where the goal is to turn
the target ops vector into a class and all the target op function
pointers into methods of this class.

Currently, the target ops is a struct of function pointers.  At the
end of the series, it becomes a class with methods, and the existing
low target definitions become subclasses.  That is, we end up with the
following class hierarchy:

  process_stratum_target
  ^
  |-- linux-low
  |-- lynx-low
  |-- nto-low
  |-- win32-low

process_stratum_target either defines the default behavior for the
target ops or leaves them as pure virtual for the subclasses to
override.

The transformation is done by first introducing a helper class, called
'process_target', that is initially empty.  An instance of this class
is added to the end of the current target ops vector.  This new field
is called 'pt'.  We will gradually carry target ops to the new class,
one by one, whereas the invocation of the target op will be converted
to a method call on 'pt'.

For instance, target op 'attach' is currently invoked as

  (*the_target->attach) (args)

After moving 'attach' as a method to 'process_target', it will be
invoked as

  the_target->pt->attach (args)

In this process, the concrete target vector definitions
(e.g. linux-low, win32-low, nto-low, etc.) are turned into derived
classes of 'process_target', so that they can either inherit the
default behavior of the target ops or can override the method.

We prefer to make this transition gradually rather than in a single
giant patch, to yield bite-size patches.  The goal is that after each
patch gdbserver will still be buildable and testable.

The general rule of thumb when converting a target op to a method is
this:

(1) If the function call is protected with a NULL-check with an
obvious default behavior, simply implement that default behavior in
the base class (e.g.: supports_non_stop).

(2) If there is no NULL-check guard, the method becomes pure
virtual, and the derived targets are required to implement the method
(e.g.: attach).

(3) If there is a NULL-check but no apparent default behavior, or if
the NULL-check is utilized to populate a feature support packet,
introduce a 'supports_XYZ' method (e.g.: pid_to_exec_file).

The overall strategy is to preserve the existing behavior as much as
possible.

When we're done moving all the target ops into 'process_target', the
target op vector will contain nothing but the field 'pt'.  At that
point, the auxiliary class 'process_target' will simply meld into
'process_stratum_target' and the method calls of the form
'the_target->pt->xyz' will be turned into 'the_target->xyz'.

The "linux-low" target has been built and reg-tested on X86_64 Linux
(Ubuntu).  The "win32-low" target has been built (but not tested) via
cross-compilation to a x86_64-w64-mingw32 target.  The "lynx-low" and
"nto-low" targets were neither built nor tested.

gdbserver/ChangeLog:
2020-02-20  Tankut Baris Aktemur  <tankut.baris.aktemur@intel.com>

* target.h (class process_target): New class definition.
(struct process_stratum_target) <pt>: New field with type
'process_target*'.
* linux-low.h (class linux_process_target): Define as a derived
class of 'process_target'.
* linux-low.cc (linux_target_ops): Add a linux_process_target*
as the 'pt' field.
* lynx-low.h (class lynx_process_target): Define as a derived
class of 'process_target'.
* lynx-low.cc (lynx_target_ops): Add a lynx_process_target*
as the 'pt' field.
* nto-low.h (class nto_process_target): Define as a derived
class of 'process_target'.
* nto-low.cc (nto_target_ops): Add an nto_process_target*
as the 'pt' field.
* win32-low.h (class win32_process_target): Define as a derived
class of 'process_target'.
* win32-low.cc (win32_target_ops): Add a win32_process_target*
as the 'pt' field.

gdbserver/ChangeLog
gdbserver/linux-low.cc
gdbserver/linux-low.h
gdbserver/lynx-low.cc
gdbserver/lynx-low.h
gdbserver/nto-low.cc
gdbserver/nto-low.h
gdbserver/target.h
gdbserver/win32-low.cc
gdbserver/win32-low.h

index 96bff86a7f3c9b4bdc06403d0294b98cafa9015c..c8f64541f19731d5a71858324ba0ee999fc7aabe 100644 (file)
@@ -1,3 +1,25 @@
+2020-02-20  Tankut Baris Aktemur  <tankut.baris.aktemur@intel.com>
+
+       * target.h (class process_target): New class definition.
+       (struct process_stratum_target) <pt>: New field with type
+       'process_target*'.
+       * linux-low.h (class linux_process_target): Define as a derived
+       class of 'process_target'.
+       * linux-low.cc (linux_target_ops): Add a linux_process_target*
+       as the 'pt' field.
+       * lynx-low.h (class lynx_process_target): Define as a derived
+       class of 'process_target'.
+       * lynx-low.cc (lynx_target_ops): Add a lynx_process_target*
+       as the 'pt' field.
+       * nto-low.h (class nto_process_target): Define as a derived
+       class of 'process_target'.
+       * nto-low.cc (nto_target_ops): Add an nto_process_target*
+       as the 'pt' field.
+       * win32-low.h (class win32_process_target): Define as a derived
+       class of 'process_target'.
+       * win32-low.cc (win32_target_ops): Add a win32_process_target*
+       as the 'pt' field.
+
 2020-02-19  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * configure: Regenerate.
index 676dea26c637afbd0a146f78810f20ccbda0b830..17f360639a4d5d4b8bcd000c3295766f93d072f8 100644 (file)
@@ -7354,6 +7354,10 @@ linux_get_hwcap2 (int wordsize)
   return hwcap2;
 }
 
+/* The linux target ops object.  */
+
+static linux_process_target the_linux_target;
+
 static process_stratum_target linux_target_ops = {
   linux_create_inferior,
   linux_post_create_inferior,
@@ -7457,6 +7461,7 @@ static process_stratum_target linux_target_ops = {
 #else
   NULL,
 #endif
+  &the_linux_target,
 };
 
 #ifdef HAVE_LINUX_REGSETS
index e25ddd024dd18c79afcfb2197b822bf88eed3d9d..e6042735f388dc006113d28712ced87cb3a0200b 100644 (file)
@@ -264,6 +264,14 @@ struct linux_target_ops
 
 extern struct linux_target_ops the_low_target;
 
+/* Target ops definitions for a Linux target.  */
+
+class linux_process_target : public process_target
+{
+public:
+
+};
+
 #define get_thread_lwp(thr) ((struct lwp_info *) (thread_target_data (thr)))
 #define get_lwp_thread(lwp) ((lwp)->thread)
 
index a5b019396fa4f784ca54853ffdc1ce2e989e4ba5..f1177920921f033abd9702be36081099d4ebe6b6 100644 (file)
@@ -719,6 +719,10 @@ lynx_request_interrupt (void)
   kill (lynx_ptid_get_pid (inferior_ptid), SIGINT);
 }
 
+/* The LynxOS target ops object.  */
+
+static lynx_process_target the_lynx_target;
+
 /* The LynxOS target_ops vector.  */
 
 static process_stratum_target lynx_target_ops = {
@@ -765,6 +769,41 @@ static process_stratum_target lynx_target_ops = {
   NULL,  /* supports_exec_events */
   NULL,  /* handle_new_gdb_connection */
   NULL,  /* handle_monitor_command */
+  NULL,  /* core_of_thread */
+  NULL,  /* read_loadmap */
+  NULL,  /* process_qsupported */
+  NULL,  /* supports_tracepoints */
+  NULL,  /* read_pc */
+  NULL,  /* write_pc */
+  NULL,  /* thread_stopped */
+  NULL,  /* get_tib_address */
+  NULL,  /* pause_all */
+  NULL,  /* unpause_all */
+  NULL,  /* stabilize_threads */
+  NULL,  /* install_fast_tracepoint_jump_pad */
+  NULL,  /* emit_ops */
+  NULL,  /* supports_disable_randomization */
+  NULL,  /* get_min_fast_tracepoint_insn_len */
+  NULL,  /* qxfer_libraries_svr4 */
+  NULL,  /* support_agent */
+  NULL,  /* enable_btrace */
+  NULL,  /* disable_btrace */
+  NULL,  /* read_btrace */
+  NULL,  /* read_btrace_conf */
+  NULL,  /* supports_range_stepping */
+  NULL,  /* pid_to_exec_file */
+  NULL,  /* multifs_open */
+  NULL,  /* multifs_unlink */
+  NULL,  /* multifs_readlink */
+  NULL,  /* breakpoint_kind_from_pc */
+  NULL,  /* sw_breakpoint_from_kind */
+  NULL,  /* thread_name */
+  NULL,  /* breakpoint_kind_from_current_state */
+  NULL,  /* supports_software_single_step */
+  NULL,  /* supports_catch_syscall */
+  NULL,  /* get_ipa_tdesc_idx */
+  NULL,  /* thread_handle */
+  &the_lynx_target,
 };
 
 void
index b122298fb880f0939738740c1d82871783ac4bee..923725dd003bfca8fed6ef9feed6e648b97e5b2a 100644 (file)
@@ -52,6 +52,14 @@ struct lynx_target_ops
 
 extern struct lynx_target_ops the_low_target;
 
+/* Target ops definitions for a LynxOS target.  */
+
+class lynx_process_target : public process_target
+{
+public:
+
+};
+
 /* The inferior's target description.  This is a global because the
    LynxOS ports support neither bi-arch nor multi-process.  */
 extern const struct target_desc *lynx_tdesc;
index b4dea479b9c3a01d8ec08cbe612cff5dd37121dd..6f12a735c1206bc787d91e62d31adff315db095c 100644 (file)
@@ -930,6 +930,9 @@ nto_sw_breakpoint_from_kind (int kind, int *size)
   return the_low_target.breakpoint;
 }
 
+/* The QNX Neutrino target ops object.  */
+
+static nto_process_target the_nto_target;
 
 static process_stratum_target nto_target_ops = {
   nto_create_inferior,
@@ -1003,6 +1006,13 @@ static process_stratum_target nto_target_ops = {
   NULL, /* multifs_readlink */
   NULL, /* breakpoint_kind_from_pc */
   nto_sw_breakpoint_from_kind,
+  NULL, /* thread_name */
+  NULL, /* breakpoint_kind_from_current_state */
+  NULL, /* supports_software_single_step */
+  NULL, /* supports_catch_syscall */
+  NULL, /* get_ipa_tdesc_idx */
+  NULL, /* thread_handle */
+  &the_nto_target,
 };
 
 
index 393b8a98695ca8f370cc5d8b33756ea71f58b7dd..2695db98737083a2d5e8f3f5a7ebf16816e307e1 100644 (file)
@@ -42,6 +42,14 @@ struct nto_target_ops
 
 extern struct nto_target_ops the_low_target;
 
+/* Target ops definitions for a QNX Neutrino target.  */
+
+class nto_process_target : public process_target
+{
+public:
+
+};
+
 /* The inferior's target description.  This is a global because the
    LynxOS ports support neither bi-arch nor multi-process.  */
 extern const struct target_desc *nto_tdesc;
index 1b0810ba04987e2522a00735833ee7c7e5d290bc..af78d8caa902acb745cc65095256f3c2efe2b8a1 100644 (file)
@@ -63,6 +63,8 @@ struct thread_resume
   CORE_ADDR step_range_end;    /* Exclusive */
 };
 
+class process_target;
+
 /* GDBserver doesn't have a concept of strata like GDB, but we call
    its target vector "process_stratum" anyway for the benefit of
    shared code.  */
@@ -477,6 +479,16 @@ struct process_stratum_target
      false for failure.  Return pointer to thread handle via HANDLE
      and the handle's length via HANDLE_LEN.  */
   bool (*thread_handle) (ptid_t ptid, gdb_byte **handle, int *handle_len);
+
+  /* The object that will gradually replace this struct.  */
+  process_target *pt;
+};
+
+class process_target
+{
+public:
+
+  virtual ~process_target () = default;
 };
 
 extern process_stratum_target *the_target;
index cdd70da837421adcae57b356a704becb37caa04a..2a7b2964d926c8e0ecd9f7e7266b4c311d100ec3 100644 (file)
@@ -1834,6 +1834,10 @@ win32_sw_breakpoint_from_kind (int kind, int *size)
   return the_low_target.breakpoint;
 }
 
+/* The win32 target ops object.  */
+
+static win32_process_target the_win32_target;
+
 static process_stratum_target win32_target_ops = {
   win32_create_inferior,
   NULL,  /* post_create_inferior */
@@ -1910,6 +1914,13 @@ static process_stratum_target win32_target_ops = {
   NULL, /* multifs_readlink */
   NULL, /* breakpoint_kind_from_pc */
   win32_sw_breakpoint_from_kind,
+  NULL, /* thread_name */
+  NULL, /* breakpoint_kind_from_current_state */
+  NULL, /* supports_software_single_step */
+  NULL, /* supports_catch_syscall */
+  NULL, /* get_ipa_tdesc_idx */
+  NULL, /* thread_handle */
+  &the_win32_target,
 };
 
 /* Initialize the Win32 backend.  */
index 7a3eeda6e24851cb3b8d641ea8926ccaff035b80..ff96f804fbdd997a34df3181498a75c6a4882880 100644 (file)
@@ -101,6 +101,14 @@ struct win32_target_ops
 
 extern struct win32_target_ops the_low_target;
 
+/* Target ops definitions for a Win32 target.  */
+
+class win32_process_target : public process_target
+{
+public:
+
+};
+
 /* Retrieve the context for this thread, if not already retrieved.  */
 extern void win32_require_context (win32_thread_info *th);