gdbserver_genode.patch

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


---
 gdb/nat/fork-inferior.c        |    4 +
 gdb/nat/gdb_ptrace.h           |    2 +
 gdb/nat/linux-ptrace.c         |   28 +++++++++
 gdb/nat/linux-ptrace.h         |    4 +
 gdbserver/linux-aarch32-low.cc |    4 +
 gdbserver/linux-arm-low.cc     |    8 +++
 gdbserver/linux-low.cc         |   73 ++++++++++++++++++++++++
 gdbserver/linux-low.h          |    8 ++-
 gdbserver/linux-x86-low.cc     |  120 +++++++++++++++++++++++++++++++++++++++-
 gdbserver/linux-x86-tdesc.cc   |    8 +++
 gdbserver/remote-utils.cc      |   15 +++++
 gdbserver/server.cc            |   32 ++++++++++-
 gdbsupport/common-defs.h       |    4 +
 gdbsupport/common-inferior.cc  |    4 +
 gdbsupport/common-types.h      |   17 ++++++
 gdbsupport/gdb-sigmask.h       |    4 +
 gdbsupport/gdb_tilde_expand.cc |   10 +++
 gdbsupport/pathstuff.cc        |    2 +
 18 files changed, 333 insertions(+), 14 deletions(-)

diff --git a/gdb/nat/fork-inferior.c b/gdb/nat/fork-inferior.c
index 559773f7..bab829fb 100644
--- a/gdb/nat/fork-inferior.c
+++ b/gdb/nat/fork-inferior.c
@@ -402,9 +402,9 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
         undebuggable.  Indeed, you probably got an error message
         saying "not parent".  Sorry; you'll have to use print
         statements!  */
-
+#ifndef __GENODE__
       restore_original_signals_state ();
-
+#endif /* __GENODE__ */
       /* There is no execlpe call, so we have to set the environment
          for our child in the global variable.  If we've vforked, this
          clobbers the parent, but environ is restored a few lines down
diff --git a/gdb/nat/gdb_ptrace.h b/gdb/nat/gdb_ptrace.h
index f7bdd113..8f148d10 100644
--- a/gdb/nat/gdb_ptrace.h
+++ b/gdb/nat/gdb_ptrace.h
@@ -121,6 +121,7 @@
 # endif
 #endif
 
+#ifndef __GENODE__
 /* Some systems, at least AIX and HP-UX have a ptrace with five
    arguments.  Since we never use the fifth argument, define a ptrace
    macro that calls the real ptrace with the last argument set to
@@ -141,5 +142,6 @@
 # define ptrace(request, pid, addr, data) \
          ptrace ((PTRACE_TYPE_ARG1) request, pid, addr, data)
 #endif
+#endif /* __GENODE__ */
 
 #endif /* NAT_GDB_PTRACE_H */
diff --git a/gdb/nat/linux-ptrace.c b/gdb/nat/linux-ptrace.c
index 17f43154..842b8077 100644
--- a/gdb/nat/linux-ptrace.c
+++ b/gdb/nat/linux-ptrace.c
@@ -36,6 +36,7 @@ static int supported_ptrace_options = -1;
 std::string
 linux_ptrace_attach_fail_reason (pid_t pid)
 {
+#ifndef __GENODE__
   pid_t tracerpid = linux_proc_get_tracerpid_nowarn (pid);
   std::string result;
 
@@ -51,6 +52,7 @@ linux_ptrace_attach_fail_reason (pid_t pid)
 		    (int) pid);
 
   return result;
+#endif
 }
 
 /* See linux-ptrace.h.  */
@@ -73,10 +75,13 @@ linux_ptrace_attach_fail_reason_string (ptid_t ptid, int err)
 /* Address of the 'ret' instruction in asm code block below.  */
 EXTERN_C void linux_ptrace_test_ret_to_nx_instr (void);
 
+#ifndef __GENODE__
 #include <sys/reg.h>
+#endif
 #include <sys/mman.h>
 #include <signal.h>
-
+#else
+#include <signal.h>
 #endif /* defined __i386__ || defined __x86_64__ */
 
 /* Kill CHILD.  WHO is used to report warnings.  */
@@ -112,6 +117,7 @@ kill_child (pid_t child, const char *who)
     }
 }
 
+#ifndef __GENODE__
 /* Test broken off-trunk Linux kernel patchset for NX support on i386.  It was
    removed in Fedora kernel 88fa1f0332d188795ed73d7ac2b1564e11a0b4cd.
 
@@ -256,6 +262,7 @@ linux_ptrace_test_ret_to_nx (void)
 	       "support detected!"));
 #endif /* defined __i386__ || defined __x86_64__ */
 }
+#endif /* __GENODE__ */
 
 /* Helper function to fork a process and make the child process call
    the function FUNCTION, passing CHILD_STACK as parameter.
@@ -341,6 +348,7 @@ static void linux_test_for_exitkill (int child_pid);
 void
 linux_check_ptrace_features (void)
 {
+#ifndef __GENODE__
   int child_pid, ret, status;
 
   /* Initialize the options.  */
@@ -370,6 +378,18 @@ linux_check_ptrace_features (void)
 
   /* Kill child_pid.  */
   kill_child (child_pid, "linux_check_ptrace_features");
+
+  /* Clean things up and kill any pending children.  */
+  do
+    {
+      ret = ptrace (PTRACE_KILL, child_pid, (PTRACE_TYPE_ARG3) 0,
+		    (PTRACE_TYPE_ARG4) 0);
+      if (ret != 0)
+	warning (_("linux_check_ptrace_features: failed to kill child"));
+      my_waitpid (child_pid, &status, 0);
+    }
+  while (WIFSTOPPED (status));
+#endif
 }
 
 /* Determine if PTRACE_O_TRACESYSGOOD can be used to catch
@@ -482,6 +502,7 @@ linux_test_for_exitkill (int child_pid)
 void
 linux_enable_event_reporting (pid_t pid, int options)
 {
+#ifndef __GENODE__
   /* Check if we have initialized the ptrace features for this
      target.  If not, do it now.  */
   if (supported_ptrace_options == -1)
@@ -496,6 +517,7 @@ linux_enable_event_reporting (pid_t pid, int options)
   /* Set the options.  */
   ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0,
 	  (PTRACE_TYPE_ARG4) (uintptr_t) options);
+#endif /* __GENODE__ */
 }
 
 /* Disable reporting of all currently supported ptrace events.  */
@@ -503,8 +525,10 @@ linux_enable_event_reporting (pid_t pid, int options)
 void
 linux_disable_event_reporting (pid_t pid)
 {
+#ifndef __GENODE__
   /* Set the options.  */
   ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0, 0);
+#endif /* __GENODE__ */
 }
 
 /* Returns non-zero if PTRACE_OPTIONS is contained within
@@ -583,7 +607,9 @@ linux_ptrace_init_warnings (void)
     return;
   warned = 1;
 
+#ifndef __GENODE__
   linux_ptrace_test_ret_to_nx ();
+#endif
 }
 
 /* Extract extended ptrace event from wait status.  */
diff --git a/gdb/nat/linux-ptrace.h b/gdb/nat/linux-ptrace.h
index 6e973dc5..16ba731f 100644
--- a/gdb/nat/linux-ptrace.h
+++ b/gdb/nat/linux-ptrace.h
@@ -115,7 +115,11 @@ struct buffer;
    way to go.  That said, some architecture may get the si_code wrong,
    and as such we're leaving fallback code in place.  We'll remove
    this after a while if no problem is reported.  */
+#ifdef __GENODE__
+#define USE_SIGTRAP_SIGINFO 0
+#else
 #define USE_SIGTRAP_SIGINFO 1
+#endif
 
 /* The x86 kernel gets some of the si_code values backwards, like
    this:
diff --git a/gdbserver/linux-aarch32-low.cc b/gdbserver/linux-aarch32-low.cc
index 8f733e7d..c621ec30 100644
--- a/gdbserver/linux-aarch32-low.cc
+++ b/gdbserver/linux-aarch32-low.cc
@@ -35,7 +35,11 @@
    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__
+#define arm_eabi_breakpoint 0xe7ffdefeUL
+#else
 #define arm_eabi_breakpoint 0xe7f001f0UL
+#endif
 
 #if (defined __ARM_EABI__ || defined __aarch64__)
 static const unsigned long arm_breakpoint = arm_eabi_breakpoint;
diff --git a/gdbserver/linux-arm-low.cc b/gdbserver/linux-arm-low.cc
index cba0f078..521e07c0 100644
--- a/gdbserver/linux-arm-low.cc
+++ b/gdbserver/linux-arm-low.cc
@@ -32,6 +32,9 @@
 #include <elf.h>
 #endif
 #include "nat/gdb_ptrace.h"
+#ifdef __GENODE__
+#include <sys/procfs.h>
+#endif
 #include <signal.h>
 #include <sys/syscall.h>
 
@@ -960,6 +963,10 @@ arm_read_description (void)
 {
   unsigned long arm_hwcap = linux_get_hwcap (4);
 
+  /* Query hardware watchpoint/breakpoint capabilities.  */
+  arm_linux_init_hwbp_cap (pid);
+
+#ifndef __GENODE__
   if (arm_hwcap & HWCAP_IWMMXT)
     return arm_linux_read_description (ARM_FP_TYPE_IWMMXT);
 
@@ -982,6 +989,7 @@ arm_read_description (void)
       else
 	return arm_linux_read_description (ARM_FP_TYPE_VFPV2);
     }
+#endif
 
   /* The default configuration uses legacy FPA registers, probably
      simulated.  */
diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc
index b1f997ae..823c5e56 100644
--- a/gdbserver/linux-low.cc
+++ b/gdbserver/linux-low.cc
@@ -27,6 +27,11 @@
 #include "nat/linux-waitpid.h"
 #include "gdbsupport/gdb_wait.h"
 #include "nat/gdb_ptrace.h"
+
+#ifdef __GENODE__
+#include "genode-low.h"
+#endif
+
 #include "nat/linux-ptrace.h"
 #include "nat/linux-procfs.h"
 #include "nat/linux-personality.h"
@@ -694,7 +699,11 @@ linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp,
       /* Set the event status.  */
       event_lwp->waitstatus.kind = TARGET_WAITKIND_EXECD;
       event_lwp->waitstatus.value.execd_pathname
+#ifdef __GENODE__
+    = xstrdup ("target");
+#else
 	= xstrdup (linux_proc_pid_to_exec_file (lwpid_of (event_thr)));
+#endif
 
       /* Mark the exec status as pending.  */
       event_lwp->stopped = 1;
@@ -970,8 +979,10 @@ linux_process_target::create_inferior (const char *program,
   ptid_t ptid;
 
   {
+#ifndef __GENODE__
     maybe_disable_address_space_randomization restore_personality
       (cs.disable_randomization);
+#endif /* __GENODE__ */
     std::string str_program_args = construct_inferior_arguments (program_args);
 
     pid = fork_inferior (program,
@@ -1016,12 +1027,17 @@ linux_process_target::attach_lwp (ptid_t ptid)
   struct lwp_info *new_lwp;
   int lwpid = ptid.lwp ();
 
+#ifndef __GENODE__
   if (ptrace (PTRACE_ATTACH, lwpid, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0)
       != 0)
     return errno;
+#endif
 
   new_lwp = add_lwp (ptid);
 
+#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;
@@ -1088,6 +1104,7 @@ linux_process_target::attach_lwp (ptid_t ptid)
      end of the list, and so the new thread has not yet reached
      wait_for_sigstop (but will).  */
   new_lwp->stop_expected = 1;
+#endif
 
   return 0;
 }
@@ -1163,6 +1180,7 @@ linux_process_target::attach (unsigned long pid)
       error ("Cannot attach to process %ld: %s", pid, reason.c_str ());
     }
 
+#ifndef __GENODE__
   /* Don't ignore the initial SIGSTOP if we just attached to this
      process.  It will be collected by wait shortly.  */
   initial_thread = find_thread_ptid (ptid_t (pid, pid, 0));
@@ -1209,6 +1227,7 @@ linux_process_target::attach (unsigned long pid)
       gdb_assert (proc->tdesc != NULL);
     }
 
+#endif
   return 0;
 }
 
@@ -1346,6 +1365,7 @@ kill_one_lwp_callback (thread_info *thread, int pid)
   kill_wait_lwp (lwp);
 }
 
+#ifndef __GENODE__
 int
 linux_process_target::kill (process_info *process)
 {
@@ -1380,6 +1400,7 @@ linux_process_target::kill (process_info *process)
   unstop_all_lwps (0, NULL);
   return 0;
 }
+#endif /* __GENODE__ */
 
 /* Get pending signal of THREAD, for detaching purposes.  This is the
    signal the thread last stopped for, which we need to deliver to the
@@ -1466,10 +1487,13 @@ void
 linux_process_target::detach_one_lwp (lwp_info *lwp)
 {
   struct thread_info *thread = get_lwp_thread (lwp);
+#ifndef __GENODE__
   int sig;
+#endif /* __GENODE__ */
   int lwpid;
 
   /* If there is a pending SIGSTOP, get rid of it.  */
+#ifndef __GENODE__
   if (lwp->stop_expected)
     {
       if (debug_threads)
@@ -1479,7 +1503,9 @@ linux_process_target::detach_one_lwp (lwp_info *lwp)
       kill_lwp (lwpid_of (thread), SIGCONT);
       lwp->stop_expected = 0;
     }
+#endif
 
+#ifndef __GENODE__
   /* Pass on any pending signal for this thread.  */
   sig = get_detach_signal (thread);
 
@@ -1540,10 +1566,12 @@ linux_process_target::detach_one_lwp (lwp_info *lwp)
 		    target_pid_to_str (ptid_of (thread)),
 		    strsignal (sig));
     }
+#endif
 
   delete_lwp (lwp);
 }
 
+#ifndef __GENODE__
 int
 linux_process_target::detach (process_info *process)
 {
@@ -1592,6 +1620,7 @@ linux_process_target::detach (process_info *process)
   unstop_all_lwps (0, NULL);
   return 0;
 }
+#endif /* __GENODE__ */
 
 /* Remove all LWPs that belong to process PROC from the lwp list.  */
 
@@ -1806,6 +1835,7 @@ iterate_over_lwps (ptid_t filter,
 void
 linux_process_target::check_zombie_leaders ()
 {
+#ifndef __GENODE__
   for_each_process ([this] (process_info *proc) {
     pid_t leader_pid = pid_of (proc);
     struct lwp_info *leader_lp;
@@ -1860,6 +1890,7 @@ linux_process_target::check_zombie_leaders ()
 	delete_lwp (leader_lp);
       }
     });
+#endif /* __GENODE__ */
 }
 
 /* Callback for `find_thread'.  Returns the first LWP that is not
@@ -2606,11 +2637,13 @@ linux_process_target::wait_for_event_filtered (ptid_t wait_ptid,
 
       if (ret > 0)
 	{
+#ifndef __GENODE__
 	  if (debug_threads)
 	    {
 	      debug_printf ("LLW: waitpid %ld received %s\n",
 			    (long) ret, status_to_str (*wstatp));
 	    }
+#endif /* __GENODE__ */
 
 	  /* Filter all events.  IOW, leave all events pending.  We'll
 	     randomly select an event LWP out of all that have events
@@ -2884,11 +2917,12 @@ linux_process_target::stabilize_threads ()
 static ptid_t
 ignore_event (struct target_waitstatus *ourstatus)
 {
+#ifndef __GENODE__
   /* If we got an event, there may still be others, as a single
      SIGCHLD can indicate more than one child stopped.  This forces
      another target_wait call.  */
   async_file_mark ();
-
+#endif /* __GENODE__ */
   ourstatus->kind = TARGET_WAITKIND_IGNORE;
   return null_ptid;
 }
@@ -3714,9 +3748,11 @@ linux_process_target::wait (ptid_t ptid,
 {
   ptid_t event_ptid;
 
+#ifndef __GENODE__
   /* Flush the async file first.  */
   if (target_is_async_p ())
     async_file_flush ();
+#endif
 
   do
     {
@@ -3726,12 +3762,14 @@ linux_process_target::wait (ptid_t ptid,
 	 && event_ptid == null_ptid
 	 && ourstatus->kind == TARGET_WAITKIND_IGNORE);
 
+#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
       && event_ptid != null_ptid)
     async_file_mark ();
+#endif
 
   return event_ptid;
 }
@@ -3741,6 +3779,9 @@ linux_process_target::wait (ptid_t ptid,
 static int
 kill_lwp (unsigned long lwpid, int signo)
 {
+#ifdef __GENODE__
+  return kill (lwpid, signo);
+#else
   int ret;
 
   errno = 0;
@@ -3752,6 +3793,7 @@ kill_lwp (unsigned long lwpid, int signo)
       perror_with_name (("tkill"));
     }
   return ret;
+#endif
 }
 
 void
@@ -4253,6 +4295,21 @@ linux_process_target::resume_one_lwp_throw (lwp_info *lwp, int step,
   regcache_invalidate_thread (thread);
   errno = 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(thread), step);
+
+#else
+
   if (step)
     ptrace_request = PTRACE_SINGLESTEP;
   else if (gdb_catching_syscalls_p (lwp))
@@ -4265,6 +4322,7 @@ linux_process_target::resume_one_lwp_throw (lwp_info *lwp, int step,
 	  /* Coerce to a uintptr_t first to avoid potential gcc warning
 	     of coercing an 8 byte integer to a 4 byte pointer.  */
 	  (PTRACE_TYPE_ARG4) (uintptr_t) signal);
+#endif
 
   current_thread = saved_thread;
   if (errno)
@@ -4308,7 +4366,7 @@ check_ptrace_stopped_lwp_gone (struct lwp_info *lp)
      (observed in Linux 3.18).  See also the note on ESRCH in the
      ptrace(2) man page.  Instead, check whether the LWP has any state
      other than ptrace-stopped.  */
-
+#ifndef __GENODE__
   /* Don't assume anything if /proc/PID/status can't be read.  */
   if (linux_proc_pid_is_trace_stopped_nowarn (lwpid_of (thread)) == 0)
     {
@@ -4316,6 +4374,7 @@ check_ptrace_stopped_lwp_gone (struct lwp_info *lp)
       lp->status_pending_p = 0;
       return 1;
     }
+#endif /* __GENODE__ */
   return 0;
 }
 
@@ -5135,6 +5194,7 @@ regsets_fetch_inferior_registers (struct regsets_info *regsets_info,
 		 optional, do not try it again for this process mode.  */
 	      disable_regset (regsets_info, regset);
 	    }
+#ifndef __GENODE__
 	  else if (errno == ENODATA)
 	    {
 	      /* ENODATA may be returned if the regset is currently
@@ -5147,6 +5207,7 @@ regsets_fetch_inferior_registers (struct regsets_info *regsets_info,
 		 already gone, in which case we simply ignore attempts
 		 to read its registers.  */
 	    }
+#endif
 	  else
 	    {
 	      char s[256];
@@ -5445,6 +5506,7 @@ linux_process_target::usr_store_inferior_registers (const regs_info *regs_info,
 #endif
 }
 
+#ifndef __GENODE__
 void
 linux_process_target::fetch_registers (regcache *regcache, int regno)
 {
@@ -5500,6 +5562,7 @@ linux_process_target::store_registers (regcache *regcache, int regno)
 	usr_store_inferior_registers (regs_info, regcache, regno, 1);
     }
 }
+#endif /* __GENODE__ */
 
 bool
 linux_process_target::low_fetch_register (regcache *regcache, int regno)
@@ -5515,6 +5578,7 @@ linux_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
   return the_target->read_memory (memaddr, myaddr, len);
 }
 
+#ifndef __GENODE__
 /* Copy LEN bytes from inferior's memory starting at MEMADDR
    to debugger memory starting at MYADDR.  */
 
@@ -5695,6 +5759,7 @@ linux_process_target::write_memory (CORE_ADDR memaddr,
 
   return 0;
 }
+#endif /* __GENODE__ */
 
 void
 linux_process_target::look_up_symbols ()
@@ -6430,6 +6495,7 @@ linux_process_target::done_accessing_memory ()
     target_unpause_all (true);
 }
 
+#ifndef __GENODE__
 /* Extract &phdr and num_phdr in the inferior.  Return 0 on success.  */
 
 static int
@@ -6922,6 +6988,7 @@ linux_process_target::qxfer_libraries_svr4 (const char *annex,
 
   return len;
 }
+#endif /* __GENODE__ */
 
 #ifdef HAVE_LINUX_BTRACE
 
@@ -7239,8 +7306,10 @@ initialize_low (void)
   memset (&sigchld_action, 0, sizeof (sigchld_action));
   set_target_ops (the_linux_target);
 
+#ifndef __GENODE__
   linux_ptrace_init_warnings ();
   linux_proc_init_warnings ();
+#endif
 
   sigchld_action.sa_handler = sigchld_handler;
   sigemptyset (&sigchld_action.sa_mask);
diff --git a/gdbserver/linux-low.h b/gdbserver/linux-low.h
index 0200e9e5..0e738698 100644
--- a/gdbserver/linux-low.h
+++ b/gdbserver/linux-low.h
@@ -20,11 +20,16 @@
 #define GDBSERVER_LINUX_LOW_H
 
 #include "nat/linux-nat.h"
+#ifndef __GENODE__
 #include "nat/gdb_thread_db.h"
+#endif
 #include <signal.h>
 
 #include "gdbthread.h"
+
+#ifndef __GENODE__
 #include "gdb_proc_service.h"
+#endif
 
 /* Included for ptrace type definitions.  */
 #include "nat/linux-ptrace.h"
@@ -552,10 +557,11 @@ class linux_process_target : public process_stratum_target
      error.  */
   int attach_lwp (ptid_t ptid);
 
-private: /* Back to private.  */
   /* Detach from LWP.  */
   void detach_one_lwp (lwp_info *lwp);
 
+private: /* Back to private.  */
+
   /* Detect zombie thread group leaders, and "exit" them.  We can't
      reap their exits until all other threads in the group have
      exited.  */
diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc
index 79284473..56555d30 100644
--- a/gdbserver/linux-x86-low.cc
+++ b/gdbserver/linux-x86-low.cc
@@ -31,13 +31,19 @@
 #include "nat/amd64-linux-siginfo.h"
 #endif
 
+#ifndef __GENODE__
 #include "gdb_proc_service.h"
+#endif
 /* Don't include elf/common.h if linux/elf.h got included by
    gdb_proc_service.h.  */
 #ifndef ELFMAG0
 #include "elf/common.h"
 #endif
 
+#ifdef __GENODE__
+#include "genode-low.h"
+#endif
+
 #include "gdbsupport/agent.h"
 #include "tdesc.h"
 #include "tracepoint.h"
@@ -52,11 +58,23 @@ static struct target_desc *tdesc_amd64_linux_no_xml;
 #endif
 static struct target_desc *tdesc_i386_linux_no_xml;
 
-
 static unsigned char jump_insn[] = { 0xe9, 0, 0, 0, 0 };
 static unsigned char small_jump_insn[] = { 0x66, 0xe9, 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>\
@@ -70,7 +88,17 @@ static const char *xmltarget_amd64_linux_no_xml = "@<target>\
 </target>";
 #endif
 
+#endif /* __GENODE__ */
+
+#ifdef __GENODE__
+#ifdef __x86_64__
+#include "amd64.h"
+#else
+#include "i386.h"
+#endif /* __x86_64__ */
+#else
 #include <sys/reg.h>
+#endif
 #include <sys/procfs.h>
 #include <sys/uio.h>
 
@@ -219,7 +247,11 @@ static /*const*/ int i386_regmap[] =
 #define ORIG_EAX ORIG_RAX
 #define REGSIZE 8
 
-static const int x86_64_regmap[] =
+static
+#ifndef __GENODE__
+const
+#endif
+int x86_64_regmap[] =
 {
   RAX * 8, RBX * 8, RCX * 8, RDX * 8,
   RSI * 8, RDI * 8, RBP * 8, RSP * 8,
@@ -232,6 +264,7 @@ static const int x86_64_regmap[] =
   -1, -1, -1, -1, -1, -1, -1, -1,
   -1,
   -1, -1, -1, -1, -1, -1, -1, -1,
+#ifndef __GENODE__
   ORIG_RAX * 8,
   21 * 8,  22 * 8,
   -1, -1, -1, -1,			/* MPX registers BND0 ... BND3.  */
@@ -246,6 +279,7 @@ static const int x86_64_regmap[] =
   -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1,
   -1					/* pkru  */
+#endif
 };
 
 #define X86_64_NUM_REGS (sizeof (x86_64_regmap) / sizeof (x86_64_regmap[0]))
@@ -287,6 +321,7 @@ is_64bit_tdesc (void)
 
 /* Called by libthread_db.  */
 
+#ifndef __GENODE__
 ps_err_e
 ps_get_thread_area (struct ps_prochandle *ph,
 		    lwpid_t lwpid, int idx, void **base)
@@ -325,6 +360,7 @@ ps_get_thread_area (struct ps_prochandle *ph,
     return PS_OK;
   }
 }
+#endif
 
 /* Get the thread area address.  This is used to recognize which
    thread is which when tracing with the in-process agent library.  We
@@ -380,7 +416,11 @@ x86_target::low_cannot_store_register (int regno)
 {
 #ifdef __x86_64__
   if (is_64bit_tdesc ())
+#ifdef __GENODE__
+    return regno >= X86_64_NUM_REGS;
+#else
     return false;
+#endif /* GENODE */
 #endif
 
   return regno >= I386_NUM_REGS;
@@ -391,12 +431,30 @@ x86_target::low_cannot_fetch_register (int regno)
 {
 #ifdef __x86_64__
   if (is_64bit_tdesc ())
+#ifdef __GENODE__
+    return regno >= X86_64_NUM_REGS;
+#else
     return false;
+#endif /* GENODE */
 #endif
 
   return regno >= I386_NUM_REGS;
 }
 
+#ifdef __x86_64__
+static int
+x86_64_cannot_store_register (int regno)
+{
+  return regno >= X86_64_NUM_REGS;
+}
+
+static int
+x86_64_cannot_fetch_register (int regno)
+{
+  return regno >= X86_64_NUM_REGS;
+}
+#endif /* __x86_64__ */
+
 static void
 x86_fill_gregset (struct regcache *regcache, void *buf)
 {
@@ -420,8 +478,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 * REGSIZE);
+#endif /* __GENODE__ */
 
 #ifdef __x86_64__
   /* Sign extend EAX value to avoid potential syscall restart
@@ -458,8 +518,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 * REGSIZE);
+#endif
 }
 
 static void
@@ -588,11 +650,23 @@ x86_target::low_set_pc (regcache *regcache, CORE_ADDR pc)
 int
 x86_target::low_decr_pc_after_break ()
 {
+#ifndef __GENODE__
   return 1;
+#else
+  return 0; /* With the HLT instruction, the PC does not get incremented */
+#endif
 }
 
 
+#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 gdb_byte x86_breakpoint[] = { 0xF4 };
+#else
 static const gdb_byte x86_breakpoint[] = { 0xCC };
+#endif
 #define x86_breakpoint_len 1
 
 bool
@@ -601,7 +675,7 @@ x86_target::low_breakpoint_at (CORE_ADDR pc)
   unsigned char c;
 
   read_memory (pc, &c, 1);
-  if (c == 0xCC)
+  if (c == x86_breakpoint[0])
     return true;
 
   return false;
@@ -689,8 +763,12 @@ x86_target::low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
 bool
 x86_target::low_stopped_by_watchpoint ()
 {
+#ifndef __GENODE__
   struct process_info *proc = current_process ();
   return x86_dr_stopped_by_watchpoint (&proc->priv->arch_private->debug_reg_state);
+#else
+  return false;
+#endif
 }
 
 CORE_ADDR
@@ -769,8 +847,10 @@ x86_target::low_new_fork (process_info *parent, process_info *child)
 void
 x86_target::low_prepare_to_resume (lwp_info *lwp)
 {
+#ifndef __GENODE__
   /* This comes from nat/.  */
   x86_linux_prepare_to_resume (lwp);
+#endif /* __GENODE__ */
 }
 
 /* See nat/x86-dregs.h.  */
@@ -798,6 +878,7 @@ x86_debug_reg_state (pid_t pid)
 bool
 x86_target::low_siginfo_fixup (siginfo_t *ptrace, gdb_byte *inf, int direction)
 {
+#ifndef __GENODE__
 #ifdef __x86_64__
   unsigned int machine;
   int tid = lwpid_of (current_thread);
@@ -812,9 +893,11 @@ x86_target::low_siginfo_fixup (siginfo_t *ptrace, gdb_byte *inf, int direction)
     return amd64_linux_siginfo_fixup_common (ptrace, inf, direction,
 					     FIXUP_X32);
 #endif
+#endif /* __GENODE__ */
 
   return false;
 }
+
 
 static int use_xml;
 
@@ -855,6 +938,13 @@ int have_ptrace_getfpxregs =
 static const struct target_desc *
 x86_linux_read_description (void)
 {
+#ifdef __GENODE__
+#ifdef __x86_64__
+  return amd64_linux_read_description(X86_XSTATE_SSE_MASK, false);
+#else
+  return i386_linux_read_description(X86_XSTATE_SSE);
+#endif
+#else
   unsigned int machine;
   int is_elf64;
   int xcr0_features;
@@ -970,7 +1060,7 @@ x86_linux_read_description (void)
 
       return tdesc;
     }
-
+#endif /* __GENODE__ */
   gdb_assert_not_reached ("failed to return tdesc");
 }
 
@@ -1005,6 +1095,14 @@ x86_target::update_xmltarget ()
 void
 x86_target::process_qsupported (gdb::array_view<const char * const> features)
 {
+#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
+
   /* Return if gdb doesn't support XML.  If gdb sends "xmlRegisters="
      with "i386" in qSupported query, it supports x86 XML target
      descriptions.  */
@@ -1045,13 +1143,24 @@ static struct regsets_info x86_regsets_info =
   };
 
 #ifdef __x86_64__
+static struct usrregs_info amd64_linux_usrregs_info =
+  {
+    X86_64_NUM_REGS,
+    x86_64_regmap,
+  };
+
 static struct regs_info amd64_linux_regs_info =
   {
     NULL, /* regset_bitmap */
+#ifdef __GENODE__
+    &amd64_linux_usrregs_info,
+#else
     NULL, /* usrregs_info */
+#endif
     &x86_regsets_info
   };
 #endif
+
 static struct usrregs_info i386_linux_usrregs_info =
   {
     I386_NUM_REGS,
@@ -1113,6 +1222,9 @@ x86_target::low_get_syscall_trapinfo (regcache *regcache, int *sysno)
 bool
 x86_target::supports_tracepoints ()
 {
+#ifdef __GENODE__
+  return false;
+#endif
   return true;
 }
 
diff --git a/gdbserver/linux-x86-tdesc.cc b/gdbserver/linux-x86-tdesc.cc
index 4682eb4c..f0861968 100644
--- a/gdbserver/linux-x86-tdesc.cc
+++ b/gdbserver/linux-x86-tdesc.cc
@@ -87,7 +87,11 @@ i386_linux_read_description (uint64_t xcr0)
 
   if (*tdesc == NULL)
     {
+#ifdef __GENODE__
+      *tdesc = i386_create_target_description (xcr0, false, false);
+#else
       *tdesc = i386_create_target_description (xcr0, true, false);
+#endif /* __GENODE__ */
 
       init_target_desc (*tdesc, i386_expedite_regs);
     }
@@ -118,7 +122,11 @@ amd64_linux_read_description (uint64_t xcr0, bool is_x32)
 
   if (*tdesc == NULL)
     {
+#ifdef __GENODE__
+      *tdesc = amd64_create_target_description (xcr0, is_x32, false, false);
+#else
       *tdesc = amd64_create_target_description (xcr0, is_x32, true, true);
+#endif /* __GENODE__ */
 
       init_target_desc (*tdesc, amd64_expedite_regs);
     }
diff --git a/gdbserver/remote-utils.cc b/gdbserver/remote-utils.cc
index 1195ce87..6e913ea2 100644
--- a/gdbserver/remote-utils.cc
+++ b/gdbserver/remote-utils.cc
@@ -30,6 +30,12 @@
 #include "gdbsupport/filestuff.h"
 #include "gdbsupport/gdb-sigmask.h"
 #include <ctype.h>
+
+#ifdef __GENODE__
+#include <sys/types.h>
+#include "genode-low.h"
+#endif
+
 #if HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
 #endif
@@ -98,7 +104,10 @@ struct sym_cache
 
 static int remote_is_stdio = 0;
 
-static int remote_desc = -1;
+#ifndef __GENODE__
+static
+#endif
+int remote_desc = -1;
 static int listen_desc = -1;
 
 #ifdef USE_WIN32API
@@ -339,7 +348,11 @@ remote_open (const char *name)
       struct stat statbuf;
 
       if (stat (name, &statbuf) == 0
+#ifndef __GENODE__
 	  && (S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode)))
+#else
+	  )
+#endif
 	remote_desc = open (name, O_RDWR);
       else
 	{
diff --git a/gdbserver/server.cc b/gdbserver/server.cc
index 9c403a64..e0d1dfc1 100644
--- a/gdbserver/server.cc
+++ b/gdbserver/server.cc
@@ -32,6 +32,14 @@
 #include "gdbsupport/gdb_wait.h"
 #include "gdbsupport/btrace-common.h"
 #include "gdbsupport/filestuff.h"
+
+#ifdef __GENODE__
+#include "genode-low.h"
+#include "linux-low.h"
+/* don't have the generated header with the declaration */
+extern "C" char *strchrnul(const char *s, int c_in);
+#endif
+
 #include "tracepoint.h"
 #include "dll.h"
 #include "hostio.h"
@@ -1286,7 +1294,9 @@ handle_detach (char *own_buf)
 	     need to hang around doing nothing, until the child is
 	     gone.  */
 	  join_inferior (pid);
+#ifndef __GENODE__
 	  exit (0);
+#endif /* __GENODE__ */
 	}
     }
 }
@@ -3156,11 +3166,11 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
 	  return;
 	}
     }
-
+#ifndef __GENODE__
   if (startswith (own_buf, "vFile:")
       && handle_vFile (own_buf, packet_len, new_packet_len))
     return;
-
+#endif
   if (startswith (own_buf, "vAttach;"))
     {
       if ((!extended_protocol || !cs.multi_process) && target_running ())
@@ -3785,7 +3795,9 @@ captured_main (int argc, char *argv[])
      opened by remote_prepare.  */
   notice_open_fds ();
 
+#ifndef __GENODE__
   save_original_signals_state (false);
+#endif /* __GENODE__ */
 
   /* We need to know whether the remote connection is stdio before
      starting the inferior.  Inferiors created in this scenario have
@@ -3987,7 +3999,11 @@ captured_main (int argc, char *argv[])
 /* Main function.  */
 
 int
+#ifdef __GENODE__
+gdbserver_main (int argc, char *argv[])
+#else
 main (int argc, char *argv[])
+#endif
 {
 
   try
@@ -4088,6 +4104,10 @@ process_serial_event (void)
     }
   response_needed = true;
 
+#ifdef __GENODE__
+  if (debug_threads) printf("GDB command = %s\n", cs.own_buf);
+#endif
+
   char ch = cs.own_buf[0];
   switch (ch)
     {
@@ -4335,7 +4355,11 @@ process_serial_event (void)
 	  return 0;
 	}
       else
+#ifndef __GENODE__
 	exit (0);
+#else
+      return 0;
+#endif
 
     case 'T':
       {
@@ -4410,7 +4434,9 @@ process_serial_event (void)
       cs.own_buf[0] = '\0';
       break;
     }
-
+#ifdef __GENODE__
+  if (debug_threads) printf("GDBserver response = %s\n", cs.own_buf);
+#endif
   if (new_packet_len != -1)
     putpkt_binary (cs.own_buf, new_packet_len);
   else
diff --git a/gdbsupport/common-defs.h b/gdbsupport/common-defs.h
index e5ece3ba..8fc25878 100644
--- a/gdbsupport/common-defs.h
+++ b/gdbsupport/common-defs.h
@@ -28,7 +28,9 @@
 #undef PACKAGE_STRING
 #undef PACKAGE_TARNAME
 
+#ifndef __GENODE__
 #include "gnulib/config.h"
+#endif /* __GENODE__ */
 
 /* From:
     https://www.gnu.org/software/gnulib/manual/html_node/stdint_002eh.html
@@ -102,6 +104,7 @@
 #endif
 
 #include "ansidecl.h"
+#ifndef __GENODE__
 /* This is defined by ansidecl.h, but we prefer gnulib's version.  On
    MinGW, gnulib might enable __USE_MINGW_ANSI_STDIO, which may or not
    require use of attribute gnu_printf instead of printf.  gnulib
@@ -109,6 +112,7 @@
    is compatible with ATTRIBUTE_PRINTF, simply use it.  */
 #undef ATTRIBUTE_PRINTF
 #define ATTRIBUTE_PRINTF _GL_ATTRIBUTE_FORMAT_PRINTF
+#endif /* __GENODE__ */
 
 #if GCC_VERSION >= 3004
 #define ATTRIBUTE_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
diff --git a/gdbsupport/common-inferior.cc b/gdbsupport/common-inferior.cc
index aed88409..2f03118d 100644
--- a/gdbsupport/common-inferior.cc
+++ b/gdbsupport/common-inferior.cc
@@ -23,7 +23,11 @@
 
 /* See common-inferior.h.  */
 
+#ifdef __GENODE__
+bool startup_with_shell = false;
+#else
 bool startup_with_shell = true;
+#endif
 
 /* See common-inferior.h.  */
 
diff --git a/gdbsupport/common-types.h b/gdbsupport/common-types.h
index 23f983d8..6c67d21d 100644
--- a/gdbsupport/common-types.h
+++ b/gdbsupport/common-types.h
@@ -26,12 +26,29 @@
 typedef unsigned char gdb_byte;
 
 /* * An address in the program being debugged.  Host byte order.  */
+#ifdef __GENODE__
+/*
+ * Genode currently uses a common symbol file for 32-bit and 64-bit platforms,
+ * so the type needs to be the same for both platform types.
+ */
+typedef unsigned long CORE_ADDR;
+#else
 typedef uint64_t CORE_ADDR;
+#endif
 
 /* LONGEST must be at least as big as CORE_ADDR.  */
 
+#ifdef __GENODE__
+/*
+ * Genode currently uses a common symbol file for 32-bit and 64-bit platforms,
+ * so the type needs to be the same for both platform types.
+ */
+typedef long LONGEST;
+typedef unsigned long ULONGEST;
+#else
 typedef int64_t LONGEST;
 typedef uint64_t ULONGEST;
+#endif
 
 /* * The largest CORE_ADDR value.  */
 #define CORE_ADDR_MAX (~(CORE_ADDR) 0)
diff --git a/gdbsupport/gdb-sigmask.h b/gdbsupport/gdb-sigmask.h
index b4988cb4..a15601eb 100644
--- a/gdbsupport/gdb-sigmask.h
+++ b/gdbsupport/gdb-sigmask.h
@@ -39,6 +39,10 @@
 #error pthread_sigmask available without sigprocmask - please report
 #endif
 
+#ifdef __GENODE__
+#define gdb_sigmask(...)
+#endif /* __GENODE__ */
+
 #endif /* HAVE_SIGPROCMASK */
 
 
diff --git a/gdbsupport/gdb_tilde_expand.cc b/gdbsupport/gdb_tilde_expand.cc
index b31fc484..dcb32777 100644
--- a/gdbsupport/gdb_tilde_expand.cc
+++ b/gdbsupport/gdb_tilde_expand.cc
@@ -71,7 +71,12 @@ private:
 std::string
 gdb_tilde_expand (const char *dir)
 {
+#ifdef __GENODE__
+  /* GLOB_TILDE_CHECK is not defined in Genode's libc */
+  gdb_glob glob (dir, GLOB_TILDE, NULL);
+#else
   gdb_glob glob (dir, GLOB_TILDE_CHECK, NULL);
+#endif /* __GENODE__ */
 
   gdb_assert (glob.pathc () > 0);
   /* "glob" may return more than one match to the path provided by the
@@ -86,7 +91,12 @@ gdb_tilde_expand (const char *dir)
 gdb::unique_xmalloc_ptr<char>
 gdb_tilde_expand_up (const char *dir)
 {
+#ifdef __GENODE__
+  /* GLOB_TILDE_CHECK is not defined in Genode's libc */
+  gdb_glob glob (dir, GLOB_TILDE, NULL);
+#else
   gdb_glob glob (dir, GLOB_TILDE_CHECK, NULL);
+#endif
 
   gdb_assert (glob.pathc () > 0);
   /* "glob" may return more than one match to the path provided by the
diff --git a/gdbsupport/pathstuff.cc b/gdbsupport/pathstuff.cc
index 48c477fa..c3065efe 100644
--- a/gdbsupport/pathstuff.cc
+++ b/gdbsupport/pathstuff.cc
@@ -55,6 +55,7 @@ gdb_realpath (const char *filename)
    does not exist locally), we rely instead on GetFullPathName to
    perform the canonicalization.  */
 
+#ifndef __GENODE__
 #if defined (_WIN32)
   {
     char buf[MAX_PATH];
@@ -75,6 +76,7 @@ gdb_realpath (const char *filename)
       return gdb::unique_xmalloc_ptr<char> (rp);
   }
 #endif
+#endif /* __GENODE__ */
 
   /* This system is a lost cause, just dup the buffer.  */
   return make_unique_xstrdup (filename);
