|
|
acf3ec |
From 5948cb9b3e622e3c87216c7c6479f509c8aeb7c1 Mon Sep 17 00:00:00 2001
|
|
|
acf3ec |
From: Tao Liu <ltao@redhat.com>
|
|
|
acf3ec |
Date: Wed, 16 Nov 2022 17:36:03 +0800
|
|
|
acf3ec |
Subject: [PATCH 18/28] Let gdb get kernel module symbols info from crash
|
|
|
acf3ec |
|
|
|
acf3ec |
Gdb will try to resolve an address to its corresponding symbol name such as
|
|
|
acf3ec |
when printing a structure. It works fine for kernel symbols, because gdb can
|
|
|
acf3ec |
find them through vmlinux. However as for kernel modules symbols, crash
|
|
|
acf3ec |
resolves them by dig into "struct module", which gdb don't know. As a result,
|
|
|
acf3ec |
gdb fails to translate a kernel module address to its symbol name without
|
|
|
acf3ec |
"mod -s|-S" options. For example we can reproduce the issue as follows.
|
|
|
acf3ec |
|
|
|
acf3ec |
crash> timer
|
|
|
acf3ec |
....
|
|
|
acf3ec |
4331308176 336 ffff94ea24240860 ffffffffc03762c0 <estimation_timer>
|
|
|
acf3ec |
....
|
|
|
acf3ec |
crash> sym 0xffffffffc03762c0
|
|
|
acf3ec |
ffffffffc03762c0 (t) estimation_timer [ip_vs]
|
|
|
acf3ec |
|
|
|
acf3ec |
Before patch:
|
|
|
acf3ec |
crash> timer_list ffff94ea24240860
|
|
|
acf3ec |
struct timer_list {
|
|
|
acf3ec |
....
|
|
|
acf3ec |
function = 0xffffffffc03762c0,
|
|
|
acf3ec |
....
|
|
|
acf3ec |
}
|
|
|
acf3ec |
|
|
|
acf3ec |
After patch:
|
|
|
acf3ec |
crash> timer_list ffff94ea24240860
|
|
|
acf3ec |
struct timer_list {
|
|
|
acf3ec |
....
|
|
|
acf3ec |
function = 0xffffffffc03762c0 <estimation_timer>,
|
|
|
acf3ec |
....
|
|
|
acf3ec |
}
|
|
|
acf3ec |
|
|
|
acf3ec |
In this patch, we add an interface for gdb, when gdb trying to build kernel
|
|
|
acf3ec |
module's address symbolic, the info can be get from crash.
|
|
|
acf3ec |
|
|
|
acf3ec |
Signed-off-by: Tao Liu <ltao@redhat.com>
|
|
|
acf3ec |
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
|
|
acf3ec |
---
|
|
|
acf3ec |
defs.h | 2 ++
|
|
|
acf3ec |
gdb-7.6.patch | 33 +++++++++++++++++++++++++++++++++
|
|
|
acf3ec |
gdb_interface.c | 12 ++++++++++++
|
|
|
acf3ec |
3 files changed, 47 insertions(+)
|
|
|
acf3ec |
|
|
|
acf3ec |
diff --git a/defs.h b/defs.h
|
|
|
acf3ec |
index f8fbfdfd1152..b7d76330141a 100644
|
|
|
acf3ec |
--- a/defs.h
|
|
|
acf3ec |
+++ b/defs.h
|
|
|
acf3ec |
@@ -4877,6 +4877,7 @@ int patch_kernel_symbol(struct gnu_request *);
|
|
|
acf3ec |
struct syment *symbol_search(char *);
|
|
|
acf3ec |
int gdb_line_number_callback(ulong, ulong, ulong);
|
|
|
acf3ec |
int gdb_print_callback(ulong);
|
|
|
acf3ec |
+char *gdb_lookup_module_symbol(ulong, ulong *);
|
|
|
acf3ec |
#endif
|
|
|
acf3ec |
|
|
|
acf3ec |
#ifndef GDB_COMMON
|
|
|
acf3ec |
@@ -7291,6 +7292,7 @@ int gdb_pass_through(char *, FILE *, ulong);
|
|
|
acf3ec |
int gdb_readmem_callback(ulong, void *, int, int);
|
|
|
acf3ec |
int gdb_line_number_callback(ulong, ulong, ulong);
|
|
|
acf3ec |
int gdb_print_callback(ulong);
|
|
|
acf3ec |
+char *gdb_lookup_module_symbol(ulong, ulong *);
|
|
|
acf3ec |
void gdb_error_hook(void);
|
|
|
acf3ec |
void restore_gdb_sanity(void);
|
|
|
acf3ec |
int is_gdb_command(int, ulong);
|
|
|
acf3ec |
diff --git a/gdb-7.6.patch b/gdb-7.6.patch
|
|
|
acf3ec |
index c63ad7d81cb0..f1c3aa734241 100644
|
|
|
acf3ec |
--- a/gdb-7.6.patch
|
|
|
acf3ec |
+++ b/gdb-7.6.patch
|
|
|
acf3ec |
@@ -2568,3 +2568,36 @@ diff -up gdb-7.6/opcodes/configure.orig gdb-7.6/opcodes/configure
|
|
|
acf3ec |
$(CC_LD) $(INTERNAL_LDFLAGS) $(WIN32LDAPP) \
|
|
|
acf3ec |
-o $(shell /bin/cat mergeobj) $(LIBGDB_OBS) \
|
|
|
acf3ec |
$(TDEPLIBS) $(TUI_LIBRARY) $(CLIBS) $(LOADLIBES) $(shell /bin/cat mergelibs)
|
|
|
acf3ec |
+--- gdb-7.6/gdb/printcmd.c.orig
|
|
|
acf3ec |
++++ gdb-7.6/gdb/printcmd.c
|
|
|
acf3ec |
+@@ -622,6 +622,10 @@ print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr,
|
|
|
acf3ec |
+ return 1;
|
|
|
acf3ec |
+ }
|
|
|
acf3ec |
+
|
|
|
acf3ec |
++#ifdef CRASH_MERGE
|
|
|
acf3ec |
++extern char *gdb_lookup_module_symbol(unsigned long, unsigned long *);
|
|
|
acf3ec |
++#endif
|
|
|
acf3ec |
++
|
|
|
acf3ec |
+ /* Given an address ADDR return all the elements needed to print the
|
|
|
acf3ec |
+ address in a symbolic form. NAME can be mangled or not depending
|
|
|
acf3ec |
+ on DO_DEMANGLE (and also on the asm_demangle global variable,
|
|
|
acf3ec |
+@@ -710,7 +714,19 @@ build_address_symbolic (struct gdbarch *gdbarch,
|
|
|
acf3ec |
+ }
|
|
|
acf3ec |
+ }
|
|
|
acf3ec |
+ if (symbol == NULL && msymbol == NULL)
|
|
|
acf3ec |
++#ifdef CRASH_MERGE
|
|
|
acf3ec |
++ {
|
|
|
acf3ec |
++ char *name_ptr = gdb_lookup_module_symbol(addr, (unsigned long *)offset);
|
|
|
acf3ec |
++ if (name_ptr) {
|
|
|
acf3ec |
++ *name = xstrdup (name_ptr);
|
|
|
acf3ec |
++ return 0;
|
|
|
acf3ec |
++ } else {
|
|
|
acf3ec |
++ return 1;
|
|
|
acf3ec |
++ }
|
|
|
acf3ec |
++ }
|
|
|
acf3ec |
++#else
|
|
|
acf3ec |
+ return 1;
|
|
|
acf3ec |
++#endif
|
|
|
acf3ec |
+
|
|
|
acf3ec |
+ /* If the nearest symbol is too far away, don't print anything symbolic. */
|
|
|
acf3ec |
+
|
|
|
acf3ec |
diff --git a/gdb_interface.c b/gdb_interface.c
|
|
|
acf3ec |
index 1f10006a2d63..f9d0018998df 100644
|
|
|
acf3ec |
--- a/gdb_interface.c
|
|
|
acf3ec |
+++ b/gdb_interface.c
|
|
|
acf3ec |
@@ -945,6 +945,18 @@ gdb_print_callback(ulong addr)
|
|
|
acf3ec |
return IS_KVADDR(addr);
|
|
|
acf3ec |
}
|
|
|
acf3ec |
|
|
|
acf3ec |
+char *
|
|
|
acf3ec |
+gdb_lookup_module_symbol(ulong addr, ulong *offset)
|
|
|
acf3ec |
+{
|
|
|
acf3ec |
+ struct syment *sp;
|
|
|
acf3ec |
+
|
|
|
acf3ec |
+ if ((sp = value_search_module(addr, offset))) {
|
|
|
acf3ec |
+ return sp->name;
|
|
|
acf3ec |
+ } else {
|
|
|
acf3ec |
+ return NULL;
|
|
|
acf3ec |
+ }
|
|
|
acf3ec |
+}
|
|
|
acf3ec |
+
|
|
|
acf3ec |
/*
|
|
|
acf3ec |
* Used by gdb_interface() to catch gdb-related errors, if desired.
|
|
|
acf3ec |
*/
|
|
|
acf3ec |
--
|
|
|
acf3ec |
2.37.1
|
|
|
acf3ec |
|