[PATCH v2 3/8] makedumpfile: Load the module symbol data from vmcore.
Ken'ichi Ohmichi
oomichi at mxs.nes.nec.co.jp
Fri Jul 29 05:42:08 EDT 2011
Hi Mahesh,
This patch is almost good, and there are some cleanup points and
error-handling points.
On Wed, 18 May 2011 01:31:53 +0530
Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote:
>
> This patch enables makedumpfile to load module symbol data from vmcore. This
> info is required during kernel module data filtering process. Traverse the
> modules list and load all module's symbol info data in the memory for fast
> lookup.
[..]
> +static int
> +load_module_symbols(void)
> +{
> + unsigned long head, cur, cur_module;
> + unsigned long symtab, strtab;
> + unsigned long mod_base, mod_init;
> + unsigned int mod_size, mod_init_size;
> + unsigned char *module_struct_mem, *module_core_mem;
> + unsigned char *module_init_mem = NULL;
> + unsigned char *symtab_mem;
> + char *module_name, *strtab_mem, *nameptr;
> + struct module_info *modules = NULL;
> + struct symbol_info *sym_info;
> + unsigned int num_symtab;
> + unsigned int i = 0, nsym;
> +
> + head = SYMBOL(modules);
> + if (!get_num_modules(head, &mod_st.num_modules)) {
> + ERRMSG("Can't get module count\n");
> + return FALSE;
> + }
> + if (!mod_st.num_modules) {
> + return FALSE;
If the above num_modules is 0, makedumpfile fails without any hint
message. How about the below change ?
@@ -7651,13 +7651,11 @@ load_module_symbols(void)
unsigned int i = 0, nsym;
head = SYMBOL(modules);
- if (!get_num_modules(head, &mod_st.num_modules)) {
+ if (!get_num_modules(head, &mod_st.num_modules) ||
+ !mod_st.num_modules) {
ERRMSG("Can't get module count\n");
return FALSE;
}
- if (!mod_st.num_modules) {
- return FALSE;
- }
mod_st.modules = calloc(mod_st.num_modules,
sizeof(struct module_info));
if (!mod_st.modules) {
---
[..]
> + /* Travese the list and read module symbols */
> + while (cur != head) {
[..]
> + if (mod_init_size > 0) {
> + module_init_mem = calloc(1, mod_init_size);
> + if (module_init_mem == NULL) {
> + ERRMSG("Can't allocate memory for module "
> + "init\n");
> + return FALSE;
> + }
> + if (!readmem(VADDR, mod_init, module_init_mem,
> + mod_init_size)) {
> + ERRMSG("Can't access module init in memory.\n");
> + return FALSE;
In the above error case, module_init_mem should be freed.
There are the same lacks of free, and I feel it is due to
a large load_module_symbols() function.
Hence I created the attached patch for making the function
small and fixing the lacks of free.
Can you review it ?
> + if (mod_init_size > 0)
> + free(module_init_mem);
> + } while (cur != head);
This is the same as the begining of this loop, and it is not necessary.
Thanks
Ken'ichi Ohmichi
---
diff --git a/makedumpfile.c b/makedumpfile.c
index 3ad2bd5..92ca23b 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -7635,20 +7635,160 @@ clean_module_symbols(void)
}
static int
-load_module_symbols(void)
+__load_module_symbol(struct module_info *modules, unsigned long addr_module)
{
- unsigned long head, cur, cur_module;
+ int ret = FALSE;
+ unsigned int nsym;
unsigned long symtab, strtab;
unsigned long mod_base, mod_init;
unsigned int mod_size, mod_init_size;
- unsigned char *module_struct_mem, *module_core_mem;
+ unsigned char *module_struct_mem = NULL;
+ unsigned char *module_core_mem = NULL;
unsigned char *module_init_mem = NULL;
unsigned char *symtab_mem;
char *module_name, *strtab_mem, *nameptr;
- struct module_info *modules = NULL;
- struct symbol_info *sym_info;
unsigned int num_symtab;
- unsigned int i = 0, nsym;
+
+ /* Allocate buffer to read struct module data from vmcore. */
+ if ((module_struct_mem = calloc(1, SIZE(module))) == NULL) {
+ ERRMSG("Failed to allocate buffer for module\n");
+ return FALSE;
+ }
+ if (!readmem(VADDR, addr_module, module_struct_mem,
+ SIZE(module))) {
+ ERRMSG("Can't get module info.\n");
+ goto out;
+ }
+
+ module_name = (char *)(module_struct_mem + OFFSET(module.name));
+ if (strlen(module_name) < MOD_NAME_LEN)
+ strcpy(modules->name, module_name);
+ else
+ strncpy(modules->name, module_name, MOD_NAME_LEN-1);
+
+ mod_init = ULONG(module_struct_mem +
+ OFFSET(module.module_init));
+ mod_init_size = UINT(module_struct_mem +
+ OFFSET(module.init_size));
+ mod_base = ULONG(module_struct_mem +
+ OFFSET(module.module_core));
+ mod_size = UINT(module_struct_mem +
+ OFFSET(module.core_size));
+
+ DEBUG_MSG("Module: %s, Base: 0x%lx, Size: %u\n",
+ module_name, mod_base, mod_size);
+ if (mod_init_size > 0) {
+ module_init_mem = calloc(1, mod_init_size);
+ if (module_init_mem == NULL) {
+ ERRMSG("Can't allocate memory for module "
+ "init\n");
+ goto out;
+ }
+ if (!readmem(VADDR, mod_init, module_init_mem,
+ mod_init_size)) {
+ ERRMSG("Can't access module init in memory.\n");
+ goto out;
+ }
+ }
+
+ if ((module_core_mem = calloc(1, mod_size)) == NULL) {
+ ERRMSG("Can't allocate memory for module\n");
+ goto out;
+ }
+ if (!readmem(VADDR, mod_base, module_core_mem, mod_size)) {
+ ERRMSG("Can't access module in memory.\n");
+ goto out;
+ }
+
+ num_symtab = UINT(module_struct_mem +
+ OFFSET(module.num_symtab));
+ if (!num_symtab) {
+ ERRMSG("%s: Symbol info not available\n", module_name);
+ goto out;
+ }
+ modules->num_syms = num_symtab;
+ DEBUG_MSG("num_sym: %d\n", num_symtab);
+
+ symtab = ULONG(module_struct_mem + OFFSET(module.symtab));
+ strtab = ULONG(module_struct_mem + OFFSET(module.strtab));
+
+ /* check if symtab and strtab are inside the module space. */
+ if (!IN_RANGE(symtab, mod_base, mod_size) &&
+ !IN_RANGE(symtab, mod_init, mod_init_size)) {
+ ERRMSG("%s: module symtab is outseide of module "
+ "address space\n", module_name);
+ goto out;
+ }
+ if (IN_RANGE(symtab, mod_base, mod_size))
+ symtab_mem = module_core_mem + (symtab - mod_base);
+ else
+ symtab_mem = module_init_mem + (symtab - mod_init);
+
+ if (!IN_RANGE(strtab, mod_base, mod_size) &&
+ !IN_RANGE(strtab, mod_init, mod_init_size)) {
+ ERRMSG("%s: module strtab is outseide of module "
+ "address space\n", module_name);
+ goto out;
+ }
+ if (IN_RANGE(strtab, mod_base, mod_size))
+ strtab_mem = (char *)(module_core_mem
+ + (strtab - mod_base));
+ else
+ strtab_mem = (char *)(module_init_mem
+ + (strtab - mod_init));
+
+ modules->sym_info = calloc(num_symtab, sizeof(struct symbol_info));
+ if (modules->sym_info == NULL) {
+ ERRMSG("Can't allocate memory to store sym info\n");
+ goto out;
+ }
+
+ /* symbols starts from 1 */
+ for (nsym = 1; nsym < num_symtab; nsym++) {
+ Elf32_Sym *sym32;
+ Elf64_Sym *sym64;
+ /* If case of ELF vmcore then the word size can be
+ * determined using info->flag_elf64_memory flag.
+ * But in case of kdump-compressed dump, kdump header
+ * does not carry word size info. May be in future
+ * this info will be available in kdump header.
+ * Until then, in order to make this logic work on both
+ * situation we depend on pointer_size that is
+ * extracted from vmlinux dwarf information.
+ */
+ if ((pointer_size * 8) == 64) {
+ sym64 = (Elf64_Sym *) (symtab_mem
+ + (nsym * sizeof(Elf64_Sym)));
+ modules->sym_info[nsym].value =
+ (unsigned long long) sym64->st_value;
+ nameptr = strtab_mem + sym64->st_name;
+ } else {
+ sym32 = (Elf32_Sym *) (symtab_mem
+ + (nsym * sizeof(Elf32_Sym)));
+ modules->sym_info[nsym].value =
+ (unsigned long long) sym32->st_value;
+ nameptr = strtab_mem + sym32->st_name;
+ }
+ if (strlen(nameptr))
+ modules->sym_info[nsym].name = strdup(nameptr);
+ DEBUG_MSG("\t[%d] %llx %s\n", nsym,
+ modules->sym_info[nsym].value, nameptr);
+ }
+ ret = TRUE;
+out:
+ free(module_struct_mem);
+ free(module_core_mem);
+ free(module_init_mem);
+
+ return ret;
+}
+
+static int
+load_module_symbols(void)
+{
+ unsigned long head, cur, cur_module;
+ struct module_info *modules = NULL;
+ unsigned int i = 0;
head = SYMBOL(modules);
if (!get_num_modules(head, &mod_st.num_modules) ||
@@ -7664,12 +7804,6 @@ load_module_symbols(void)
}
modules = mod_st.modules;
- /* Allocate buffer to read struct module data from vmcore. */
- if ((module_struct_mem = calloc(1, SIZE(module))) == NULL) {
- ERRMSG("Failed to allocate buffer for module\n");
- return FALSE;
- }
-
if (!readmem(VADDR, head + OFFSET(list_head.next), &cur, sizeof cur)) {
ERRMSG("Can't get next list_head.\n");
return FALSE;
@@ -7678,129 +7812,9 @@ load_module_symbols(void)
/* Travese the list and read module symbols */
while (cur != head) {
cur_module = cur - OFFSET(module.list);
- if (!readmem(VADDR, cur_module, module_struct_mem,
- SIZE(module))) {
- ERRMSG("Can't get module info.\n");
- return FALSE;
- }
-
- module_name = (char *)(module_struct_mem + OFFSET(module.name));
- if (strlen(module_name) < MOD_NAME_LEN)
- strcpy(modules[i].name, module_name);
- else
- strncpy(modules[i].name, module_name, MOD_NAME_LEN-1);
-
- mod_init = ULONG(module_struct_mem +
- OFFSET(module.module_init));
- mod_init_size = UINT(module_struct_mem +
- OFFSET(module.init_size));
- mod_base = ULONG(module_struct_mem +
- OFFSET(module.module_core));
- mod_size = UINT(module_struct_mem +
- OFFSET(module.core_size));
-
- DEBUG_MSG("Module: %s, Base: 0x%lx, Size: %u\n",
- module_name, mod_base, mod_size);
- if (mod_init_size > 0) {
- module_init_mem = calloc(1, mod_init_size);
- if (module_init_mem == NULL) {
- ERRMSG("Can't allocate memory for module "
- "init\n");
- return FALSE;
- }
- if (!readmem(VADDR, mod_init, module_init_mem,
- mod_init_size)) {
- ERRMSG("Can't access module init in memory.\n");
- return FALSE;
- }
- }
- if ((module_core_mem = calloc(1, mod_size)) == NULL) {
- ERRMSG("Can't allocate memory for module\n");
+ if (!__load_module_symbol(&modules[i], cur_module))
return FALSE;
- }
- if (!readmem(VADDR, mod_base, module_core_mem, mod_size)) {
- ERRMSG("Can't access module in memory.\n");
- return FALSE;
- }
-
- num_symtab = UINT(module_struct_mem +
- OFFSET(module.num_symtab));
- if (!num_symtab) {
- ERRMSG("%s: Symbol info not available\n", module_name);
- return FALSE;
- }
- modules[i].num_syms = num_symtab;
- DEBUG_MSG("num_sym: %d\n", num_symtab);
-
- symtab = ULONG(module_struct_mem + OFFSET(module.symtab));
- strtab = ULONG(module_struct_mem + OFFSET(module.strtab));
-
- /* check if symtab and strtab are inside the module space. */
- if (!IN_RANGE(symtab, mod_base, mod_size) &&
- !IN_RANGE(symtab, mod_init, mod_init_size)) {
- ERRMSG("%s: module symtab is outseide of module "
- "address space\n", module_name);
- return FALSE;
- }
- if (IN_RANGE(symtab, mod_base, mod_size))
- symtab_mem = module_core_mem + (symtab - mod_base);
- else
- symtab_mem = module_init_mem + (symtab - mod_init);
-
- if (!IN_RANGE(strtab, mod_base, mod_size) &&
- !IN_RANGE(strtab, mod_init, mod_init_size)) {
- ERRMSG("%s: module strtab is outseide of module "
- "address space\n", module_name);
- return FALSE;
- }
- if (IN_RANGE(strtab, mod_base, mod_size))
- strtab_mem = (char *)(module_core_mem
- + (strtab - mod_base));
- else
- strtab_mem = (char *)(module_init_mem
- + (strtab - mod_init));
-
- modules[i].sym_info = calloc(num_symtab,
- sizeof(struct symbol_info));
- if (modules[i].sym_info == NULL) {
- ERRMSG("Can't allocate memory to store sym info\n");
- return FALSE;
- }
- sym_info = modules[i].sym_info;
-
- /* symbols starts from 1 */
- for (nsym = 1; nsym < num_symtab; nsym++) {
- Elf32_Sym *sym32;
- Elf64_Sym *sym64;
- /* If case of ELF vmcore then the word size can be
- * determined using info->flag_elf64_memory flag.
- * But in case of kdump-compressed dump, kdump header
- * does not carry word size info. May be in future
- * this info will be available in kdump header.
- * Until then, in order to make this logic work on both
- * situation we depend on pointer_size that is
- * extracted from vmlinux dwarf information.
- */
- if ((pointer_size * 8) == 64) {
- sym64 = (Elf64_Sym *) (symtab_mem
- + (nsym * sizeof(Elf64_Sym)));
- sym_info[nsym].value =
- (unsigned long long) sym64->st_value;
- nameptr = strtab_mem + sym64->st_name;
- }
- else {
- sym32 = (Elf32_Sym *) (symtab_mem
- + (nsym * sizeof(Elf32_Sym)));
- sym_info[nsym].value =
- (unsigned long long) sym32->st_value;
- nameptr = strtab_mem + sym32->st_name;
- }
- if (strlen(nameptr))
- sym_info[nsym].name = strdup(nameptr);
- DEBUG_MSG("\t[%d] %llx %s\n", nsym,
- sym_info[nsym].value, nameptr);
- }
if (!readmem(VADDR, cur + OFFSET(list_head.next),
&cur, sizeof cur)) {
@@ -7808,11 +7822,7 @@ load_module_symbols(void)
return FALSE;
}
i++;
- free(module_core_mem);
- if (mod_init_size > 0)
- free(module_init_mem);
} while (cur != head);
- free(module_struct_mem);
return TRUE;
}
More information about the kexec
mailing list