[v3,26/29] Add read_pc / write_pc support to win32-low

Message ID 20200313190855.28662-27-tromey@adacore.com
State New
Headers show
Series
  • Windows code sharing + bug fix
Related show

Commit Message

Tom Tromey March 13, 2020, 7:08 p.m.
This changes win32-low.c to implement the read_pc and write_pc
methods.  A subsequent patch will need these.

Note that I have no way to test, or even compile, the win32-arm-low.c
change.

gdbserver/ChangeLog
2020-03-13  Tom Tromey  <tromey@adacore.com>

	* win32-low.h (win32_process_target::read_pc)
	(win32_process_target::write_pc): Declare.
	* win32-low.c (win32_process_target::read_pc)
	(win32_process_target::write_pc): New methods.
	* win32-i386-low.c (i386_win32_get_pc, i386_win32_set_pc): New
	functions.
	(the_low_target): Update.
	* win32-arm-low.c (arm_win32_get_pc, arm_win32_set_pc): New
	functions.
	(the_low_target): Update.
---
 gdbserver/ChangeLog         | 13 +++++++++++
 gdbserver/win32-arm-low.cc  | 23 +++++++++++++++++++
 gdbserver/win32-i386-low.cc | 46 +++++++++++++++++++++++++++++++++++++
 gdbserver/win32-low.cc      | 12 ++++++++++
 gdbserver/win32-low.h       |  9 ++++++++
 5 files changed, 103 insertions(+)

-- 
2.21.1

Patch

diff --git a/gdbserver/win32-arm-low.cc b/gdbserver/win32-arm-low.cc
index 78b7fd09ec3..77200112df1 100644
--- a/gdbserver/win32-arm-low.cc
+++ b/gdbserver/win32-arm-low.cc
@@ -115,6 +115,27 @@  arm_arch_setup (void)
 static const unsigned long arm_wince_breakpoint = 0xe6000010;
 #define arm_wince_breakpoint_len 4
 
+/* Implement win32_target_ops "get_pc" method.  */
+
+static CORE_ADDR
+arm_win32_get_pc (struct regcache *regcache)
+{
+  uint32_t pc;
+
+  collect_register_by_name (regcache, "pc", &pc);
+  return (CORE_ADDR) pc;
+}
+
+/* Implement win32_target_ops "set_pc" method.  */
+
+static void
+arm_win32_set_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  uint32_t newpc = pc;
+
+  supply_register_by_name (regcache, "pc", &newpc);
+}
+
 struct win32_target_ops the_low_target = {
   arm_arch_setup,
   sizeof (mappings) / sizeof (mappings[0]),
@@ -127,6 +148,8 @@  struct win32_target_ops the_low_target = {
   NULL, /* single_step */
   (const unsigned char *) &arm_wince_breakpoint,
   arm_wince_breakpoint_len,
+  arm_win32_get_pc,
+  arm_win32_set_pc,
   /* Watchpoint related functions.  See target.h for comments.  */
   NULL, /* supports_z_point_type */
   NULL, /* insert_point */
diff --git a/gdbserver/win32-i386-low.cc b/gdbserver/win32-i386-low.cc
index 1c14bc70362..eac15b5694a 100644
--- a/gdbserver/win32-i386-low.cc
+++ b/gdbserver/win32-i386-low.cc
@@ -450,6 +450,50 @@  i386_arch_setup (void)
   win32_tdesc = tdesc;
 }
 
+/* Implement win32_target_ops "get_pc" method.  */
+
+static CORE_ADDR
+i386_win32_get_pc (struct regcache *regcache)
+{
+  bool use_64bit = register_size (regcache->tdesc, 0) == 8;
+
+  if (use_64bit)
+    {
+      uint64_t pc;
+
+      collect_register_by_name (regcache, "rip", &pc);
+      return (CORE_ADDR) pc;
+    }
+  else
+    {
+      uint32_t pc;
+
+      collect_register_by_name (regcache, "eip", &pc);
+      return (CORE_ADDR) pc;
+    }
+}
+
+/* Implement win32_target_ops "set_pc" method.  */
+
+static void
+i386_win32_set_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  bool use_64bit = register_size (regcache->tdesc, 0) == 8;
+
+  if (use_64bit)
+    {
+      uint64_t newpc = pc;
+
+      supply_register_by_name (regcache, "rip", &newpc);
+    }
+  else
+    {
+      uint32_t newpc = pc;
+
+      supply_register_by_name (regcache, "eip", &newpc);
+    }
+}
+
 struct win32_target_ops the_low_target = {
   i386_arch_setup,
   sizeof (mappings) / sizeof (mappings[0]),
@@ -462,6 +506,8 @@  struct win32_target_ops the_low_target = {
   i386_single_step,
   &i386_win32_breakpoint,
   i386_win32_breakpoint_len,
+  i386_win32_get_pc,
+  i386_win32_set_pc,
   i386_supports_z_point_type,
   i386_insert_point,
   i386_remove_point,
diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc
index d151505e9f8..131eacb13c4 100644
--- a/gdbserver/win32-low.cc
+++ b/gdbserver/win32-low.cc
@@ -1659,6 +1659,18 @@  win32_process_target::sw_breakpoint_from_kind (int kind, int *size)
   return the_low_target.breakpoint;
 }
 
+CORE_ADDR
+win32_process_target::read_pc (struct regcache *regcache)
+{
+  return (*the_low_target.get_pc) (regcache);
+}
+
+void
+win32_process_target::write_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  return (*the_low_target.set_pc) (regcache, pc);
+}
+
 /* The win32 target ops object.  */
 
 static win32_process_target the_win32_target;
diff --git a/gdbserver/win32-low.h b/gdbserver/win32-low.h
index 917f7275622..56ff8a9baf2 100644
--- a/gdbserver/win32-low.h
+++ b/gdbserver/win32-low.h
@@ -63,6 +63,11 @@  struct win32_target_ops
   const unsigned char *breakpoint;
   int breakpoint_len;
 
+  /* Get the PC register from REGCACHE.  */
+  CORE_ADDR (*get_pc) (struct regcache *regcache);
+  /* Set the PC register in REGCACHE.  */
+  void (*set_pc) (struct regcache *regcache, CORE_ADDR newpc);
+
   /* Breakpoint/Watchpoint related functions.  See target.h for comments.  */
   int (*supports_z_point_type) (char z_type);
   int (*insert_point) (enum raw_bkpt_type type, CORE_ADDR addr,
@@ -142,6 +147,10 @@  class win32_process_target : public process_stratum_target
   int get_tib_address (ptid_t ptid, CORE_ADDR *addr) override;
 
   const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override;
+
+  CORE_ADDR read_pc (regcache *regcache) override;
+
+  void write_pc (regcache *regcache, CORE_ADDR pc) override;
 };
 
 /* Retrieve the context for this thread, if not already retrieved.  */