Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* symbolic debug of loadable modules with kgdb light
@ 2009-01-09 15:51 Caz Yokoyama
  2009-04-24 15:33 ` Tom Tromey
  0 siblings, 1 reply; 55+ messages in thread
From: Caz Yokoyama @ 2009-01-09 15:51 UTC (permalink / raw)
  To: 'Joel Brobecker'; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1113 bytes --]

Hello,
I have attached the patch against gdb-6.8.
- This patch is based on http://kgdb.cvs.sourceforge.net/viewvc/kgdb/gdb/. I
removed garbage as mush as possible. But it still has the code which I don't
know what it is. I don't remove copyright notice which is there.
- I haven't run testsuite because I could not find how to do that while I
run make in testsuite directory.
- I believe that the code follows coding standard. Let me know if not.
- The patch is produced by "svn diff". I believe patch format is the one you
want. Let me know if not.
-caz
P.S. I accidentally send the patch to gdb while I recalled. 

-----Original Message-----
From: Joel Brobecker [mailto:brobecker@adacore.com] 
Sent: Thursday, January 08, 2009 8:18 PM
To: Caz Yokoyama
Cc: gdb@sourceware.org
Subject: Re: symbolic debug of loadable modules with kgdb light

> Is there anyway to integrate my modifications to gdb?

We indeed welcome contributes. Hopefully most of your questions
will be answered by a file called CONTRIBUTE in the gdb/ subdirectory.
Could you have a look and let us know if some things are not clear?

-- 
Joel

[-- Attachment #2: gdb-6.8-KgdbLight.patch --]
[-- Type: application/octet-stream, Size: 49662 bytes --]

Index: gdb/remote.c
===================================================================
--- gdb/remote.c	(revision 4)
+++ gdb/remote.c	(working copy)
@@ -3,6 +3,7 @@
    Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
    1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
+   Copyright (C) 2009 Caz Yokoyama, caz at caztech dot com.
 
    This file is part of GDB.
 
@@ -2595,6 +2596,7 @@
 remote_open_1 (char *name, int from_tty, struct target_ops *target,
 	       int extended_p, int async_p)
 {
+  extern int debugvmlinux;
   struct remote_state *rs = get_remote_state ();
   if (name == 0)
     error (_("To open a remote debug connection, you need to specify what\n"
@@ -2685,6 +2687,11 @@
   use_threadinfo_query = 1;
   use_threadextra_query = 1;
 
+  if (debugvmlinux) {
+    serial_send_break(remote_desc);
+    serial_write(remote_desc, "g", 1);
+  }
+
   /* The first packet we send to the target is the optional "supported
      packets" request.  If the target can answer this, it will tell us
      which later probes to skip.  */
@@ -3261,14 +3268,21 @@
 static void
 remote_stop (void)
 {
+  extern int debugkernel;
+
   /* Send a break or a ^C, depending on user preference.  */
   if (remote_debug)
     fprintf_unfiltered (gdb_stdlog, "remote_stop called\n");
 
-  if (remote_break)
+  if (debugkernel) {
     serial_send_break (remote_desc);
-  else
-    serial_write (remote_desc, "\003", 1);
+    serial_write (remote_desc, "g", 1);
+  } else {
+    if (remote_break)
+      serial_send_break (remote_desc);
+    else
+      serial_write (remote_desc, "\003", 1);
+  }
 }
 
 /* Ask the user what to do when an interrupt is received.  */
Index: gdb/dwarf2read.c
===================================================================
--- gdb/dwarf2read.c	(revision 4)
+++ gdb/dwarf2read.c	(working copy)
@@ -2,6 +2,7 @@
 
    Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
                  2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2009 Caz Yokoyama, caz at caztech dot com.
 
    Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
    Inc.  with support from Florida State University (under contract
@@ -1701,6 +1702,7 @@
   struct objfile *objfile = cu->objfile;
   bfd *abfd = objfile->obfd;
   struct partial_die_info *pdi;
+  extern int debugvmlinux;
 
   /* Now, march along the PDI's, descending into ones which have
      interesting children but skipping the children of the other ones,
@@ -1775,6 +1777,13 @@
       /* If the die has a sibling, skip to the sibling.  */
 
       pdi = pdi->die_sibling;
+
+      if (debugvmlinux) {
+	if (pdi != NULL && pdi->highpc >= 0xffffffffff000000) {
+	  if (pdi->die_sibling != NULL)
+	    pdi = pdi->die_sibling;
+	}
+      }
     }
 }
 
Index: gdb/ChangeLog-2009
===================================================================
--- gdb/ChangeLog-2009	(revision 0)
+++ gdb/ChangeLog-2009	(revision 12)
@@ -0,0 +1,7 @@
+2009-01-09  Caz Yokoyama  <caz@caztech.com>
+
+	* remote.c send Magic SysRq, i.e. BREAK g when for kgdb light.
+	* dwarf2read.c work around for doubtfull high address in 2.6.27.8 kernel
+	* main.c set whether debugging kernel
+	* amd64-linux-tdep.c add x86_64 linux kernel OS abi
+	* solib-svr4.c read symbol tables of loadable modules.
Index: gdb/main.c
===================================================================
--- gdb/main.c	(revision 4)
+++ gdb/main.c	(working copy)
@@ -3,6 +3,7 @@
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
    1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
    Free Software Foundation, Inc.
+   Copyright (C) 2009 Caz Yokoyama, caz at caztech dot com.
 
    This file is part of GDB.
 
@@ -62,6 +63,10 @@
 /* System root path, used to find libraries etc.  */
 char *gdb_sysroot = 0;
 
+/* Whether debugging a kernel */
+int debugkernel = 0;
+int debugvmlinux = 0;  /* debugging vmlinx? */
+
 struct ui_file *gdb_stdout;
 struct ui_file *gdb_stderr;
 struct ui_file *gdb_stdlog;
@@ -131,6 +136,7 @@
   char *pid_or_core_arg = NULL;
   char *cdarg = NULL;
   char *ttyarg = NULL;
+  char *filename, *dir;
 
   /* These are static so that we can take their address in an initializer.  */
   static int print_help;
@@ -679,6 +685,17 @@
   quit_pre_print = error_pre_print;
   warning_pre_print = _("\nwarning: ");
 
+  if (symarg != NULL) {
+    for (filename = symarg;
+	 (dir = strchr(filename, '/')) != NULL;
+	 filename = dir + 1) ;
+    /* only require the given characters to match, so that longer filenames
+       will still match */
+    if (strncmp(filename, LINUX_KERNEL_NAME_STEM,
+		strlen(LINUX_KERNEL_NAME_STEM)) == 0)
+      debugvmlinux = 1;
+  }
+
   /* Read and execute $HOME/.gdbinit file, if it exists.  This is done
      *before* all the command line arguments are processed; it sets
      global parameters, which are independent of what file you are
Index: gdb/solib-svr4.c
===================================================================
--- gdb/solib-svr4.c	(revision 4)
+++ gdb/solib-svr4.c	(working copy)
@@ -2,6 +2,7 @@
 
    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
    2001, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2009 Caz Yokoyama, caz at caztech dot com.
 
    This file is part of GDB.
 
@@ -45,6 +46,7 @@
 
 static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
 static int svr4_have_link_map_offsets (void);
+static struct so_list *kernel_current_sos (void);
 
 /* Link map info to include in an allocated so_list entry */
 
@@ -90,6 +92,7 @@
 #ifdef SOLIB_BKPT_NAME
   SOLIB_BKPT_NAME,		/* Prefer configured name if it exists. */
 #endif
+  "module_event",
   "_start",
   "__start",
   "main",
@@ -103,6 +106,113 @@
   NULL
 };
 
+/* Macro to extract an address from a solib structure.  When GDB is
+   configured for some 32-bit targets (e.g. Solaris 2.7 sparc), BFD is
+   configured to handle 64-bit targets, so CORE_ADDR is 64 bits.  We
+   have to extract only the significant bits of addresses to get the
+   right address when accessing the core file BFD.
+
+   Assume that the address is unsigned.  */
+
+#define SOLIB_EXTRACT_ADDRESS(MEMBER) \
+	extract_unsigned_integer (&(MEMBER), sizeof (MEMBER))
+
+
+/* Kernel debugging structures */
+extern int debugkernel;
+
+struct list_head {
+  CORE_ADDR next;
+  CORE_ADDR prev;
+};
+
+#define MODULE_NAME_LEN (64 - sizeof(CORE_ADDR))
+
+#define MAX_SECTNAME 31
+
+struct mod_section {
+  CORE_ADDR address;
+  char name[MAX_SECTNAME + 1];
+};
+
+/* taken from kernel source code */
+typedef unsigned int __kernel_mode_t;
+typedef __kernel_mode_t mode_t;
+
+struct module;
+
+struct attribute {
+  const char *name;
+  struct module *owner;
+  mode_t mode;
+};
+
+struct attribute_group {
+  const char *name;
+  struct attribute **attrs;
+};
+
+struct module_attribute {
+  struct attribute attr;
+  ssize_t (*show)(struct module_attribute *, struct module *, char *);
+  ssize_t (*store)(struct module_attribute *, struct module *,
+		   const char *, size_t count);
+  void (*setup)(struct module *, const char *);
+  int (*test)(struct module *);
+  void (*free)(struct module *);
+};
+
+#define MODULE_SECT_NAME_LEN 32
+struct module_sect_attr
+{
+  struct module_attribute mattr;
+  char name[MODULE_SECT_NAME_LEN];
+  unsigned long address;
+};
+
+struct module_sect_attrs
+{
+  struct attribute_group grp;
+  struct module_sect_attr attrs[0];
+};
+#define NUM_SECTIONS 1  // number of sections
+
+struct attribute_group_2_6_27 {
+	const char		*name;
+	mode_t			(*is_visible)();
+	struct attribute	**attrs;
+};
+
+struct module_sect_attr_2_6_27
+{
+	struct module_attribute mattr;
+	char *name;
+	unsigned long address;
+};
+
+struct module_sect_attrs_2_6_27
+{
+	struct attribute_group_2_6_27 grp;
+	unsigned int nsections;
+	struct module_sect_attr_2_6_27 attrs[0];
+};
+
+struct module
+{
+  CORE_ADDR unused_state;
+  struct list_head list;
+  char name[MODULE_NAME_LEN];
+};
+
+struct kern_lm_info {
+  unsigned int nsections;
+  struct module_sect_attr module_sect_attr[0];
+};
+
+#define OFFSET(structure, field) ((CORE_ADDR)(&((struct structure *)0)->field))
+
+/* local data declarations */
+
 /* link map access functions */
 
 static CORE_ADDR
@@ -714,10 +824,18 @@
   struct so_list **link_ptr = &head;
   CORE_ADDR ldsomap = 0;
 
+  if (debugkernel)
+    {
+      return kernel_current_sos();
+    }
+
   /* Always locate the debug struct, in case it has moved.  */
   debug_base = 0;
   locate_base ();
 
+  /* Make sure we've looked up the inferior's dynamic linker's base
+     structure.  */
+
   /* If we can't find the dynamic linker's base structure, this
      must not be a dynamically linked executable.  Hmm.  */
   if (! debug_base)
@@ -1411,6 +1529,11 @@
   if (!enable_break ())
     return;
 
+  if (debugkernel)
+    {
+      solib_add (NULL, 0, NULL, 1);
+    }
+
 #if defined(_SCO_DS)
   /* SCO needs the loop below, other systems should be using the
      special shared library breakpoints and the shared library breakpoint
@@ -1481,10 +1604,32 @@
 svr4_relocate_section_addresses (struct so_list *so,
                                  struct section_table *sec)
 {
-  sec->addr    = svr4_truncate_ptr (sec->addr    + LM_ADDR_CHECK (so,
-								  sec->bfd));
-  sec->endaddr = svr4_truncate_ptr (sec->endaddr + LM_ADDR_CHECK (so,
-								  sec->bfd));
+  if (debugkernel)
+    {
+      int i;
+      struct kern_lm_info *kern_lm_info =
+	(struct kern_lm_info *)so->lm_info->lm;
+      for (i = 0; i < kern_lm_info->nsections; i++)
+	{
+	  if (!strcmp(kern_lm_info->module_sect_attr[i].name,
+	    sec->the_bfd_section->name))
+	    {
+	      CORE_ADDR sect_addr = extract_typed_address(
+		(gdb_byte *)&kern_lm_info->module_sect_attr[i].address,
+	        builtin_type_void_data_ptr);
+	      sec->addr = sec->addr + sect_addr;
+	      sec->endaddr = sec->endaddr + sect_addr;
+	      break;
+            }
+	}
+    }
+  else
+    {
+      sec->addr    = svr4_truncate_ptr (sec->addr    + LM_ADDR_CHECK (so,
+								      sec->bfd));
+      sec->endaddr = svr4_truncate_ptr (sec->endaddr + LM_ADDR_CHECK (so,
+								      sec->bfd));
+    }
 }
 \f
 
@@ -1670,4 +1815,152 @@
   svr4_so_ops.in_dynsym_resolve_code = svr4_in_dynsym_resolve_code;
   svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
   svr4_so_ops.same = svr4_same;
+
+  /* FIXME: Don't do this here.  *_gdbarch_init() should set so_ops. */
+  current_target_so_ops = &svr4_so_ops;
 }
+
+/* Scans the list of modules in a kernel and finds out section addresses for
+ * those symbols */
+static struct so_list *kernel_current_sos(void)
+{
+  enum kversion {v2_6_18, v2_6_27};
+  short n;
+  struct expression *expr;
+  struct value *val;
+  unsigned int offset_sect_attrs;
+  enum kversion kv;
+  struct symbol *modules;
+  CORE_ADDR modlistaddr;
+  CORE_ADDR modnameaddr;
+  struct so_list *head = 0;
+  struct so_list **link_ptr = &head;
+
+  expr = parse_expression("&((struct module *)0)->sect_attrs");
+  val = evaluate_expression(expr);
+  offset_sect_attrs = val->aligner.force_longest_align;
+  expr = parse_expression("&((struct module_sect_attrs *)0)->attrs[1]");
+  val = evaluate_expression(expr);
+  if (val->aligner.force_longest_align == (int)&((struct module_sect_attrs *)0)->attrs[1]) {
+    kv = v2_6_18;
+  } else if (val->aligner.force_longest_align ==
+	     (int)&((struct module_sect_attrs_2_6_27 *)0)->attrs[1]) {
+    kv = v2_6_27;
+  } else {
+    warning("struct module_sect_attrs is not the one of v2_6_18 nor v2_6_27");
+    goto nolist;
+  }
+
+  modules = lookup_symbol("modules", NULL, VAR_DOMAIN, NULL, NULL);
+  if (modules == NULL)
+	goto nolist;
+
+  /* Pointer to first module */
+  modlistaddr = read_memory_typed_address(SYMBOL_VALUE_ADDRESS(modules),
+			builtin_type_void_data_ptr);
+  while (modlistaddr != SYMBOL_VALUE_ADDRESS(modules)) {
+	struct so_list *new = (struct so_list *) xmalloc (sizeof (struct so_list));
+	struct cleanup *old_chain = make_cleanup (xfree, new);
+	char *buffer;
+	int errcode;
+	CORE_ADDR mod_struct_addr;
+	CORE_ADDR mod_addr_sections;
+	struct kern_lm_info *kern_lm_info;
+	unsigned int nsections;
+	struct module_sect_attr_2_6_27 *attr_2_6_27;
+
+	memset (new, 0, sizeof (*new));
+
+	mod_struct_addr = modlistaddr - OFFSET(module, list);
+
+	/* Read module name */
+	target_read_string(mod_struct_addr + OFFSET(module, name), &buffer,
+					   MODULE_NAME_LEN, &errcode);
+	if (errcode || !strlen(buffer))
+	  {
+		warning("Couldn't read module name");
+		do_cleanups (old_chain);
+		goto next_mod;
+	  }
+	strncpy (new->so_name, buffer, SO_NAME_MAX_PATH_SIZE - 1);
+	new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+	strcpy (new->so_original_name, new->so_name);
+	new->next = 0;
+
+	new->lm_info = xmalloc(sizeof (struct lm_info));
+	make_cleanup(xfree, new->lm_info);
+
+	mod_addr_sections = read_memory_typed_address(mod_struct_addr + offset_sect_attrs,
+						      builtin_type_void_data_ptr);
+	switch (kv) {
+	case v2_6_18:
+	  new->lm_info->lm = xmalloc(sizeof(struct kern_lm_info) +
+				     sizeof(struct module_sect_attr) *
+				     NUM_SECTIONS);
+	  make_cleanup(xfree, new->lm_info->lm);
+	  kern_lm_info = (struct kern_lm_info *)new->lm_info->lm;
+	  kern_lm_info->nsections = NUM_SECTIONS;
+	  if (target_read_memory(mod_addr_sections + OFFSET(module_sect_attrs, attrs),
+				 (char *)kern_lm_info->module_sect_attr,
+				 sizeof(struct module_sect_attr) * NUM_SECTIONS) != 0) {
+	    warning("can't read module_sects in module %s", new->so_name);
+	    do_cleanups(old_chain);
+	    goto next_mod;
+	  }
+	  if (strcmp(kern_lm_info->module_sect_attr[0].name, ".text") != 0) {
+	    warning("The first section is not .text: %s", kern_lm_info->module_sect_attr[0].name);
+	    do_cleanups(old_chain);
+	    goto next_mod;
+	  }
+	  break;
+	case v2_6_27:
+	  nsections = read_memory_unsigned_integer(mod_addr_sections +
+						   OFFSET(module_sect_attrs_2_6_27, nsections),
+						   sizeof(nsections));
+	  new->lm_info->lm = xmalloc(sizeof(struct kern_lm_info) +
+				     sizeof(struct module_sect_attr) *
+				     nsections);
+	  make_cleanup(xfree, new->lm_info->lm);
+	  kern_lm_info = (struct kern_lm_info *)new->lm_info->lm;
+	  attr_2_6_27 = (struct module_sect_attr_2_6_27 *)malloc(
+								 sizeof(*attr_2_6_27) *
+								 nsections);
+	  memset(attr_2_6_27, 0, sizeof(*attr_2_6_27) * nsections);
+	  if (target_read_memory(mod_addr_sections + OFFSET(module_sect_attrs_2_6_27, attrs),
+				 (char *)attr_2_6_27,
+				 sizeof(*attr_2_6_27) * nsections) != 0) {
+	    warning("can't read attr_attr_2_6_27 in module %s for v2_6_27", new->so_name);
+	    do_cleanups(old_chain);
+	    goto next_mod;
+	  }
+	  for (n = 0; n < nsections; n++) {
+	    if (target_read_memory((CORE_ADDR)attr_2_6_27[n].name,
+				   kern_lm_info->module_sect_attr[n].name,
+				   MODULE_SECT_NAME_LEN) != 0) {
+	      warning("can't read attr_attr_2_6_27 in module %s for v2_6_27", new->so_name);
+	      do_cleanups(old_chain);
+	      goto next_mod;
+	    }
+	    kern_lm_info->module_sect_attr[n].name[MODULE_SECT_NAME_LEN - 1] = '\0';
+	    kern_lm_info->module_sect_attr[n].address = attr_2_6_27[n].address;
+	  }
+	  kern_lm_info->nsections = nsections;
+	  free(attr_2_6_27);
+	  break;
+	}
+	*link_ptr = new;
+	link_ptr = &new->next;
+	if (strlen(new->so_name) <= SO_NAME_MAX_PATH_SIZE - 2) {
+	  strcat(new->so_name, ".ko");
+	}
+	xfree(buffer);
+	discard_cleanups(old_chain);
+
+  next_mod:
+	modlistaddr = read_memory_typed_address(modlistaddr, builtin_type_void_data_ptr);
+  }
+  return head;
+
+ nolist:
+  return NULL;
+}
Index: gdb/ada-lang.c
===================================================================
--- gdb/ada-lang.c	(revision 4)
+++ gdb/ada-lang.c	(working copy)
@@ -3834,7 +3834,7 @@
       /* The following is taken from the structure-return code in
 	 call_function_by_hand. FIXME: Therefore, some refactoring seems 
 	 indicated. */
-      if (gdbarch_inner_than (current_gdbarch, 1, 2))
+      if (gdbarch_inner_than(current_gdbarch, 1, 2, 0, 0))
 	{
 	  /* Stack grows downward.  Align SP and VALUE_ADDRESS (val) after
 	     reserving sufficient space. */
Index: gdb/value.c
===================================================================
--- gdb/value.c	(revision 4)
+++ gdb/value.c	(working copy)
@@ -40,142 +40,6 @@
 
 void _initialize_values (void);
 
-struct value
-{
-  /* Type of value; either not an lval, or one of the various
-     different possible kinds of lval.  */
-  enum lval_type lval;
-
-  /* Is it modifiable?  Only relevant if lval != not_lval.  */
-  int modifiable;
-
-  /* Location of value (if lval).  */
-  union
-  {
-    /* If lval == lval_memory, this is the address in the inferior.
-       If lval == lval_register, this is the byte offset into the
-       registers structure.  */
-    CORE_ADDR address;
-
-    /* Pointer to internal variable.  */
-    struct internalvar *internalvar;
-  } location;
-
-  /* Describes offset of a value within lval of a structure in bytes.
-     If lval == lval_memory, this is an offset to the address.  If
-     lval == lval_register, this is a further offset from
-     location.address within the registers structure.  Note also the
-     member embedded_offset below.  */
-  int offset;
-
-  /* Only used for bitfields; number of bits contained in them.  */
-  int bitsize;
-
-  /* Only used for bitfields; position of start of field.  For
-     gdbarch_bits_big_endian=0 targets, it is the position of the LSB.  For
-     gdbarch_bits_big_endian=1 targets, it is the position of the MSB. */
-  int bitpos;
-
-  /* Frame register value is relative to.  This will be described in
-     the lval enum above as "lval_register".  */
-  struct frame_id frame_id;
-
-  /* Type of the value.  */
-  struct type *type;
-
-  /* If a value represents a C++ object, then the `type' field gives
-     the object's compile-time type.  If the object actually belongs
-     to some class derived from `type', perhaps with other base
-     classes and additional members, then `type' is just a subobject
-     of the real thing, and the full object is probably larger than
-     `type' would suggest.
-
-     If `type' is a dynamic class (i.e. one with a vtable), then GDB
-     can actually determine the object's run-time type by looking at
-     the run-time type information in the vtable.  When this
-     information is available, we may elect to read in the entire
-     object, for several reasons:
-
-     - When printing the value, the user would probably rather see the
-     full object, not just the limited portion apparent from the
-     compile-time type.
-
-     - If `type' has virtual base classes, then even printing `type'
-     alone may require reaching outside the `type' portion of the
-     object to wherever the virtual base class has been stored.
-
-     When we store the entire object, `enclosing_type' is the run-time
-     type -- the complete object -- and `embedded_offset' is the
-     offset of `type' within that larger type, in bytes.  The
-     value_contents() macro takes `embedded_offset' into account, so
-     most GDB code continues to see the `type' portion of the value,
-     just as the inferior would.
-
-     If `type' is a pointer to an object, then `enclosing_type' is a
-     pointer to the object's run-time type, and `pointed_to_offset' is
-     the offset in bytes from the full object to the pointed-to object
-     -- that is, the value `embedded_offset' would have if we followed
-     the pointer and fetched the complete object.  (I don't really see
-     the point.  Why not just determine the run-time type when you
-     indirect, and avoid the special case?  The contents don't matter
-     until you indirect anyway.)
-
-     If we're not doing anything fancy, `enclosing_type' is equal to
-     `type', and `embedded_offset' is zero, so everything works
-     normally.  */
-  struct type *enclosing_type;
-  int embedded_offset;
-  int pointed_to_offset;
-
-  /* Values are stored in a chain, so that they can be deleted easily
-     over calls to the inferior.  Values assigned to internal
-     variables or put into the value history are taken off this
-     list.  */
-  struct value *next;
-
-  /* Register number if the value is from a register.  */
-  short regnum;
-
-  /* If zero, contents of this value are in the contents field.  If
-     nonzero, contents are in inferior memory at address in the
-     location.address field plus the offset field (and the lval field
-     should be lval_memory).
-
-     WARNING: This field is used by the code which handles watchpoints
-     (see breakpoint.c) to decide whether a particular value can be
-     watched by hardware watchpoints.  If the lazy flag is set for
-     some member of a value chain, it is assumed that this member of
-     the chain doesn't need to be watched as part of watching the
-     value itself.  This is how GDB avoids watching the entire struct
-     or array when the user wants to watch a single struct member or
-     array element.  If you ever change the way lazy flag is set and
-     reset, be sure to consider this use as well!  */
-  char lazy;
-
-  /* If nonzero, this is the value of a variable which does not
-     actually exist in the program.  */
-  char optimized_out;
-
-  /* If value is a variable, is it initialized or not.  */
-  int initialized;
-
-  /* Actual contents of the value.  For use of this value; setting it
-     uses the stuff above.  Not valid if lazy is nonzero.  Target
-     byte-order.  We force it to be aligned properly for any possible
-     value.  Note that a value therefore extends beyond what is
-     declared here.  */
-  union
-  {
-    gdb_byte contents[1];
-    DOUBLEST force_doublest_align;
-    LONGEST force_longest_align;
-    CORE_ADDR force_core_addr_align;
-    void *force_pointer_align;
-  } aligner;
-  /* Do not add any new members here -- contents above will trash
-     them.  */
-};
-
 /* Prototypes for local functions. */
 
 static void show_values (char *, int);
Index: gdb/value.h
===================================================================
--- gdb/value.h	(revision 4)
+++ gdb/value.h	(working copy)
@@ -554,4 +554,140 @@
 
 extern struct value *value_of_local (const char *name, int complain);
 
+struct value
+{
+  /* Type of value; either not an lval, or one of the various
+     different possible kinds of lval.  */
+  enum lval_type lval;
+
+  /* Is it modifiable?  Only relevant if lval != not_lval.  */
+  int modifiable;
+
+  /* Location of value (if lval).  */
+  union
+  {
+    /* If lval == lval_memory, this is the address in the inferior.
+       If lval == lval_register, this is the byte offset into the
+       registers structure.  */
+    CORE_ADDR address;
+
+    /* Pointer to internal variable.  */
+    struct internalvar *internalvar;
+  } location;
+
+  /* Describes offset of a value within lval of a structure in bytes.
+     If lval == lval_memory, this is an offset to the address.  If
+     lval == lval_register, this is a further offset from
+     location.address within the registers structure.  Note also the
+     member embedded_offset below.  */
+  int offset;
+
+  /* Only used for bitfields; number of bits contained in them.  */
+  int bitsize;
+
+  /* Only used for bitfields; position of start of field.  For
+     gdbarch_bits_big_endian=0 targets, it is the position of the LSB.  For
+     gdbarch_bits_big_endian=1 targets, it is the position of the MSB. */
+  int bitpos;
+
+  /* Frame register value is relative to.  This will be described in
+     the lval enum above as "lval_register".  */
+  struct frame_id frame_id;
+
+  /* Type of the value.  */
+  struct type *type;
+
+  /* If a value represents a C++ object, then the `type' field gives
+     the object's compile-time type.  If the object actually belongs
+     to some class derived from `type', perhaps with other base
+     classes and additional members, then `type' is just a subobject
+     of the real thing, and the full object is probably larger than
+     `type' would suggest.
+
+     If `type' is a dynamic class (i.e. one with a vtable), then GDB
+     can actually determine the object's run-time type by looking at
+     the run-time type information in the vtable.  When this
+     information is available, we may elect to read in the entire
+     object, for several reasons:
+
+     - When printing the value, the user would probably rather see the
+     full object, not just the limited portion apparent from the
+     compile-time type.
+
+     - If `type' has virtual base classes, then even printing `type'
+     alone may require reaching outside the `type' portion of the
+     object to wherever the virtual base class has been stored.
+
+     When we store the entire object, `enclosing_type' is the run-time
+     type -- the complete object -- and `embedded_offset' is the
+     offset of `type' within that larger type, in bytes.  The
+     value_contents() macro takes `embedded_offset' into account, so
+     most GDB code continues to see the `type' portion of the value,
+     just as the inferior would.
+
+     If `type' is a pointer to an object, then `enclosing_type' is a
+     pointer to the object's run-time type, and `pointed_to_offset' is
+     the offset in bytes from the full object to the pointed-to object
+     -- that is, the value `embedded_offset' would have if we followed
+     the pointer and fetched the complete object.  (I don't really see
+     the point.  Why not just determine the run-time type when you
+     indirect, and avoid the special case?  The contents don't matter
+     until you indirect anyway.)
+
+     If we're not doing anything fancy, `enclosing_type' is equal to
+     `type', and `embedded_offset' is zero, so everything works
+     normally.  */
+  struct type *enclosing_type;
+  int embedded_offset;
+  int pointed_to_offset;
+
+  /* Values are stored in a chain, so that they can be deleted easily
+     over calls to the inferior.  Values assigned to internal
+     variables or put into the value history are taken off this
+     list.  */
+  struct value *next;
+
+  /* Register number if the value is from a register.  */
+  short regnum;
+
+  /* If zero, contents of this value are in the contents field.  If
+     nonzero, contents are in inferior memory at address in the
+     location.address field plus the offset field (and the lval field
+     should be lval_memory).
+
+     WARNING: This field is used by the code which handles watchpoints
+     (see breakpoint.c) to decide whether a particular value can be
+     watched by hardware watchpoints.  If the lazy flag is set for
+     some member of a value chain, it is assumed that this member of
+     the chain doesn't need to be watched as part of watching the
+     value itself.  This is how GDB avoids watching the entire struct
+     or array when the user wants to watch a single struct member or
+     array element.  If you ever change the way lazy flag is set and
+     reset, be sure to consider this use as well!  */
+  char lazy;
+
+  /* If nonzero, this is the value of a variable which does not
+     actually exist in the program.  */
+  char optimized_out;
+
+  /* If value is a variable, is it initialized or not.  */
+  int initialized;
+
+  /* Actual contents of the value.  For use of this value; setting it
+     uses the stuff above.  Not valid if lazy is nonzero.  Target
+     byte-order.  We force it to be aligned properly for any possible
+     value.  Note that a value therefore extends beyond what is
+     declared here.  */
+  union
+  {
+    gdb_byte contents[1];
+    DOUBLEST force_doublest_align;
+    LONGEST force_longest_align;
+    CORE_ADDR force_core_addr_align;
+    void *force_pointer_align;
+  } aligner;
+  /* Do not add any new members here -- contents above will trash
+     them.  */
+};
+
 #endif /* !defined (VALUE_H) */
Index: gdb/infcall.c
===================================================================
--- gdb/infcall.c	(revision 4)
+++ gdb/infcall.c	(working copy)
@@ -283,7 +283,7 @@
   sp = gdbarch_frame_align (gdbarch, sp);
   /* Allocate space for, and then position the breakpoint on the
      stack.  */
-  if (gdbarch_inner_than (gdbarch, 1, 2))
+  if (gdbarch_inner_than (gdbarch, 1, 2, 0, 0))
     {
       CORE_ADDR bppc = sp;
       gdbarch_breakpoint_from_pc (gdbarch, &bppc, &bplen);
@@ -407,7 +407,7 @@
 	   address.  AMD64 called that region the "red zone".  Skip at
 	   least the "red zone" size before allocating any space on
 	   the stack.  */
-	if (gdbarch_inner_than (gdbarch, 1, 2))
+	if (gdbarch_inner_than (gdbarch, 1, 2, 0, 0))
 	  sp -= gdbarch_frame_red_zone_size (gdbarch);
 	else
 	  sp += gdbarch_frame_red_zone_size (gdbarch);
@@ -435,16 +435,16 @@
 	   to pay :-).  */
 	if (sp == old_sp)
 	  {
-	    if (gdbarch_inner_than (gdbarch, 1, 2))
+	    if (gdbarch_inner_than (gdbarch, 1, 2, 0, 0))
 	      /* Stack grows down.  */
 	      sp = gdbarch_frame_align (gdbarch, old_sp - 1);
 	    else
 	      /* Stack grows up.  */
 	      sp = gdbarch_frame_align (gdbarch, old_sp + 1);
 	  }
-	gdb_assert ((gdbarch_inner_than (gdbarch, 1, 2)
+	gdb_assert ((gdbarch_inner_than (gdbarch, 1, 2, 0, 0)
 		    && sp <= old_sp)
-		    || (gdbarch_inner_than (gdbarch, 2, 1)
+		    || (gdbarch_inner_than (gdbarch, 2, 1, 0, 0)
 		       && sp >= old_sp));
       }
     else
@@ -505,7 +505,7 @@
     case ON_STACK:
       /* "dummy_addr" is here just to keep old targets happy.  New
 	 targets return that same information via "sp" and "bp_addr".  */
-      if (gdbarch_inner_than (gdbarch, 1, 2))
+      if (gdbarch_inner_than (gdbarch, 1, 2, 0, 0))
 	{
 	  sp = push_dummy_code (gdbarch, sp, funaddr,
 				args, nargs, target_values_type,
@@ -598,7 +598,7 @@
   if (struct_return || lang_struct_return)
     {
       int len = TYPE_LENGTH (values_type);
-      if (gdbarch_inner_than (gdbarch, 1, 2))
+      if (gdbarch_inner_than (gdbarch, 1, 2, 0, 0))
 	{
 	  /* Stack grows downward.  Align STRUCT_ADDR and SP after
              making space for the return value.  */
Index: gdb/gdbarch.c
===================================================================
--- gdb/gdbarch.c	(revision 4)
+++ gdb/gdbarch.c	(working copy)
@@ -542,8 +542,7 @@
   /* Skip verify of return_value, has predicate */
   if (gdbarch->skip_prologue == 0)
     fprintf_unfiltered (log, "\n\tskip_prologue");
-  if (gdbarch->inner_than == 0)
-    fprintf_unfiltered (log, "\n\tinner_than");
+  /* Skip verify of inner_than */
   if (gdbarch->breakpoint_from_pc == 0)
     fprintf_unfiltered (log, "\n\tbreakpoint_from_pc");
   /* Skip verify of adjust_breakpoint_address, has predicate */
@@ -781,6 +780,10 @@
                       "gdbarch_dump: in_solib_return_trampoline = <0x%lx>\n",
                       (long) gdbarch->in_solib_return_trampoline);
   fprintf_unfiltered (file,
+                      "gdbarch_dump: %s # %s\n",
+                      "INNER_THAN(lhs, rhs)",
+                      XSTRING (INNER_THAN (lhs, rhs, 0, 0)));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: inner_than = <0x%lx>\n",
                       (long) gdbarch->inner_than);
   fprintf_unfiltered (file,
@@ -2075,13 +2078,14 @@
 }
 
 int
-gdbarch_inner_than (struct gdbarch *gdbarch, CORE_ADDR lhs, CORE_ADDR rhs)
+gdbarch_inner_than (struct gdbarch *gdbarch, CORE_ADDR lhsf, CORE_ADDR rhsf,
+		CORE_ADDR lhsc, CORE_ADDR rhsc)
 {
   gdb_assert (gdbarch != NULL);
   gdb_assert (gdbarch->inner_than != NULL);
   if (gdbarch_debug >= 2)
     fprintf_unfiltered (gdb_stdlog, "gdbarch_inner_than called\n");
-  return gdbarch->inner_than (lhs, rhs);
+  return gdbarch->inner_than (lhsf, rhsf, lhsc, rhsc);
 }
 
 void
Index: gdb/gdbarch.h
===================================================================
--- gdb/gdbarch.h	(revision 4)
+++ gdb/gdbarch.h	(working copy)
@@ -374,8 +374,10 @@
 extern CORE_ADDR gdbarch_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR ip);
 extern void set_gdbarch_skip_prologue (struct gdbarch *gdbarch, gdbarch_skip_prologue_ftype *skip_prologue);
 
-typedef int (gdbarch_inner_than_ftype) (CORE_ADDR lhs, CORE_ADDR rhs);
-extern int gdbarch_inner_than (struct gdbarch *gdbarch, CORE_ADDR lhs, CORE_ADDR rhs);
+typedef int (gdbarch_inner_than_ftype) (CORE_ADDR lhsf, CORE_ADDR rhsf,
+					CORE_ADDR lhsc, CORE_ADDR rhsc);
+extern int gdbarch_inner_than (struct gdbarch *gdbarch, CORE_ADDR lhsf,
+			       CORE_ADDR rhsf, CORE_ADDR lhsc, CORE_ADDR rhsc);
 extern void set_gdbarch_inner_than (struct gdbarch *gdbarch, gdbarch_inner_than_ftype *inner_than);
 
 typedef const gdb_byte * (gdbarch_breakpoint_from_pc_ftype) (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr);
Index: gdb/amd64-linux-tdep.c
===================================================================
--- gdb/amd64-linux-tdep.c	(revision 4)
+++ gdb/amd64-linux-tdep.c	(working copy)
@@ -3,6 +3,7 @@
    Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
    Contributed by Jiri Smid, SuSE Labs.
+   Copyright 2004 LinSysSoft Technologies Pvt. Ltd.
 
    This file is part of GDB.
 
@@ -288,6 +289,23 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
 }
+
+static void
+amd64_linux_kernel_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* We can use the register offsets used for linux applications. Only
+   * first 18 elements of the array will be used for kernel. Offsets of those
+   * are identical for applications and kernel.  */
+  tdep->gregset_reg_offset = amd64_linux_gregset_reg_offset;
+  tdep->gregset_num_regs = AMD64_NUM_GREGS;
+  tdep->sizeof_gregset = AMD64_NUM_GREGS * 8;
+
+  amd64_init_abi (info, gdbarch);
+
+}
+
 \f
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
@@ -298,4 +316,6 @@
 {
   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
 			  GDB_OSABI_LINUX, amd64_linux_init_abi);
+  gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
+			  GDB_OSABI_LINUX_KERNEL, amd64_linux_kernel_init_abi);
 }
Index: gdb/symfile.c
===================================================================
--- gdb/symfile.c	(revision 4)
+++ gdb/symfile.c	(working copy)
@@ -971,6 +971,10 @@
 void
 new_symfile_objfile (struct objfile *objfile, int mainline, int verbo)
 {
+  char *filename;
+  struct symbol *sym;
+  char *dir;
+  extern int debugkernel;
 
   /* If this is the main symbol file we have to clean up all users of the
      old main symbol file. Otherwise it is sufficient to fixup all the
@@ -980,6 +984,17 @@
       /* OK, make it the "real" symbol file.  */
       symfile_objfile = objfile;
 
+      debugkernel = 0;
+      filename = symfile_objfile->name;
+      while ((dir = strchr(filename, '/')) != NULL)
+        filename = dir + 1;
+      /* only require the given characters to match, so that longer filenames will still match */
+      if (!strncmp(filename, LINUX_KERNEL_NAME_STEM, strlen(LINUX_KERNEL_NAME_STEM)))
+        {
+          sym = lookup_symbol ("start_kernel", NULL, VAR_DOMAIN, NULL, NULL);
+          if (sym)
+	    debugkernel = 1;
+        }
       clear_symtab_users ();
     }
   else
Index: gdb/solib.c
===================================================================
--- gdb/solib.c	(revision 4)
+++ gdb/solib.c	(working copy)
@@ -44,6 +44,7 @@
 #include "solist.h"
 #include "observer.h"
 #include "readline/readline.h"
+#include <glob.h>
 
 /* Architecture-specific operations.  */
 
@@ -78,6 +79,7 @@
 \f
 
 /* external data declarations */
+extern int debugkernel;
 
 /* FIXME: gdbarch needs to control this variable, or else every
    configuration needs to call set_solib_ops.  */
@@ -102,6 +104,172 @@
 		    value);
 }
 
+/* Return True if the file NAME exists and is a regular file */
+static int
+is_regular_file (const char *name)
+{
+  struct stat st;
+  const int status = stat (name, &st);
+
+  /* Stat should never fail except when the file does not exist.
+     If stat fails, analyze the source of error and return True
+     unless the file does not exist, to avoid returning false results
+     on obscure systems where stat does not work as expected.
+   */
+  if (status != 0)
+    return (errno != ENOENT);
+
+  return S_ISREG (st.st_mode);
+}
+
+/* Open a file named STRING, searching path PATH (dir names sep by some char)
+   using mode MODE and protection bits PROT in the calls to open.
+
+   If TRY_CWD_FIRST, try to open ./STRING before searching PATH.
+   (ie pretend the first element of PATH is ".").  This also indicates
+   that a slash in STRING disables searching of the path (this is
+   so that "exec-file ./foo" or "symbol-file ./foo" insures that you
+   get that particular version of foo or an error message).
+
+   If FILENAME_OPENED is non-null, set it to a newly allocated string naming
+   the actual file opened (this string will always start with a "/").  We
+   have to take special pains to avoid doubling the "/" between the directory
+   and the file, sigh!  Emacs gets confuzzed by this when we print the
+   source file name!!! 
+
+   If a file is found, return the descriptor.
+   Otherwise, return -1, with errno set for the last name we tried to open.  */
+
+/*  >>>> This should only allow files of certain types,
+    >>>>  eg executable, non-directory */
+static int
+module_openp (const char *path, int try_cwd_first, const char *string,
+       int mode, int prot,
+       char **filename_opened)
+{
+  register int fd;
+  register char *filename;
+  const char *p;
+  const char *p1;
+  register int len;
+  int alloclen;
+  int uscount;
+  const char *fnptr;
+  char *fnptr2;
+  glob_t globbuf;
+
+  if (!path)
+    path = ".";
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+  mode |= O_BINARY;
+#endif
+
+  /* ./foo => foo */
+  while (string[0] == '.' && IS_DIR_SEPARATOR (string[1]))
+    string += 2;
+
+  for (uscount = 0, fnptr = string; *fnptr; fnptr++)
+      if(*fnptr== '_')
+	uscount++;
+  alloclen = strlen (path) + strlen (string) + 2 + uscount * 4;
+  filename = alloca (alloclen);
+  fd = -1;
+  for (p = path; p; p = p1 ? p1 + 1 : 0)
+    {
+      p1 = strchr (p, DIRNAME_SEPARATOR);
+      if (p1)
+	len = p1 - p;
+      else
+	len = strlen (p);
+
+      if (len == 4 && p[0] == '$' && p[1] == 'c'
+	  && p[2] == 'w' && p[3] == 'd')
+	{
+	  /* Name is $cwd -- insert current directory name instead.  */
+	  int newlen;
+
+	  /* First, realloc the filename buffer if too short. */
+	  len = strlen (current_directory);
+	  newlen = len + strlen (string) + 2;
+	  if (newlen > alloclen)
+	    {
+	      alloclen = newlen;
+	      filename = alloca (alloclen);
+	    }
+	  strcpy (filename, current_directory);
+	}
+      else
+	{
+	  /* Normal file name in path -- just use it.  */
+	  strncpy (filename, p, len);
+	  filename[len] = 0;
+	}
+
+      /* Remove trailing slashes */
+      while (len > 0 && IS_DIR_SEPARATOR (filename[len - 1]))
+	filename[--len] = 0;
+
+      strcat (filename + len, SLASH_STRING);
+      fnptr2 = filename + strlen(filename);
+      for (uscount = 0, fnptr = string; ;fnptr++)
+	{
+	  if(*fnptr== '_')
+	    {
+	      *(fnptr2++) = '[';
+	      *(fnptr2++) = '_';
+	      *(fnptr2++) = '-';
+	      *(fnptr2++) = ']';
+	    }
+	  else
+	    {
+	      *(fnptr2++) = *fnptr;
+	      if (!*fnptr)
+		break;
+	    }
+	}
+      globbuf.gl_offs = 0;
+      glob(filename, GLOB_DOOFFS, NULL, &globbuf);
+      if (!globbuf.gl_pathv[0])
+	continue;
+
+      strcpy(filename, globbuf.gl_pathv[0]);
+      if (is_regular_file (filename))
+      {
+        fd = open (filename, mode);
+        if (fd >= 0)
+          break;
+      }
+    }
+
+  if (filename_opened)
+    {
+      /* If a file was opened, canonicalize its filename. Use xfullpath
+         rather than gdb_realpath to avoid resolving the basename part
+         of filenames when the associated file is a symbolic link. This
+         fixes a potential inconsistency between the filenames known to
+         GDB and the filenames it prints in the annotations.  */
+      if (fd < 0)
+	*filename_opened = NULL;
+      else if (IS_ABSOLUTE_PATH (filename))
+	*filename_opened = xfullpath (filename);
+      else
+	{
+	  /* Beware the // my son, the Emacs barfs, the botch that catch... */
+
+	  char *f = concat (current_directory,
+           IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
+				     ? "" : SLASH_STRING,
+				     filename, NULL);
+	  *filename_opened = xfullpath (f);
+	  xfree (f);
+	}
+    }
+
+  return fd;
+}
+
+
 /*
 
    GLOBAL FUNCTION
@@ -201,6 +369,12 @@
   if (found_file < 0 && solib_search_path != NULL)
     found_file = openp (solib_search_path, OPF_TRY_CWD_FIRST,
 			in_pathname, O_RDONLY | O_BINARY, 0, &temp_pathname);
+ 
+   /* If not found and debugging a kernel, try _ and - changes */
+   if (found_file < 0 && solib_search_path != NULL && debugkernel) {
+     found_file = module_openp(solib_search_path,
+ 			1, in_pathname, O_RDONLY, 0, &temp_pathname);
+   }
   
   /* If not found, next search the solib_search_path (if any) for the basename
      only (ignoring the path).  This is to allow reading solibs from a path
@@ -419,7 +593,7 @@
                                                     so->sections_end);
 
   so->objfile = symbol_file_add (so->so_name, so->from_tty,
-				 sap, 0, OBJF_SHARED);
+				 sap, 0, OBJF_SHARED | (debugkernel ? OBJF_READNOW : 0));
   free_section_addr_info (sap);
 
   return (1);
@@ -625,6 +799,7 @@
 	  /* Notify any observer that the shared object has been
              loaded now that we've added it to GDB's tables.  */
 	  observer_notify_solib_loaded (i);
+          solib_read_symbols (i, from_tty); 
 	}
     }
 }
Index: gdb/i386-linux-tdep.c
===================================================================
--- gdb/i386-linux-tdep.c	(revision 4)
+++ gdb/i386-linux-tdep.c	(working copy)
@@ -2,6 +2,7 @@
 
    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
    Free Software Foundation, Inc.
+   Copyright 2004 LinSysSoft Technologies Pvt. Ltd.
 
    This file is part of GDB.
 
@@ -28,12 +29,15 @@
 #include "reggroups.h"
 #include "dwarf2-frame.h"
 #include "gdb_string.h"
+#include "elf-bfd.h"
 
 #include "i386-tdep.h"
 #include "i386-linux-tdep.h"
 #include "glibc-tdep.h"
 #include "solib-svr4.h"
 #include "symtab.h"
+#include "arch-utils.h"
+#include "gdbarch.h"
 
 /* Return the name of register REG.  */
 
@@ -402,6 +406,39 @@
   0 * 4				/* %gs */
 };
 
+int i386_inner_than (CORE_ADDR lhsf, CORE_ADDR rhsf, CORE_ADDR lhsc,
+		     CORE_ADDR rhsc)
+{
+  /* Read code at rhsc, if it contains a stack switch instruction, return
+   * true. We check for 4 instructions.
+   * 89C4	mov eax, esp
+   * 89DC	mov ebx, esp
+   * 89CC	mov ecx, esp
+   * 89D4	mov edx, esp
+   * 94		xchg eax, esp
+   * 87DC	xchg ebx, esp
+   * 87CC	xchg ecx, esp
+   * 87D4	xchg edx, esp
+   */
+  unsigned short twobyte_insns[] = { 0x89c4, 0x89dc, 0x89cc, 0x89d4, 0x87dc,
+	  0x87dc, 0x87cc, 0x87d4 };
+  unsigned char onebyte_insns[] = { 0x94 };
+  unsigned short tmp;
+  int i;
+
+  if (rhsc &&
+      target_read_memory(rhsc, (gdb_byte *)&tmp, sizeof(unsigned short)) == 0)
+    {
+      for (i = 0; i < sizeof(onebyte_insns); i++)
+	if (onebyte_insns[i] == (unsigned char)tmp)
+	  return 0;
+      for (i = 0; i < sizeof(twobyte_insns); i++)
+	if (twobyte_insns[i] == tmp)
+	  return 0;
+    }
+  return core_addr_lessthan(lhsf, rhsf, lhsc, rhsc);
+}
+
 static void
 i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -446,8 +483,32 @@
   /* Enable TLS support.  */
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
+
+  /* Stack grows downward.  */
+  set_gdbarch_inner_than (gdbarch, i386_inner_than);
 }
 
+static void
+i386_linux_kernel_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* Linux Kernel uses ELF format for vmlinux file.  */
+  i386_elf_init_abi (info, gdbarch);
+
+  /* We can use the register offsets used for linux applications. Only
+   * first 16 elements of the array will be used for kernel. Offsets of those
+   * are identical for applications and kernel.  */
+  tdep->gregset_reg_offset = i386_linux_gregset_reg_offset;
+  tdep->gregset_num_regs = I386_NUM_GREGS;
+  tdep->sizeof_gregset = I386_NUM_GREGS * 4;
+
+  tdep->jb_pc_offset = 20;	/* From <bits/setjmp.h>.  */
+
+  /* Stack grows downward.  */
+  set_gdbarch_inner_than (gdbarch, i386_inner_than);
+}
+
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 extern void _initialize_i386_linux_tdep (void);
 
@@ -456,4 +517,7 @@
 {
   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_LINUX,
 			  i386_linux_init_abi);
+  gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_LINUX_KERNEL,
+			  i386_linux_kernel_init_abi);
+
 }
Index: gdb/frame.c
===================================================================
--- gdb/frame.c	(revision 4)
+++ gdb/frame.c	(working copy)
@@ -380,7 +380,8 @@
        comment in "frame.h", there is some fuzz here.  Frameless
        functions are not strictly inner than (same .stack but
        different .code and/or .special address).  */
-    inner = gdbarch_inner_than (gdbarch, l.stack_addr, r.stack_addr);
+    inner = gdbarch_inner_than (gdbarch, l.stack_addr, r.stack_addr,
+				l.code_addr, r.code_addr);
   if (frame_debug)
     {
       fprintf_unfiltered (gdb_stdlog, "{ frame_id_inner (l=");
Index: gdb/arch-utils.c
===================================================================
--- gdb/arch-utils.c	(revision 4)
+++ gdb/arch-utils.c	(working copy)
@@ -80,9 +80,10 @@
 /* Helper functions for gdbarch_inner_than */
 
 int
-core_addr_lessthan (CORE_ADDR lhs, CORE_ADDR rhs)
+core_addr_lessthan (CORE_ADDR lhsf, CORE_ADDR rhsf, CORE_ADDR lhsc,
+		    CORE_ADDR rhsc)
 {
-  return (lhs < rhs);
+  return (lhsf < rhsf);
 }
 
 int
Index: gdb/arch-utils.h
===================================================================
--- gdb/arch-utils.h	(revision 4)
+++ gdb/arch-utils.h	(working copy)
@@ -31,7 +31,8 @@
 extern int gdbarch_debug;
 
 /* The only possible cases for inner_than. */
-extern int core_addr_lessthan (CORE_ADDR lhs, CORE_ADDR rhs);
+extern int core_addr_lessthan (CORE_ADDR lhsf, CORE_ADDR rhsf,
+		CORE_ADDR lhsc, CORE_ADDR rhsc);
 extern int core_addr_greaterthan (CORE_ADDR lhs, CORE_ADDR rhs);
 
 /* Identity functions on a CORE_ADDR.  Just return the "addr".  */
Index: gdb/osabi.c
===================================================================
--- gdb/osabi.c	(revision 4)
+++ gdb/osabi.c	(working copy)
@@ -56,6 +56,7 @@
   "Solaris",
   "OSF/1",
   "GNU/Linux",
+  "Linux-kernel",
   "FreeBSD a.out",
   "FreeBSD ELF",
   "NetBSD a.out",
Index: gdb/gcore.c
===================================================================
--- gdb/gcore.c	(revision 4)
+++ gdb/gcore.c	(working copy)
@@ -184,7 +184,8 @@
   /* Save frame pointer of TOS frame.  */
   *top = get_frame_base (fi);
   /* If current stack pointer is more "inner", use that instead.  */
-  if (gdbarch_inner_than (get_frame_arch (fi), get_frame_sp (fi), *top))
+  if (gdbarch_inner_than (get_frame_arch (fi), get_frame_sp (fi),
+			  *top, (CORE_ADDR)NULL, (CORE_ADDR)NULL))
     *top = get_frame_sp (fi);
 
   /* Find prev-most frame.  */
Index: gdb/defs.h
===================================================================
--- gdb/defs.h	(revision 4)
+++ gdb/defs.h	(working copy)
@@ -918,6 +918,7 @@
   GDB_OSABI_SOLARIS,
   GDB_OSABI_OSF1,
   GDB_OSABI_LINUX,
+  GDB_OSABI_LINUX_KERNEL,
   GDB_OSABI_FREEBSD_AOUT,
   GDB_OSABI_FREEBSD_ELF,
   GDB_OSABI_NETBSD_AOUT,
@@ -1182,6 +1183,7 @@
 
 extern ULONGEST align_up (ULONGEST v, int n);
 extern ULONGEST align_down (ULONGEST v, int n);
+#define LINUX_KERNEL_NAME_STEM "vmlinux"
 
 /* Allocation and deallocation functions for the libiberty hash table
    which use obstacks.  */

^ permalink raw reply	[flat|nested] 55+ messages in thread

end of thread, other threads:[~2009-10-28 15:05 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-01-09 15:51 symbolic debug of loadable modules with kgdb light Caz Yokoyama
2009-04-24 15:33 ` Tom Tromey
2009-04-24 16:49   ` Caz Yokoyama
2009-04-26  0:39   ` Caz Yokoyama
2009-05-15 21:14   ` Caz Yokoyama
2009-05-15 21:23     ` Pedro Alves
2009-05-15 21:34       ` Daniel Jacobowitz
2009-05-15 21:41         ` Caz Yokoyama
2009-05-15 22:13           ` Michael Snyder
2009-05-15 22:25             ` Caz Yokoyama
2009-08-07  7:17             ` Caz Yokoyama
2009-08-07  9:22               ` Eli Zaretskii
2009-08-07 20:42                 ` Caz Yokoyama
2009-09-23  0:48               ` Joel Brobecker
2009-09-23  1:39                 ` Daniel Jacobowitz
2009-09-23  4:16                 ` Caz Yokoyama
2009-09-23 11:36                 ` Caz Yokoyama
2009-09-24 16:40                 ` Caz Yokoyama
2009-09-24 22:42                 ` Caz Yokoyama
2009-09-25 16:06                   ` Joel Brobecker
2009-09-26  3:43                     ` Caz Yokoyama
     [not found]                       ` <535d47e30909260627n662135a1hf6d1a0bb33368b3a@mail.gmail.com>
2009-09-29  1:58                         ` Joel Brobecker
2009-09-29  3:23                           ` Caz Yokoyama
2009-09-29  4:22                             ` Joel Brobecker
2009-09-29  4:58                               ` Caz Yokoyama
2009-09-29  5:19                                 ` Joel Brobecker
2009-09-29 16:12                                   ` Caz Yokoyama
2009-09-29 16:39                                     ` Joel Brobecker
2009-09-30  4:45                                       ` Caz Yokoyama
2009-09-30 17:28                                         ` Joel Brobecker
2009-09-30 19:16                                         ` Eli Zaretskii
2009-09-30 20:12                                           ` Joel Brobecker
2009-10-01  3:48                                             ` Caz Yokoyama
2009-10-01  4:08                                               ` Eli Zaretskii
2009-10-01  4:51                                                 ` Caz Yokoyama
2009-10-01 20:04                                                   ` Eli Zaretskii
2009-10-01 16:33                                               ` Joel Brobecker
2009-10-01 17:18                                                 ` Caz Yokoyama
2009-10-01 19:37                                                   ` Joel Brobecker
2009-10-01 19:53                                                     ` Caz Yokoyama
2009-10-01 20:25                                                     ` Eli Zaretskii
2009-10-01 20:19                                                   ` Eli Zaretskii
2009-10-01 20:29                                                     ` Caz Yokoyama
2009-10-01 20:46                                                       ` Joel Brobecker
2009-10-01 21:10                                                         ` Daniel Jacobowitz
2009-10-01 21:58                                                           ` Caz Yokoyama
2009-10-01 22:13                                                           ` Pedro Alves
2009-10-01 23:04                                                             ` Caz Yokoyama
2009-10-01 23:32                                                               ` Joel Brobecker
2009-10-02  1:18                                                                 ` Caz Yokoyama
2009-10-02 22:14                                                                   ` Joel Brobecker
2009-10-02  8:55                                                                 ` Eli Zaretskii
2009-10-28 15:05                                                                 ` Joel Brobecker
2009-10-01 20:13                                                 ` Caz Yokoyama
2009-05-15 21:34       ` Caz Yokoyama

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox