Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* patch to eliminate ADDR on loading symbols of Linux module
@ 2009-09-24 20:10 Caz Yokoyama
  2009-09-24 20:16 ` Daniel Jacobowitz
  0 siblings, 1 reply; 4+ messages in thread
From: Caz Yokoyama @ 2009-09-24 20:10 UTC (permalink / raw)
  To: gdb-patches

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

Hello,
When we debug a loadable module of Linux kernel, we use the command,
add-symbol-file to read its symbols. We have to specify its loaded address
like
(gdb) add-symbol-file drivers/net/e1000e/e1000e.ko 0xfffffffffa008000
The address is appeared in /proc/modules. Someone said several months ago
that the address is taken by python script. But I don't know how. Therefore,
I did by my way.
When we develop kernel module, we are interested in several module at most
which we are developing. We don't care the symbols of nfs for example.
Therefore, extending add-symbol-file may be a best way. So the syntax of
add-symbol-file is
Usage: add-symbol-file FILE [ADDR [-s <SECT> <SECT_ADDR> -s <SECT>
<SECT_ADDR> ...] ]
I.e. ADDR becomes optional.
In add_symbol_file(), it checks to see there is only one parameter, FILE.
Then searching the module in the linked list of kernel modules and getting
loaded address. Construct new string which has FILE and ADDR and pass to
original add_symbol_file(). It assumes the modification of
http://sourceware.org/ml/gdb-patches/2009-08/msg00115.html

Thank you.
-Caz Yokoyama, caz at caztech dot com. 503-804-1028(m).


[-- Attachment #2: LinuxModuleSymbolLoad.patch --]
[-- Type: application/octet-stream, Size: 7360 bytes --]

Index: gdb/symfile.c
===================================================================
RCS file: /cvs/src/src/gdb/symfile.c,v
retrieving revision 1.246
diff -u -r1.246 symfile.c
--- gdb/symfile.c	18 Sep 2009 17:33:51 -0000	1.246
+++ gdb/symfile.c	24 Sep 2009 19:27:58 -0000
@@ -2068,6 +2068,194 @@
   ui_out_text (uiout, ".\n");
 }
 
+/*
+  Read symboles of a module file(.ko) of Linux kernel
+*/
+/* taken from kernel source code */
+struct list_head {
+  CORE_ADDR next;
+  CORE_ADDR prev;
+};
+struct module;
+typedef unsigned int __kernel_mode_t;
+typedef __kernel_mode_t mode_t;
+
+struct attribute {
+  const char *name;
+  struct module *owner;
+  mode_t mode;
+};
+
+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 *);
+};
+
+struct attribute_group {
+	const char		*name;
+	mode_t			(*is_visible)();
+	struct attribute	**attrs;
+};
+
+struct module_sect_attr
+{
+	struct module_attribute mattr;
+	char *name;
+	unsigned long address;
+};
+
+struct module_sect_attrs
+{
+	struct attribute_group grp;
+	unsigned int nsections;
+	struct module_sect_attr attrs[0];
+};
+
+#define MODULE_NAME_LEN (64 - sizeof(CORE_ADDR))
+struct module
+{
+  CORE_ADDR unused_state;
+  struct list_head list;
+  char name[MODULE_NAME_LEN];
+};
+#define OFFSET(structure, field) ((CORE_ADDR)(&((struct structure *)0)->field))
+
+static char *
+add_addr_on_linux_module (char *module_name)
+{
+  char *module_base_name, *s;
+  struct expression *expr;
+  struct value *val;
+  int offset_sect_attrs, ret, n;
+  struct symbol *modules;
+  struct module module;
+  CORE_ADDR module_addr, _msas;
+  struct module_sect_attrs msas;
+  struct module_sect_attr *kmsas;
+  char section_name[MODULE_NAME_LEN], *arg_str;
+
+  /* Get base name of module.  */
+  s = strrchr (module_name, '/');
+  if (s == NULL) /* not found  */
+    s = module_name;
+  else
+    s++;
+  module_base_name = xmalloc (strlen(s) + 1);
+  if (module_base_name == NULL)
+    {
+      warning ("can't allocate module_base_name");
+      return NULL;
+    }
+  make_cleanup (xfree, module_base_name);
+  strcpy(module_base_name, s);
+  /* Discard .ko  */
+  s = strchr(module_base_name, '.');
+  if (s != NULL)
+    *s = '\0';
+
+  /* Find whether the module is loaded.  */
+  /* Check to see if Linux is the supported version.  */
+  expr = parse_expression ("&((struct module *)0)->sect_attrs");
+  val = evaluate_expression (expr);
+  offset_sect_attrs = unpack_long (value_type(val), value_contents_all(val));
+  expr = parse_expression ("&((struct module_sect_attrs *)0)->attrs[1]");
+  val = evaluate_expression (expr);
+  if (unpack_long (value_type(val), value_contents_all(val)) !=
+	     (long)&((struct module_sect_attrs *)0)->attrs[1]) {
+    warning ("your target kernel has difference struct module_sect_attrs");
+    return NULL;
+  }
+
+  /* Modules are in the linked list pointed by "modules"  */
+  modules = lookup_symbol ("modules", NULL, VAR_DOMAIN, NULL);
+  if (modules == NULL) {
+    warning ("can't find the address of modules");
+    return NULL;
+  }
+  module_addr = SYMBOL_VALUE_ADDRESS(modules) - OFFSET(module, list.next);
+  do {
+    ret = target_read_memory(module_addr,
+		       (gdb_byte *)&module, sizeof(module));
+    if (ret != 0)
+      {
+	warning("can't read module");
+	return NULL;
+      }
+    if (strcmp(module_base_name, module.name) == 0) /* found the module */
+      break;
+    module_addr = module.list.next - OFFSET(module, list.next);
+  } while (module_addr + OFFSET(module, list.next) !=
+	   SYMBOL_VALUE_ADDRESS(modules));
+  if (module_addr + OFFSET(module, list.next) ==
+      SYMBOL_VALUE_ADDRESS(modules)) /* not found the module */
+    {
+      warning("can't find %s in the linked list of Linux modules",
+	      module_base_name);
+      return NULL;
+    }
+
+  ret = target_read_memory (module_addr + offset_sect_attrs,
+			    (gdb_byte *)&_msas, sizeof(_msas));
+  if (ret != 0)
+    {
+      warning("can't read _msas on %s", module.name);
+      return NULL;
+    }
+  ret = target_read_memory (_msas,
+			    (gdb_byte *)&msas, sizeof(msas));
+  if (ret != 0)
+    {
+      warning("can't read msas on %s", module.name);
+      return NULL;
+    }
+  kmsas = xmalloc (sizeof(struct module_sect_attr) * msas.nsections);
+  if (kmsas == NULL)
+    {
+      warning ("can't allocate kmsas");
+      return NULL;
+    }
+  make_cleanup (xfree, kmsas);
+  ret = target_read_memory (_msas + OFFSET(module_sect_attrs, attrs[0]),
+			    (char *)kmsas,
+			    sizeof(*kmsas) * msas.nsections);
+  if (ret != 0)
+    {
+      warning ("can't read kmsas");
+      return NULL;
+    }
+  /* Look for .text section  */
+  for (n = 0; n < msas.nsections; n++, kmsas++)
+    {
+      ret = target_read_memory((CORE_ADDR)kmsas->name,
+			       section_name, MODULE_NAME_LEN);
+      if (ret != 0)
+	{
+	  warning ("can't read kmsas->name");
+	  return NULL;
+	}
+      if (strcmp(section_name, ".text") == 0)
+	break;
+    }
+  if (n < msas.nsections) /* found .text section */
+    {
+      /* " 0x%016lx" + terminating '\0' */
+      arg_str = xmalloc (strlen(module_name) + 1 + 2 + 16 + 1);
+      if (arg_str == NULL) {
+	warning ("can't allocate arg_str");
+	return NULL;
+      }
+      sprintf (arg_str, "%s 0x%016lx", module_name, kmsas->address);
+      /* No need to free arg_str. make_cleanup_freeargv() takes care. */
+    }
+
+  return arg_str;
+}
+
 /* This function allows the addition of incrementally linked object files.
    It does not modify any state in the target, only in the debugger.  */
 /* Note: ezannoni 2000-04-13 This function/command used to have a
@@ -2110,12 +2298,25 @@
 
   dont_repeat ();
 
-  if (args == NULL)
-    error (_("add-symbol-file takes a file name and an address"));
+  if (args == NULL || *args == '\0')
+    error (_("Usage: add-symbol-file FILE [ADDR [-s <SECT> <SECT_ADDR> -s <SECT> <SECT_ADDR> ...] ]"));
 
   argv = gdb_buildargv (args);
   make_cleanup_freeargv (argv);
 
+  if (argv[1] == NULL) /* no ADDR */
+    {
+      if (remote_break_mode != remote_break_sysrq_g)
+	{
+	  error (_("Don't you forget \"set remotebreak sysrq-g\"?"));
+	}
+      args = add_addr_on_linux_module (args);
+      if (args == NULL)
+	return;
+      argv = gdb_buildargv (args);
+      make_cleanup_freeargv (argv);
+    }
+
   for (arg = argv[0], argcnt = 0; arg != NULL; arg = argv[++argcnt])
     {
       /* Process the argument. */
@@ -2222,8 +2423,11 @@
 	 so we can't determine what section names are valid.  */
     }
 
-  if (from_tty && (!query ("%s", "")))
-    error (_("Not confirmed."));
+  if (remote_break_mode != remote_break_sysrq_g) /* Not module loading */
+    {
+      if (from_tty && (!query ("%s", "")))
+	error (_("Not confirmed."));
+    }
 
   symbol_file_add (filename, from_tty ? SYMFILE_VERBOSE : 0,
                    section_addrs, flags);

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

end of thread, other threads:[~2009-09-24 20:32 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-24 20:10 patch to eliminate ADDR on loading symbols of Linux module Caz Yokoyama
2009-09-24 20:16 ` Daniel Jacobowitz
2009-09-24 20:22   ` Tom Tromey
2009-09-24 20:32     ` Daniel Jacobowitz

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