Mirror of the gdb mailing list
 help / color / mirror / Atom feed
* RE: symbolic debug of loadable modules with kgdb light
@ 2009-01-08 14:09 Caz Yokoyama
  2009-01-08 19:04 ` Tiago Maluta
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Caz Yokoyama @ 2009-01-08 14:09 UTC (permalink / raw)
  To: gdb

Hello,
I started a sourceforge project called kgdb-light
(http://sourceforge.net/projects/kgdb-light/). kgdb-light is a modified gdb
which handles symbol tables of loadable modules of Linux kernel 2.6.26 and
later. Linux kernel 2.6.26 and later integrates kernel debugging under
kernel hacking. Gdb handles symbol table of Linux kernel, but it does not
for loadable modules. Kgdb-light updates internal symbol table by reading
"struct module" in kernel. I also modified gdb to send Magic SysRq,
therefore, target may locate far away.

Is there anyway to integrate my modifications to gdb?
-Caz Yokoyama, caz at caztech dot com. 503-804-1028(m).



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

* RE: symbolic debug of loadable modules with kgdb light
  2009-01-08 14:09 symbolic debug of loadable modules with kgdb light Caz Yokoyama
@ 2009-01-08 19:04 ` Tiago Maluta
  2009-01-08 19:40   ` Caz Yokoyama
  2009-01-08 19:42   ` Caz Yokoyama
  2009-01-09  4:18 ` Joel Brobecker
  2009-01-09 11:11 ` Jan Kiszka
  2 siblings, 2 replies; 14+ messages in thread
From: Tiago Maluta @ 2009-01-08 19:04 UTC (permalink / raw)
  To: gdb, Caz Yokoyama

--- On Thu, 1/8/09, Caz Yokoyama <cazyokoyama@gmail.com> wrote:

> Hello,
> I started a sourceforge project called kgdb-light
> (http://sourceforge.net/projects/kgdb-light/). kgdb-light
> is a modified gdb
> which handles symbol tables of loadable modules of Linux
> kernel 2.6.26 and
> later. Linux kernel 2.6.26 and later integrates kernel
> debugging under
> kernel hacking. 

About a year ago I saw the topic 'Kgdb Light' on KernelTrap [1]. This project on SF uses the modifications proposed there? 

[1] http://kerneltrap.org/Linux/Kgdb_Light

Best regards,
Tiago Maluta



      


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

* RE: symbolic debug of loadable modules with kgdb light
  2009-01-08 19:04 ` Tiago Maluta
@ 2009-01-08 19:40   ` Caz Yokoyama
  2009-01-08 19:42   ` Caz Yokoyama
  1 sibling, 0 replies; 14+ messages in thread
From: Caz Yokoyama @ 2009-01-08 19:40 UTC (permalink / raw)
  To: maluta_tiago, gdb

Hello,
No. Their Kgdb light is the modification for Linux kernel. It is already
integrated in Linux kernel since  2.6.26. When you run gdb of Fedora 8, for
example, against kgdb light enabled kernel, you can't refer the symbols in
loadable modules. You also can't break in to kernel if your target is far
away from your reach. You have to physically type Ctrl+Alt+Sysrq and g. My
kgdb-light solves these problems. Let me know if you have any question.
-caz

-----Original Message-----
From: Tiago Maluta [mailto:maluta_tiago@yahoo.com.br] 
Sent: Thursday, January 08, 2009 11:04 AM
To: gdb@sourceware.org; Caz Yokoyama
Subject: RE: symbolic debug of loadable modules with kgdb light

--- On Thu, 1/8/09, Caz Yokoyama <cazyokoyama@gmail.com> wrote:

> Hello,
> I started a sourceforge project called kgdb-light
> (http://sourceforge.net/projects/kgdb-light/). kgdb-light
> is a modified gdb
> which handles symbol tables of loadable modules of Linux
> kernel 2.6.26 and
> later. Linux kernel 2.6.26 and later integrates kernel
> debugging under
> kernel hacking. 

About a year ago I saw the topic 'Kgdb Light' on KernelTrap [1]. This
project on SF uses the modifications proposed there? 

[1] http://kerneltrap.org/Linux/Kgdb_Light

Best regards,
Tiago Maluta



      


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

* RE: symbolic debug of loadable modules with kgdb light
  2009-01-08 19:04 ` Tiago Maluta
  2009-01-08 19:40   ` Caz Yokoyama
@ 2009-01-08 19:42   ` Caz Yokoyama
  1 sibling, 0 replies; 14+ messages in thread
From: Caz Yokoyama @ 2009-01-08 19:42 UTC (permalink / raw)
  To: maluta_tiago, gdb

Yes.
-caz

-----Original Message-----
From: Tiago Maluta [mailto:maluta_tiago@yahoo.com.br] 
Sent: Thursday, January 08, 2009 11:04 AM
To: gdb@sourceware.org; Caz Yokoyama
Subject: RE: symbolic debug of loadable modules with kgdb light

--- On Thu, 1/8/09, Caz Yokoyama <cazyokoyama@gmail.com> wrote:

> Hello,
> I started a sourceforge project called kgdb-light
> (http://sourceforge.net/projects/kgdb-light/). kgdb-light
> is a modified gdb
> which handles symbol tables of loadable modules of Linux
> kernel 2.6.26 and
> later. Linux kernel 2.6.26 and later integrates kernel
> debugging under
> kernel hacking. 

About a year ago I saw the topic 'Kgdb Light' on KernelTrap [1]. This
project on SF uses the modifications proposed there? 

[1] http://kerneltrap.org/Linux/Kgdb_Light

Best regards,
Tiago Maluta



      


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

* Re: symbolic debug of loadable modules with kgdb light
  2009-01-08 14:09 symbolic debug of loadable modules with kgdb light Caz Yokoyama
  2009-01-08 19:04 ` Tiago Maluta
@ 2009-01-09  4:18 ` Joel Brobecker
  2009-01-09 14:52   ` Caz Yokoyama
  2009-01-09 11:11 ` Jan Kiszka
  2 siblings, 1 reply; 14+ messages in thread
From: Joel Brobecker @ 2009-01-09  4:18 UTC (permalink / raw)
  To: Caz Yokoyama; +Cc: gdb

> 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


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

* Re: symbolic debug of loadable modules with kgdb light
  2009-01-08 14:09 symbolic debug of loadable modules with kgdb light Caz Yokoyama
  2009-01-08 19:04 ` Tiago Maluta
  2009-01-09  4:18 ` Joel Brobecker
@ 2009-01-09 11:11 ` Jan Kiszka
  2009-01-09 11:28   ` Caz Yokoyama
  2 siblings, 1 reply; 14+ messages in thread
From: Jan Kiszka @ 2009-01-09 11:11 UTC (permalink / raw)
  To: Caz Yokoyama; +Cc: gdb

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

Caz Yokoyama wrote:
> Hello,
> I started a sourceforge project called kgdb-light
> (http://sourceforge.net/projects/kgdb-light/). kgdb-light is a modified gdb
> which handles symbol tables of loadable modules of Linux kernel 2.6.26 and
> later. Linux kernel 2.6.26 and later integrates kernel debugging under
> kernel hacking. Gdb handles symbol table of Linux kernel, but it does not
> for loadable modules. Kgdb-light updates internal symbol table by reading
> "struct module" in kernel. I also modified gdb to send Magic SysRq,
> therefore, target may locate far away.
> 

Sounds very interesting. Did you happend to try the former extension
with the QEMU or KVM backend already? Would be _very_ cool if such
support became mainline (I'm tired of add-symbol-file with manually
looked-up module addresses...). Is it possible to disable the SysRq
interrupt for this use case? [ I still consider this variation of the
original remote protocol an unfortunate decision of the kernel
developers, but back then I wasn't able to convince them to change it. ]

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

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

* RE: symbolic debug of loadable modules with kgdb light
  2009-01-09 11:11 ` Jan Kiszka
@ 2009-01-09 11:28   ` Caz Yokoyama
  2009-01-09 12:38     ` Jan Kiszka
  0 siblings, 1 reply; 14+ messages in thread
From: Caz Yokoyama @ 2009-01-09 11:28 UTC (permalink / raw)
  To: jan.kiszka; +Cc: gdb

Hello,
Did you happen to try the former extension with the QEMU or KVM backend
already? 
---
No. I am glad if you tell me how to do that. I saw a paper which talked
about running kgdb for guest OS of Xen.
(http://www.kernel.org/doc/ols/2006/ols2006v2-pages-9-24.pdf). I know there
is serial console in Virtual Machine Manager, i.e. select Guest OS ->
Details -> view -> serial console. But I have no idea how to connect it.

Is it possible to disable the SysRq interrupt for this use case?
----
I am not clear your point. My modification uses SysRq. I mean there are two
ways to generate SysRq, 1) from keyboard and 2) from serial port. 1) is
obvious, i.e. hit Ctrl+Alt+SysRq + g. 2) is BREAK and g. When my modified
gdb is invoked, it sends BREAK and g which break-in to kernel. Did I answer
your question? Or are you asking something else?
-caz

-----Original Message-----
From: jan.kiszka@web.de [mailto:jan.kiszka@web.de] 
Sent: Friday, January 09, 2009 3:11 AM
To: Caz Yokoyama
Cc: gdb@sourceware.org
Subject: Re: symbolic debug of loadable modules with kgdb light

Caz Yokoyama wrote:
> Hello,
> I started a sourceforge project called kgdb-light
> (http://sourceforge.net/projects/kgdb-light/). kgdb-light is a modified
gdb
> which handles symbol tables of loadable modules of Linux kernel 2.6.26 and
> later. Linux kernel 2.6.26 and later integrates kernel debugging under
> kernel hacking. Gdb handles symbol table of Linux kernel, but it does not
> for loadable modules. Kgdb-light updates internal symbol table by reading
> "struct module" in kernel. I also modified gdb to send Magic SysRq,
> therefore, target may locate far away.
> 

Sounds very interesting. Did you happend to try the former extension
with the QEMU or KVM backend already? Would be _very_ cool if such
support became mainline (I'm tired of add-symbol-file with manually
looked-up module addresses...). Is it possible to disable the SysRq
interrupt for this use case? [ I still consider this variation of the
original remote protocol an unfortunate decision of the kernel
developers, but back then I wasn't able to convince them to change it. ]

Jan



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

* Re: symbolic debug of loadable modules with kgdb light
  2009-01-09 11:28   ` Caz Yokoyama
@ 2009-01-09 12:38     ` Jan Kiszka
  2009-01-09 16:29       ` Caz Yokoyama
  0 siblings, 1 reply; 14+ messages in thread
From: Jan Kiszka @ 2009-01-09 12:38 UTC (permalink / raw)
  To: Caz Yokoyama; +Cc: gdb

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

Caz Yokoyama wrote:
> Hello,
> Did you happen to try the former extension with the QEMU or KVM backend
> already? 
> ---
> No. I am glad if you tell me how to do that. I saw a paper which talked
> about running kgdb for guest OS of Xen.

AFAIK, Xen's gdbserver is not that advanced as the one of QEMU or KVM.
Both support hardware watchpoints/breakpoints now and present guest CPUs
as threads to the frontend.

> (http://www.kernel.org/doc/ols/2006/ols2006v2-pages-9-24.pdf). I know there
> is serial console in Virtual Machine Manager, i.e. select Guest OS ->
> Details -> view -> serial console. But I have no idea how to connect it.

Start qemu (or qemu-system-x86_64) with -s as additional switch, using
some Linux system image that will boot the kernel you want to debug.
Then fire up "gdb vmlinux" and connect via "tar re :1234" to qemu's
gdbserver (once the kernel is booting, otherwise you will end up in the
BIOS).

> 
> Is it possible to disable the SysRq interrupt for this use case?
> ----
> I am not clear your point. My modification uses SysRq. I mean there are two
> ways to generate SysRq, 1) from keyboard and 2) from serial port. 1) is
> obvious, i.e. hit Ctrl+Alt+SysRq + g. 2) is BREAK and g. When my modified
> gdb is invoked, it sends BREAK and g which break-in to kernel. Did I answer
> your question? Or are you asking something else?

Right now gdb sends CTRL+C on start-up or when you interrupt the target
during runtime. For kgdb you had to replace this with the SysRq
sequence, right? But as qemu uses the standard way of interruption, this
replacement would have to be disabled again (probably via some "set
whatever-variable") - mmh, unless it is only coupled to serial line
links (QEMU works via TCP). In that case forget my question.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 258 bytes --]

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

* RE: symbolic debug of loadable modules with kgdb light
  2009-01-09  4:18 ` Joel Brobecker
@ 2009-01-09 14:52   ` Caz Yokoyama
  2009-01-09 18:17     ` Joel Brobecker
  0 siblings, 1 reply; 14+ messages in thread
From: Caz Yokoyama @ 2009-01-09 14:52 UTC (permalink / raw)
  To: 'Joel Brobecker'; +Cc: gdb

[-- Attachment #1: Type: text/plain, Size: 1052 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

-----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] 14+ messages in thread

* RE: symbolic debug of loadable modules with kgdb light
  2009-01-09 12:38     ` Jan Kiszka
@ 2009-01-09 16:29       ` Caz Yokoyama
  0 siblings, 0 replies; 14+ messages in thread
From: Caz Yokoyama @ 2009-01-09 16:29 UTC (permalink / raw)
  To: jan.kiszka; +Cc: gdb

Right now gdb sends CTRL+C on start-up or when you interrupt the target
during runtime. For kgdb you had to replace this with the SysRq
sequence, right? But as qemu uses the standard way of interruption, this
replacement would have to be disabled again (probably via some "set
whatever-variable") - mmh, unless it is only coupled to serial line
links (QEMU works via TCP). In that case forget my question.
-----------
Whether my gdb sends BREAK+g on startup is determined by whether target
program is vmlinux. As you said, whether CTRL+C or BREAK is determined by
remote_break. remote_break is set and showed by set and show command. If
remote_break is enum  {Ctl_C, BREAK, BREAK_g}, what's happen. I'll try.

-----Original Message-----
From: jan.kiszka@web.de [mailto:jan.kiszka@web.de] 
Sent: Friday, January 09, 2009 4:38 AM
To: Caz Yokoyama
Cc: gdb@sourceware.org
Subject: Re: symbolic debug of loadable modules with kgdb light

Caz Yokoyama wrote:
> Hello,
> Did you happen to try the former extension with the QEMU or KVM backend
> already? 
> ---
> No. I am glad if you tell me how to do that. I saw a paper which talked
> about running kgdb for guest OS of Xen.

AFAIK, Xen's gdbserver is not that advanced as the one of QEMU or KVM.
Both support hardware watchpoints/breakpoints now and present guest CPUs
as threads to the frontend.

> (http://www.kernel.org/doc/ols/2006/ols2006v2-pages-9-24.pdf). I know
there
> is serial console in Virtual Machine Manager, i.e. select Guest OS ->
> Details -> view -> serial console. But I have no idea how to connect it.

Start qemu (or qemu-system-x86_64) with -s as additional switch, using
some Linux system image that will boot the kernel you want to debug.
Then fire up "gdb vmlinux" and connect via "tar re :1234" to qemu's
gdbserver (once the kernel is booting, otherwise you will end up in the
BIOS).

> 
> Is it possible to disable the SysRq interrupt for this use case?
> ----
> I am not clear your point. My modification uses SysRq. I mean there are
two
> ways to generate SysRq, 1) from keyboard and 2) from serial port. 1) is
> obvious, i.e. hit Ctrl+Alt+SysRq + g. 2) is BREAK and g. When my modified
> gdb is invoked, it sends BREAK and g which break-in to kernel. Did I
answer
> your question? Or are you asking something else?

Right now gdb sends CTRL+C on start-up or when you interrupt the target
during runtime. For kgdb you had to replace this with the SysRq
sequence, right? But as qemu uses the standard way of interruption, this
replacement would have to be disabled again (probably via some "set
whatever-variable") - mmh, unless it is only coupled to serial line
links (QEMU works via TCP). In that case forget my question.

Jan



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

* Re: symbolic debug of loadable modules with kgdb light
  2009-01-09 14:52   ` Caz Yokoyama
@ 2009-01-09 18:17     ` Joel Brobecker
  2009-01-09 19:33       ` Caz Yokoyama
                         ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Joel Brobecker @ 2009-01-09 18:17 UTC (permalink / raw)
  To: Caz Yokoyama; +Cc: gdb

Caz,

I have a few remarks:

> I have attached the patch against gdb-6.8.

The patches first need to be brought up to date with our CVS head.
Our gdb-6.8 branch is more or less dead at this point, and the
current CVS head is sometimes significantly different from gdb-6.8.

Also, the patches should be broken down into small patches. I don't
know how well the other maintainers know the Linux kernel (I suspect
some of them know it very well), but most of us don't have much time
available to do code review. So breaking down the patches and explaining
what they are about is very very very very very very helpful. If you
don't do that, unless someone from the GDB Maintainers group is
expecially motivated in getting the feature you are submitting,
you are dramatically reducing your chances of us reviewing your patch.

> - This patch is based on http://kgdb.cvs.sourceforge.net/viewvc/kgdb/gdb/. I
> removed garbage as mush as possible.

I tried to have a look at who the authors are. The changes need to be
assigned to the FSF. I'm not a big specialist in legal matters, but
I believe that only the author of the changes can do that; someone
else who knows better about might want to confirm or correct.  There
is a provision for changes that are obvious, or small (usually less
than 10 lines). But this patch does not qualify. Some parts of it
might.

> But it still has the code which I don't know what it is.

As far as I am concerned, this is a problem. I personally am not going
to approve changes whose purpose I don't understand. My approach in
this case has always been to leave the change aside, and wait until
I hit a problem. If that change ends up fixing the problem, at least
I will know why (and I will make sure to add a comment besides the
code).

> - I haven't run testsuite because I could not find how to do that while I
> run make in testsuite directory.

The magic command for testing your changes natively is "make check".
What you need to do is run the testsuite before and after your
changes, and make sure that it does not introduce any regression.
Somes parts of the patch will be hard to exercise except manually,
since they refer to debugging kernel modules, which I don't think
is something that our testsuite knows how to do...

I hope all the above doesn't discourage you...

-- 
Joel


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

* RE: symbolic debug of loadable modules with kgdb light
  2009-01-09 18:17     ` Joel Brobecker
@ 2009-01-09 19:33       ` Caz Yokoyama
  2009-01-10  6:40       ` Daniel Jacobowitz
       [not found]       ` <B28296C4454C4B539564033161523A12@xpjpn>
  2 siblings, 0 replies; 14+ messages in thread
From: Caz Yokoyama @ 2009-01-09 19:33 UTC (permalink / raw)
  To: 'Joel Brobecker'; +Cc: gdb

Joel,
Thank you for your comments. I'll minimize the modification as little as
possible and find if there is code comes from
http://kgdb.cvs.sourceforge.net/viewvc/kgdb/gdb/.
-caz

-----Original Message-----
From: Joel Brobecker [mailto:brobecker@adacore.com] 
Sent: Friday, January 09, 2009 10:17 AM
To: Caz Yokoyama
Cc: gdb@sourceware.org
Subject: Re: symbolic debug of loadable modules with kgdb light

Caz,

I have a few remarks:

> I have attached the patch against gdb-6.8.

The patches first need to be brought up to date with our CVS head.
Our gdb-6.8 branch is more or less dead at this point, and the
current CVS head is sometimes significantly different from gdb-6.8.

Also, the patches should be broken down into small patches. I don't
know how well the other maintainers know the Linux kernel (I suspect
some of them know it very well), but most of us don't have much time
available to do code review. So breaking down the patches and explaining
what they are about is very very very very very very helpful. If you
don't do that, unless someone from the GDB Maintainers group is
expecially motivated in getting the feature you are submitting,
you are dramatically reducing your chances of us reviewing your patch.

> - This patch is based on http://kgdb.cvs.sourceforge.net/viewvc/kgdb/gdb/.
I
> removed garbage as mush as possible.

I tried to have a look at who the authors are. The changes need to be
assigned to the FSF. I'm not a big specialist in legal matters, but
I believe that only the author of the changes can do that; someone
else who knows better about might want to confirm or correct.  There
is a provision for changes that are obvious, or small (usually less
than 10 lines). But this patch does not qualify. Some parts of it
might.

> But it still has the code which I don't know what it is.

As far as I am concerned, this is a problem. I personally am not going
to approve changes whose purpose I don't understand. My approach in
this case has always been to leave the change aside, and wait until
I hit a problem. If that change ends up fixing the problem, at least
I will know why (and I will make sure to add a comment besides the
code).

> - I haven't run testsuite because I could not find how to do that while I
> run make in testsuite directory.

The magic command for testing your changes natively is "make check".
What you need to do is run the testsuite before and after your
changes, and make sure that it does not introduce any regression.
Somes parts of the patch will be hard to exercise except manually,
since they refer to debugging kernel modules, which I don't think
is something that our testsuite knows how to do...

I hope all the above doesn't discourage you...

-- 
Joel


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

* Re: symbolic debug of loadable modules with kgdb light
  2009-01-09 18:17     ` Joel Brobecker
  2009-01-09 19:33       ` Caz Yokoyama
@ 2009-01-10  6:40       ` Daniel Jacobowitz
       [not found]       ` <B28296C4454C4B539564033161523A12@xpjpn>
  2 siblings, 0 replies; 14+ messages in thread
From: Daniel Jacobowitz @ 2009-01-10  6:40 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Caz Yokoyama, gdb

On Fri, Jan 09, 2009 at 10:17:20PM +0400, Joel Brobecker wrote:
> > - This patch is based on http://kgdb.cvs.sourceforge.net/viewvc/kgdb/gdb/. I
> > removed garbage as mush as possible.
> 
> I tried to have a look at who the authors are. The changes need to be
> assigned to the FSF. I'm not a big specialist in legal matters, but
> I believe that only the author of the changes can do that; someone
> else who knows better about might want to confirm or correct.

Your understanding is correct.  There are some other cases, for
instance it is possible to transfer the ownership to some other party
which can then assign it to the FSF, but I wouldn't mess about with
any of the alternatives without legal advice.

-- 
Daniel Jacobowitz
CodeSourcery


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

* Re: symbolic debug of loadable modules with kgdb light
       [not found]       ` <B28296C4454C4B539564033161523A12@xpjpn>
@ 2009-01-11  3:38         ` Joel Brobecker
  0 siblings, 0 replies; 14+ messages in thread
From: Joel Brobecker @ 2009-01-11  3:38 UTC (permalink / raw)
  To: Caz Yokoyama; +Cc: gdb

> About 25 lines come from
> http://kgdb.cvs.sourceforge.net/viewvc/kgdb/gdb/. These are an
> essential part. I could not delete it. From your comments, I have 3
> options in the order of most aggressive to conservative, 1) re-write
> the code which come from kgdb, 2) ask the author of the code for his
> permission and 3) don't submit the patch to gdb. I am wondering what
> is right choice.

It's hard to tell without knowing what the code is doing.  If you can
easily track down the author (all the authors, actually), then you
can ask them to contribute this code. I think the safest for everyone
would be if they have a copyright assignment on file with the FSF.
On the other hand, if it's easy for you to rewrite the code in
a different way, doing so allows you do remove a dependency on
external factors.

The other alternative is if we can determine that the change is not
a "legally significant change", as our guidelines call it:

  http://www.gnu.org/prep/maintain/maintain.html#Legally-Significant

> Regarding testsuite,
> - gdb-6.8
> # of expected passes            11844
> # of unexpected failures        82
> # of unexpected successes       2
> # of expected failures          43
> # of known failures             39
> # of untested testcases         10
> # of unsupported tests          47
> - Modified gdb-6.8, 
> # of expected passes            11841
> # of unexpected failures        83
> # of unexpected successes       2
> # of expected failures          43
> # of known failures             39
> # of untested testcases         10
> # of unsupported tests          47
> So I believe the modification does not break anything. 

Looking at pure numbers can be misleading sometimes (which is why
I diff the .sum files before and after applying my patch), but
the numbers you published show that you have 3 less PASSes and
one more FAIL. Sometimes, this does not indicate any regression,
but often it does... Did you check were the difference come from?

> All modifications are clear to me. I can write explanation for each
> modifications and files. Also making a patch against cvd HEAD is not a
> issue.

Great! My recommendation is to first bring your patches up to date
with CVS HEAD and, once done, to break them down into individual pieces.
Then send each piece for review to the gdb-patches mailing list,
explaining what the problem is and how you're solving it. The more
information you provide, the easier it is for us to review the patches.

-- 
Joel


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

end of thread, other threads:[~2009-01-11  3:38 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-01-08 14:09 symbolic debug of loadable modules with kgdb light Caz Yokoyama
2009-01-08 19:04 ` Tiago Maluta
2009-01-08 19:40   ` Caz Yokoyama
2009-01-08 19:42   ` Caz Yokoyama
2009-01-09  4:18 ` Joel Brobecker
2009-01-09 14:52   ` Caz Yokoyama
2009-01-09 18:17     ` Joel Brobecker
2009-01-09 19:33       ` Caz Yokoyama
2009-01-10  6:40       ` Daniel Jacobowitz
     [not found]       ` <B28296C4454C4B539564033161523A12@xpjpn>
2009-01-11  3:38         ` Joel Brobecker
2009-01-09 11:11 ` Jan Kiszka
2009-01-09 11:28   ` Caz Yokoyama
2009-01-09 12:38     ` Jan Kiszka
2009-01-09 16:29       ` Caz Yokoyama

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