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

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