diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index ec2af52dc44d..ff324c393f23 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -721,7 +721,8 @@ ALL_TARGET_OBS = \
 	symfile-mem.o \
 	windows-tdep.o \
 	linux-record.o \
-	ravenscar-thread.o
+	ravenscar-thread.o \
+	lkd-main.o lkd-process.o
 
 # Host-dependent makefile fragment comes in here.
 @host_makefile_frag@
@@ -988,7 +989,7 @@ common/common-exceptions.h target/target.h common/symbol.h \
 common/common-regcache.h fbsd-tdep.h nat/linux-personality.h \
 common/fileio.h nat/x86-linux.h nat/x86-linux-dregs.h nat/amd64-linux-siginfo.h\
 nat/linux-namespaces.h arch/arm.h common/gdb_sys_time.h arch/aarch64-insn.h \
-tid-parse.h
+tid-parse.h lkd/lkd.h lkd/lkd-process.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -1355,6 +1356,7 @@ init.c: $(INIT_FILES)
 	    -e '/[a-z0-9A-Z_]*-exp.tab.[co]$$/d' \
 	    -e 's/\.[co]$$/.c/' \
 	    -e 's,signals\.c,common/signals\.c,' \
+	    -e 's,\(lkd-.*\.c\),lkd/\1,' \
 	    -e 's|^\([^  /][^     ]*\)|$(srcdir)/\1|g' | \
 	while read f; do \
 	    sed -n -e 's/^_initialize_\([a-z_0-9A-Z]*\).*/\1/p' $$f 2>/dev/null; \
@@ -1754,7 +1756,8 @@ ALLDEPFILES = \
 	xcoffread.c \
 	xstormy16-tdep.c \
 	xtensa-tdep.c xtensa-config.c \
-	xtensa-linux-tdep.c xtensa-linux-nat.c xtensa-xtregs.c
+	xtensa-linux-tdep.c xtensa-linux-nat.c xtensa-xtregs.c \
+	lkd/lkd-main.c lkd/lkd-process.c
 
 # Some files need explicit build rules (due to -Werror problems) or due
 # to sub-directory fun 'n' games.
@@ -2717,6 +2720,20 @@ py-varobj.o: $(srcdir)/python/py-varobj.c
 	$(POSTCOMPILE)
 
 #
+# gdb/lkd/ dependencies
+#
+# Need to explicitly specify the compile rule as make will do nothing
+# or try to compile the object file into the sub-directory.
+
+lkd-main.o: $(srcdir)/lkd/lkd-main.c
+lkd-process.o: $(srcdir)/lkd/lkd-process.c
+
+# Generalised lkd-compile rule
+lkd-%:
+	$(COMPILE) $<
+	$(POSTCOMPILE)
+
+#
 # Dependency tracking.  Most of this is conditional on GNU Make being
 # found by configure; if GNU Make is not found, we fall back to a
 # simpler scheme.
diff --git a/gdb/config.in b/gdb/config.in
index dc9da0a73610..676bd60cac9f 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -33,6 +33,9 @@
 /* Define to BFD's default target vector. */
 #undef DEFAULT_BFD_VEC
 
+/* Define to 1 if Linux Kernel Debug is enabled */
+#undef ENABLE_LKD
+
 /* Define to 1 if translation of program messages to the user's native
    language is requested. */
 #undef ENABLE_NLS
diff --git a/gdb/configure b/gdb/configure
index b523debe484e..03aae841e917 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -816,6 +816,7 @@ with_auto_load_dir
 with_auto_load_safe_path
 enable_targets
 enable_64_bit_bfd
+enable_linux_kernel_aware
 enable_gdbcli
 enable_gdbmi
 enable_tui
@@ -1506,6 +1507,8 @@ Optional Features:
   --enable-targets=TARGETS
                           alternative target configurations
   --enable-64-bit-bfd     64-bit support (on hosts with narrower word sizes)
+  --enable-linux-kernel-aware
+                          enable linux kernel aware debugging
   --disable-gdbcli        disable command-line interface (CLI)
   --disable-gdbmi         disable machine-interface (MI)
   --enable-tui            enable full-screen terminal user interface (TUI)
@@ -5687,6 +5690,26 @@ else
   want64=false
 fi
 
+# Check whether to support linux kernel aware debugging
+# Check whether --enable-linux-kernel-aware was given.
+if test "${enable_linux_kernel_aware+set}" = set; then :
+  enableval=$enable_linux_kernel_aware; case $enableval in
+    yes | no)
+      ;;
+    *)
+      as_fn_error "bad value $enableval for --enable-linux-kernel-aware" "$LINENO" 5 ;;
+  esac
+else
+  enable_linux_kernel_aware=no
+fi
+
+
+if test "${enable_linux_kernel_aware}" = "yes"; then
+
+$as_echo "#define ENABLE_LKD 1" >>confdefs.h
+
+fi
+
 # Provide defaults for some variables set by the per-host and per-target
 # configuration.
 gdb_host_obs=posix-hdep.o
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 70452d3ff056..a148c1c41fed 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -198,6 +198,21 @@ AS_HELP_STRING([--enable-64-bit-bfd], [64-bit support (on hosts with narrower wo
   *)    AC_MSG_ERROR(bad value ${enableval} for 64-bit-bfd option) ;;
 esac],[want64=false])dnl
 
+# Check whether to support linux kernel aware debugging
+AC_ARG_ENABLE(linux-kernel-aware,
+AS_HELP_STRING([--enable-linux-kernel-aware], [enable linux kernel aware debugging]),
+  [case $enableval in
+    yes | no)
+      ;;
+    *)
+      AC_MSG_ERROR([bad value $enableval for --enable-linux-kernel-aware]) ;;
+  esac],
+  [enable_linux_kernel_aware=no])
+
+if test "${enable_linux_kernel_aware}" = "yes"; then
+  AC_DEFINE(ENABLE_LKD, 1, [Define to 1 if Linux Kernel Debug is enabled])
+fi
+
 # Provide defaults for some variables set by the per-host and per-target
 # configuration.
 gdb_host_obs=posix-hdep.o
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 54245c3d5522..8a685afe5c1e 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -725,3 +725,11 @@ for t in x ${gdb_target_obs}; do
     gdb_have_gcore=true
   fi
 done
+
+
+# Add linux kernel awareness obs and set no default OS ABI
+if test x"$enable_linux_kernel_aware" = xyes; then
+  gdb_target_obs="$gdb_target_obs lkd-main.o lkd-process.o"
+  gdb_osabi=
+fi
+
diff --git a/gdb/lkd/lkd-main.c b/gdb/lkd/lkd-main.c
new file mode 100644
index 000000000000..89a3c9dd8de8
--- /dev/null
+++ b/gdb/lkd/lkd-main.c
@@ -0,0 +1,2160 @@
+/*
+  Copyright 2005-2013 STMicroelectronics.
+
+  This file contains the architecture neutral part of the Linux
+  Awareness layer for GDB.
+
+ */
+
+#include <ctype.h>
+
+#include "defs.h"
+#include "ui-out.h"
+#include "arch-utils.h"
+#include "block.h"
+#include "breakpoint.h"
+#include "cli/cli-decode.h"
+#include "cli/cli-script.h"
+#include "command.h"
+#include "completer.h"
+#include "dictionary.h"
+#include "event-loop.h"
+#include "exceptions.h"
+#include "exec.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "gdb.h"
+#include "gdb_assert.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "gdbthread.h"
+#include "gdbtypes.h"
+#include "inferior.h"
+#include "location.h"
+#include "objfiles.h"
+#include "observer.h"
+#include "regcache.h"
+#include "solib.h"
+#include "solist.h"
+#include "symtab.h"
+#include "psympriv.h"
+#include "target.h"
+#include "top.h"
+
+#include "bfd.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+#include "tui/tui.h"
+
+
+#include "lkd.h"
+#include "lkd-process.h"
+
+/******************************* from shtdi.c *********************************/
+/* Signal Handling.  */
+#include <signal.h>
+
+/* A target interrupt has been requested.  */
+
+/* A SIGTERM has been requested.  */
+static volatile int terminate_requested = 0;
+
+/* Remember the regular SIG handlers while ours are installed.  */
+static void (*old_interrupt_handler) (int);
+static void (*old_terminate_handler) (int);
+static void terminate_once (int signo);
+static void disable_terminate (void);
+static void enable_terminate (void);
+
+/******************************************************************************/
+
+#define BENEATH linux_aware_ops.beneath
+
+struct lkd_private_data lkd_private;
+
+/***************************** Added commands *********************************/
+static char linux_awareness_doc[] = "";
+
+/* The cmd_list_element where we register all the 'set
+ linux-awareness...' and 'show linux-awareness...' commands. */
+struct cmd_list_element *set_linux_awareness_cmd_list;
+struct cmd_list_element *show_linux_awareness_cmd_list;
+
+/* The definition of the log domains and the storage for their
+ associated log levels. */
+struct debug_domain linux_aware_debug_domains_info[] = {
+  {"debug-task", 0},
+  {"debug-target", 0},
+  {"debug-init", 0},
+  {NULL, 0}
+};
+
+/* The definition of the log domains and the storage for their
+ associated log levels. */
+struct linux_awareness_params lkd_params = {
+  .enabled = 0,
+  .loaded = LKD_NOTLOADED,
+  .enable_task_awareness = 1,
+  .auto_activate = 1,
+  .skip_schedule_frame = 0,	/*RnDCT0001394: changed default behavior */
+  .no_colors = 0,
+  .loglevel = 0
+};
+
+
+/* 'set target-root-prefix' is introduced as an alias for 'set
+ solib-absolute-prefix', this variable contains a pointer to the value
+ of that variable. */
+char **target_root_prefix;
+static int target_root_prefix_dirty = 1;
+
+/********************************* GDB glue ***********************************/
+
+/* The target ops that adds the linux awareness. */
+struct target_ops linux_aware_ops;
+
+/* The structure that gives access to target-dependent knowledge
+ required by the Linux awareness layer. Declared in lkd.h
+ and defined in a targetting file (eg. lkd-arm.c). */
+struct linux_awareness_ops *linux_awareness_ops;
+
+/**************************** Execution control *******************************/
+
+/* This ugly variable is a way to pass information from the
+ target_ops->to_resume to the target_ops->to_wait callbacks. It
+ indicates if the last execution request was a singlstep. It's used
+ in linux_aware_wait to perform additional step in some
+ circumstances. */
+int lkd_stepping;
+
+/* A simple flag indicating that the target is running (ie. we are
+ between a target_resume () and a target_wait () call). This is used
+ to properly disconnect when the debugger is killed by a signal. */
+static int running;
+
+/* This is the observer registered for the normal_stop event. The
+ observer callback (normal_stop_callback ()) is called when the user
+ gets the hand back after a target execution. It's used to collect
+ some information and to cleanup some state. */
+static struct observer *normal_stop_observer;
+
+/******************************* Function Prototypes **************************/
+
+void set_skip_schedule_frame (char *arg, int from_tty,
+			      struct cmd_list_element *c);
+
+/*********************** Addresses and Structure descriptions *****************/
+
+/* The Linux Awareness Layer needs to know a lot about the addresses
+ and layout of the data structures used in the kernel. This is
+ handled through these declaration and the associated macros and
+ functions (see linux-awareness.h). */
+
+/* Storage for the field layout and addresses already gathered. */
+struct field_info *field_info;
+struct addr_info *addr_info;
+
+/* Declaration of the required addresses. */
+DECLARE_ADDR (start_kernel);
+DECLARE_ADDR (do_exit);
+
+DECLARE_ADDR (try_to_unmap);
+
+DECLARE_ADDR (linux_banner);
+
+DECLARE_ADDR (system_utsname);
+DECLARE_ADDR (init_uts_ns);
+
+/* Structure fields */
+
+DECLARE_FIELD (list_head, next);
+DECLARE_FIELD (new_utsname, release);
+
+
+DECLARE_FIELD (pid_namespace, last_pid);
+DECLARE_FIELD (qstr, len);
+DECLARE_FIELD (qstr, name);
+
+DECLARE_FIELD (task_struct, mm);
+DECLARE_FIELD (task_struct, tasks);
+DECLARE_FIELD (task_struct, children);
+DECLARE_FIELD (task_struct, thread_group);
+DECLARE_FIELD (task_struct, sibling);
+DECLARE_FIELD (task_struct, pid);
+DECLARE_FIELD (task_struct, tgid);
+DECLARE_FIELD (task_struct, namespace);
+DECLARE_FIELD (task_struct, nsproxy);
+DECLARE_FIELD (task_struct, prio);
+DECLARE_FIELD (task_struct, cred);
+DECLARE_FIELD (task_struct, comm);	/* far offset in the task_struct, to bulk-read everything needed. */
+
+
+DECLARE_FIELD (thread_info, preempt_count);
+DECLARE_FIELD (uts_namespace, name);
+
+
+int max_cores = MAX_CORES;
+
+/****************************** Task handling *********************************/
+
+/* The internal breakpoints used to be notified of interesting task
+ events. */
+static struct breakpoint *thread_event_low_mem_bp;
+static struct breakpoint *thread_event_do_exec_bp;
+static struct breakpoint *thread_event_do_exit_bp;
+static struct breakpoint *thread_event_do_exec_return_bp;
+
+/* This value is incremented and decremented by
+ thread_awareness_(in|ex)hibit (). The target actions (eg. read
+ register) requested by the platform specific part of the linux
+ awareness are guaranteed to access the real state of the target,
+ whatever the user selected as current task in the debugger. To
+ achieve this, this variable is incremented/decremented around the
+ calls to linux_awareness_ops, and tested in each target access
+ method. */
+static int _inhibit_thread_register_awareness;
+
+/* the core that triggered the event (zero-based)*/
+int stop_core = 0;
+/* When doing userspace debug, there's the very annoying limitation
+ that the debugged application creation isn't handled by the
+ debugger, but by the user in an environement decorelated from the
+ debugger. This precludes using the debugger to debug an application
+ from the start.
+ To overcome that annoying limitation, tha command 'wait_exe' has
+ been added. It's used like that:
+
+ (gdb) wait_exe foo
+ Type commands that will be executed the next time the binary is exec'd:
+ End with a line saying just "end".
+ >b main
+ >p global = 1
+ >end
+
+ This tells the debugger to watch for process creation, and that
+ when a process called 'foo' is launched, the debugger should
+ execute 'b main' and 'p global = 1' before the process is allowed
+ to start executing. Once the user launches the process it should
+ then stop on main. Of course this is just an example; the
+ machinery is generic enough to allow many other uses.
+
+ Note that putting a control execution command (next, continue...)
+ inside the wait_exe command list will break things (Unfortunately
+ it's not possible to detect it genericaly).
+
+ The below struct and list contains the wait_exe requests currently
+ in fly.
+ */
+struct waited_exe
+{
+  struct waited_exe *next;
+  char *name;
+  struct command_line *cmds;
+  uid_t uid;
+} *waited_exes = NULL;
+
+/* The bellow data structures deal with the handling of breakpoints on
+ virtual memory pages that aren't mapped to memory yet. The idea is
+ to put a watchpoint on the page table entry that represents the
+ page and to associate commands that create the final breakpoint
+ with the watchpoint. */
+struct bp_list
+{
+  struct bp_list *next;
+  struct breakpoint *b;
+};
+
+
+/* This key is used to store a reference count associated with GDB
+ objfiles. Objfiles are shared between userspace thread of the same
+ application, thus we reference count them to know when we can
+ discard the information. */
+const struct objfile_data *linux_uprocess_objfile_data_key;
+
+/****************** Local functions forward declarations **********************/
+static void normal_stop_callback (struct bpstats *bs, int);
+
+/***************** End Local functions forward declarations *******************/
+
+/* Called by ADDR to fetch the address of a symbol declared using
+ DECLARE_ADDR. */
+int
+linux_init_addr (struct addr_info *addr, int check)
+{
+  if (addr->bmsym.minsym)
+    return 1;
+
+  addr->bmsym = lookup_minimal_symbol (addr->name, NULL, NULL);
+
+  if (addr->bmsym.minsym)
+    {
+      DEBUG (D_INIT, 4, "Checking for address of '%s' : OK\n", addr->name);
+    }
+  else
+    {
+      DEBUG (D_INIT, 1, "Checking for address of '%s' : NOT FOUND\n",
+	     addr->name);
+      if (!check)
+	error ("Couldn't find address of %s", addr->name);
+      return 0;
+    }
+
+  /* Chain initialized entries for cleanup. */
+  addr->next = addr_info;
+  addr_info = addr;
+
+  DEBUG (D_INIT, 4, "%s address is %s\n", addr->name,
+	 phex (BMSYMBOL_VALUE_ADDRESS (addr->bmsym), 4));
+  return 1;
+}
+
+/* Helper for linux_init_field. */
+static int
+find_struct_field (struct type *type, char *field, int *offset, int *size)
+{
+  int i;
+
+  for (i = 0; i < TYPE_NFIELDS (type); ++i)
+    {
+      if (!strcmp (FIELD_NAME (TYPE_FIELDS (type)[i]), field))
+	break;
+    }
+
+  if (i >= TYPE_NFIELDS (type))
+    return 0;
+
+  *offset = FIELD_BITPOS (TYPE_FIELDS (type)[i]) / TARGET_CHAR_BIT;
+  *size = TYPE_LENGTH (check_typedef (TYPE_FIELDS (type)[i].type));
+  return 1;
+}
+
+/* Called by F_OFFSET or F_SIZE to compute the description of a field
+ declared using DECLARE_FIELD. */
+int
+linux_init_field (struct field_info *field, int check)
+{
+  if (field->type != NULL)
+    return 1;
+
+  field->type =
+    lookup_symbol (field->struct_name, NULL, STRUCT_DOMAIN, NULL).symbol;
+  if (field->type)
+    {
+      DEBUG (D_INIT, 4, "Checking for 'struct %s' : OK\n",
+	     field->struct_name);
+    }
+  else
+    {
+      field->type = lookup_symbol (field->struct_name,
+				   NULL, VAR_DOMAIN, NULL).symbol;
+
+      if (field->type
+	  && TYPE_CODE (check_typedef (SYMBOL_TYPE (field->type)))
+	  != TYPE_CODE_STRUCT)
+	field->type = NULL;
+
+      if (field->type != NULL)
+	DEBUG (D_INIT, 4, "Checking for 'struct %s' : TYPEDEF\n",
+	       field->struct_name);
+      else
+	DEBUG (D_INIT, 1, "Checking for 'struct %s' : NOT FOUND\n",
+	       field->struct_name);
+    }
+
+  if (field->type == NULL
+      || !find_struct_field (check_typedef (SYMBOL_TYPE (field->type)),
+			     field->field_name, &field->offset, &field->size))
+    {
+      field->type = NULL;
+      if (!check)
+	error ("No such field %s::%s\n", field->struct_name,
+	       field->field_name);
+
+      return 0;
+    }
+
+  /* Chain initialized entries for cleanup. */
+  field->next = field_info;
+  field_info = field;
+
+  DEBUG (D_INIT, 4, "%s::%s => offset %i  size %i\n", field->struct_name,
+	 field->field_name, field->offset, field->size);
+  return 1;
+}
+
+/* Cleanup all the field and address info that has been gathered. */
+static void
+fields_and_addrs_clear (void)
+{
+  struct field_info *next_field = field_info;
+  struct addr_info *next_addr = addr_info;
+
+  while (next_field)
+    {
+      next_field = field_info->next;
+      field_info->type = NULL;
+      field_info->next = NULL;
+      field_info = next_field;
+    }
+
+  while (next_addr)
+    {
+      next_addr = addr_info->next;
+      addr_info->bmsym.minsym = NULL;
+      addr_info->bmsym.objfile = NULL;
+      addr_info->next = NULL;
+      addr_info = next_addr;
+    }
+}
+
+/* If this returns true, we want to access the target registers and
+ memory whatever the user nominated as the current task. */
+static int
+thread_awareness_inhibited (void)
+{
+  return !lkd_params.enable_task_awareness
+    || _inhibit_thread_register_awareness;
+}
+
+/* See the description of _inhibit_thread_register_awareness. */
+static void
+thread_awareness_inhibit (void)
+{
+  ++_inhibit_thread_register_awareness;
+}
+
+/* See the description of _inhibit_thread_register_awareness. */
+static void
+thread_awareness_exhibit (void *unused)
+{
+  --_inhibit_thread_register_awareness;
+}
+
+/* Remove the trailing white spaces from target-root-prefix.
+ FIXME: do this when the string is input, not all the time !
+ */
+void
+sanitize_path (char *path)
+{
+  char *dir = path + strlen (path) - 1;
+  while (dir > path && isspace (*dir))
+    {
+      *dir-- = '\0';
+    };
+  /* remove trailing '/' too.
+   **/
+  if (*dir == '/')
+    *dir = '\0';
+}
+
+char *
+linux_aware_get_target_root_prefix (void)
+{
+  if (target_root_prefix_dirty && *target_root_prefix)
+    {
+      sanitize_path (*target_root_prefix);
+      target_root_prefix_dirty = 0;
+    }
+  return *target_root_prefix;
+}
+
+
+/****************************************************************************/
+
+/* Reads the Linux version string from memory
+ * into global lkd_private.utsname_release. */
+static int
+set_utsname_release (void)
+{
+  int i = 0;
+  CORE_ADDR release_addr;
+  asection *data;
+  int ret = 0;
+  int build = 0;
+
+  gdb_assert (lkd_private.utsname_release);
+
+  lkd_private.utsname_release[0] = '\0';
+  lkd_private.utsname_release_valid = 0;
+
+  /* Find the address of the string. */
+  if (HAS_ADDR (init_uts_ns)
+      && HAS_FIELD (uts_namespace, name) && HAS_FIELD (new_utsname, release))
+    release_addr = ADDR (init_uts_ns)
+      + F_OFFSET (uts_namespace, name) + F_OFFSET (new_utsname, release);
+  else if (HAS_ADDR (system_utsname) && HAS_FIELD (new_utsname, release))
+    release_addr = ADDR (system_utsname) + F_OFFSET (new_utsname, release);
+  else
+    return -1;
+
+  ret = target_read_memory (release_addr,
+			    (gdb_byte *) (lkd_private.utsname_release),
+			    lkd_private.utsname_release_size);
+
+  lkd_private.utsname_release_valid = ret ? 0 : 1;
+
+  return ret;
+}
+
+/******************************************************************************/
+/*****************              TASK AWARENESS               ******************/
+/******************************************************************************/
+
+/* target_ops callback that GDB queries to know if the given PTID is
+ still an active task. */
+static int
+linux_aware_thread_alive (struct target_ops *ops, ptid_t ptid)
+{
+  /* if we are resetting the thread list, return false
+   * because shtdi will return true for the h/w thread
+   * and this would lead to keep a previous occurrence of the ptid.
+   */
+  if (lkd_private.loaded == LKD_LOADING)
+    return 0;
+
+  if (lkd_private.loaded == LKD_NOTLOADED)
+    {
+      if (BENEATH && BENEATH->to_thread_alive)
+	return BENEATH->to_thread_alive (ops, ptid);
+      return 0;			/* GDB default */
+    }
+
+  return (lkd_proc_get_by_ptid (ptid) != NULL);
+}
+
+/* target_ops callback that GDB queries to know core id of the given PTID. */
+static int
+linux_aware_core_of_thread (struct target_ops *ops, ptid_t ptid)
+{
+  if (lkd_private.loaded == LKD_LOADED)
+    return lkd_proc_core_of_thread (ptid);
+  else if (BENEATH->to_core_of_thread)
+    return BENEATH->to_core_of_thread (ops, ptid);
+
+  return CORE_INVAL;
+}
+
+/* target_ops callback that GDB queries add new threads to its thread
+ list. */
+static void
+linux_aware_update_thread_list (struct target_ops *ops)
+{
+  if (lkd_private.loaded != LKD_LOADED)
+    {
+      /* in case the user attaches, but did not yet set the target pack. */
+      if (BENEATH->to_update_thread_list)
+	BENEATH->to_update_thread_list (ops);	/* may not exist */
+    }
+  else
+    lkd_proc_get_list ();
+}
+
+/*
+ * the default post exec stop handler tries  to activatie L-A
+ * if it previously failed
+ **/
+static void
+linux_aware_post_exec_stop (int step)
+{
+  if (!step && lkd_private.connected	/*make sure kernel code is in target-ram */
+      && (lkd_private.loaded == LKD_NOTLOADED)
+      && (lkd_params.auto_activate == 1))
+    {
+      CORE_ADDR pc = regcache_read_pc (get_current_regcache ());
+
+      /* if we broke in start_kernel, we may be about to execute
+       * the user "set" commands, do not rely on lkd_params yet.
+       **/
+      if (pc == ADDR (start_kernel))
+	return;
+      /* In case we need to delay set loaded by the time the mmu is correctly set,
+       * this will be set at latest by the time the user breaks
+       **/
+      lkd_params.loaded = LKD_LOADED;
+      lkd_loaded_set (NULL, 0, NULL);
+    }
+}
+
+extern void nullify_last_target_wait_ptid (void);
+
+static int
+dump_thread_list (struct thread_info *tp, void *ignored)
+{
+  printf_filtered ("thread_list: {%d.%d}= {%d-%ld-%ld}\n",
+		   tp->global_num, tp->per_inf_num,
+		   ptid_get_pid (tp->ptid),
+		   ptid_get_lwp (tp->ptid), ptid_get_tid (tp->ptid));
+  return 0;
+}
+
+void
+lkd_reset_thread_list (void)
+{
+  struct thread_info *tp = NULL;
+  int pid = ptid_get_pid (inferior_ptid);
+  int loaded_state = lkd_private.loaded;
+  struct cleanup *cleanup;
+
+  switch_to_thread (null_ptid);	/* Ensure inferior_ptid is invalid.  */
+
+  /* remove all gdb threads, we need to call this as
+   * gdb and complying targets assume there is always a thread
+   * but we need to manage our own thread numbering.
+   */
+  init_thread_list ();
+
+  DBG_IF (D_INIT)
+	iterate_over_threads (dump_thread_list, NULL);
+  DBG_ENDIF (D_INIT)
+    /* setup LKD "thread alive" method to return FALSE and "find new threads"
+       method to call the BENEATH version */
+    lkd_private.loaded = LKD_LOADING;
+
+  cleanup = make_cleanup_restore_integer (&print_thread_events);
+  print_thread_events = 0;
+  update_thread_list ();
+  do_cleanups (cleanup);
+
+  DBG_IF (D_INIT)
+	iterate_over_threads (dump_thread_list, NULL);
+  DBG_ENDIF (D_INIT)
+
+  tp = any_live_thread_of_process (pid);
+  gdb_assert (tp != NULL);	/* A live thread must exist.  */
+  switch_to_thread (tp->ptid);
+
+  /* make sure update_inferior_thread will not switch to a wait_ptid
+   * that is no-more upon resuming
+   */
+  nullify_last_target_wait_ptid ();
+
+  /* return LKD "thread alive" and "find new threads" methods to their
+     natural states */
+  lkd_private.loaded = loaded_state;
+}
+
+/* target_ops callback that GDB queries to translate a PTID to a human
+ readable string to display. */
+static char *
+linux_aware_pid_to_str (struct target_ops *ops, ptid_t ptid)
+{
+  process_t *ps;
+  struct thread_info *tp;
+
+  if (lkd_private.loaded == LKD_NOTLOADED)
+    {
+      if (BENEATH && BENEATH->to_pid_to_str)
+	return BENEATH->to_pid_to_str (ops, ptid);
+      return normal_pid_to_str (ptid);	/* GDB default */
+    }
+
+  if (!ptid_get_tid (ptid))	/* when quitting typically */
+    return "Linux Kernel";
+
+  tp = find_thread_ptid (ptid);
+
+  if (!tp || !tp->priv)
+    return "";
+
+  /* we use the gdb thread private field for storing the process_t */
+  ps = (process_t *) tp->priv;
+
+  gdb_assert (ps->comm);
+  return ps->comm;
+}
+
+/* extra informations with display options
+ **/
+static char *
+extra_thread_info_ext (struct thread_info *thread)
+{
+  static char msg[256];
+  char *pos = msg, *ret;
+  process_t *ps;
+  int core;
+
+  if (!(tui_active || lkd_params.no_colors))
+    pos += sprintf (pos, "\e[30m");
+  else
+    *pos = '\0';
+  ret = pos;			/* skip color setting by default */
+
+  ps = (process_t *) thread->priv;
+
+  DBG_IF (TASK) if (!ps)
+    {
+      printf_filtered ("thread_info %p not found in process_list\n", thread);
+      printf_filtered ("  thread_info.ptid = {%d, %ld, %ld}\n",
+		       ptid_get_pid (thread->ptid),
+		       ptid_get_lwp (thread->ptid),
+		       ptid_get_tid (thread->ptid));
+      printf_filtered ("  thread_info.num = %d.%d\n", thread->global_num,
+		       thread->per_inf_num);
+    }
+  DBG_ENDIF (TASK) if (ps)
+    {
+      core = ps->core;
+
+      DBG_IF (TASK) if (core != CORE_INVAL)
+	pos += sprintf (pos,
+			"lwp=%li, tid=%li, gdbt=%lx, task_str=%lx-%lx",
+			ptid_get_lwp (PTID_OF (ps)),
+			ptid_get_tid (PTID_OF (ps)),
+			(unsigned long) ps->gdb_thread,
+			(unsigned long) ps->task_struct,
+			(unsigned long) lkd_proc_get_rq_curr (core));
+      else
+	pos += sprintf (pos,
+			"lwp=%li, tid=%li, gdbt=%lx, task_str=%lx",
+			ptid_get_lwp (PTID_OF (ps)),
+			ptid_get_tid (PTID_OF (ps)),
+			(unsigned long) ps->gdb_thread,
+			(unsigned long) ps->task_struct);
+      DBG_ELSE if (ps->tgid == ptid_get_lwp (PTID_OF (ps)))
+	/* thread group leader */
+	pos += sprintf (pos, "TGID:%i", ps->tgid);
+      else
+	/* thread of a thread group */
+	pos += sprintf (pos, "|----%li", ptid_get_lwp (PTID_OF (ps)));
+      DBG_ENDIF (TASK) if (lkd_proc_is_curr_task (ps))
+	{
+	  pos += sprintf (pos, " <C%u>", core);
+
+	  /* highlight currently running threads */
+	  if (!(tui_active || lkd_params.no_colors))
+	    {
+	      ret = msg;
+	      msg[3] = '1' + (2 * core);
+	      strcpy (pos, "\e[m");
+	    }
+	}
+    }
+
+  return ret;
+}
+
+/* target_ops callback that GDB queries to get extra information to
+ display for a given thread. */
+static char *
+linux_aware_extra_thread_info (struct target_ops *ops,
+			       struct thread_info *thread)
+{
+  if (lkd_private.loaded == LKD_LOADED)
+    {
+      /* FIXME: Bodge for STWorkbench which expects different format */
+      if (lkd_params.no_colors)
+	{
+	  process_t *ps = (process_t *) thread->priv;
+
+	  if (ps)
+	    {
+	      static char msg[256];
+	      char *pos = msg;
+
+	      pos += sprintf (pos, "pid: %li tgid: %i",
+			      ptid_get_lwp (PTID_OF (ps)), ps->tgid);
+	      if (lkd_proc_is_curr_task (ps))
+		sprintf (pos, " <C%u>", ps->core);
+
+	      return msg;
+	    }
+	}
+      else
+	return extra_thread_info_ext (thread);
+    }
+  else if (BENEATH->to_extra_thread_info)
+    return BENEATH->to_extra_thread_info (ops, thread);
+
+  return "";
+}
+
+static const char *
+linux_aware_thread_name (struct target_ops *ops, struct thread_info *thread)
+{
+  /* All the thread name information has generally been
+   * returned already through the pid_to_str.
+   *
+   * We could refactor this around and 'correct' the naming
+   * but then you wouldn't get niceties such as
+   *    [Switching to thread 52 (getty)]
+   */
+
+  return NULL;
+}
+
+/* target_ops callback queried by GDB to read the registers of the
+ currently selected task. */
+static void
+linux_aware_fetch_registers (struct target_ops *ops,
+			     struct regcache *rc, int regno)
+{
+  struct cleanup *cleanup;
+  process_t *ps;
+  int res;
+
+  DEBUG (TARGET, 2, "fetch_registers %i\n", regno);
+
+  if ((lkd_private.loaded != LKD_LOADED)	/*check this first */
+      || !(ps = lkd_proc_get_by_ptid (inferior_ptid))
+      || lkd_proc_is_curr_task (ps))
+    return BENEATH->to_fetch_registers (ops, rc, regno);
+
+  /* Call the platform specific code. */
+  thread_awareness_inhibit ();
+  cleanup = make_cleanup (thread_awareness_exhibit, NULL);
+  res =
+    linux_awareness_ops->lo_fetch_context_register (regno, ps->task_struct);
+  do_cleanups (cleanup);
+
+  if (!res)
+    warning ("Could not fetch task register.");
+
+  return;
+}
+
+/* target_ops callback queried by GDB to write the registers of the
+ currently selected task. */
+static void
+linux_aware_store_registers (struct target_ops *ops,
+			     struct regcache *rc, int regno)
+{
+  struct cleanup *cleanup;
+  process_t *ps;
+  int res;
+
+  DEBUG (TARGET, 2, "store_registers %i\n", regno);
+
+  if ((lkd_private.loaded != LKD_LOADED)	/*check this first */
+      || !(ps = lkd_proc_get_by_ptid (inferior_ptid))
+      || lkd_proc_is_curr_task (ps))
+    return BENEATH->to_store_registers (ops, rc, regno);
+
+  /* Call the platform specific code. */
+  thread_awareness_inhibit ();
+  cleanup = make_cleanup (thread_awareness_exhibit, NULL);
+  res =
+    linux_awareness_ops->lo_store_context_register (regno, ps->task_struct);
+  do_cleanups (cleanup);
+
+  if (res)
+    warning ("Could not store task register.");
+
+  return;
+}
+
+
+/* This is the target_ops callback that is called by GDB to start the
+ execution of the processor. */
+static void
+linux_aware_resume (struct target_ops *ops,
+		    ptid_t pid, int step, enum gdb_signal sig)
+{
+  struct cleanup *cleanup;
+
+  DEBUG (TARGET, 1, "Resuming %i with sig %i (step %i)\n",
+	 (int) ptid_get_pid (pid), (int) sig, step);
+
+  /* Store the last execution request type. See the stepping
+     variable comment above, and the usage in linux_aware_wait. */
+  lkd_stepping = step;
+
+  /* Call platform dependant resume callback if needed. */
+  if (linux_awareness_ops && linux_awareness_ops->lo_pre_exec_start)
+    {
+      thread_awareness_inhibit ();
+      cleanup = make_cleanup (thread_awareness_exhibit, NULL);
+      linux_awareness_ops->lo_pre_exec_start ();
+      do_cleanups (cleanup);
+    }
+
+  if (lkd_private.loaded != LKD_LOADED)
+    return BENEATH->to_resume (ops, pid, step, sig);
+
+  if (thread_event_do_exec_bp && thread_event_do_exec_return_bp)
+    {
+      delete_breakpoint (thread_event_do_exec_bp);
+      thread_event_do_exec_bp = NULL;
+    }
+
+  lkd_uninstall_do_exit_event ();
+
+  /* Before restarting first need to clear some caches.  */
+  thread_awareness_inhibit ();
+  cleanup = make_cleanup (thread_awareness_exhibit, NULL);
+  linux_awareness_ops->lo_clear_cache ();
+  do_cleanups (cleanup);
+
+  /* Perform the execution request. */
+  BENEATH->to_resume (ops, pid, step, sig);
+
+
+  /* Set the running flag. (See the variable's comment). */
+  running = 1;
+}
+
+/* This is the target_ops callback that is called by GDB to wait for the
+ processor to stop executing. */
+static ptid_t
+linux_aware_wait (struct target_ops *ops,
+		  ptid_t ptid, struct target_waitstatus *status, int opts)
+{
+  struct cleanup *cleanup;
+  ptid_t stop_ptid;
+
+  /* We aren't running anymore. */
+  running = 0;
+
+  if (thread_awareness_inhibited () || !(lkd_private.kflags & KFLAG_DBGINFO))
+    return BENEATH->to_wait (ops, ptid, status, opts);
+
+  /* The linux aware wait begins here. */
+  thread_awareness_inhibit ();
+  cleanup = make_cleanup (thread_awareness_exhibit, NULL);
+
+  stop_ptid = BENEATH->to_wait (ops, ptid, status, opts);
+  if (max_cores > 1)
+    stop_core = ptid_get_tid (stop_ptid) - 1;
+  else
+    stop_core = 0;
+
+  disable_terminate ();
+
+  /*reset the inferior_ptid to the stopped ptid */
+  inferior_ptid = stop_ptid;
+
+  /* if we are not just stepping, check for auto-activation */
+  linux_aware_post_exec_stop (lkd_stepping);
+
+  if (lkd_private.loaded == LKD_LOADED)
+    {
+      CORE_ADDR pc;
+      CORE_ADDR task;
+      int i;
+      struct regcache *regcache;
+
+      /* rescan for new task, but avoid storming the debug connection
+       **/
+      lkd_proc_refresh_info (stop_core);
+
+      /* The above calls might will end up accessing the registers
+         of the target because of inhibit_thread_awareness(). However,
+         this will populate a register cache associated with
+         inferior_ptid, which we haven't updated yet. Force a flush
+         of these cached values so that they end up associated to
+         the right context. */
+      registers_changed ();
+
+      /* This is normally done by infrun.c:handle_inferior_event (),
+         but we need it set to access the frames for some operations
+         below (eg. in check_exec_actions (), where we don't know
+         what the user will ask in his commands. */
+      set_executing (minus_one_ptid, 0);
+
+      regcache = get_thread_regcache (inferior_ptid);
+
+      pc = regcache_read_pc (regcache);
+
+      /*
+       * Handle the installation of the module's specific init routine hook.
+       **/
+      thread_awareness_inhibit ();
+      make_cleanup (thread_awareness_exhibit, NULL);
+
+      /* pull-in the symbols of each core's running process if auto-debug
+       * is activated
+       **/
+      target_root_prefix_dirty = 1;	// fixme: code a proper command handler.
+
+      /* wait_process is non-null once we've successfully loaded lkd,
+       * and we could compute the current process for that core.
+       **/
+      if (wait_process)
+	{
+	  inferior_ptid = PTID_OF (wait_process);
+	  stop_ptid = inferior_ptid;
+	}
+    }
+
+  do_cleanups (cleanup);
+
+  enable_terminate ();
+
+  return stop_ptid;
+}
+
+/*
+ * arch-common post load op
+ **/
+
+/*
+ * try to find a BFD
+ **/
+static bfd *
+get_cur_bfd (int from_tty)
+{
+  /*give precedence to symfile */
+  if (symfile_objfile && symfile_objfile->obfd)
+    return symfile_objfile->obfd;
+
+  if (from_tty && !exec_bfd)
+    printf_filtered ("No executable file specified\n");
+
+  return exec_bfd;
+}
+
+/* the post load hook, and the callback to re-install
+ * what ever LKD patches into the gdb arch.*/
+static void
+linux_aware_post_load (char *prog, int fromtty)
+{
+  DEBUG (D_INIT, 1, "linux_aware_POST_load %s\n", prog);
+
+  /*let the arch specific part decide when loaded = 1 */
+  if (linux_awareness_ops->lo_post_load)
+    linux_awareness_ops->lo_post_load (prog, fromtty);
+
+}
+
+/* The target_ops callback called by GDB to load the debugged program
+ to the target. Just a wrapper for BENEATH->to_load with hooks that
+ call into the platform specific part. */
+static void
+linux_aware_load (struct target_ops *ops, const char *prog, int fromtty)
+{
+  DEBUG (D_INIT, 1, "linux_aware_load %s\n", prog);
+
+  /* make sure the load conditions are met, so that putting
+     'set linux-awareness loaded 1' in his .shgdbinit file does not crash. */
+
+  if ((BENEATH->to_shortname[0] == 'e' /*exec */ )
+      || (BENEATH->to_shortname[0] == 'n' /*none */ ))
+    {
+      execute_command ("maint print target-stack", 0);
+      error ("underlying target is not valid (might be exec or none).\n");
+    }
+
+  BENEATH->to_load (ops, prog, fromtty);
+
+  lkd_params.loaded = LKD_NOTLOADED;
+  lkd_private.loaded = LKD_NOTLOADED;
+
+  if (lkd_params.auto_activate)
+    {
+      lkd_params.loaded = LKD_LOADED;
+      lkd_loaded_set (0, 0, 0);
+    }
+
+  lkd_private.connected = 1;
+}
+
+/* The target_ops callback called by GDB to load the attach to an
+ already running program. Just sets 'loaded' to 1, as the program is
+ already loaded. If you attach with a non standard command, you have
+ to do 'set linux-awareness loaded 1' by hand. */
+static void
+linux_aware_attach (struct target_ops *ops, const char *prog, int fromtty)
+{
+  DEBUG (D_INIT, 1, "linux_aware_attach %s\n", prog);
+
+  if (BENEATH && BENEATH->to_attach != NULL)
+    BENEATH->to_attach (ops, prog, fromtty);
+
+  if (lkd_params.auto_activate)
+    {
+      lkd_params.loaded = LKD_LOADED;
+      lkd_loaded_set (0, 0, 0);
+    }
+
+  lkd_private.connected = 1;
+  DEBUG (TARGET, 3, "end linux_aware_attach %s\n", prog);
+}
+
+/* Used to trigger the disconnection. */
+static void
+linux_aware_disconnect (struct target_ops *target, const char *args,
+			int from_tty)
+{
+  DEBUG (D_INIT, 1, "linux_aware_disconnect\n");
+
+  unpush_target (&linux_aware_ops);
+  target_disconnect (args, from_tty);
+
+  lkd_private.connected = 0;
+}
+
+/* This callback is called on 'normal stop', ie. when the user gets
+ the control back. We do various bookkeeping at this point. */
+static void
+normal_stop_callback (struct bpstats *bs, int unsused)
+{
+  /* If there's no userspace breakpoint left, remove the breakpoints
+     we use to notify about conditions we need to handle like 'out of
+     memory' or 'process exit'. */
+  if (thread_event_low_mem_bp != NULL)
+    {
+      int has_bp = 0;
+      struct bp_location *loc;
+      struct breakpoint *bp;
+
+      ALL_BREAKPOINTS (bp) for (loc = bp->loc; loc; loc = loc->next)
+	{
+	  if (loc->address
+	      && linux_awareness_ops->lo_is_user_address (loc->address))
+	    {
+	      has_bp = 1;
+	      break;
+	    }
+	}
+
+      if (!has_bp)
+	{
+	  if (thread_event_low_mem_bp != NULL)
+	    {
+	      delete_breakpoint (thread_event_low_mem_bp);
+	      thread_event_low_mem_bp = NULL;
+	    }
+	}
+    }
+}
+
+/* target_has_all_memory() target_ops callback.
+   Note that if a beneath target exists then return 0 to indicate that the
+   beneath target to be used if this target cannot handle the request.  */
+static int
+linux_aware_has_all_memory (struct target_ops *ops)
+{
+  if (BENEATH && BENEATH->to_has_all_memory)
+    return 0;
+  return default_child_has_all_memory (ops);
+}
+
+/* target_has_memory() target_ops callback. */
+static int
+linux_aware_has_memory (struct target_ops *ops)
+{
+  if (BENEATH && BENEATH->to_has_memory)
+    return BENEATH->to_has_memory (ops);
+  return default_child_has_memory (ops);
+}
+
+/* target_has_stack() target_ops callback. */
+static int
+linux_aware_has_stack (struct target_ops *ops)
+{
+  if (BENEATH && BENEATH->to_has_stack)
+    return BENEATH->to_has_stack (ops);
+  return default_child_has_stack (ops);
+}
+
+/* target_has_registers() target_ops callback. */
+static int
+linux_aware_has_registers (struct target_ops *ops)
+{
+  if (BENEATH && BENEATH->to_has_registers)
+    return BENEATH->to_has_registers (ops);
+  return default_child_has_registers (ops);
+}
+
+/* target_has_execution() target_ops callback. */
+static int
+linux_aware_has_execution (struct target_ops *ops, ptid_t ptid)
+{
+  if (BENEATH && BENEATH->to_has_execution)
+    return BENEATH->to_has_execution (ops, ptid);
+  return default_child_has_execution (ops, ptid);
+}
+
+/* target_close() target_ops callback. */
+static void
+linux_aware_close (struct target_ops *ops)
+{
+  struct target_waitstatus dummy;
+
+  DEBUG (D_INIT, 1, "Closing... \n");
+
+  /* We might be called by a signal handler */
+  if (running)
+    {
+      target_stop (inferior_ptid);
+      if (BENEATH != NULL && BENEATH->to_wait != NULL)
+	BENEATH->to_wait (&linux_aware_ops, minus_one_ptid, &dummy, 0);
+    }
+
+  lkd_params.enabled = 0;
+  lkd_enabled_set (0, 0, 0);
+
+  if (normal_stop_observer)
+    {
+      observer_detach_normal_stop (normal_stop_observer);
+      normal_stop_observer = NULL;
+    }
+
+  wait_process = NULL;
+
+  _inhibit_thread_register_awareness = 0;
+
+  if (thread_event_low_mem_bp)
+    {
+      delete_breakpoint (thread_event_low_mem_bp);
+      thread_event_low_mem_bp = NULL;
+    }
+
+
+  lkd_proc_free_list ();
+
+  fields_and_addrs_clear ();
+
+  if (running)
+    {
+      /* If we leave the board run, we'd better remove breakpoints
+         so that it's functional. */
+      remove_breakpoints ();
+
+      if (BENEATH != NULL && BENEATH->to_resume != NULL)
+	BENEATH->to_resume (&linux_aware_ops, inferior_ptid, 0, 0);
+    }
+
+  lkd_private.banner_file_valid = 0;
+  lkd_private.banner_mem_valid = 0;
+  running = 0;
+}
+
+static void
+linux_aware_files_info (struct target_ops *target)
+{
+  printf_filtered (_("Connected to remote linux kernel\n"));
+}
+
+static int
+linux_aware_can_async_p (struct target_ops *ops)
+{
+  return 0;
+}
+
+static int
+linux_aware_is_async_p (struct target_ops *ops)
+{
+  return 0;
+}
+
+/* Setup the target_ops callbacks. */
+static void
+init_linux_aware_target (void)
+{
+  DEBUG (D_INIT, 1, "init_linux_aware_target\n");
+
+  linux_aware_ops.to_shortname = "linux-aware";
+  linux_aware_ops.to_longname = "Linux-aware target interface";
+  linux_aware_ops.to_doc = linux_awareness_doc;
+
+  /* Dirty hook to stack above anythin else, event something above
+     the thread stratum (like starm) */
+  linux_aware_ops.to_stratum = LKD_STRATUM_LINUX;
+
+  linux_aware_ops.to_load = linux_aware_load;
+  linux_aware_ops.to_close = linux_aware_close;
+  linux_aware_ops.to_attach = linux_aware_attach;
+  linux_aware_ops.to_disconnect = linux_aware_disconnect;
+  linux_aware_ops.to_magic = OPS_MAGIC;
+
+
+  /* Registers */
+  linux_aware_ops.to_fetch_registers = linux_aware_fetch_registers;
+  linux_aware_ops.to_store_registers = linux_aware_store_registers;
+
+  /* Execution */
+  linux_aware_ops.to_resume = linux_aware_resume;
+  linux_aware_ops.to_wait = linux_aware_wait;
+
+  /* Threads */
+  linux_aware_ops.to_thread_alive = linux_aware_thread_alive;
+  linux_aware_ops.to_update_thread_list = linux_aware_update_thread_list;
+  linux_aware_ops.to_pid_to_str = linux_aware_pid_to_str;
+  linux_aware_ops.to_extra_thread_info = linux_aware_extra_thread_info;
+  linux_aware_ops.to_thread_name = linux_aware_thread_name;
+  linux_aware_ops.to_core_of_thread = linux_aware_core_of_thread;
+  linux_aware_ops.to_has_thread_control = tc_none;
+
+  linux_aware_ops.to_has_all_memory = linux_aware_has_all_memory;
+  linux_aware_ops.to_has_memory = linux_aware_has_memory;
+  linux_aware_ops.to_has_stack = linux_aware_has_stack;
+  linux_aware_ops.to_has_registers = linux_aware_has_registers;
+  linux_aware_ops.to_has_execution = linux_aware_has_execution;
+  linux_aware_ops.to_files_info = linux_aware_files_info;
+
+  /* Prevent Async operations
+   * LKD doesn't yet support ASync,
+   * Particularly on connect/resume, which can break things
+   * when connecting to an async target such as QEmu
+   */
+  linux_aware_ops.to_can_async_p = linux_aware_can_async_p;
+  linux_aware_ops.to_is_async_p = linux_aware_is_async_p;
+}
+
+
+
+/* This function is here to replace the default display for
+ breakpoints set on code that has been unloaded. This display
+ routine doesn't display the 0xFFFFFFFF that could confuse the
+ user. */
+static void
+init_bp_mention (struct breakpoint *bpt)
+{
+  bpt->ops = NULL;
+  printf_filtered (_("Breakpoint %d (%s) pending."),
+		   bpt->number, event_location_to_string (bpt->location));
+}
+
+static struct breakpoint_ops init_breakpoints_ops = {
+  .print_mention = init_bp_mention
+};
+
+static void
+lkd_install_do_exit_event (void)
+{
+/* install hook for do_exit */
+  if (thread_event_do_exit_bp == NULL)
+    {
+      thread_event_do_exit_bp =
+	create_thread_event_breakpoint (target_gdbarch (), ADDR (do_exit));
+
+      /*do no remove on resume */
+      lkd_private.keep_do_exit_event = 1;
+    }
+}
+
+void
+lkd_uninstall_do_exit_event (void)
+{
+  /* uninstall hook for do_exit */
+  if ((thread_event_do_exit_bp != NULL) && (!lkd_private.keep_do_exit_event))
+    {
+      delete_breakpoint (thread_event_do_exit_bp);
+      thread_event_do_exit_bp = NULL;
+    }
+}
+
+/* This callback is called when a new breakpoint is created. */
+static void
+linux_aware_create_breakpoint_hook (struct breakpoint *bpt)
+{
+  struct lm_info *info;
+
+  if (lkd_private.loaded != LKD_LOADED)
+    return;
+
+
+  if (bpt->loc && bpt->loc->address == ~(CORE_ADDR) 0)
+    {
+      warning
+	("You have inserted a breakpoint on a location that is not currently\n"
+	 "mapped to memory (it is flagged as __init code and the initialization\n"
+	 "phase of the module has completed). The breakpoint will be reset if you\n"
+	 "reload the module.");
+      /* Display correct breakpoint info and disable the breakpoint. */
+      bpt->ops = &init_breakpoints_ops;
+      bpt->loc->shlib_disabled = 1;
+    }
+  else if (bpt->loc
+	   && bpt->loc->address
+	   && bpt->loc->loc_type == bp_loc_software_breakpoint
+	   && linux_awareness_ops->lo_is_user_address (bpt->loc->address))
+    {
+      CORE_ADDR addr = bpt->loc->address;
+
+      /* All the userspace breakpoints are set to a specific task. */
+      bpt->thread = ptid_to_global_thread_id (inferior_ptid);
+
+
+      lkd_install_do_exit_event ();
+
+      /*Q: does setting a bpt to a usermode pages prevent Linux
+       * to unmap it ? This seems to say so.*/
+      if (HAS_ADDR (try_to_unmap))
+	{
+	  if (thread_event_low_mem_bp == NULL)
+	    thread_event_low_mem_bp =
+	      create_thread_event_breakpoint
+	      (target_gdbarch (), ADDR (try_to_unmap));
+	}
+      else
+	warning ("'try_to_unmap' wasn't found.");
+    }
+}
+
+
+static char *
+get_banner_from_file (bfd * cur_bfd)
+{
+  CORE_ADDR banner_addr = ADDR (linux_banner);
+  CORE_ADDR section_addr, section_size;
+  asection *data;
+
+  gdb_assert (lkd_private.banner_file);
+
+  if (lkd_private.banner_file_valid)
+    return lkd_private.banner_file;
+
+  lkd_private.banner_file_valid = 1;
+
+  /* first try to find linux_banner in .rodata */
+  data = bfd_get_section_by_name (cur_bfd, ".rodata");
+  if (data)
+    {
+      section_addr = bfd_get_section_vma (cur_bfd, data);
+      section_size = bfd_get_section_size (data);
+      if ((banner_addr < section_addr)
+	  || (banner_addr >= section_addr + section_size))
+	data = NULL;
+    }
+
+  if (!data)
+    {
+      /* then, try .text */
+      data = bfd_get_section_by_name (cur_bfd, ".text");
+      if (data)
+	{
+	  section_addr = bfd_get_section_vma (cur_bfd, data);
+	  section_size = bfd_get_section_size (data);
+	  if ((banner_addr < section_addr)
+	      || (banner_addr >= section_addr + section_size))
+	    data = NULL;
+	}
+    }
+
+  if (data)
+    {
+      int i = 0;
+      char c;
+      bfd_seek (cur_bfd,
+		data->filepos + banner_addr -
+		bfd_get_section_vma (cur_bfd, data), SEEK_SET);
+      do
+	{
+	  bfd_bread (&c, 1, cur_bfd);
+	  lkd_private.banner_file[i++] = c;
+	}
+      while ((c != '\0') && (i < lkd_private.banner_file_size));
+    }
+  else
+    {
+      printf_filtered ("Linux banner not found in any of .text or .rodata\n");
+      lkd_private.banner_file_valid = 0;
+    }
+
+  /* for security */
+  lkd_private.banner_file[lkd_private.banner_file_size - 1] = '\0';
+
+  DEBUG (D_INIT, 1, "Got banner from file: %s\n", lkd_private.banner_file);
+
+  return lkd_private.banner_file;
+}
+
+static char *
+get_banner (void)
+{
+  if (lkd_private.banner_mem_valid)
+    return lkd_private.banner_mem;
+
+  gdb_assert (lkd_private.banner_mem);
+
+  lkd_private.banner_mem_valid = 1;
+
+  read_memory_string (ADDR (linux_banner),
+		      lkd_private.banner_mem, lkd_private.banner_mem_size);
+
+  lkd_private.banner_mem[lkd_private.banner_mem_size - 1] = '\0';
+
+  DEBUG (D_INIT, 1, "Read banner from mem: %s\n", lkd_private.banner_mem);
+
+  return lkd_private.banner_mem;
+}
+
+
+
+
+/******************************************************************************/
+/*************  LINUX AWARENESS INIT / AUTODETECTION / ENABLEMENT   ***********/
+/******************************************************************************/
+int
+lkd_try_push_target (void)
+{
+  DEBUG (D_INIT, 1, "lkd_try_push_target\n");
+
+  if (!BENEATH)
+    push_target (&linux_aware_ops);
+
+  return LKD_LOADED;
+}
+
+/* This function is called after load, or after attach, when we know
+ that the kernel code is in memory. (This might be called direclty
+ by the user by issuing 'set linux-awareness loaded', if he doesn't
+ use a standard attach mechanism. */
+void
+lkd_loaded_set (char *arg, int from_tty, struct cmd_list_element *c)
+{
+  bfd *cur_bfd;
+  process_t *ps;
+  char *banner1;
+  char *banner2, *file_name;
+  int i;
+
+  DEBUG (D_INIT, 1, "lkd_loaded_set\n");
+
+  if (lkd_params.loaded == lkd_private.loaded)
+    return;
+
+  if ((lkd_params.loaded == LKD_LOADED) && (!lkd_params.enabled))
+    {
+      lkd_enabled_set ((char *) 1, 0, NULL);
+      /* Could not enable so not debugging a kernel */
+      if (!lkd_params.enabled)
+	goto __sl_fail;
+    }
+
+  stop_core = 0;
+  cur_bfd = get_cur_bfd (from_tty);
+
+  /* if user forces loaded = off, also remove auto-load
+   **/
+  if (lkd_params.loaded == LKD_NOTLOADED)
+    {
+      struct cleanup *cleanup;
+
+      /* Before switching off first need to clear some caches.  */
+      thread_awareness_inhibit ();
+      cleanup = make_cleanup (thread_awareness_exhibit, NULL);
+      linux_awareness_ops->lo_clear_cache ();
+      do_cleanups (cleanup);
+
+      lkd_private.loaded = LKD_NOTLOADED;
+
+      if (lkd_params.auto_activate)
+	{
+	  lkd_params.auto_activate = 0;
+	  if (from_tty)
+	    printf_filtered
+	      ("(also disabling linux-awareness auto-activation)\n");
+	}
+
+      lkd_proc_free_list ();
+
+      /* fallback to any thread that makes sense for the beneath target */
+      lkd_reset_thread_list ();
+
+      return;
+    }
+
+  /* if the user want to set loaded = on, do some sanity checks
+   **/
+  if (lkd_params.loaded == LKD_LOADED)
+    {
+      /* check if symbol-file was set first */
+      if (!get_cur_bfd (from_tty))
+	goto __sl_fail;
+
+      cur_bfd = get_cur_bfd (from_tty);
+      banner2 = get_banner_from_file (cur_bfd);
+      file_name = bfd_get_filename (cur_bfd);
+
+      lkd_private.target_pointer_type =
+	builtin_type (target_gdbarch ())->builtin_data_ptr;
+
+      if (linux_awareness_ops->lo_pre_load)
+	linux_awareness_ops->lo_pre_load (file_name, from_tty);
+
+      lkd_private.loaded = LKD_LOADING;
+
+      gdb_assert (lkd_params.enabled);
+
+      if (!(lkd_private.kflags & KFLAG_DBGINFO))
+	{
+	  warning
+	    ("\"set loaded\" failed because kernel has no debug info.\n");
+	  goto __sl_fail;
+	}
+
+      if (lkd_try_push_target () != LKD_LOADED)
+	{
+	  warning
+	    ("\"set loaded\" failed because L-A target could not be pushed.\n");
+	  goto __sl_fail;
+	}
+
+
+      /* (re)init the thread_list with hardware threads */
+      lkd_proc_init ();
+
+      /*do arch-specific fixup (mmu for instance) */
+      linux_aware_post_load (file_name, 0);
+
+      /*needs access to mem */
+      if (set_utsname_release () != 0 /*EOK*/)
+	{
+	  warning
+	    ("\"set loaded\" failed because L-A target could not access target memory.\n");
+	  goto __sl_fail;
+	}
+
+      /*get banner from mem */
+      banner1 = get_banner ();
+
+      /* Check that the kernel in memory corresponds to the
+       * binary file we were given.
+       */
+      if (banner1 == NULL || banner2 == NULL || strcmp (banner1, banner2))
+	{
+	  if (!nquery
+	      ("Kernel banner in debugger file: \n%s\n"
+	       "Kernel banner in target memory: \n%s\n"
+	       "WARNING: do you want to continue ?\n"
+	       "(if the kernels don't match the debugger might crash)",
+	       banner2, banner1))
+	    {
+	      error ("Aborted (kernel banner mismatch).");
+	      goto __sl_fail;
+	    }
+	}
+
+      lkd_proc_invalidate_list ();
+
+      /* scan the linux threads */
+
+      if (!lkd_proc_refresh_info (stop_core))
+	{
+	  if (from_tty)
+	    printf_filtered ("failed: has this kernel started?\n");
+	  goto __sl_fail;
+	}
+
+      lkd_proc_set_symfile ();
+
+
+      lkd_private.loaded = lkd_params.loaded;
+    }
+
+  printf_filtered ("Kernel image version: %s\n", lkd_private.utsname_release);
+
+  return;
+
+__sl_fail:
+  /* silently fail, we retry later.
+   **/
+  lkd_params.loaded = LKD_NOTLOADED;
+  lkd_private.loaded = LKD_NOTLOADED;
+  return;
+}
+
+/* Helper for linux_awareness_fix_debug_info() that locates the lowest
+ section in a BFD. */
+static void
+find_min_load_addr (bfd * abfd, asection * sectp, void *addr)
+{
+  CORE_ADDR *min_addr = addr;
+  CORE_ADDR vma;
+
+  if (!(bfd_get_section_flags (abfd, sectp) & SEC_ALLOC))
+    return;
+  if (!(bfd_get_section_flags (abfd, sectp) & SEC_HAS_CONTENTS))
+    return;
+
+  vma = bfd_get_section_vma (abfd, sectp);
+  if (vma < *min_addr)
+    *min_addr = vma;
+}
+
+/*
+ * The functionalities that can be built as modules often have a
+ * cleanup routine (marked with module_exit). When the driver is built
+ * into the kernel (i.e. not as a module), the cleanup routines aren't
+ * linked in, but their debug information remains... These routines
+ * all have very low addresses (as they haven't been relocated). This
+ * functions try to partially fix the debug info, so that the psymtabs
+ * don't advertise a too wide range of text addresses.
+ */
+static void
+linux_awareness_fix_debug_info (void)
+{
+  CORE_ADDR min_load_addr = (CORE_ADDR) - 1;
+  struct partial_symtab *pst;
+
+  bfd_map_over_sections (symfile_objfile->obfd, find_min_load_addr,
+			 &min_load_addr);
+
+  ALL_OBJFILE_PSYMTABS (symfile_objfile, pst)
+  {
+    if (pst->textlow < min_load_addr)
+      pst->textlow = min_load_addr;
+  }
+}
+
+/* GDB wants the stack it reads to have a strictly decreasing SP. This
+ relation isn't true when the backtrace goes from kerne- to
+ user-space. Overload the inner_than method to hide this
+ peculiarity. */
+static int
+linux_aware_inner_than (CORE_ADDR lhs, CORE_ADDR rhs)
+{
+  if (linux_awareness_ops->lo_is_kernel_address (rhs)
+      && linux_awareness_ops->lo_is_user_address (lhs))
+    return 0;
+
+  return core_addr_lessthan (lhs, rhs);
+}
+
+void
+set_skip_schedule_frame (char *arg, int from_tty, struct cmd_list_element *c)
+{
+  reinit_frame_cache ();
+}
+
+
+/* Function called to init the linux awareness layer once we know
+ we're debugging a known kernel. */
+static void
+linux_awareness_init (void)
+{
+  struct cmd_list_element *c;
+  const char *linux_awareness_postinit = "linux-awareness-postinit";
+
+  DEBUG (D_INIT, 1, "linux_awareness_init\n");
+
+  /* Stack our layer over the real target stack. */
+  lkd_try_push_target ();
+
+  /* this may set the OS ABI (reset the solib ops too!) */
+  linux_awareness_ops->lo_init ();
+
+  printf_filtered ("Enabling Linux Kernel Debugger %s build %s.\n",
+		   LKD_VERSION_STRING, __DATE__);
+
+  /* Set this as early as we can */
+  lkd_private.target_pointer_type =
+    builtin_type (target_gdbarch ())->builtin_data_ptr;
+
+  /* Init some data structures. */
+  linux_awareness_fix_debug_info ();
+
+  /* Register the various callbacks we use. */
+  normal_stop_observer = observer_attach_normal_stop (normal_stop_callback);
+  observer_attach_breakpoint_created (linux_aware_create_breakpoint_hook);
+
+
+  set_gdbarch_inner_than (target_gdbarch (), linux_aware_inner_than);
+
+
+  add_info_alias ("tasks", "threads", 0);
+  add_com_alias ("task", "thread", class_run, 0);
+
+  add_com ("running_task", class_lkd, running_task_command,
+	   "Switch to the currently running task.");
+
+
+  add_setshow_integer_cmd ("skip_schedule_frame",
+			   class_lkd,
+			   &lkd_params.skip_schedule_frame,
+			   "Set whether the debugger should hide the schedule() frame for sleeping tasks",
+			   "Show whether the debugger should hide the schedule() frame for sleeping tasks",
+			   "Typical value is between 0 for full stack to 4",
+			   &set_skip_schedule_frame, NULL,
+			   &set_linux_awareness_cmd_list,
+			   &show_linux_awareness_cmd_list);
+
+
+  /* Call the user-defined linux_awareness_postinit command if it
+     exists. (Allows the user to put code in his .gdbinit that will
+     be run only if the layer is loaded). */
+  c = lookup_cmd (&linux_awareness_postinit, cmdlist, "", 1, 1);
+  if (c != NULL && c->theclass == class_user)
+    execute_user_command (c, 0);
+
+}
+
+/* Helper for the autoactivation symbol lookup. */
+static inline int
+linux_awareness_lookup_symbol (const char *name)
+{
+  int found = lookup_minimal_symbol (name, NULL, NULL).minsym != NULL;
+
+  if (!found)
+    DEBUG (D_INIT, 1, "Symbol '%s' not found\n", name);
+  else
+    DEBUG (D_INIT, 4, "Symbol '%s' found\n", name);
+
+  return found;
+}
+
+/* Helper for the autoactivation symbol lookup. */
+static inline int
+linux_awareness_lookup_symtab (const char *name)
+{
+  int found = lookup_symtab (name) != NULL;
+
+  if (!found)
+    DEBUG (D_INIT, 1, "Symtab '%s' not found\n", name);
+  else
+    DEBUG (D_INIT, 4, "Symtab '%s' found\n", name);
+
+  return found;
+}
+
+/* make sure we have a kernel objfile */
+static int
+linux_awareness_check (void)
+{
+  int build = 0;
+  int check = 0;
+
+  DEBUG (D_INIT, 1, "linux_awareness_check\n");
+
+  /* reset flags */
+  lkd_private.kflags &= ~(KFLAG_LINUX | KFLAG_DBGINFO);
+
+  /* Look for some specific Linux symbols. */
+  if (!linux_awareness_lookup_symbol ("schedule")
+      || !linux_awareness_lookup_symbol ("linux_banner"))
+    return 0;			/* KO */
+
+  /* Make sure we have an architecture layer */
+  if (!linux_awareness_ops)
+    {
+      /* More verbose here, as we believe we are looking at a kernel,
+       * and the --enable-linux-awareness configure flag has been set */
+      warning ("Architecture Layer Missing. Can't enable linux awareness");
+      return 0;
+    }
+
+  lkd_private.kflags |= KFLAG_LINUX;
+
+  /* More checks. */
+  lookup_symtab ("page_io.c");
+
+  /* check for mandatory structure and fields */
+
+  check = HAS_FIELD (pid_namespace, last_pid)
+    && HAS_FIELD (task_struct, nsproxy);
+
+  if (!check)			/*look for older kernels */
+    check = HAS_FIELD (list_head, next) && HAS_FIELD (task_struct, namespace);
+
+  check = check && HAS_FIELD (task_struct, children)
+    && HAS_FIELD (task_struct, sibling)
+    && HAS_FIELD (task_struct, thread_group)
+    && HAS_FIELD (task_struct, pid)
+    && HAS_FIELD (task_struct, tgid)
+    && HAS_FIELD (task_struct, comm)
+    && HAS_FIELD (thread_info, preempt_count);
+
+  /* load some data that GDB seems to loose otherwise */
+  if (check && linux_awareness_lookup_symtab ("mmap.c")
+      && linux_awareness_lookup_symtab ("fork.c")
+      && linux_awareness_lookup_symtab ("block_dev.c")
+      && linux_awareness_lookup_symtab ("vmalloc.c")
+      && linux_awareness_lookup_symtab ("page_alloc.c")
+      && linux_awareness_ops->lo_check_kernel ())
+    lkd_private.kflags |= KFLAG_DBGINFO;
+  else
+    warning ("debug information missing.");
+
+  return 1;			/* OK */
+}
+
+/* Function called when we enable or disable the linux awareness
+ layer. */
+void
+lkd_enabled_set (char *args, int from_tty, struct cmd_list_element *c)
+{
+  static int stored_state = 0;
+
+  DEBUG (D_INIT, 1, "lkd_enabled_set\n");
+
+  /*if not from tty, we can use args as a parameter. */
+  if ((!from_tty) && ((uintptr_t) args == 1))
+    lkd_params.enabled = 1;
+
+  if (lkd_params.enabled == stored_state)
+    return;
+
+  if (lkd_params.enabled == 1)
+    {
+
+      /* make sure that a bfd is available,
+       * reevaluate the current objfile
+       */
+      if (linux_awareness_check () && get_cur_bfd (from_tty))
+	linux_awareness_init ();
+      else
+	{
+	  /* bare machine debuggee, do not auto-enable
+	   * but allow bold user commands...*/
+	  lkd_params.enabled = 0;
+
+	  /* try to push the target anyway,
+	   * so that we get called into to_load */
+	  if (!BENEATH)
+	    push_target (&linux_aware_ops);
+
+	  if (from_tty)
+	    warning ("Could not enable linux-awareness: no objfile ?");
+	}
+
+    }
+  else if (!ptid_equal (inferior_ptid, null_ptid))	/*if not `mourned`already */
+    {
+      struct target_waitstatus dummy;
+      struct thread_info *tp;
+
+
+      /* this will reinit the thread_list.
+       * and record the current "loaded" status.
+       **/
+      lkd_params.loaded = LKD_NOTLOADED;
+      lkd_loaded_set (NULL, 0, NULL);
+    }
+
+  stored_state = lkd_params.enabled;
+}
+
+/* This callback is called each time the user loads a new executable
+ in GDB, and it tries to determine if it's a Linux kernel. If it's
+ the case, it loads the linux awareness layer. */
+static void
+linux_awareness_on_new_objfile (struct objfile *objf)
+{
+  DEBUG (D_INIT, 1, "linux_awareness_on_new_objfile\n");
+
+  /* try pushing target and enabling at least.
+   **/
+  if (lkd_params.auto_activate)
+    lkd_enabled_set ((char *) 1, 0, 0);
+}
+
+static void
+set_linux_awareness (char *arg, int from_tty)
+{
+  printf_unfiltered
+    ("'set linux-awareness' must be followed by the name of a print subcommand.\n");
+  help_list (set_linux_awareness_cmd_list, "set linux-awareness ", -1,
+	     gdb_stdout);
+}
+
+static void
+show_linux_awareness (char *args, int from_tty)
+{
+  cmd_show_list (show_linux_awareness_cmd_list, from_tty, "");
+}
+
+static void
+set_global_loglevel (char *arg, int from_tty, struct cmd_list_element *c)
+{
+  struct debug_domain *domain = linux_aware_debug_domains_info;
+
+  while (domain->name != NULL)
+    domain++->level = lkd_params.loglevel;
+}
+
+volatile int stop_loop = 1;
+
+/* initialize private data
+ * when will gdb go OOP at least !??
+ **/
+static void
+init_private_data (void)
+{
+  lkd_private.string_buf_size = 4096;
+  lkd_private.string_buf =
+    xcalloc (lkd_private.string_buf_size, sizeof (char));
+  lkd_private.banner_file_size = 256;
+  lkd_private.banner_file =
+    xcalloc (lkd_private.banner_file_size, sizeof (char));
+  lkd_private.banner_file_valid = 0;
+  lkd_private.banner_mem_size = 256;
+  lkd_private.banner_mem =
+    xcalloc (lkd_private.banner_mem_size, sizeof (char));
+  lkd_private.banner_mem_valid = 0;
+  lkd_private.utsname_release_size = 256;
+  lkd_private.utsname_release =
+    xcalloc (lkd_private.banner_mem_size, sizeof (char));
+  lkd_private.utsname_release_valid = 0;
+  lkd_private.kflags = KFLAG_NOLINUX;
+}
+
+static void
+linux_awareness_inferior_created (struct target_ops *ops, int from_tty)
+{
+  DEBUG (D_INIT, 1, "linux_awareness_inferior_created\n");
+  if (lkd_params.auto_activate)
+    lkd_enabled_set ((char *) 1, 0, 0);
+}
+
+static ptid_t target_thread_ptid;
+
+static void
+linux_awareness_target_thread_changed (ptid_t ptid)
+{
+  DEBUG (D_INIT, 1, "linux_awareness_target_thread_changed {%d, %ld, %ld}\n",
+	 ptid_get_pid (ptid), ptid_get_lwp (ptid), ptid_get_tid (ptid));
+
+  if (ptid_equal (ptid, null_ptid) || ptid_equal (ptid, minus_one_ptid))
+    target_thread_ptid = null_ptid;
+  else if (ptid_get_tid (ptid) != CORE_INVAL)
+    target_thread_ptid = ptid;
+}
+
+int
+linux_aware_target_core (void)
+{
+  gdb_assert (!ptid_equal (target_thread_ptid, null_ptid));
+
+  return ptid_get_tid (target_thread_ptid) - 1;
+}
+
+/* -Wmissing-prototypes */
+extern initialize_file_ftype _initialize_linux_awareness;
+
+/* Function called automatically by GDB on each start. */
+void
+_initialize_linux_awareness (void)
+{
+  struct debug_domain *domain;
+
+  while (!stop_loop);
+
+  linux_uprocess_objfile_data_key = register_objfile_data ();
+
+  init_private_data ();
+
+  target_thread_ptid = null_ptid;
+
+  observer_attach_inferior_created (linux_awareness_inferior_created);
+  observer_attach_new_objfile (linux_awareness_on_new_objfile);
+  observer_attach_target_thread_changed
+    (linux_awareness_target_thread_changed);
+
+  init_linux_aware_target ();
+  add_target (&linux_aware_ops);
+
+  target_root_prefix = &gdb_sysroot;
+
+  add_prefix_cmd ("linux-awareness",
+		  class_lkd,
+		  set_linux_awareness,
+		  "Command for setting linux-awareness variables",
+		  &set_linux_awareness_cmd_list,
+		  "set linux-awareness ", 0, &setlist);
+
+  add_prefix_cmd ("linux-awareness",
+		  class_lkd,
+		  show_linux_awareness,
+		  "Command for showing linux-awareness variables",
+		  &show_linux_awareness_cmd_list,
+		  "show linux-awareness ", 0, &showlist);
+
+  add_setshow_boolean_cmd ("enabled",
+			   class_lkd,
+			   &lkd_params.enabled,
+			   "Set the activation state of the the linux "
+			   "awareness layer",
+			   "Show the activation state of the the linux "
+			   "awareness layer",
+			   NULL, &lkd_enabled_set, NULL,
+			   &set_linux_awareness_cmd_list,
+			   &show_linux_awareness_cmd_list);
+
+  add_setshow_boolean_cmd ("loaded", class_lkd, (int *) &lkd_params.loaded,	/*warn: can be '2' to detect transient states */
+			   "Set the loaded state of the kernel image",
+			   "Show the loaded state of the kernel image",
+			   NULL, &lkd_loaded_set, NULL,
+			   &set_linux_awareness_cmd_list,
+			   &show_linux_awareness_cmd_list);
+
+  domain = linux_aware_debug_domains_info;
+
+  while (domain->name != NULL)
+    {
+      static const char fmt[] =
+	"%s the debug level of the linux awareness " "layer %s part.";
+      const char *name = domain->name + 6;	/* Skip debug- */
+      char *help_set = xstrprintf (fmt, "Set", name);
+      char *help_show = xstrprintf (fmt, "Show", name);
+      add_setshow_zinteger_cmd ((char *) domain->name,
+				class_lkd,
+				&(domain->level),
+				help_set,
+				help_show,
+				NULL,
+				NULL, NULL,
+				&set_linux_awareness_cmd_list,
+				&show_linux_awareness_cmd_list);
+      xfree (help_set);
+      xfree (help_show);
+      ++domain;
+    }
+
+  add_setshow_zinteger_cmd ("debug-all",
+			    class_lkd,
+			    &lkd_params.loglevel,
+			    "Set the debug level of the linux awareness "
+			    "layer",
+			    "Show the debug level of the linux awareness "
+			    "layer",
+			    NULL,
+			    &set_global_loglevel, NULL,
+			    &set_linux_awareness_cmd_list,
+			    &show_linux_awareness_cmd_list);
+
+  add_setshow_boolean_cmd ("enable_task_awareness",
+			   class_lkd,
+			   &lkd_params.enable_task_awareness,
+			   "Set whether we implement task awareness",
+			   "Show whether we implement task awareness",
+			   NULL, NULL, NULL,
+			   &set_linux_awareness_cmd_list,
+			   &show_linux_awareness_cmd_list);
+
+  add_setshow_boolean_cmd ("auto_activate",
+			   class_lkd,
+			   &lkd_params.auto_activate,
+			   "Set whether we try to autodetect linux kernels.",
+			   "Show whether we try to autodetect linux kernels.",
+			   NULL, NULL, NULL,
+			   &set_linux_awareness_cmd_list,
+			   &show_linux_awareness_cmd_list);
+
+  add_setshow_boolean_cmd ("no-colors",
+			   class_lkd,
+			   &lkd_params.no_colors,
+			   "Set disable thread info coloring.",
+			   "Show thread info coloring status.",
+			   NULL, NULL, NULL,
+			   &set_linux_awareness_cmd_list,
+			   &show_linux_awareness_cmd_list);
+}
+
+/******************************* from shtdi.c *********************************/
+
+static void
+terminate_once (int signo)
+{
+  signal (signo, SIG_IGN);	/* Ignore further signals */
+  terminate_requested = signo;
+}
+
+static void
+disable_terminate (void)
+{
+  terminate_requested = 0;	/* Reset */
+  old_terminate_handler = signal (SIGTERM, terminate_once);
+  old_interrupt_handler = signal (SIGINT, terminate_once);
+}
+
+static void
+enable_terminate (void)
+{
+  signal (SIGTERM, old_terminate_handler);
+  signal (SIGINT, old_interrupt_handler);
+  if (terminate_requested)
+    raise (terminate_requested);
+}
diff --git a/gdb/lkd/lkd-process.c b/gdb/lkd/lkd-process.c
new file mode 100644
index 000000000000..5f791da9e5e2
--- /dev/null
+++ b/gdb/lkd/lkd-process.c
@@ -0,0 +1,892 @@
+/*
+  Linux Awareness extension target (Linux Kernel Debugger)
+  Copyright 2011-2013 STMicroelectronics.
+*/
+
+#include "defs.h"
+#include "ui-out.h"
+#include "arch-utils.h"
+#include "block.h"
+#include "breakpoint.h"
+#include "cli/cli-decode.h"
+#include "cli/cli-script.h"
+#include "command.h"
+#include "completer.h"
+#include "dictionary.h"
+#include "event-loop.h"
+#include "exceptions.h"
+#include "exec.h"
+#include "frame.h"
+#include "gdb.h"
+#include "gdb_assert.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "gdbthread.h"
+#include "gdbtypes.h"
+#include "inferior.h"
+#include "objfiles.h"
+#include "observer.h"
+#include "regcache.h"
+#include "solib.h"
+#include "solist.h"
+#include "symtab.h"
+#include "psympriv.h"
+#include "target.h"
+
+#include "bfd.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+#include "tui/tui.h"
+#include "lkd.h"
+#include "lkd-process.h"
+
+#define BENEATH linux_aware_ops.beneath
+
+/* Declaration of the required addresses. */
+DECLARE_ADDR (swapper_pg_dir);
+DECLARE_ADDR (init_thread_union);
+DECLARE_ADDR (init_task);
+
+DECLARE_ADDR (init_pid_ns);
+DECLARE_FIELD (pid_namespace, last_pid);
+
+/*realize cur_rq(cpu)->curr*/
+DECLARE_ADDR (__per_cpu_offset);
+DECLARE_ADDR (per_cpu__process_counts);
+DECLARE_ADDR (process_counts);
+DECLARE_ADDR (per_cpu__runqueues);
+DECLARE_ADDR (runqueues);
+
+DECLARE_FIELD (rq, curr);
+DECLARE_FIELD (rq, idle);
+DECLARE_FIELD (rq, lock);
+DECLARE_FIELD (raw_spinlock, magic);
+
+DECLARE_FIELD (list_head, next);
+
+
+DECLARE_FIELD (task_struct, active_mm);
+DECLARE_FIELD (mnt_namespace, list);
+ /**/ DECLARE_FIELD (path, dentry);
+ /**/ DECLARE_FIELD (task_struct, mm);
+DECLARE_FIELD (task_struct, tasks);
+DECLARE_FIELD (task_struct, children);
+DECLARE_FIELD (task_struct, thread_group);
+DECLARE_FIELD (task_struct, sibling);
+DECLARE_FIELD (task_struct, pid);
+DECLARE_FIELD (task_struct, tgid);
+DECLARE_FIELD (task_struct, namespace);
+DECLARE_FIELD (task_struct, nsproxy);
+DECLARE_FIELD (task_struct, prio);
+DECLARE_FIELD (task_struct, cred);
+DECLARE_FIELD (task_struct, comm);	/* far offset in the task_struct, to bulk-read everything needed. */
+
+
+ /**/ DECLARE_FIELD (thread_info, preempt_count);
+DECLARE_FIELD (vm_area_struct, vm_next);
+DECLARE_FIELD (vm_area_struct, vm_file);
+DECLARE_FIELD (vm_area_struct, vm_flags);
+DECLARE_FIELD (vm_area_struct, vm_start);
+DECLARE_FIELD (vm_area_struct, vm_end);
+DECLARE_FIELD (vm_area_struct, vm_pgoff);
+DECLARE_FIELD (vm_struct, next);
+DECLARE_FIELD (vm_struct, size);
+
+/* The current task. */
+
+process_t *process_list = NULL;	/*the processes list from the linux prospective */
+process_t *wait_process = NULL;	/*process we stopped at in target_wait */
+process_t *running_process[MAX_CORES];	/*scheduled process as seen by each core */
+uint32_t per_cpu_offset[MAX_CORES]; /*__per_cpu_offset*/
+
+/* per cpu peeks */
+CORE_ADDR runqueues_addr;
+CORE_ADDR rq_curr[MAX_CORES];	/*cur_rq(cpu) */
+CORE_ADDR rq_idle[MAX_CORES];	/*rq->idle */
+
+/* process list housekeeping*/
+static int process_counts[MAX_CORES];
+static int last_pid;
+
+struct mmu_infos mmu_info[MAX_CORES];
+
+
+static int
+find_thread_lwp (struct thread_info *tp, void *arg)
+{
+  long lwp = *(long*)arg;
+
+  return (ptid_get_lwp(tp->ptid) == lwp);
+}
+
+static int
+find_thread_swapper (struct thread_info *tp, void *arg)
+{
+  long core = *(long*)arg;
+
+  if ((!ptid_get_lwp(tp->ptid)) && (ptid_get_tid(tp->ptid) == core))
+    {
+      DEBUG (TASK, 2, "swapper found: tp->ptid(%d-%ld-%ld) core=%ld\n",
+	     ptid_get_pid(tp->ptid),
+	     ptid_get_lwp(tp->ptid),
+	     ptid_get_tid(tp->ptid),
+	     core);
+      return 1;
+    }
+  return 0;
+}
+
+/* invalidate the cached task list. */
+static void
+proc_private_dtor (struct private_thread_info * dummy)
+{
+	/* nop, do not free. */
+}
+
+/* Create the 'process_t' for the task pointed by the passed
+ TASK_STRUCT. */
+static void
+get_task_info (CORE_ADDR task_struct, process_t ** ps,
+	       int core /*zero-based */ )
+{
+  process_t *l_ps;
+  size_t size;
+  unsigned char *task_name;
+  int i = 0;
+  int lwp = 0;
+  ptid_t this_ptid;
+
+  while (*ps && (*ps)->valid)
+      ps = &((*ps)->next);
+
+  if (*ps == NULL)
+    *ps = XCNEW (process_t);
+
+  l_ps = *ps;
+
+  if (task_struct == 0)
+    {
+      /* create a fake swapper entry now for the additional core
+       * to keep the gdb_thread ordering
+       **/
+      l_ps->task_struct = 0;
+      l_ps->mm = 0;
+      l_ps->tgid = 0;
+      l_ps->prio = 0;
+      l_ps->core = -1;
+
+      if (l_ps->comm)
+        {
+	  xfree (l_ps->comm);
+	  l_ps->comm = NULL;
+        }
+      l_ps->comm = xstrdup ("[swapper]");
+    }
+  else
+    {
+      size = F_OFFSET (task_struct, comm) + F_SIZE (task_struct, comm);
+
+      task_name = lkd_private.string_buf + F_OFFSET (task_struct, comm);
+
+      /* use scratch area for messing around with strings
+       * to avoid static arrays and dispersed mallocs and frees
+       **/
+      gdb_assert (lkd_private.string_buf);
+      gdb_assert (lkd_private.string_buf_size >= size);
+
+      /* the task struct is not likely to change much from one kernel version
+       * to another. Knowing that comm is one of the far fields,
+       * try read the task struct in one command */
+      read_memory (task_struct, lkd_private.string_buf, size);
+
+      l_ps->task_struct = task_struct;
+      lwp = extract_unsigned_field (lkd_private.string_buf, task_struct, pid);
+      l_ps->mm = extract_pointer_field (lkd_private.string_buf,
+					task_struct, mm);
+      l_ps->active_mm = extract_pointer_field (lkd_private.string_buf,
+					       task_struct, active_mm);
+      l_ps->tgid = extract_unsigned_field (lkd_private.string_buf,
+					 task_struct, tgid);
+      l_ps->prio = extract_unsigned_field (lkd_private.string_buf,
+					   task_struct, prio);
+      l_ps->core = core;	/* for to_core_of_threads */
+
+      if (!l_ps->mm)
+	{
+	  int len = strlen ((char *)task_name);
+	  *(task_name + len) = ']';
+	  *(task_name + len + 1) = '\0';
+	  *(--task_name) = '[';
+	}
+
+      if (l_ps->comm)
+        {
+	  xfree (l_ps->comm);
+	  l_ps->comm = NULL;
+        }
+      l_ps->comm = xstrdup ((char*)task_name);
+    }
+
+  if (core != CORE_INVAL)
+    {
+      /* Long usage to map to LWP */
+      long core_mapped = core + 1;
+
+      /* swapper[core] */
+      gdb_assert (lwp==0);
+
+      this_ptid = ptid_build (ptid_get_pid(inferior_ptid), lwp /* == 0 */ , core_mapped);
+      l_ps->gdb_thread =
+	iterate_over_threads (find_thread_swapper, &core_mapped);
+    }
+  else
+    {
+      this_ptid = ptid_build (ptid_get_pid(inferior_ptid), lwp, CORE_INVAL);
+      l_ps->gdb_thread = iterate_over_threads (find_thread_lwp, &lwp);
+
+      /*reset the thread core value, if existing */
+      if (l_ps->gdb_thread)
+	{
+	  gdb_assert (!l_ps->gdb_thread->priv);
+	  PTID_OF (l_ps).tid = CORE_INVAL;
+	}
+    }
+
+  l_ps->pgd = 0;
+  l_ps->valid = 1;
+
+  /* allocate if not found
+   */
+  if (!l_ps->gdb_thread)
+   {
+      DBG_IF (TASK)
+	/*sanity check : go through the list and check if lwp already there */
+      process_t *tps = process_list;
+
+      while (tps && (tps)->valid)
+	{
+	  if (lwp && (tps)->gdb_thread && (ptid_get_lwp(PTID_OF (tps)) == lwp))
+	    gdb_assert (0);
+	  tps = tps->next;
+	};
+      DBG_ENDIF (TASK)
+
+      /* add with info so that pid_to_string works. */
+      l_ps->gdb_thread =  add_thread_with_info (this_ptid,
+				(struct private_thread_info *)l_ps);
+    }
+
+  /* forcibly update the private fields, as some thread may
+   * already have been created without, like hw threads.
+   * and this also tell is the gdb_thread is pruned or not!*/
+  l_ps->gdb_thread->priv = (struct private_thread_info *)l_ps;
+
+  DEBUG (TASK, 1, "gdb_thread->lwp %ld <=> ps %p\n",
+		  ptid_get_lwp(PTID_OF (*ps)), ps);
+
+  /* the process list freeing is not handled thanks to
+   * this `private` facility, yet.
+   */
+  l_ps->gdb_thread->private_dtor = proc_private_dtor;
+
+  /* keep trace of the last state to notify a change */
+  l_ps->old_ptid = PTID_OF (l_ps);
+}
+
+
+/* Returns the 'process_t' corresponding to the passed task_struct or
+ NULL if not in the list. */
+process_t *
+lkd_proc_get_by_task_struct (CORE_ADDR task_struct)
+{
+  process_t *ps = lkd_proc_get_list ();
+
+  while ((ps != NULL) && (ps->valid == 1))
+    {
+      if (ps->task_struct == task_struct)
+	return ps;
+      ps = ps->next;
+    }
+  return NULL;
+}
+
+/* Return the process currently scheduled on one core */
+process_t *
+lkd_proc_get_running (int core)
+{
+  process_t *current = NULL;
+  CORE_ADDR task;
+  struct thread_info *tp;	/*gdb ti */
+  ptid_t old_ptid;
+
+  if (core == CORE_INVAL)
+    return NULL;
+
+  if (running_process[core] == NULL)
+    {
+
+      gdb_assert (lkd_proc_get_runqueues (0));
+
+      task = lkd_proc_get_rq_curr (core);
+
+      if (task)
+	{			/* smp cpu is initialized */
+	  current = lkd_proc_get_by_task_struct (task);
+
+	  if (!current)
+	    {
+	      /* this task struct is not known yet AND was not seen
+	       * while running down the tasks lists, so this is presumably
+	       * the swapper of an secondary SMP core.
+	       */
+	      current =
+		lkd_proc_get_by_ptid (ptid_build
+				      (ptid_get_pid(inferior_ptid),
+				      0, core + 1));
+	      gdb_assert(current);
+
+	      current->task_struct = task;
+	    }
+	  else
+	    {
+	      /* update the thread's tid in thread_list if it exists and wasn't scheduled
+	       * so that tid makes sense for both the gdbserver and infrun.c
+	       **/
+	      PTID_OF (current).tid = core + 1;
+	    }
+
+	  current->core = core;	/* was CORE_INVAL */
+	  running_process[core] = current;
+	}			// task
+    }				// running_process[core]
+
+  return running_process[core];
+}
+
+/* Return 1 if this is a current task (or 0)*/
+int
+lkd_proc_is_curr_task (process_t * ps)
+{
+  return (ps && (ps == lkd_proc_get_running (ps->core)));
+}
+
+static CORE_ADDR get_rq_idle (int core);	/* forward decl. */
+
+/* Helper function that iterates the task list in the kernel
+   memory which are stored in a tree like structure. From sched.h:
+
+ #define do_each_thread(g, t) \
+        for (g = t = &init_task ; (g = t = next_task(g)) != &init_task ; ) do
+
+ #define while_each_thread(g, t) \
+        while ((t = next_thread(t)) != g)
+*/
+static CORE_ADDR
+_next_task (CORE_ADDR p)
+{
+  CORE_ADDR cur_entry = read_unsigned_embedded_field (p, task_struct, tasks, list_head, next);
+
+  if (!cur_entry)
+    {
+      warning ("kernel task list contains NULL pointer");
+      return 0;
+    }
+
+  return container_of (cur_entry, task_struct, tasks);
+}
+
+static CORE_ADDR
+_next_thread (CORE_ADDR p)
+{
+  CORE_ADDR cur_entry = read_unsigned_embedded_field (p, task_struct, thread_group, list_head, next);
+
+  if (!cur_entry)
+    {
+      DEBUG (TASK, 3, "kernel thread group list contains NULL pointer\n");
+      return 0;
+    }
+
+  return container_of (cur_entry, task_struct, thread_group);
+}
+
+static process_t **
+get_list_helper (process_t ** ps)
+{
+  CORE_ADDR g, t, init_task_addr;
+  int core;
+
+  init_task_addr = ADDR (init_task);
+  g = init_task_addr;
+  core = 0;
+
+  do
+    {
+      t = g;
+      do
+        {
+          if (!linux_awareness_ops->lo_is_kernel_address (t))
+	    {
+              warning ("parsing of task list stopped because of invalid address %s", phex (t, 4));
+              break;
+	    }
+
+          get_task_info (t, ps, core /*zero-based */ );
+          core = CORE_INVAL;
+
+          if (ptid_get_lwp (PTID_OF (*ps)) == 0)
+            {
+              /* this is init_task, let's insert the other cores swapper now */
+              int i;
+              for (i = 1; i < max_cores; i++)
+                {
+                  CORE_ADDR idle;
+                  ps = &((*ps)->next);
+                  idle = get_rq_idle (i);
+                  get_task_info (idle, ps, i);
+                }
+            }
+
+           DEBUG (TASK, 2, "Got task info for %s (%li)\n",
+              (*ps)->comm, ptid_get_lwp (PTID_OF (*ps)));
+
+          ps = &((*ps)->next);
+
+          /* mark end of chain and remove those threads
+           * that disappeared from the thread_list
+           * to avoid any_thread_of_process() to select a ghost.
+           **/
+          if (*ps)
+            (*ps)->valid = 0;
+
+          t = _next_thread (t);
+        } while (t && (t != g));
+
+      g = _next_task (g);
+    } while (g && (g != init_task_addr));
+
+  return ps;
+}
+
+
+/*----------------------------------------------------------------------------------------------*/
+
+/* This function returns a the list of 'process_t' corresponding
+ to the tasks in the kernel's task list. */
+process_t *
+lkd_proc_get_list (void)
+{
+  /* Return the cached copy if there's one,
+   * or rebuild it.
+   **/
+  if (process_list && process_list->valid)
+	  return process_list;
+
+  gdb_assert(lkd_private.proc_list_invalid);
+
+  get_list_helper (&process_list);
+
+  lkd_private.proc_list_invalid = 0;
+
+  return process_list;
+}
+
+/* Returns a valid 'process_t' corresponding to
+ * the passed ptid or NULL if not found.
+ */
+process_t *
+lkd_proc_get_by_ptid (ptid_t ptid)
+{
+  struct thread_info *tp;
+  long lwp = ptid_get_lwp(ptid);
+  process_t *ps;
+
+  gdb_assert(!lkd_private.proc_list_invalid);
+
+  if (lwp)
+	  /*non-swapper, ignore TID */
+	  tp = iterate_over_threads (find_thread_lwp, &lwp);
+  else
+	  /*swapper, TID gives the core, lwp = 0 is not unique */
+	  tp = find_thread_ptid(ptid);
+
+  ps = (process_t *)tp->priv;
+
+  /* Prune the gdb-thread is the process is not valid
+   * meaning is was no longer found in the task list. */
+  return ps;
+}
+
+/* invalidate the gdb thread is the linux ps has died.*/
+static int
+thread_clear_info (struct thread_info *tp, void *ignored)
+{
+  tp->priv = NULL;
+  return 0;
+}
+
+/* invalidate the cached task list. */
+void
+lkd_proc_invalidate_list (void)
+{
+  process_t *ps = process_list;
+  process_t *cur;
+  while (ps)
+    {
+      cur = ps;
+      ps = ps->next;
+      cur->valid = 0;
+    }
+
+  /* We invalidate the processes attached to the gdb_thread
+  * setting tp->private to null tells if the thread can
+  * be deleted or not. */
+  iterate_over_threads (thread_clear_info, NULL);
+
+  lkd_private.proc_list_invalid = 1;
+}
+
+void
+lkd_proc_free_list (void)
+{
+  process_t *ps = process_list;
+  process_t *cur;
+  while (ps)
+    {
+      cur = ps;
+      ps = ps->next;
+      // xfree does check for null pointers.
+      xfree (cur->comm);
+      xfree (cur);
+    }
+  process_list = NULL;
+}
+
+/* Return the processor core that thread PTID was last seen on.
+   This information is updated only when:
+   - update_thread_list is called
+   - thread stops
+   If the core cannot be determined -- either for the specified thread, or
+   right now, or in this debug session, or for this target -- return -1.  */
+int
+lkd_proc_core_of_thread (ptid_t ptid)
+{
+  int i = 0;
+  process_t *ps;
+
+  ps = lkd_proc_get_by_ptid (ptid);
+
+  if (!ps || (ps != lkd_proc_get_running (ps->core)))
+    return CORE_INVAL;
+  else
+    return ps->core;
+}
+
+CORE_ADDR
+lkd_proc_get_runqueues (int reset)
+{
+      CORE_ADDR swapper = 0;
+      process_t *test_ps;
+
+      runqueues_addr = 0;
+
+      if (HAS_ADDR (runqueues))
+	{
+	  runqueues_addr = ADDR (runqueues);
+	}
+      else
+	{
+	  runqueues_addr = ADDR (per_cpu__runqueues);
+	}
+      /* check validity */
+
+    DBG_IF (TASK)
+     if (HAS_FIELD (raw_spinlock, magic))
+	{
+
+	  CORE_ADDR lock_magic = ADDR (runqueues)
+	    + (CORE_ADDR) per_cpu_offset[0]
+	    + F_OFFSET (rq, lock) + F_OFFSET (raw_spinlock,
+					      magic);
+
+	  if ((read_memory_unsigned_integer (lock_magic, 4 /*uint32 */ ,
+					     LKD_BYTE_ORDER) & 0xdead0000)
+	      != 0xdead0000)
+	    error ("accessing the core runqueues seems to be compromised.");
+	}
+      else
+	printf_filtered ("runqueues access validated OK.");
+    DBG_ENDIF (TASK)
+
+  return runqueues_addr;
+}
+
+/*attempt getting the runqueue address for a core*/
+CORE_ADDR
+lkd_proc_get_rq_curr (int core)
+{
+
+  if (!rq_curr[core])
+    {
+      CORE_ADDR curr_addr = lkd_proc_get_runqueues (0);
+      if (!curr_addr)
+	return 0;
+      curr_addr =
+	curr_addr + (CORE_ADDR) per_cpu_offset[core] + F_OFFSET (rq, curr);
+      rq_curr[core] = read_memory_unsigned_integer (curr_addr, 4 /*uint32 */ ,
+						    LKD_BYTE_ORDER);
+    }
+  return rq_curr[core];
+};
+
+/*attempt getting the idle task for a core*/
+static CORE_ADDR
+get_rq_idle (int core)
+{
+  CORE_ADDR curr_addr = lkd_proc_get_runqueues (0);
+
+  if (!curr_addr || !HAS_FIELD (rq, idle))
+    return 0;
+
+  if (!rq_idle[core])
+    {
+      curr_addr += (CORE_ADDR) per_cpu_offset[core] + F_OFFSET (rq, idle);
+
+      rq_idle[core] = read_memory_unsigned_integer (curr_addr, 4 /*uint32 */ ,
+						    LKD_BYTE_ORDER);
+    }
+  return rq_idle[core];
+};
+
+static int
+get_process_count (int core)
+{
+  CORE_ADDR curr_addr = (CORE_ADDR) per_cpu_offset[core];
+  int proc_cnt;
+  static int warned = 0;
+
+  /* curr_addr can be null on UNI systems
+   * */
+  if (HAS_ADDR (process_counts))
+    curr_addr += ADDR (process_counts);
+  else if (HAS_ADDR (per_cpu__process_counts))
+    curr_addr += ADDR (per_cpu__process_counts);
+  else
+    {
+      /* return a fake, changing value
+       * at lest the list will be refreshed, but in a less optimal way.*/
+      if (!warned)
+	printf_filtered ("this kernel does not support `process_counts`\n");
+
+      if (!lkd_stepping)
+	warned++;
+
+      return warned;
+    }
+
+  proc_cnt = read_memory_unsigned_integer (curr_addr, 4 /*uint32 */ ,
+					   LKD_BYTE_ORDER);
+
+  return proc_cnt;
+};
+
+static int
+get_last_pid (void)
+{
+  int new_last_pid = 0;
+
+  if (HAS_ADDR (init_pid_ns))
+    {
+      /* Since STLinux 2.3 (2.6.23) */
+      new_last_pid = read_signed_field (ADDR (init_pid_ns),
+					pid_namespace, last_pid);
+    }
+  else
+    printf_filtered ("this kernel does not support `init_pid_ns`\n");
+
+  return new_last_pid;
+};
+
+void
+lkd_proc_init (void)
+{
+  int i = MAX_CORES;
+  struct thread_info *th = NULL;
+  struct cleanup *cleanup;
+
+  memset (per_cpu_offset, 0, MAX_CORES * sizeof (uint32_t));
+  memset (mmu_info, 0, MAX_CORES * sizeof (struct mmu_infos));
+
+  /* ensure thread list from beneath target is up to date */
+  cleanup = make_cleanup_restore_integer (&print_thread_events);
+  print_thread_events = 0;
+  update_thread_list ();
+  do_cleanups (cleanup);
+
+  /* count the h/w threads
+   */
+  max_cores = thread_count ();
+  gdb_assert (max_cores);
+
+  if (HAS_ADDR (__per_cpu_offset))
+    {
+      int core = max_cores;
+
+      read_memory (ADDR (__per_cpu_offset),
+		   (gdb_byte *) (per_cpu_offset),
+		   max_cores * sizeof (uint32_t));
+
+      while (--core)
+	if (!per_cpu_offset[core])
+	  {
+	    warning ("Suspicious null per-cpu offsets,"
+		     " or wrong number of detected cores:\n"
+		     "ADDR (__per_cpu_offset) = %s\nmax_cores = %d",
+		     phex (ADDR (__per_cpu_offset),4), max_cores);
+	    break;
+	  }
+    }
+  else
+    {
+      DEBUG (D_INIT, 1, "Assuming non-SMP kernel.\n");
+    }
+
+  if (!lkd_proc_get_runqueues (1 /*reset */ ) && (max_cores > 1))
+    printf_filtered ("\nCould not find the address of cpu runqueues:"
+		     "\ncurrent context information maybe less precise\n.");
+}
+
+/* still useful with non-smp systems
+ **/
+CORE_ADDR current_task_struct[MAX_CORES];
+CORE_ADDR current_thread_info[MAX_CORES];
+
+int
+lkd_proc_refresh_info (int cur_core)
+{
+  int i = max_cores;
+  int new_last_pid;
+  process_t *ps;
+  int do_invalidate = 0;
+
+  memset (running_process, 0, max_cores * sizeof (process_t *));
+  memset (current_thread_info, 0, max_cores * (sizeof (CORE_ADDR)));
+  memset (current_task_struct, 0, max_cores * (sizeof (CORE_ADDR)));
+  memset (rq_curr, 0, max_cores * sizeof (CORE_ADDR));
+
+  DEBUG (TASK, 1, "WAS: last_pid=%d, pcount[0]=%d, pcount[1]=%d\n",
+	 last_pid, process_counts[0], process_counts[1]);
+
+  new_last_pid = get_last_pid ();
+  if (new_last_pid != last_pid)
+    {
+      do_invalidate = 1;
+      last_pid = new_last_pid;
+    }
+
+  /* check if a process exited */
+  for (i = 0; i < max_cores; i++)
+    {
+      int new_pcount = get_process_count (i);
+      if (new_pcount != process_counts[i])
+	{
+	  process_counts[i] = new_pcount;
+	  do_invalidate = 1;
+	}
+    }
+
+  DEBUG (TASK, 1, "NEW: last_pid=%d, pcount[0]=%d, pcount[1]=%d\n",
+	 last_pid, process_counts[0], process_counts[1]);
+
+  if (do_invalidate)
+    lkd_proc_invalidate_list ();
+
+  /* Update the process_list now, so that init_task is in there. */
+  (void) lkd_proc_get_list ();
+
+  /* Call update to prune gdb_thread no longer linked to a linux task.*/
+  if (lkd_private.loaded == LKD_LOADED)
+    update_thread_list();
+
+  /* Set the running process
+   *
+   * we now have a thread_list looking like this:
+   * [1] = { 42000, 0, 1  }
+   * [2] = { 42000, 0, 2  }
+   * [3] = { 42000, 1, -1 }
+   *  ....
+   * [N] = { 42000, PID_N, -1 }
+   *
+   * Now set the tid according to the running core,
+   * */
+  for (i = 0; i < max_cores; i++)
+    lkd_proc_get_running (i);
+
+  wait_process = lkd_proc_get_running (cur_core);
+
+  if (!wait_process)
+    return 0;
+
+  DEBUG (TASK, 1, "wait_process: lwp = %ld\n", ptid_get_lwp(PTID_OF (wait_process)));
+  DEBUG (TASK, 1, "wait_process: pid = %d\n", ptid_get_pid(PTID_OF (wait_process)));
+  DEBUG (TASK, 1, "wait_process: tid = %ld\n", ptid_get_tid(PTID_OF (wait_process)));
+
+  gdb_assert(wait_process->gdb_thread);
+  gdb_assert((process_t *) wait_process->gdb_thread->priv == wait_process);
+
+  /* Notify ptid changed. */
+  ps = process_list;
+  while (ps && ps->valid)
+    {
+      if (ptid_get_tid(ps->old_ptid) != ptid_get_tid(PTID_OF (ps)))
+	{
+	  observer_notify_thread_ptid_changed (ps->old_ptid, PTID_OF (ps));
+	  ps->old_ptid.tid = ptid_get_tid(PTID_OF (ps));
+	}
+      ps = ps->next;
+    }
+
+  switch_to_thread(PTID_OF (wait_process));
+  gdb_assert(lkd_proc_get_by_ptid(inferior_ptid) == wait_process);
+
+  return 1;
+}
+
+/* Setup the symbols to reflect the namespace of the passed
+ process. GDB doesn't really support this. We hack this support by
+ appending the list of objfiles containing the debug information
+ for the process to the list of objfiles that contain the debug
+ info for the kernel. When we switch to another process, we remove
+ the objfiles for the old process and replace it with the objfiles
+ for the new one. The pointers to the objfiles for a given process
+ are stored in the associated process_t. */
+void
+lkd_proc_set_symfile (void)
+{
+  process_t *ps;
+
+
+  ps = lkd_proc_get_by_ptid (inferior_ptid);
+  if (ps && ps->main_objfile)
+        symfile_objfile = ps->main_objfile;
+}
+
+
+/* Selected the task that is really running on the CPU. */
+void
+running_task_command (char *args, int from_tty)
+{
+  ptid_t ptid;
+  char *thread_id;
+
+  if (!wait_process)
+    return;
+
+  ptid = PTID_OF (wait_process);
+  thread_id = xstrprintf ("%d", ptid_to_global_thread_id (ptid));
+
+  /* switch_to_thread() sets inferior_ptid to ptid */
+  gdb_thread_select (current_uiout, thread_id, NULL);
+
+  xfree (thread_id);
+}
diff --git a/gdb/lkd/lkd-process.h b/gdb/lkd/lkd-process.h
new file mode 100644
index 000000000000..15dbe9a5df6f
--- /dev/null
+++ b/gdb/lkd/lkd-process.h
@@ -0,0 +1,63 @@
+/*
+  Linux Awareness extension target (Linux Kernel Debugger)
+  Copyright 2011-2013 STMicroelectronics.
+*/
+
+#ifndef __LKD_PROCESS_H__
+#define __LKD_PROCESS_H__
+
+/* The list of tasks as cached in the debugger. */
+typedef struct process_t_
+{
+  struct process_t_ *next;
+  CORE_ADDR task_struct;
+  CORE_ADDR mm;
+  CORE_ADDR active_mm;
+  CORE_ADDR pgd;		/* FIXME: this should be arch specific, needs fix for SH4 */
+
+  ptid_t old_ptid;
+
+  int core;			/*this is the "dynamic" core info */
+
+  int tgid;
+  unsigned int prio;
+  char *comm;
+  int valid;
+
+  struct thread_info *gdb_thread;
+
+  /* user process info */
+  struct objfile *objfiles;
+  struct objfile *main_objfile;
+} process_t;
+
+#define VM_EXECUTABLE   0x00001000
+#define VM_EXEC         0x00000004
+
+#define PTID_OF(ps) ((ps)->gdb_thread->ptid)
+
+extern process_t *running_process[];
+extern process_t *selected_process;
+extern process_t *wait_process;
+extern uint32_t per_cpu_offset[];
+
+
+/* API */
+void lkd_proc_init (void);
+int lkd_proc_core_of_thread (ptid_t ptid);
+void lkd_proc_invalidate_list (void);
+void lkd_proc_free_list (void);
+int lkd_proc_refresh_info (int core);
+void lkd_proc_set_symfile (void);
+process_t *lkd_proc_get_list (void);
+process_t *lkd_proc_get_by_ptid (ptid_t ptid);
+process_t *lkd_proc_get_by_task_struct (CORE_ADDR task);
+process_t *lkd_proc_get_running (int core);
+CORE_ADDR lkd_proc_get_runqueues (int reset);
+CORE_ADDR lkd_proc_get_rq_curr (int core);
+int lkd_proc_is_curr_task (process_t * ps);
+
+/*commands*/
+void running_task_command (char *args, int from_tty);
+
+#endif /*__LKD_PROCESS_H__*/
diff --git a/gdb/lkd/lkd.h b/gdb/lkd/lkd.h
new file mode 100644
index 000000000000..91cc8632111e
--- /dev/null
+++ b/gdb/lkd/lkd.h
@@ -0,0 +1,486 @@
+/*
+	Linux Awareness extension target (Linux Kernel Debugger)
+
+	Copyright 2010-2013 STMicroelectronics.
+
+	The Linux Awareness layer allows GDB to debug a Linux kernel
+  through a H/W link (presumably a JTAG) as if it were a normal
+  executable. One major issue with debugging the kernel through a
+  JTAG link is the handling of virtual memory.
+
+  Virtual memory raises some issues while debugging through the JTAG
+  because the processor needs to have been correctly setup to be able
+  to access such memory. Usually, the TLB needs to be loaded with the
+  correct virtual memory translation so that the debugger may access
+  it. When some code running above (or inside) Linuux accesses virtual
+  memory, the processor raises an exception that will trigger
+  handlers in the kernel that in turn will setup everything needed
+  for the access to succeed. When the user wants to access such
+  memory from the debugger, the processor is basically 'stalled'. No
+  handlers will be called in case of exception and the access will
+  (sometimes silently) fail. This means the debugger has to setup
+  everything correctly *before* trying any virtual memory access.
+
+  Once the debugger knows how to handle virtual memory, it can try to
+  debug modules. In most Linux ports, kernel modules are loaded in
+  kernel virtual memory (as returned by vmalloc()). This layer tries
+  to expose kernel modules as shared libraries to the rest of
+  GDB. This is done by registering a 'struct target_so_ops' that
+  implements a shared library handling that know how to deal with
+  kernel modules. Indeed, kernel modules are different from shared
+  libraries in some fundamental ways. First, the kernel module binary
+  files are relocatable files, they haven't undergone a link
+  step. This means eg. that the files might contain multiple sections
+  at the same address. This isn't handled nicely by GDB. The solution
+  implemented is to mimic the little linker that does the relocation
+  job in the kernel and do a real link that generates a fully
+  relocated file. This file can then be handled like a stantdard
+  shared library. There's another major difference between modules
+  and shared libraries: part of the module code and data might be
+  unmapped after the module's init step is over. GDB isn't designed
+  to allow part of debug information to disappear, thus we have to
+  work around that. It's important to handle that case, because the
+  freed memory will be reused by subsequent module loads, leading to
+  a big mess of overlapping informations if the information from the
+  unloaded code isn't somehow handled. As said above, GDB can't
+  forget part of the debug information. The workaround use is to
+  'destroy' the debug information relating to the unloaded code by
+  pretending that every object that disappeared is located at
+  0xFFFFFFFF (there is a repeating ~(CORE_ADDR)0 pattern in the
+  file). The detection of module load, unloads and end of init events
+  is done by installing breakpoints at carefully chosen points.
+
+  The other major thing done in this file, is to expose all the
+  running tasks of the Linux kernel as threads of the debugged
+  application to GDB. To make abstraction more natural from an UI
+  point of view, the command 'info tasks' is introduced as an alias
+  for 'info threads'.
+
+  Most of the above is achieved by inserting the 'struct target_ops
+  linux_aware_ops' on the top of the target stack. The target stack
+  is the way GDB talks to the debugged target. It exposes an API
+  defined in 'struct target_ops'. Most of the functions have explicit
+  names, like 'fetch_register', 'resume', 'xfer_memory'. This is a
+  stack because it is constructed by piling up layers that provide
+  certain functionality. For example, when you first open an
+  executable file, a layer (or stratum in GDB speak) that knows how
+  to read the memory from the file is on the target stack. Then you
+  run the executable and a layer that knows how to access the runtime
+  memory and control the execution of the process is pushed on the
+  stack. Then it might be that this is a threaded application, and
+  the thread awareness is pushed as another layer on the target
+  stack. Each stratum has the ability to overload the functions
+  defined by the target_ops structure and to access the layers below
+  its level. The code in target.c constructs the current_target
+  structure each time the target stack is modified by a call to
+  (push|unpush)_target (). In this file we push 'linux_aware_ops' at
+  the very top of the target stack, and thus it's able to intercept
+  every communication between GDB and the debugged processor. For
+  example we trap virtual memory accesses this way and do the
+  required setup before passing the access to the lower layer of the
+  target stack that will really perform the access.
+
+  A last thing that is implemented in this file is a few generic data
+  display commands like 'dmesg', 'proc_iomem', 'proc_ioports', ...
+ */
+#ifndef __LINUX_AWARENESS_H__
+#define __LINUX_AWARENESS_H__
+
+#define LKD_VERSION_STRING "7.11-development"
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+
+/********** from breakpoint.c **********************/
+
+extern struct breakpoint *breakpoint_chain;
+extern struct bp_location **bp_location;
+extern int breakpoint_count;
+extern unsigned bp_location_count;
+
+#define ALL_BREAKPOINTS(B)  for (B = breakpoint_chain; B; B = B->next)
+
+#define ALL_BREAKPOINTS_SAFE(B,TMP)	\
+	for (B = breakpoint_chain;	\
+	     B ? (TMP=B->next, 1): 0;	\
+	     B = TMP)
+
+#define ALL_BP_LOCATIONS(B,BP_TMP)					\
+	for (BP_TMP = bp_location;					\
+	     BP_TMP < bp_location + bp_location_count && (B = *BP_TMP);	\
+	     BP_TMP++)
+
+/*************************************************/
+
+#define LKD_BYTE_ORDER BFD_ENDIAN_LITTLE
+
+/* target stack ordering */
+#define LKD_STRATUM_LINUX (thread_stratum + 10)
+
+
+typedef enum
+{
+  LKD_NOTLOADED = 0,
+  LKD_LOADED = 1,		/*must be one */
+  LKD_LOADING = 2,
+} lkd_load_states_t;
+
+/**
+ *  LKD user parameters.
+ */
+struct linux_awareness_params
+{
+
+  /* Global flag set by 'set linux-awareness enabled'. The user
+     shouldn't have to use that as the enablementlinux_awareness_check should be triggered
+     automatically by the kernel autodetection routines. */
+  int enabled;
+
+  /* Flag indicating that the kernel has been loaded. This is set by the
+     'load' command, but it might be necessary to set it by hand ('set
+     linux-awareness loaded 1'), eg. when attaching to a running target
+     with another command than the standard 'attach'. */
+  lkd_load_states_t loaded;
+
+  /* For debugging. One can disable the task handling
+     issuing 'set linux-awareness enable_task_awareness 0' */
+  int enable_task_awareness;
+
+  /* A user might disable the automatic load of the Linux awareness
+     layer by issuing 'set linux-awareness auto_activate 0' before
+     loading the kernel binary. (This might be usefull in a .(sh)gdbinit
+     file. */
+  int auto_activate;
+
+  /* The current global loglevel as set by 'set linux-awareness
+     debug-all' */
+  int loglevel;
+
+  /* skip the schedule() frame in the backtrace */
+  int skip_schedule_frame;
+
+  /* disable thread info coloring */
+  int no_colors;
+};
+
+extern struct linux_awareness_params lkd_params;
+
+/* use scratch area for messing around with strings
+ * to avoid static arrays and dispersed mallocs and frees
+ **/
+struct lkd_private_data
+{
+  lkd_load_states_t loaded;
+  int connected;
+  int keep_do_exit_event;
+
+  unsigned char *string_buf;
+  int string_buf_size;
+
+  char *banner_file;		/* string for the banner as read from vmlinx */
+  int banner_file_size;		/* max size allocated */
+  int banner_file_valid;	/* valid or to refresh */
+
+  int proc_list_invalid;
+
+  char *banner_mem;		/* string for the banner as read from vmlinx */
+  int banner_mem_size;		/* max size allocated */
+  int banner_mem_valid;		/* valid or to refresh */
+
+  /* The UTS name as extracted from the file or the memory. This serves
+     to build the path that points to the depmod cache. */
+  char *utsname_release;
+  int utsname_release_size;	/* max size allocated */
+  int utsname_release_valid;	/* valid or to refresh */
+
+  struct type *target_pointer_type;
+
+  uint32_t kflags;
+};
+
+extern struct lkd_private_data lkd_private;
+
+void lkd_loaded_set (char *arg, int from_tty, struct cmd_list_element *c);
+void lkd_enabled_set (char *args, int from_tty, struct cmd_list_element *c);
+void lkd_reset_thread_list (void);
+long lkd_eval_long (char *string);
+
+/* lkd-irqs.c*/
+void interrupts_command (char *args, int from_tty);
+
+/* Mimic kernel macros */
+#define container_of(ptr, struc, field)  ((ptr) - F_OFFSET(struc, field))
+
+extern int max_cores;
+#define MAX_CORES 5
+#define CORE_INVAL (-1)		/* 0 = name on the inferior, cannot be used */
+
+extern const struct objfile_data *linux_uprocess_objfile_data_key;
+
+extern int stopped_core;
+extern int lkd_stepping;
+
+struct process_t_;
+
+struct linux_awareness_ops
+{
+  const char *name;
+
+  /* Check if the current application is a compatible Linux kernel. */
+  int (*lo_check_kernel) ();
+
+  int (*lo_check_mem_rdy) ();	/*must implement. */
+
+  /* Called at the beginning of a debugging session. */
+  int (*lo_init) ();
+  /* Called at the end of a debugging session. Can be NULL. */
+  void (*lo_close) ();
+  /* Called before detaching from the targe. Can be NULL. */
+  int (*lo_pre_detach) (char *prog, int fromtty);
+  /* Called before the load of the kernel. Can be NULL. */
+  void (*lo_pre_load) (char *prog, int fromtty);
+  /* Called after the load of the kernel. Can be NULL. */
+  void (*lo_post_load) (char *prog, int fromtty);
+  /* Called before the processor is resumed. Can be NULL. */
+  void (*lo_pre_exec_start) ();
+
+
+  /* Returns wether the page containing addr in the context of task_struct
+     is mapped as writable. */
+  int (*lo_can_write) (CORE_ADDR addr, CORE_ADDR task_struct);
+  /* Returns wether the passed address is a userspace address. */
+  int (*lo_is_user_address) (CORE_ADDR addr);
+  /* Returns wether the passed address is a kernelspace address. */
+  int (*lo_is_kernel_address) (CORE_ADDR addr);
+  /* Returns wether the passed handler lies inside a TLB miss
+     handler. This is used to singlestep through code in virtual
+     memory: when this code produces an exception, the awareness
+     layer will hide from the user (by silently singlstepping
+     through) all the code where that callback returns true. */
+  int (*lo_is_tlb_miss_handler) (CORE_ADDR addr);
+  /* Flush the processor cache lines corresponding to the virtual
+     address virtaddr and physical addr physaddr (as returned by
+     lo_translate_memory_address() above).
+     Called with virtaddr == physaddr, the aim is to flush the
+     aliased line that might have been introduced by directly
+     accessing the physical address.
+
+     Precondition :
+     [virtaddr..virtaddr+len[ lies on the same physical page.
+   */
+  void (*lo_flush_cache) (CORE_ADDR virtaddr, CORE_ADDR physaddr,
+			  int len, int write);
+  /* If the target has to use software singlestepping, this callback
+     is called and returns the instruction that'll be executed after
+     the one at pc. Can be NULL. */
+    CORE_ADDR (*lo_single_step_destination) (CORE_ADDR pc);
+  /* This callback is called when the execution is resumed and we
+     might switch task. It's different from lo_pre_exec_start() that
+     will be called systematically. For example, cached virtual
+     memory translations can be discarded here. When this called
+     back isn't called, the debugger stays in the same task, thus
+     the cached translations should stay valid. */
+  void (*lo_clear_cache) ();
+
+  /* Should supply the current regcache with the value of register
+     regno in the context of task_struct. This will only be called
+     for tasks that are stopped in the scheduler. The way the task
+     state is stored on context switch is target specific. */
+  int (*lo_fetch_context_register) (int regno, CORE_ADDR task_struct);
+  /* Should store in the target the value of register regno from the
+     current regcache in the context of task_struct. This will only
+     be called for tasks that are stopped in the scheduler. The way
+     the task state is stored on context switch is target specific. */
+  int (*lo_store_context_register) (int regno, CORE_ADDR task_struct);
+
+  int kernel_offset;
+};
+
+extern struct target_ops linux_aware_ops;
+extern struct linux_awareness_ops *linux_awareness_ops;
+
+extern bfd *cur_bfd;
+
+struct type;
+struct cmd_list_element;
+
+extern struct cmd_list_element *set_linux_awareness_cmd_list;
+extern struct cmd_list_element *show_linux_awareness_cmd_list;
+
+struct addr_info
+{
+  char *name;
+  struct bound_minimal_symbol bmsym;
+  struct addr_info *next;
+};
+
+struct field_info
+{
+  char *struct_name;
+  char *field_name;
+  struct symbol *type;
+  int offset;
+  int size;
+  struct field_info *next;
+};
+
+#define FIELD_INFO(s_name, field) _FIELD_##s_name##__##field
+
+#define DECLARE_FIELD(s_name, field) \
+		static struct field_info FIELD_INFO(s_name, field) \
+		= { .struct_name = #s_name, .field_name = #field, 0 }
+
+#define F_OFFSET(struct, field) \
+		linux_get_field_offset (&FIELD_INFO(struct, field))
+#define F_SIZE(struct, field) \
+		linux_get_field_size (&FIELD_INFO(struct, field))
+#define HAS_FIELD(struct, field) \
+		(FIELD_INFO(struct, field).type != NULL \
+				|| (linux_init_field(&FIELD_INFO(struct, field), 1), \
+						FIELD_INFO(struct, field).type != NULL))
+
+#define ADDR_INFO(symb) _ADDR_##symb
+
+#define DECLARE_ADDR(symb) \
+		static struct addr_info ADDR_INFO(symb) = { .name = #symb, .bmsym = {NULL, NULL} }
+
+#define HAS_ADDR(symb) \
+		(ADDR_INFO(symb).bmsym.minsym != NULL \
+				|| (linux_init_addr(&ADDR_INFO(symb), 1), ADDR_INFO(symb).bmsym.minsym != NULL))
+
+#define ADDR(sym) linux_get_address (&ADDR_INFO(sym))
+
+#define read_unsigned_field(base, struct, field) \
+		read_memory_unsigned_integer (base + F_OFFSET (struct, field), \
+				F_SIZE (struct, field), LKD_BYTE_ORDER)
+
+#define read_signed_field(base, struct, field) \
+		read_memory_integer (base + F_OFFSET (struct, field), \
+				F_SIZE (struct, field), LKD_BYTE_ORDER)
+
+#define read_pointer_field(base, struct, field) \
+		read_memory_typed_address (base + F_OFFSET (struct, field), \
+				builtin_type (target_gdbarch ())->builtin_data_ptr)
+
+#define read_unsigned_embedded_field(base, struct, field, emb_str, emb_field) \
+		read_memory_unsigned_integer (base + F_OFFSET (struct, field) \
+				+ F_OFFSET (emb_str, emb_field), \
+				F_SIZE (emb_str, emb_field), LKD_BYTE_ORDER)
+
+#define read_signed_embedded_field(base, struct, field, emb_str, emb_field) \
+		read_memory_integer (base + F_OFFSET (struct, field) \
+				+ F_OFFSET (emb_str, emb_field), \
+				F_SIZE (emb_str, emb_field), LKD_BYTE_ORDER)
+
+#define read_pointer_embedded_field(base, struct, field, emb_str, emb_field) \
+		read_memory_typed_address (base + F_OFFSET (struct, field) \
+				+ F_OFFSET (emb_str, emb_field), \
+				builtin_type (target_gdbarch ())->builtin_data_ptr)
+
+#define extract_unsigned_field(base, struct, field) \
+		extract_unsigned_integer(base + F_OFFSET (struct, field), \
+				F_SIZE (struct, field), LKD_BYTE_ORDER)
+
+#define extract_signed_field(base, struct, field) \
+		extract_signed_integer (base + F_OFFSET (struct, field), \
+				F_SIZE (struct, field), LKD_BYTE_ORDER)
+
+#define extract_pointer_field(base, struct, field) \
+		extract_typed_address (base + F_OFFSET (struct, field), \
+				builtin_type(target_gdbarch ())->builtin_data_ptr)
+
+/*cleanup macro to compare an address to a bp loc value*/
+#define IS_LOC(pc,evnt)  ((evnt != NULL) && (pc == evnt->loc->address))
+
+enum page_status
+{
+  PAGE_PRESENT,
+  PAGE_SWAPPED,
+  PAGE_NOTMAPPED,
+  PAGE_NOPAGE,
+  PAGE_UNKNOWN
+};
+
+/*kversion building macros */
+#define KERNEL_VERSION(MM,mm,bb) (((MM) << 16) + ((mm) << 8) + (bb))
+
+/* last known (validated) STLinux kernel version for this LKD.
+ * if we're beyond this version, of not on STLinux, issue a warning
+ **/
+#define KFLAG_NOLINUX	0x00000000	/* not linux */
+#define KFLAG_LINUX 	0x00000001	/* is linux */
+#define KFLAG_STLINUX	0x00000002	/* STMicroelectronics linux distro */
+#define KFLAG_DBGINFO	0x00000004	/* has debug information */
+
+/* kernel release string */
+extern char g_utsname_release[];
+
+struct debug_domain
+{
+  const char *name;
+  int level;
+};
+
+extern struct debug_domain linux_aware_debug_domains_info[];
+
+enum linux_aware_debug_domain
+{
+  TASK,
+  TARGET,
+  D_INIT,
+  KEEP_LAST
+};
+
+#define DEBUG(domain, l, ...) \
+		({if (domain < KEEP_LAST \
+				&& linux_aware_debug_domains_info[domain].level >= l) \
+				fprintf_filtered(gdb_stdlog, "linux: " __VA_ARGS__);})
+
+/*do thing a different way in debug mode.*/
+#define DBG_IF(domain)          if (linux_aware_debug_domains_info[domain].level) {
+#define DBG_ELSE                } else {
+#define DBG_ENDIF(domain)       }
+
+#define LA_NOT_LOADED_STRING "Please type \"set linux-awareness loaded\".\n"
+
+int linux_init_addr (struct addr_info *field, int check);
+int linux_init_field (struct field_info *field, int check);
+
+static inline CORE_ADDR
+linux_get_address (struct addr_info *addr)
+{
+  if (addr->bmsym.minsym == NULL)
+    linux_init_addr (addr, 0);
+
+  return BMSYMBOL_VALUE_ADDRESS (addr->bmsym);
+}
+
+static inline unsigned int
+linux_get_field_offset (struct field_info *field)
+{
+  if (field->type == NULL)
+    linux_init_field (field, 0);
+
+  return field->offset;
+}
+
+static inline unsigned int
+linux_get_field_size (struct field_info *field)
+{
+  if (field->type == NULL)
+    linux_init_field (field, 0);
+
+  return field->size;
+}
+
+int lkd_try_push_target (void);
+void lkd_uninstall_do_exit_event (void);
+
+void sanitize_path (char *path);
+char *linux_aware_get_target_root_prefix (void);
+
+int linux_aware_target_core (void);
+
+#endif /*__LINUX_AWARENESS_H__*/
