Blame SOURCES/0018-Let-gdb-get-kernel-module-symbols-info-from-crash.patch

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