The address range may overlap for kernel modules global block vector,
for example:
module compunit_symtab block start block end
floppy floppy.c ffffffffc0092000 ffffffffc00a4fa6
virtio_blk virtio_blk.c ffffffffc00a4000 ffffffffc00fd080
According to the gdb source code, the distance(block end - block start) of
floppy(0x12fa6) is smaller than virtio_blk(0x59080), so address
0xffffffffc00a45b0, 0xffffffffc00a4370, 0xffffffffc00a4260 are translated
by floppy module instead of virtio_blk module. However according
to crash, the address range for the 2 modules are:
crash> sym -l
ffffffffc0092000 MODULE START: floppy
...snip...
ffffffffc00a2f29 MODULE END: floppy
ffffffffc00a4000 MODULE START: virtio_blk
...snip...
ffffffffc00a86ec MODULE END: virtio_blk
So the block vector address arrange and distance is not a reliable way to
determine the symbol belonging of a specific kernel module. This patch will
let gdb to query the module address range from crash, in order to locate the
symbol belongings more percisely.
Without the patch:
crash> mod -S
crash> struct blk_mq_ops 0xffffffffc00a7160
struct blk_mq_ops {
queue_rq = 0xffffffffc00a45b0 <floppy_module_init+1151>, <-- symbol translated
from module floppy
map_queue = 0xffffffff813015c0 <blk_mq_map_queue>,
...snip...
complete = 0xffffffffc00a4370 <floppy_module_init+575>,
init_request = 0xffffffffc00a4260 <floppy_module_init+303>,
...snip...
}
With the patch:
crash> mod -S
crash> struct blk_mq_ops 0xffffffffc00a7160
struct blk_mq_ops {
queue_rq = 0xffffffffc00a45b0 <virtio_queue_rq>, <-- symbol translated from
module virtio_blk
map_queue = 0xffffffff813015c0 <blk_mq_map_queue>,
...snip...
complete = 0xffffffffc00a4370 <virtblk_request_done>,
init_request = 0xffffffffc00a4260 <virtblk_init_request>,
...snip...
}
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
defs.h | 2 ++
gdb-10.2.patch | 37 ++++++++++++++++++++++++++++++++++++-
gdb_interface.c | 18 ++++++++++++++++++
3 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/defs.h b/defs.h
index 788f63a..09e6738 100644
--- a/defs.h
+++ b/defs.h
@@ -5130,6 +5130,7 @@ struct syment *symbol_search(char *);
int gdb_line_number_callback(ulong, ulong, ulong);
int gdb_print_callback(ulong);
char *gdb_lookup_module_symbol(ulong, ulong *);
+ulong gdb_get_module_boundary(const char *, bool);
extern "C" int same_file(char *, char *);
#endif
@@ -7687,6 +7688,7 @@ int gdb_readmem_callback(ulong, void *, int, int);
int gdb_line_number_callback(ulong, ulong, ulong);
int gdb_print_callback(ulong);
char *gdb_lookup_module_symbol(ulong, ulong *);
+ulong gdb_get_module_boundary(const char *, bool);
void gdb_error_hook(void);
void restore_gdb_sanity(void);
int is_gdb_command(int, ulong);
diff --git a/gdb-10.2.patch b/gdb-10.2.patch
index 31135ca..a5c10d3 100644
--- a/gdb-10.2.patch
+++ b/gdb-10.2.patch
@@ -3203,4 +3203,39 @@ exit 0
+#endif
for (compunit_symtab *cust : obj_file->compunits ())
{
- const struct block *b;
\ No newline at end of file
+ const struct block *b;
+--- gdb-10.2/gdb/symtab.c.orig
++++ gdb-10.2/gdb/symtab.c
+@@ -2895,6 +2895,10 @@ iterate_over_symbols_terminated
+ return callback (&block_sym);
+ }
+
++#ifdef CRASH_MERGE
++extern "C" ulong gdb_get_module_boundary(const char *, bool);
++#endif
++
+ /* Find the compunit symtab associated with PC and SECTION.
+ This will read in debug info as necessary. */
+
+@@ -2932,11 +2936,21 @@ find_pc_sect_compunit_symtab (CORE_ADDR pc, struct obj_section
*section)
+ for (objfile *obj_file : current_program_space->objfiles ())
+ {
+ #ifdef CRASH_MERGE
++ size_t sep;
+ std::string objfile_name = objfile_filename(obj_file);
++ const char *mod_name;
+
+ if (objfile_name.find(".ko") != std::string::npos) {
+ if (obj_file->sf && obj_file->compunit_symtabs == nullptr)
+ obj_file->sf->qf->expand_all_symtabs(obj_file);
++ sep = objfile_name.find_last_of("/");
++ objfile_name = objfile_name.substr(sep + 1, objfile_name.size() - sep - 1);
++ sep = objfile_name.find_first_of(".");
++ objfile_name = objfile_name.substr(0, sep);
++ mod_name = objfile_name.c_str();
++ if (pc < gdb_get_module_boundary(mod_name, true) ||
++ pc > gdb_get_module_boundary(mod_name, false))
++ continue;
+ }
+ #endif
+ for (compunit_symtab *cust : obj_file->compunits ())
diff --git a/gdb_interface.c b/gdb_interface.c
index b14319c..a58fd68 100644
--- a/gdb_interface.c
+++ b/gdb_interface.c
@@ -947,6 +947,24 @@ gdb_lookup_module_symbol(ulong addr, ulong *offset)
}
}
+ulong
+gdb_get_module_boundary(const char *module, bool is_start)
+{
+ char buf[256];
+ struct syment *sp;
+
+ if (is_start) {
+ snprintf(buf, sizeof(buf), "_MODULE_START_%s", module);
+ } else {
+ snprintf(buf, sizeof(buf), "_MODULE_END_%s", module);
+ }
+ sp = symbol_search(buf);
+ if (sp)
+ return sp->value;
+ else
+ return is_start ? 0 : (ulong)(-1);
+}
+
/*
* Used by gdb_interface() to catch gdb-related errors, if desired.
*/
--
2.40.1