[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