[PATCH] makedumpfile: Add support to module symbols

Aravinda Prasad aravinda at linux.vnet.ibm.com
Mon Mar 11 04:26:21 EDT 2013


Current version of makedumpfile/eppic integration patches
works only for symbols in vmlinux. This patch adds support
to module symbols.

I have tested the patch on dynamically linked version of
makedumpfile with EPPIC_LEGACY_MODE=1. However it should
work on non-legacy mode also.

Signed-off-by: Aravinda Prasad <aravinda at linux.vnet.ibm.com>
Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
---
 erase_info.c      |  115 +++++++++++++++++++++++++++++++++++++++++++++++------
 erase_info.h      |    4 +-
 extension_eppic.c |    3 +
 extension_eppic.h |    2 -
 4 files changed, 109 insertions(+), 15 deletions(-)

diff --git a/erase_info.c b/erase_info.c
index 61fe637..2fa8387 100644
--- a/erase_info.c
+++ b/erase_info.c
@@ -35,7 +35,7 @@ struct call_back eppic_cb = {
 	&get_die_length,
 	&get_die_member,
 	&get_die_nfields,
-	&get_symbol_addr,
+	&get_symbol_addr_all,
 	&update_filter_info_raw
 };
 
@@ -161,13 +161,27 @@ get_loaded_module(char *mod_name)
 	return &modules[mod_st.current_mod];
 }
 
+static unsigned long long
+find_module_symbol(struct module_info *module_ptr, char *symname)
+{
+	int i;
+	struct symbol_info *sym_info;
+
+	sym_info = module_ptr->sym_info;
+	if (!sym_info)
+		return FALSE;
+	for (i = 1; i < module_ptr->num_syms; i++) {
+		if (sym_info[i].name && !strcmp(sym_info[i].name, symname))
+			return sym_info[i].value;
+	}
+	return NOT_FOUND_SYMBOL;
+}
+
 static int
 sym_in_module(char *symname, unsigned long long *symbol_addr)
 {
-	int i;
 	char *module_name;
 	struct module_info *module_ptr;
-	struct symbol_info *sym_info;
 
 	module_name = get_dwarf_module_name();
 	if (!mod_st.num_modules
@@ -178,16 +192,11 @@ sym_in_module(char *symname, unsigned long long *symbol_addr)
 	module_ptr = get_loaded_module(module_name);
 	if (!module_ptr)
 		return FALSE;
-	sym_info = module_ptr->sym_info;
-	if (!sym_info)
+	*symbol_addr = find_module_symbol(module_ptr, symname);
+	if (*symbol_addr == NOT_FOUND_SYMBOL)
 		return FALSE;
-	for (i = 1; i < module_ptr->num_syms; i++) {
-		if (sym_info[i].name && !strcmp(sym_info[i].name, symname)) {
-			*symbol_addr = sym_info[i].value;
-			return TRUE;
-		}
-	}
-	return FALSE;
+	else
+		return TRUE;
 }
 
 static unsigned int
@@ -1858,6 +1867,88 @@ process_config_file(const char *name_config)
 	return TRUE;
 }
 
+/*
+ * Search for symbol in modules as well as vmlinux
+ */
+unsigned long long
+get_symbol_addr_all(char *name) {
+
+	short vmlinux_searched = 0;
+	unsigned long long symbol_addr = 0;
+	unsigned int i, current_mod;
+	struct module_info *modules;
+
+	/* Search in vmlinux if debuginfo is set to vmlinux */
+	if (!strcmp(get_dwarf_module_name(), "vmlinux")) {
+		symbol_addr = get_symbol_addr(name);
+		if (symbol_addr)
+			return symbol_addr;
+
+		vmlinux_searched = 1;
+	}
+
+	/*
+	 * Proceed the search in modules. Try in the module
+	 * which resulted in a hit in the previous search
+	 */
+
+	modules = mod_st.modules;
+	current_mod = mod_st.current_mod;
+
+	if (strcmp(get_dwarf_module_name(), modules[current_mod].name)) {
+		if (!set_dwarf_debuginfo(modules[current_mod].name,
+				info->system_utsname.release, NULL, -1)) {
+			ERRMSG("Cannot set to current module %s\n",
+					modules[current_mod].name);
+			return NOT_FOUND_SYMBOL;
+		}
+	}
+
+	symbol_addr = find_module_symbol(&modules[current_mod], name);
+	if (symbol_addr)
+		return symbol_addr;
+
+	/* Search in all modules */
+	for (i = 0; i < mod_st.num_modules; i++) {
+
+		/* Already searched. Skip */
+		if (i == current_mod)
+			continue;
+
+		if (!set_dwarf_debuginfo(modules[i].name,
+				info->system_utsname.release, NULL, -1)) {
+			ERRMSG("Skipping Module section %s\n", modules[i].name);
+			continue;
+		}
+
+		symbol_addr = find_module_symbol(&modules[i], name);
+
+		if (!symbol_addr)
+			continue;
+
+		/*
+		 * Symbol found. Set the current_mod to this module index, a
+		 * minor optimization for fast lookup next time
+		 */
+		mod_st.current_mod = i;
+		return symbol_addr;
+	}
+
+	/* Symbol not found in any module. Set debuginfo back to vmlinux  */
+	set_dwarf_debuginfo("vmlinux", NULL, info->name_vmlinux,
+			info->fd_vmlinux);
+
+	/*
+	 * Search vmlinux if not already searched. This can happen when
+	 * this function is called with debuginfo set to a particular
+	 * kernel module and we are looking for symbol in vmlinux
+	 */
+	if (!vmlinux_searched)
+		return get_symbol_addr(name);
+	else
+		return NOT_FOUND_SYMBOL;
+}
+
 
 /* Process the eppic macro using eppic library */
 static int
diff --git a/erase_info.h b/erase_info.h
index 1822034..b1a8895 100644
--- a/erase_info.h
+++ b/erase_info.h
@@ -31,6 +31,8 @@ struct erase_info {
 	int		erased;		/* 1= erased, 0= Not erased */
 };
 
+unsigned long long get_symbol_addr_all(char *);
+
 struct call_back {
     long (*get_domain)(char *, int, unsigned long long *);
     int (*readmem)(int type_addr, unsigned long long addr, void *bufptr,
@@ -43,7 +45,7 @@ struct call_back {
     int (*get_die_member)(unsigned long long die_off, int index, long *offset,
             char **name, int *nbits, int *fbits, unsigned long long *m_die);
     int (*get_die_nfields)(unsigned long long die_off);
-    unsigned long long (*get_symbol_addr)(char *symname);
+	unsigned long long (*get_symbol_addr_all)(char *symname);
     int (*update_filter_info_raw)(unsigned long long, int, int);
 };
 
diff --git a/extension_eppic.c b/extension_eppic.c
index e8591fd..a1981eb 100644
--- a/extension_eppic.c
+++ b/extension_eppic.c
@@ -307,7 +307,8 @@ apigetval(char *name, ull *val, VALUE_S *value)
 {
 	ull ptr = 0;
 
-	ptr = GET_SYMBOL_ADDR(name);
+	ptr = GET_SYMBOL_ADDR_ALL(name);
+
 	if (!ptr)
 		return 0;
 
diff --git a/extension_eppic.h b/extension_eppic.h
index 6edc318..caa44dc 100644
--- a/extension_eppic.h
+++ b/extension_eppic.h
@@ -89,7 +89,7 @@ struct call_back *cb;
 #define GET_DIE_LENGTH cb->get_die_length
 #define GET_DIE_MEMBER cb->get_die_member
 #define GET_DIE_NFIELDS cb->get_die_nfields
-#define GET_SYMBOL_ADDR cb->get_symbol_addr
+#define GET_SYMBOL_ADDR_ALL cb->get_symbol_addr_all
 #define UPDATE_FILTER_INFO_RAW cb->update_filter_info_raw
 
 #endif /* _EXTENSION_EPPIC_H */




More information about the kexec mailing list