gdbserver_genode.patch

From: Christian Prochaska <christian.prochaska@genode-labs.com>


---
 gdb/gdbserver/linux-arm-low.c |   13 +++++
 gdb/gdbserver/linux-low.c     |  114 +++++++++++++++++++++++++++++++++++++++++
 gdb/gdbserver/linux-low.h     |    2 +
 gdb/gdbserver/linux-x86-low.c |   53 +++++++++++++++++++
 gdb/gdbserver/remote-utils.c  |   12 ++++
 gdb/gdbserver/server.c        |   30 +++++++++--
 gdb/gdbserver/server.h        |    4 +
 7 files changed, 217 insertions(+), 11 deletions(-)

diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c
index babb20c..23d9e60 100644
--- a/gdb/gdbserver/linux-arm-low.c
+++ b/gdb/gdbserver/linux-arm-low.c
@@ -25,6 +25,9 @@
 #ifndef ELFMAG0
 #include <elf.h>
 #endif
+#ifdef __GENODE__
+#include <sys/procfs.h>
+#endif
 #include <sys/ptrace.h>
 
 /* Defined in auto-generated files.  */
@@ -209,7 +212,11 @@ static const unsigned short thumb2_breakpoint[] = { 0xf7f0, 0xa000 };
    is used for gdbserver, so single threaded debugging should work
    OK, but for multi-threaded debugging we only insert the current
    ABI's breakpoint instruction.  For now at least.  */
+#ifdef __GENODE__
+static const unsigned long arm_eabi_breakpoint = 0xe7ffdefe;
+#else
 static const unsigned long arm_eabi_breakpoint = 0xe7f001f0;
+#endif
 
 static int
 arm_breakpoint_at (CORE_ADDR where)
@@ -306,6 +313,11 @@ static void
 arm_arch_setup (void)
 {
   arm_hwcap = 0;
+
+#ifndef __GENODE__
+
+  /* Genode: 'init_registers_arm_with_*()' functions not generated */
+
   if (arm_get_hwcap (&arm_hwcap) == 0)
     {
       init_registers_arm ();
@@ -347,6 +359,7 @@ arm_arch_setup (void)
 
       return;
     }
+#endif
 
   /* The default configuration uses legacy FPA registers, probably
      simulated.  */
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index e597e2f..62215fc 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -20,6 +20,10 @@
 #include "server.h"
 #include "linux-low.h"
 
+#ifdef __GENODE__
+#include "genode-low.h"
+#endif
+
 #include <sys/wait.h>
 #include <stdio.h>
 #include <sys/param.h>
@@ -606,6 +610,7 @@ linux_attach_lwp_1 (unsigned long lwpid, int initial)
   ptid_t ptid;
   struct lwp_info *new_lwp;
 
+#ifndef __GENODE__
   if (ptrace (PTRACE_ATTACH, lwpid, 0, 0) != 0)
     {
       if (!initial)
@@ -621,6 +626,7 @@ linux_attach_lwp_1 (unsigned long lwpid, int initial)
 	error ("Cannot attach to lwp %ld: %s (%d)\n", lwpid,
 	       strerror (errno), errno);
     }
+#endif
 
   if (initial)
     /* NOTE/FIXME: This lwp might have not been the tgid.  */
@@ -637,6 +643,9 @@ linux_attach_lwp_1 (unsigned long lwpid, int initial)
   new_lwp = (struct lwp_info *) add_lwp (ptid);
   add_thread (ptid, new_lwp);
 
+#ifdef __GENODE__
+  new_lwp->stopped = 1;
+#else
   /* We need to wait for SIGSTOP before being able to make the next
      ptrace call on this LWP.  */
   new_lwp->must_set_ptrace_flags = 1;
@@ -675,6 +684,7 @@ linux_attach_lwp_1 (unsigned long lwpid, int initial)
      end of the list, and so the new thread has not yet reached
      wait_for_sigstop (but will).  */
   new_lwp->stop_expected = 1;
+#endif
 }
 
 void
@@ -689,6 +699,7 @@ linux_attach (unsigned long pid)
   linux_attach_lwp_1 (pid, 1);
   linux_add_process (pid, 1);
 
+#ifndef __GENODE__
   if (!non_stop)
     {
       struct thread_info *thread;
@@ -698,6 +709,7 @@ linux_attach (unsigned long pid)
       thread = find_thread_ptid (ptid_build (pid, pid, 0));
       thread->last_resume_kind = resume_stop;
     }
+#endif
 
   return 0;
 }
@@ -812,7 +824,11 @@ linux_kill (int pid)
   return 0;
 }
 
+#ifdef __GENODE__
+int
+#else
 static int
+#endif
 linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
 {
   struct thread_info *thread = (struct thread_info *) entry;
@@ -822,6 +838,7 @@ linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
   if (ptid_get_pid (entry->id) != pid)
     return 0;
 
+#ifndef __GENODE__
   /* If this process is stopped but is expecting a SIGSTOP, then make
      sure we take care of that now.  This isn't absolutely guaranteed
      to collect the SIGSTOP, but is fairly likely to.  */
@@ -833,13 +850,16 @@ linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
       linux_resume_one_lwp (lwp, 0, 0, NULL);
       linux_wait_for_event (lwp->head.id, &wstat, __WALL);
     }
+#endif
 
   /* Flush any pending changes to the process's registers.  */
   regcache_invalidate_one ((struct inferior_list_entry *)
 			   get_lwp_thread (lwp));
 
+#ifndef __GENODE__
   /* Finally, let it resume.  */
   ptrace (PTRACE_DETACH, lwpid_of (lwp), 0, 0);
+#endif
 
   delete_lwp (lwp);
   return 0;
@@ -1071,6 +1091,10 @@ retry:
 
   if (WIFSTOPPED (*wstatp) && WSTOPSIG (*wstatp) == SIGTRAP)
     {
+#ifdef __GENODE__
+      /* no watchpoint support yet */
+	  child->stopped_by_watchpoint = 0;
+#else
       if (the_low_target.stopped_by_watchpoint == NULL)
 	{
 	  child->stopped_by_watchpoint = 0;
@@ -1096,7 +1120,8 @@ retry:
 
 	  current_inferior = saved_inferior;
 	}
-    }
+#endif
+	}
 
   /* Store the STOP_PC, with adjustment applied.  This depends on the
      architecture being defined already (so that CHILD has a valid
@@ -2469,18 +2494,22 @@ linux_wait (ptid_t ptid,
   if (debug_threads)
     fprintf (stderr, "linux_wait: [%s]\n", target_pid_to_str (ptid));
 
+#ifndef __GENODE__
   /* Flush the async file first.  */
   if (target_is_async_p ())
     async_file_flush ();
+#endif
 
   event_ptid = linux_wait_1 (ptid, ourstatus, target_options);
 
+#ifndef __GENODE__
   /* If at least one stop was reported, there may be more.  A single
      SIGCHLD can signal more than one child stop.  */
   if (target_is_async_p ()
       && (target_options & TARGET_WNOHANG) != 0
       && !ptid_equal (event_ptid, null_ptid))
     async_file_mark ();
+#endif
 
   return event_ptid;
 }
@@ -2958,10 +2987,25 @@ lwp %ld wants to get out of fast tracepoint jump pad single-stepping\n",
   lwp->stopped = 0;
   lwp->stopped_by_watchpoint = 0;
   lwp->stepping = step;
+
+#ifdef __GENODE__
+
+  /*
+   * On Linux, the thread would get stopped immediately after resuming
+   * if a SIGSTOP is pending. This is not the case on Genode, so we
+   * just keep the thread stopped.
+   */
+  if (lwp->stop_expected)
+	return;
+
+  genode_continue_thread(lwpid_of(lwp), step);
+
+#else
   ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, lwpid_of (lwp), 0,
 	  /* Coerce to a uintptr_t first to avoid potential gcc warning
 	     of coercing an 8 byte integer to a 4 byte pointer.  */
 	  (PTRACE_ARG4_TYPE) (uintptr_t) signal);
+#endif
 
   current_inferior = saved_inferior;
   if (errno)
@@ -5009,6 +5053,13 @@ linux_core_of_thread (ptid_t ptid)
 static void
 linux_process_qsupported (const char *query)
 {
+#ifdef __GENODE__
+  /*
+   * 'qSupported' is the first command sent by GDB when attaching to the
+   * server, so when at this location, GDB has just (re-)attached itself.
+   */
+  genode_stop_all_threads();
+#endif
   if (the_low_target.process_qsupported != NULL)
     the_low_target.process_qsupported (query);
 }
@@ -5110,26 +5161,56 @@ linux_emit_ops (void)
 static struct target_ops linux_target_ops = {
   linux_create_inferior,
   linux_attach,
+#ifndef __GENODE__
   linux_kill,
   linux_detach,
   linux_mourn,
   linux_join,
+#else
+  genode_kill,
+  genode_detach,
+  NULL,
+  NULL,
+#endif
   linux_thread_alive,
   linux_resume,
   linux_wait,
+#ifndef __GENODE__
   linux_fetch_registers,
   linux_store_registers,
+#else
+  genode_fetch_registers,
+  genode_store_registers,
+#endif
   linux_prepare_to_access_memory,
   linux_done_accessing_memory,
+#ifndef __GENODE__
   linux_read_memory,
   linux_write_memory,
+#else
+  genode_read_memory,
+  genode_write_memory,
+#endif
+#ifndef __GENODE__
   linux_look_up_symbols,
+#else
+  NULL,
+#endif
   linux_request_interrupt,
+#ifndef __GENODE__
   linux_read_auxv,
+#else
+  NULL,
+#endif
   linux_insert_point,
   linux_remove_point,
+#ifndef __GENODE__
   linux_stopped_by_watchpoint,
   linux_stopped_data_address,
+#else
+  NULL,
+  NULL,
+#endif
 #if defined(__UCLIBC__) && defined(HAS_NOMMU)
   linux_read_offsets,
 #else
@@ -5140,6 +5221,7 @@ static struct target_ops linux_target_ops = {
 #else
   NULL,
 #endif
+#ifndef __GENODE__
   linux_qxfer_spu,
   hostio_last_error_from_errno,
   linux_qxfer_osdata,
@@ -5148,13 +5230,28 @@ static struct target_ops linux_target_ops = {
   linux_async,
   linux_start_non_stop,
   linux_supports_multi_process,
+#else
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+#endif
 #ifdef USE_THREAD_DB
   thread_db_handle_monitor_command,
 #else
   NULL,
 #endif
+#ifndef __GENODE__
   linux_core_of_thread,
+#else
+  NULL,
+#endif
   linux_process_qsupported,
+#ifndef __GENODE__
   linux_supports_tracepoints,
   linux_read_pc,
   linux_write_pc,
@@ -5166,6 +5263,19 @@ static struct target_ops linux_target_ops = {
   linux_stabilize_threads,
   linux_install_fast_tracepoint_jump_pad,
   linux_emit_ops
+#else
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL
+#endif
 };
 
 static void
@@ -5187,7 +5297,9 @@ initialize_low (void)
   set_breakpoint_data (the_low_target.breakpoint,
 		       the_low_target.breakpoint_len);
   linux_init_signals ();
+#ifndef __GENODE__
   linux_test_for_tracefork ();
+#endif
 #ifdef HAVE_LINUX_REGSETS
   for (num_regsets = 0; target_regsets[num_regsets].size >= 0; num_regsets++)
     ;
diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
index d449e1b..0bbcbfd 100644
--- a/gdb/gdbserver/linux-low.h
+++ b/gdb/gdbserver/linux-low.h
@@ -22,7 +22,9 @@
 #endif
 
 #include <signal.h>
+#ifndef __GENODE__
 #include "gdb_proc_service.h"
+#endif
 
 #ifdef HAVE_LINUX_REGSETS
 typedef void (*regset_fill_func) (struct regcache *, void *);
diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
index 82dcf83..e98e3bd 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -28,8 +28,17 @@
 #include "i386-xstate.h"
 #include "elf/common.h"
 
+#ifndef __GENODE__
 #include "gdb_proc_service.h"
+#endif
 
+#ifdef __GENODE__
+/* Defined in auto-generated file i386.c.  */
+void init_registers_i386 (void);
+static inline void init_registers_i386_linux(void) { init_registers_i386(); }
+void init_registers_i386_avx (void);
+static inline void init_registers_i386_avx_linux(void) { init_registers_i386_avx(); }
+#else
 /* Defined in auto-generated file i386-linux.c.  */
 void init_registers_i386_linux (void);
 /* Defined in auto-generated file amd64-linux.c.  */
@@ -40,10 +49,24 @@ void init_registers_i386_avx_linux (void);
 void init_registers_amd64_avx_linux (void);
 /* Defined in auto-generated file i386-mmx-linux.c.  */
 void init_registers_i386_mmx_linux (void);
+#endif
 
 static unsigned char jump_insn[] = { 0xe9, 0, 0, 0, 0 };
 
 /* Backward compatibility for gdb without XML support.  */
+#ifdef __GENODE__
+
+static const char *xmltarget_i386_linux_no_xml = "@<target>\
+<architecture>i386</architecture>\
+</target>";
+
+#ifdef __x86_64__
+static const char *xmltarget_amd64_linux_no_xml = "@<target>\
+<architecture>i386:x86-64</architecture>\
+</target>";
+#endif
+
+#else
 
 static const char *xmltarget_i386_linux_no_xml = "@<target>\
 <architecture>i386</architecture>\
@@ -57,7 +80,15 @@ static const char *xmltarget_amd64_linux_no_xml = "@<target>\
 </target>";
 #endif
 
+#endif /* __GENODE__ */
+
+#ifdef __GENODE__
+#ifndef __x86_64__
+#include "i386.h"
+#endif /* __x86_64__ */
+#else
 #include <sys/reg.h>
+#endif
 #include <sys/procfs.h>
 #include <sys/ptrace.h>
 #include <sys/uio.h>
@@ -273,8 +304,10 @@ x86_fill_gregset (struct regcache *regcache, void *buf)
   for (i = 0; i < I386_NUM_REGS; i++)
     collect_register (regcache, i, ((char *) buf) + i386_regmap[i]);
 
+#ifndef __GENODE__
   collect_register_by_name (regcache, "orig_eax",
 			    ((char *) buf) + ORIG_EAX * 4);
+#endif
 }
 
 static void
@@ -295,8 +328,10 @@ x86_store_gregset (struct regcache *regcache, const void *buf)
   for (i = 0; i < I386_NUM_REGS; i++)
     supply_register (regcache, i, ((char *) buf) + i386_regmap[i]);
 
+#ifndef __GENODE__
   supply_register_by_name (regcache, "orig_eax",
 			   ((char *) buf) + ORIG_EAX * 4);
+#endif
 }
 
 static void
@@ -414,7 +449,15 @@ x86_set_pc (struct regcache *regcache, CORE_ADDR pc)
     }
 }
 
+#ifdef __GENODE__
+/* The 'INT3' instruction is used by some kernel debuggers and thus cannot
+ * serve as breakpoint instruction for the GDB monitor. Instead, the 'HLT'
+ * instruction gets used. It's a privileged instruction which triggers an
+ * exception when executed in user mode */
+static const unsigned char x86_breakpoint[] = { 0xF4 };
+#else
 static const unsigned char x86_breakpoint[] = { 0xCC };
+#endif
 #define x86_breakpoint_len 1
 
 static int
@@ -423,7 +466,7 @@ x86_breakpoint_at (CORE_ADDR pc)
   unsigned char c;
 
   (*the_target->read_memory) (pc, &c, 1);
-  if (c == 0xCC)
+  if (c == x86_breakpoint[0])
     return 1;
 
   return 0;
@@ -2561,7 +2604,11 @@ struct linux_target_ops the_low_target =
   x86_breakpoint,
   x86_breakpoint_len,
   NULL,
+#ifndef __GENODE__
   1,
+#else
+  0, /* With the HLT instruction, the PC does not get incremented */
+#endif
   x86_breakpoint_at,
   x86_insert_point,
   x86_remove_point,
@@ -2576,7 +2623,11 @@ struct linux_target_ops the_low_target =
   x86_siginfo_fixup,
   x86_linux_new_process,
   x86_linux_new_thread,
+#ifndef __GENODE__
   x86_linux_prepare_to_resume,
+#else
+  NULL,
+#endif
   x86_linux_process_qsupported,
   x86_supports_tracepoints,
   x86_get_thread_area,
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index 650ddf8..7a53e77 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -21,6 +21,12 @@
 #include "server.h"
 #include "terminal.h"
 #include "target.h"
+
+#ifdef __GENODE__
+#include <sys/types.h>
+#include "genode-low.h"
+#endif
+
 #include <stdio.h>
 #include <string.h>
 #if HAVE_SYS_IOCTL_H
@@ -106,8 +112,10 @@ struct sym_cache
 
 int remote_debug = 0;
 struct ui_file *gdb_stdlog;
-
-static gdb_fildes_t remote_desc = INVALID_DESCRIPTOR;
+#ifndef __GENODE__
+static
+#endif
+gdb_fildes_t remote_desc = INVALID_DESCRIPTOR;
 static gdb_fildes_t listen_desc = INVALID_DESCRIPTOR;
 
 /* FIXME headerize? */
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 2f4484f..124c98d 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -20,6 +20,11 @@
 
 #include "server.h"
 
+#ifdef __GENODE__
+#include "genode-low.h"
+#include "linux-low.h"
+#endif
+
 #if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -2055,11 +2060,11 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
 	  return;
 	}
     }
-
+#ifndef __GENODE__
   if (strncmp (own_buf, "vFile:", 6) == 0
       && handle_vFile (own_buf, packet_len, new_packet_len))
     return;
-
+#endif
   if (strncmp (own_buf, "vAttach;", 8) == 0)
     {
       if (!multi_process && target_running ())
@@ -2449,7 +2454,11 @@ join_inferiors_callback (struct inferior_list_entry *entry)
 }
 
 int
+#ifdef __GENODE__
+gdbserver_main (int argc, char *argv[])
+#else
 main (int argc, char *argv[])
+#endif
 {
   int bad_attach;
   int pid;
@@ -2754,6 +2763,9 @@ process_serial_event (void)
   response_needed = 1;
 
   i = 0;
+#ifdef __GENODE
+  if (debug_threads) printf("GDB command = %s\n", own_buf);
+#endif
   ch = own_buf[i++];
   switch (ch)
     {
@@ -2844,7 +2856,9 @@ process_serial_event (void)
 		 gone.  */
 	      for_each_inferior (&all_processes,
 				 join_inferiors_callback);
+#ifndef __GENODE__
 	      exit (0);
+#endif
 	    }
 	}
       break;
@@ -3076,7 +3090,11 @@ process_serial_event (void)
 	  return 0;
 	}
       else
+#ifndef __GENODE__
 	exit (0);
+#else
+      return 0;
+#endif
 
     case 'T':
       {
@@ -3140,14 +3158,16 @@ process_serial_event (void)
       own_buf[0] = '\0';
       break;
     }
-
+#ifdef __GENODE__
+  if (debug_threads) printf("GDBserver response = %s\n", own_buf);
+#endif
   if (new_packet_len != -1)
     putpkt_binary (own_buf, new_packet_len);
   else
     putpkt (own_buf);
 
   response_needed = 0;
-
+#ifndef __GENODE__
   if (!extended_protocol && have_ran && !target_running ())
     {
       /* In non-stop, defer exiting until GDB had a chance to query
@@ -3159,7 +3179,7 @@ process_serial_event (void)
 	  exit (0);
 	}
     }
-
+#endif
   if (exit_requested)
     return -1;
 
diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
index 77f5dd6..897abed 100644
--- a/gdb/gdbserver/server.h
+++ b/gdb/gdbserver/server.h
@@ -664,8 +664,8 @@ struct emit_ops
 /* Returns the address of the get_raw_reg function in the IPA.  */
 CORE_ADDR get_raw_reg_func_addr (void);
 
-CORE_ADDR current_insn_ptr;
-int emit_error;
+extern CORE_ADDR current_insn_ptr;
+extern int emit_error;
 
 /* Version information, from version.c.  */
 extern const char version[];
