* 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* Re: patch to eliminate ADDR on loading symbols of Linux module
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
0 siblings, 1 reply; 4+ messages in thread
From: Daniel Jacobowitz @ 2009-09-24 20:16 UTC (permalink / raw)
To: Caz Yokoyama; +Cc: gdb-patches
On Thu, Sep 24, 2009 at 01:11:02PM -0700, Caz Yokoyama wrote:
> 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.
I want to make this fully automatic. But if you're going to keep
using add-symbol-file, it's not hard to do this automatically from a
script without having to rebuild GDB.
Yes, you have to use the new Python interface. Have the script search
the module list and then issue an appropriate gdb.execute().
... Except you'd need gdb.parse_and_eval, wouldn't you. Tom, that
missed 7.0, I guess?
I firmly maintain that GDB should not have code baked into it that
knows about the layout of the Linux kernel. That's impossible to
maintain.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: patch to eliminate ADDR on loading symbols of Linux module
2009-09-24 20:16 ` Daniel Jacobowitz
@ 2009-09-24 20:22 ` Tom Tromey
2009-09-24 20:32 ` Daniel Jacobowitz
0 siblings, 1 reply; 4+ messages in thread
From: Tom Tromey @ 2009-09-24 20:22 UTC (permalink / raw)
To: Caz Yokoyama; +Cc: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
Daniel> ... Except you'd need gdb.parse_and_eval, wouldn't you. Tom, that
Daniel> missed 7.0, I guess?
Yes, I never got around to rewriting the documentation.
Sorry about that.
Does this need parse_and_eval, or just gdb.execute? parse_and_eval is
for expressions, execute invokes gdb commands. The latter is in CVS.
Tom
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: patch to eliminate ADDR on loading symbols of Linux module
2009-09-24 20:22 ` Tom Tromey
@ 2009-09-24 20:32 ` Daniel Jacobowitz
0 siblings, 0 replies; 4+ messages in thread
From: Daniel Jacobowitz @ 2009-09-24 20:32 UTC (permalink / raw)
To: Tom Tromey; +Cc: Caz Yokoyama, gdb-patches
On Thu, Sep 24, 2009 at 02:21:57PM -0600, Tom Tromey wrote:
> >>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
>
> Daniel> ... Except you'd need gdb.parse_and_eval, wouldn't you. Tom, that
> Daniel> missed 7.0, I guess?
>
> Yes, I never got around to rewriting the documentation.
> Sorry about that.
>
> Does this need parse_and_eval, or just gdb.execute? parse_and_eval is
> for expressions, execute invokes gdb commands. The latter is in CVS.
I think you'd need parse_and_eval to search the kernel's module list.
At least, besides gdb.Frame.read_var, I can't find any other way to
look up a symbol in the target...
--
Daniel Jacobowitz
CodeSourcery
^ 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