----- "Dave Anderson" <anderson@xxxxxxxxxx> wrote: > ----- "Toshikazu Nakayama" <nakayama.ts@xxxxxxxxxxxxxx> wrote: > > > > I'll fix remained problems and send next patch with updated portion only. > > I would like to follow your advisement. > > OK, I'll take a look. > > Thanks, > Dave Hello Toshi, I made several changes to your last patch as we discussed before, and successfully tested it on the x86, x86_64, ia64, s390 and s390x architectures. I've attached the patch as it is queued for the next release. Because I was working against my own updated tree, the patch also contains a couple other symbol-handling related changes that are also queued for the next release. Thanks for getting the ball rolling for this feature, Dave
--- crash-5.0.9/help.c 2010-11-12 15:34:12.000000000 -0500 +++ crash/help.c 2010-11-11 16:46:40.000000000 -0500 @@ -1479,11 +1479,11 @@ char *help_bt[] = { " START: schedule at c01190e0", " [c1aa1f28] dput at c0157dbc", " [c1aa1f4c] schedule_timeout at c0124cd4", -" [c1aa1f78] svc_recv at cb22c4d8", +" [c1aa1f78] svc_recv at cb22c4d8 [sunrpc]", " [c1aa1f98] put_files_struct at c011eb21", -" [c1aa1fcc] nlmclnt_proc at cb237bef", +" [c1aa1fcc] nlmclnt_proc at cb237bef [lockd]", " [c1aa1ff0] kernel_thread at c0105826", -" [c1aa1ff8] nlmclnt_proc at cb237a60", +" [c1aa1ff8] nlmclnt_proc at cb237a60 [lockd]", " ", " Search the current stack for possible exception frames:\n", " %s> bt -e", @@ -1529,7 +1529,7 @@ char *help_bt[] = { " EAX: 00000013 EBX: cb297000 ECX: 00000000 EDX: c5962000 EBP: c74dff28", " DS: 0018 ESI: 00000000 ES: 0018 EDI: 00000000", " CS: 0010 EIP: cb297076 ERR: ffffffff EFLAGS: 00010282", -" #3 [c74dff1c] crash_init at cb297076", +" #3 [c74dff1c] crash_init at cb297076 [crash]", " #4 [c74dff2c] sys_init_module at c011d233", " #5 [c74dffc0] system_call at c0107154", " EAX: 00000080 EBX: 08060528 ECX: 08076450 EDX: 0000000a", @@ -4671,6 +4671,10 @@ char *help_sym[] = { " -q string searches for all symbols containing \"string\".", " symbol a kernel text or data symbol.", " vaddr a kernel virtual address.", +" ", +" If the \"symbol\", \"vaddr\" or \"string\" argument resolves to a module", +" symbol, then the module name will be displayed in brackets following the", +" symbol value.", "\nEXAMPLES", " Translate data symbol jiffies to its value, and vice-versa:\n", " %s> sym jiffies", @@ -4781,6 +4785,10 @@ char *help_sym[] = { " c023027c (D) prof_shift", " c0230280 (D) jiffies ", " c02302a0 (D) task", +"\n Translate a symbol value to its name and module:\n", +" crash> sym f88878d1", +" f88878d1 (t) ext3_readdir [ext3]", +" crash>", NULL }; --- crash-5.0.9/kernel.c 2010-11-12 15:34:12.000000000 -0500 +++ crash/kernel.c 2010-11-11 16:46:43.000000000 -0500 @@ -2083,6 +2083,7 @@ print_stack_text_syms(struct bt_info *bt ulong next_sp, next_pc; int i; ulong *up; + struct load_module *lm; char buf[BUFSIZE]; if (bt->flags & BT_TEXT_SYMBOLS) { @@ -2107,8 +2108,8 @@ print_stack_text_syms(struct bt_info *bt } if (is_kernel_text(*up) && (bt->flags & (BT_TEXT_SYMBOLS|BT_TEXT_SYMBOLS_PRINT))) { - if (bt->flags & (BT_ERROR_MASK|BT_TEXT_SYMBOLS)) - fprintf(fp, " %s[%s] %s at %lx\n", + if (bt->flags & (BT_ERROR_MASK|BT_TEXT_SYMBOLS)) { + fprintf(fp, " %s[%s] %s at %lx", bt->flags & BT_ERROR_MASK ? " " : "", mkstring(buf, VADDR_PRLEN, @@ -2116,7 +2117,10 @@ print_stack_text_syms(struct bt_info *bt MKSTR(bt->stackbase + (i * sizeof(long)))), closest_symbol(*up), *up); - else + if (module_symbol(*up, NULL, &lm, NULL, 0)) + fprintf(fp, " [%s]", lm->mod_name); + fprintf(fp, "\n"); + } else fprintf(fp, "%lx: %s\n", bt->stackbase + (i * sizeof(long)), @@ -2694,6 +2698,7 @@ module_init(void) MEMBER_OFFSET_INIT(module_init_size, "module", "init_size"); MEMBER_OFFSET_INIT(module_init_text_size, "module", "init_text_size"); + MEMBER_OFFSET_INIT(module_percpu, "module", "percpu"); /* * Make sure to pick the kernel "modules" list_head symbol, --- crash-5.0.9/alpha.c 2010-11-12 15:34:12.000000000 -0500 +++ crash/alpha.c 2010-11-08 09:52:07.000000000 -0500 @@ -1,8 +1,8 @@ /* alpha.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2010 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2010 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -589,6 +589,8 @@ alpha_print_stack_entry(struct gnu_reque ulong flags, struct bt_info *bt) { + struct load_module *lm; + if (BT_REFERENCE_CHECK(bt)) { switch (bt->ref->cmdflags & (BT_REF_SYMBOL|BT_REF_HEXVAL)) { @@ -606,10 +608,13 @@ alpha_print_stack_entry(struct gnu_reque break; } } else { - fprintf(fp, "%s#%d [%lx] %s at %lx\n", + fprintf(fp, "%s#%d [%lx] %s at %lx", req->curframe < 10 ? " " : "", req->curframe, req->sp, STREQ(name, "strace") ? "strace (via entSys)" : name, callpc); + if (module_symbol(callpc, NULL, &lm, NULL, 0)) + fprintf(fp, " [%s]", lm->mod_name); + fprintf(fp, "\n"); } if (!(flags & BT_SPECULATE)) --- crash-5.0.9/ppc.c 2010-11-12 15:34:12.000000000 -0500 +++ crash/ppc.c 2010-11-08 09:52:46.000000000 -0500 @@ -1,8 +1,8 @@ /* ppc.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2010 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2010 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -843,6 +843,8 @@ ppc_print_stack_entry(int frame, char *name, struct bt_info *bt) { + struct load_module *lm; + if (BT_REFERENCE_CHECK(bt)) { switch (bt->ref->cmdflags & (BT_REF_SYMBOL|BT_REF_HEXVAL)) { @@ -857,9 +859,12 @@ ppc_print_stack_entry(int frame, break; } } else { - fprintf(fp, "%s#%d [%lx] %s at %lx\n", + fprintf(fp, "%s#%d [%lx] %s at %lx", frame < 10 ? " " : "", frame, req->sp, name, callpc); + if (module_symbol(callpc, NULL, &lm, NULL, 0)) + fprintf(fp, " [%s]", lm->mod_name); + fprintf(fp, "\n"); } if (bt->flags & BT_SAVE_LASTSP) --- crash-5.0.9/s390.c 2010-11-12 15:34:12.000000000 -0500 +++ crash/s390.c 2010-11-05 16:25:36.000000000 -0400 @@ -663,6 +663,7 @@ s390_back_trace_cmd(struct bt_info *bt) backchain = ksp; do { unsigned long r14_stack_off; + struct load_module *lm; int j; /* Find stack: Either async, panic stack or task stack */ @@ -697,7 +698,10 @@ s390_back_trace_cmd(struct bt_info *bt) skip_first_frame=0; } else { fprintf(fp," #%i [%08lx] ",i,backchain); - fprintf(fp,"%s at %x\n", closest_symbol(r14), r14); + fprintf(fp,"%s at %x", closest_symbol(r14), r14); + if (module_symbol(r14, NULL, &lm, NULL, 0)) + fprintf(fp, " [%s]", lm->mod_name); + fprintf(fp, "\n"); if (bt->flags & BT_LINE_NUMBERS) s390_dump_line_number(r14); i++; --- crash-5.0.9/s390x.c 2010-11-12 15:34:12.000000000 -0500 +++ crash/s390x.c 2010-11-05 16:48:56.000000000 -0400 @@ -896,6 +896,7 @@ s390x_back_trace_cmd(struct bt_info *bt) backchain = ksp; do { unsigned long r14_stack_off; + struct load_module *lm; int j; /* Find stack: Either async, panic stack or task stack */ @@ -930,7 +931,10 @@ s390x_back_trace_cmd(struct bt_info *bt) skip_first_frame=0; } else { fprintf(fp," #%i [%08lx] ",i,backchain); - fprintf(fp,"%s at %lx\n", closest_symbol(r14), r14); + fprintf(fp,"%s at %lx", closest_symbol(r14), r14); + if (module_symbol(r14, NULL, &lm, NULL, 0)) + fprintf(fp, " [%s]", lm->mod_name); + fprintf(fp, "\n"); if (bt->flags & BT_LINE_NUMBERS) s390x_dump_line_number(r14); i++; --- crash-5.0.9/ppc64.c 2010-11-12 15:34:12.000000000 -0500 +++ crash/ppc64.c 2010-11-05 16:36:08.000000000 -0400 @@ -1561,6 +1561,7 @@ ppc64_print_stack_entry(int frame, ulong lr, struct bt_info *bt) { + struct load_module *lm; char *lrname = NULL; if (BT_REFERENCE_CHECK(bt)) { switch (bt->ref->cmdflags & (BT_REF_SYMBOL|BT_REF_HEXVAL)) @@ -1579,6 +1580,8 @@ ppc64_print_stack_entry(int frame, fprintf(fp, "%s#%d [%lx] %s at %lx", frame < 10 ? " " : "", frame, req->sp, req->name, req->pc); + if (module_symbol(req->pc, NULL, &lm, NULL, 0)) + fprintf(fp, " [%s]", lm->mod_name); if (req->ra) { /* --- crash-5.0.9/x86_64.c 2010-11-12 15:34:12.000000000 -0500 +++ crash/x86_64.c 2010-11-05 16:53:47.000000000 -0400 @@ -2407,6 +2407,7 @@ x86_64_print_stack_entry(struct bt_info int i, result; long eframe_check; char buf[BUFSIZE]; + struct load_module *lm; eframe_check = -1; if (!(bt->flags & BT_SAVE_EFRAME_IP)) @@ -2423,9 +2424,12 @@ x86_64_print_stack_entry(struct bt_info rsp = bt->stkptr; else rsp = bt->stackbase + (stkindex * sizeof(long)); - fprintf(ofp, " [%s] %s at %lx\n", + fprintf(ofp, " [%s] %s at %lx", mkstring(buf, VADDR_PRLEN, RJUST|LONG_HEX, MKSTR(rsp)), name, text); + if (module_symbol(text, NULL, &lm, NULL, 0)) + fprintf(ofp, " [%s]", lm->mod_name); + fprintf(ofp, "\n"); if (BT_REFERENCE_CHECK(bt)) x86_64_do_bt_reference_check(bt, text, name); return BACKTRACE_ENTRY_DISPLAYED; @@ -2501,6 +2505,8 @@ x86_64_print_stack_entry(struct bt_info (spl = value_search(locking_func, &offset))) fprintf(ofp, " (via %s)", spl->name); } + if (module_symbol(text, NULL, &lm, NULL, 0)) + fprintf(ofp, " [%s]", lm->mod_name); if (bt->flags & BT_FRAMESIZE_DISABLE) fprintf(ofp, " *"); --- crash-5.0.9/symbols.c 2010-11-12 15:34:12.000000000 -0500 +++ crash/symbols.c 2010-11-11 17:33:10.000000000 -0500 @@ -71,7 +71,9 @@ static void Elf32_Sym_to_common(Elf32_Sy static void Elf64_Sym_to_common(Elf64_Sym *, struct elf_common *); static void cmd_datatype_common(ulong); static int display_per_cpu_info(struct syment *); - +static struct load_module *get_module_percpu_sym_owner(struct syment *); +static int is_percpu_symbol(struct syment *); +static void dump_percpu_symbols(struct load_module *); #define KERNEL_SECTIONS (void *)(1) #define MODULE_SECTIONS (void *)(2) @@ -896,11 +898,14 @@ symname_hash_search(char *name) static void symbol_dump(ulong flags, char *module) { - int i; + int i, start, percpu_syms; struct syment *sp, *sp_end; struct load_module *lm; char *p1, *p2;; +#define TBD 1 +#define DISPLAYED 2 + if (flags & KERNEL_SYMS) { for (sp = st->symtable; sp < st->symend; sp++) show_symbol(sp, 0, SHOW_RADIX()); @@ -917,17 +922,41 @@ symbol_dump(ulong flags, char *module) sp = lm->mod_symtable; sp_end = lm->mod_symend; + percpu_syms = 0; + + for (start = FALSE; sp <= sp_end; sp++) { + + if (IN_MODULE_PERCPU(sp->value, lm)) { + if (percpu_syms == DISPLAYED) + continue; + if (!start) { + percpu_syms = TBD; + continue; + } + dump_percpu_symbols(lm); + percpu_syms = DISPLAYED; + } - for ( ; sp <= sp_end; sp++) { if (MODULE_PSEUDO_SYMBOL(sp)) { if (MODULE_START(sp)) { p1 = "MODULE START"; p2 = sp->name+strlen("_MODULE_START_"); + start = TRUE; } else { p1 = "MODULE END"; p2 = sp->name+strlen("_MODULE_END_"); + if (MODULE_PERCPU_SYMS_LOADED(lm) && + !percpu_syms) { + dump_percpu_symbols(lm); + percpu_syms = DISPLAYED; + } } fprintf(fp, "%lx %s: %s\n", sp->value, p1, p2); + + if (percpu_syms == TBD) { + dump_percpu_symbols(lm); + percpu_syms = DISPLAYED; + } } else show_symbol(sp, 0, SHOW_RADIX()); } @@ -950,7 +979,23 @@ symbol_dump(ulong flags, char *module) show_symbol(sp, 0, SHOW_RADIX()); } } + } +#undef TBD +#undef DISPLAYED +} + +static void +dump_percpu_symbols(struct load_module *lm) +{ + struct syment *sp, *sp_end; + if (MODULE_PERCPU_SYMS_LOADED(lm)) { + sp = lm->mod_symtable; + sp_end = lm->mod_symend; + for ( ; sp <= sp_end; sp++) { + if (IN_MODULE_PERCPU(sp->value, lm)) + show_symbol(sp, 0, SHOW_RADIX()); + } } } @@ -1092,6 +1137,7 @@ store_module_symbols_v1(ulong total, int st->ext_module_symtable[mcnt].value = mod; st->ext_module_symtable[mcnt].type = 'm'; + st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL; sprintf(buf2, "%s%s", "_MODULE_START_", name); namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace, &st->ext_module_symtable[mcnt], buf2); @@ -1153,6 +1199,7 @@ store_module_symbols_v1(ulong total, int st->ext_module_symtable[mcnt].value = modsym->value; st->ext_module_symtable[mcnt].type = '?'; + st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL; strip_module_symbol_end(buf1); namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace, @@ -1194,6 +1241,7 @@ store_module_symbols_v1(ulong total, int st->ext_module_symtable[mcnt].value = mod + size; st->ext_module_symtable[mcnt].type = 'm'; + st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL; sprintf(buf2, "%s%s", "_MODULE_END_", name); namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace, @@ -1349,6 +1397,7 @@ store_module_symbols_v2(ulong total, int lm->mod_ext_symcnt = mcnt; lm->mod_init_module_ptr = ULONG(modbuf + OFFSET(module_module_init)); + lm->mod_percpu = ULONG(modbuf + OFFSET(module_percpu)); if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) { lm->mod_etext_guess = lm->mod_base + UINT(modbuf + OFFSET(module_core_text_size)); @@ -1368,6 +1417,7 @@ store_module_symbols_v2(ulong total, int st->ext_module_symtable[mcnt].value = lm->mod_base; st->ext_module_symtable[mcnt].type = 'm'; + st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL; sprintf(buf2, "%s%s", "_MODULE_START_", mod_name); namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace, &st->ext_module_symtable[mcnt], buf2); @@ -1377,6 +1427,7 @@ store_module_symbols_v2(ulong total, int if (lm->mod_init_size > 0) { st->ext_module_symtable[mcnt].value = lm->mod_init_module_ptr; st->ext_module_symtable[mcnt].type = 'm'; + st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL; sprintf(buf3, "%s%s", "_MODULE_INIT_START_", mod_name); namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace, @@ -1450,6 +1501,7 @@ store_module_symbols_v2(ulong total, int st->ext_module_symtable[mcnt].value = modsym->value; st->ext_module_symtable[mcnt].type = '?'; + st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL; strip_module_symbol_end(buf1); namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace, @@ -1523,6 +1575,7 @@ store_module_symbols_v2(ulong total, int st->ext_module_symtable[mcnt].value = modsym->value; st->ext_module_symtable[mcnt].type = '?'; + st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL; strip_module_symbol_end(buf1); namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace, @@ -1557,6 +1610,7 @@ store_module_symbols_v2(ulong total, int st->ext_module_symtable[mcnt].value = lm->mod_base + size; st->ext_module_symtable[mcnt].type = 'm'; + st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL; sprintf(buf2, "%s%s", "_MODULE_END_", mod_name); namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace, @@ -1566,6 +1620,7 @@ store_module_symbols_v2(ulong total, int if (lm->mod_init_size > 0) { st->ext_module_symtable[mcnt].value = lm->mod_init_module_ptr + lm->mod_init_size; st->ext_module_symtable[mcnt].type = 'm'; + st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL; sprintf(buf4, "%s%s", "_MODULE_INIT_END_", mod_name); namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace, @@ -1624,6 +1679,10 @@ store_module_symbols_v2(ulong total, int if (symbol_query("__insmod_", NULL, NULL)) st->flags |= INSMOD_BUILTIN; + + if (mcnt > total) + error(FATAL, "store_module_symbols_v2: total: %ld mcnt: %d\n", + total, mcnt); } /* @@ -1756,6 +1815,7 @@ store_module_kallsyms_v1(struct load_mod st->ext_module_symtable[mcnt_idx].value = symbol_addr; st->ext_module_symtable[mcnt_idx].type = type; + st->ext_module_symtable[mcnt_idx].flags |= MODULE_SYMBOL; namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace, &st->ext_module_symtable[mcnt_idx++], nameptr); @@ -1945,6 +2005,7 @@ store_module_kallsyms_v2(struct load_mod st->ext_module_symtable[mcnt_idx].value = ec->st_value; st->ext_module_symtable[mcnt_idx].type = ec->st_info; + st->ext_module_symtable[mcnt_idx].flags |= MODULE_SYMBOL; namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace, &st->ext_module_symtable[mcnt_idx++], nameptr); @@ -2632,6 +2693,26 @@ dump_symbol_table(void) lm->mod_init_text_size); fprintf(fp, " mod_init_module_ptr: %lx\n", lm->mod_init_module_ptr); + if (lm->mod_percpu_size) { + fprintf(fp, " mod_percpu_size: %lx\n", + lm->mod_percpu_size); + fprintf(fp, " mod_percpu: %lx - %lx\n", + lm->mod_percpu, + lm->mod_percpu + lm->mod_percpu_size); + } else { + if (lm->mod_percpu) { + fprintf(fp, + " mod_percpu_size: (not loaded)\n"); + fprintf(fp, + " mod_percpu: %lx - (unknown)\n", + lm->mod_percpu); + } else { + fprintf(fp, + " mod_percpu_size: (not used)\n"); + fprintf(fp, + " mod_percpu: (not used)\n"); + } + } fprintf(fp, " mod_sections: %d\n", lm->mod_sections); fprintf(fp, " mod_section_data: %lx %s\n", @@ -3140,6 +3221,7 @@ cmd_sym(void) name = NULL; multiples = 0; sp = NULL; + show_flags &= ~SHOW_MODULE; if (hexadecimal(args[optind], 0)) { errflag = 0; @@ -3150,6 +3232,9 @@ cmd_sym(void) args[optind]); } else if ((sp = value_search(value, &offset))){ name = sp->name; + if (module_symbol(sp->value, NULL, NULL, + NULL, 0)) + show_flags |= SHOW_MODULE; if (prev && (spp = prev_symbol(NULL, sp))) show_symbol(spp, 0, show_flags); @@ -3173,6 +3258,9 @@ cmd_sym(void) if ((sp = symbol_search(args[optind]))) { multiples = symbol_name_count(sp->name); do_multiples: + if (module_symbol(sp->value, NULL, NULL, + NULL, 0)) + show_flags |= SHOW_MODULE; name = sp->name; if (prev && (spp = prev_symbol(NULL, sp))) @@ -3214,6 +3302,9 @@ show_symbol(struct syment *sp, ulong off char buf[BUFSIZE]; char *p1; ulong radix; + struct load_module *lm; + + lm = NULL; switch (show_flags & (SHOW_HEX_OFFS|SHOW_DEC_OFFS)) { @@ -3227,7 +3318,6 @@ show_symbol(struct syment *sp, ulong off break; } - if (MODULE_START(sp)) { p1 = sp->name + strlen("_MODULE_START_"); fprintf(fp, "%lx (%c) (%s module)", sp->value, sp->type, p1); @@ -3236,24 +3326,27 @@ show_symbol(struct syment *sp, ulong off offset); fprintf(fp, "\n"); return; - } + } else if (show_flags & SHOW_MODULE) + module_symbol(sp->value, NULL, &lm, NULL, 0); if (offset) fprintf(fp, (radix == 16) ? - "%lx (%c) %s+0x%lx " : "%lx (%c) %s+%ld ", + "%lx (%c) %s+0x%lx" : "%lx (%c) %s+%ld", sp->value+offset, sp->type, sp->name, offset); else - fprintf(fp, "%lx (%c) %s ", sp->value, sp->type, sp->name); + fprintf(fp, "%lx (%c) %s", sp->value, sp->type, sp->name); + + if (lm) + fprintf(fp, " [%s]", lm->mod_name); if (is_kernel_text(sp->value+offset) && (show_flags & SHOW_LINENUM)) - fprintf(fp, "%s", + fprintf(fp, " %s", get_line_number(sp->value+offset, buf, TRUE)); if (show_flags & SHOW_SECTION) - fprintf(fp, "[%s]", get_section(sp->value+offset, buf)); + fprintf(fp, " [%s]", get_section(sp->value+offset, buf)); - fprintf(fp, "\n"); } @@ -3419,7 +3512,8 @@ symbol_query(char *s, char *print_pad, s if (print_pad) { if (strlen(print_pad)) fprintf(fp, "%s", print_pad); - show_symbol(sp, 0, SHOW_RADIX()); + show_symbol(sp, 0, + SHOW_RADIX()|SHOW_MODULE); } if (spp) *spp = sp; @@ -3446,7 +3540,8 @@ symbol_query(char *s, char *print_pad, s if (print_pad) { if (strlen(print_pad)) fprintf(fp, "%s", print_pad); - show_symbol(sp, 0, SHOW_RADIX()); + show_symbol(sp, 0, + SHOW_RADIX()|SHOW_MODULE); } if (spp) *spp = sp; @@ -3487,10 +3582,9 @@ symbol_search(char *s) sp = lm->mod_symtable; sp_end = lm->mod_symend; - for ( ; sp < sp_end; sp++) { + for ( ; sp <= sp_end; sp++) { if (!pseudos && MODULE_PSEUDO_SYMBOL(sp)) continue; - if (STREQ(s, sp->name)) return(sp); } @@ -3726,7 +3820,9 @@ module_symbol(ulong value, } else if (IN_MODULE_INIT(value, lm)) { base = lm->mod_init_module_ptr; end = lm->mod_init_module_ptr + lm->mod_init_size; - + } else if (IN_MODULE_PERCPU(value, lm)) { + base = lm->mod_percpu; + end = lm->mod_percpu + lm->mod_percpu_size; } else continue; @@ -4432,16 +4528,12 @@ per_cpu_symbol_search(char *symbol) return sp; new = symbol + strlen("per_cpu__"); if ((sp = symbol_search(new))) { - if ((sp->type == 'V') || - ((sp->value >= st->__per_cpu_start) && - (sp->value < st->__per_cpu_end))) + if ((sp->type == 'V') || (is_percpu_symbol(sp))) return sp; } } else { if ((sp = symbol_search(symbol))) { - if ((sp->type == 'V') || - ((sp->value >= st->__per_cpu_start) && - (sp->value < st->__per_cpu_end))) + if ((sp->type == 'V') || (is_percpu_symbol(sp))) return sp; } @@ -5638,7 +5730,10 @@ cmd_p(void) leader = strlen(buf2); if (module_symbol(sp->value, NULL, NULL, NULL, *gdb_output_radix)) do_load_module_filter = TRUE; - } else if (st->flags & LOAD_MODULE_SYMS) + } else if ((percpu_sp = per_cpu_symbol_search(args[optind])) && + display_per_cpu_info(percpu_sp)) + return; + else if (st->flags & LOAD_MODULE_SYMS) do_load_module_filter = TRUE; if (leader || do_load_module_filter) @@ -5698,8 +5793,7 @@ display_per_cpu_info(struct syment *sp) char buf[BUFSIZE]; if (((kt->flags & (SMP|PER_CPU_OFF)) != (SMP|PER_CPU_OFF)) || - (sp->value < symbol_value("__per_cpu_start")) || - (sp->value >= symbol_value("__per_cpu_end")) || + (!is_percpu_symbol(sp)) || !((sp->type == 'd') || (sp->type == 'D') || (sp->type == 'V'))) return FALSE; @@ -5719,6 +5813,43 @@ display_per_cpu_info(struct syment *sp) return TRUE; } +static struct load_module * +get_module_percpu_sym_owner(struct syment *sp) +{ + int i; + struct load_module *lm; + + if (!IS_MODULE_SYMBOL(sp)) + return NULL; + + /* + * Find out percpu symbol owner module. + * If found out, sp is module's percpu symbol. + */ + for (i = 0; i < st->mods_installed; i++) { + lm = &st->load_modules[i]; + if (!MODULE_PERCPU_SYMS_LOADED(lm)) + continue; + if (IN_MODULE_PERCPU(sp->value, lm)) + return lm; + } + return NULL; +} + +static int +is_percpu_symbol(struct syment *sp) +{ + if (sp->value >= st->__per_cpu_start) { + if (sp->value < st->__per_cpu_end) + /* kernel percpu symbol */ + return 1; + else if (get_module_percpu_sym_owner(sp)) + /* module percpu symbol */ + return 2; + } + return 0; +} + /* * As a latch ditch effort before a command is thrown away by exec_command(), * args[0] is checked to see whether it's the name of a variable, structure, @@ -6903,6 +7034,8 @@ dump_offset_table(char *spec, ulong make OFFSET(module_symtab)); fprintf(fp, " module_strtab: %ld\n", OFFSET(module_strtab)); + fprintf(fp, " module_percpu: %ld\n", + OFFSET(module_percpu)); fprintf(fp, " module_sect_attrs: %ld\n", OFFSET(module_sect_attrs)); @@ -8346,6 +8479,14 @@ store_section_data(struct load_module *l lm->mod_section_data[i].section = section; lm->mod_section_data[i].priority = prio; lm->mod_section_data[i].flags = section->flags & ~SEC_FOUND; + /* + * The percpu section isn't included in kallsyms or module_core area. + */ + if (lm->mod_percpu && + (STREQ(name,".data.percpu") || STREQ(name, ".data..percpu"))) { + lm->mod_percpu_size = bfd_section_size(bfd, section); + lm->mod_section_data[i].flags |= SEC_FOUND; + } lm->mod_section_data[i].size = bfd_section_size(bfd, section); lm->mod_section_data[i].offset = 0; if (strlen(name) < MAX_MOD_SEC_NAME) @@ -8791,13 +8932,26 @@ add_symbol_file(struct load_module *lm) { secname = lm->mod_section_data[i].name; if ((lm->mod_section_data[i].flags & SEC_FOUND) && - !STREQ(secname, ".text")) { + (!STREQ(secname, ".text") && + !STREQ(secname, ".data.percpu") && + !STREQ(secname, ".data..percpu"))) { sprintf(buf, " -s %s 0x%lx", secname, lm->mod_section_data[i].offset + lm->mod_base); len += strlen(buf); } } + for (i = 0; i < lm->mod_sections; i++) + { + secname = lm->mod_section_data[i].name; + if ((lm->mod_section_data[i].flags & SEC_FOUND) && + (STREQ(secname, ".data.percpu") || + STREQ(secname, ".data..percpu"))) { + sprintf(buf, " -s %s 0x%lx", secname, lm->mod_percpu); + len += strlen(buf); + } + } + req->command = GNU_ADD_SYMBOL_FILE; req->addr = (ulong)lm; req->buf = GETBUF(len+BUFSIZE); @@ -8816,6 +8970,31 @@ add_symbol_file(struct load_module *lm) } #ifdef GDB_7_0 +static int +add_symbol_file_percpu(struct load_module *lm, struct gnu_request *req, int buflen) +{ + char pbuf[BUFSIZE]; + int i, len; + char *secname; + + len = strlen(req->buf); + for (i = 0; i < lm->mod_sections; i++) { + secname = lm->mod_section_data[i].name; + if ((lm->mod_section_data[i].flags & SEC_FOUND) && + (STREQ(secname, ".data.percpu") || + STREQ(secname, ".data..percpu"))) { + sprintf(pbuf, " -s %s 0x%lx", secname, lm->mod_percpu); + while ((len + strlen(pbuf)) >= buflen) { + RESIZEBUF(req->buf, buflen, buflen * 2); + buflen *= 2; + } + strcat(req->buf, pbuf); + len += strlen(pbuf); + } + } + return buflen; +} + /* * Gather the module section data from the in-kernel data structures. */ @@ -9035,6 +9214,11 @@ add_symbol_file_kallsyms(struct load_mod return FALSE; } + /* + * Special case for per-cpu symbols + */ + buflen = add_symbol_file_percpu(lm, req, buflen); + lm->mod_flags |= MOD_NOPATCH; req->command = GNU_ADD_SYMBOL_FILE; req->addr = (ulong)lm; @@ -9176,7 +9360,7 @@ store_load_module_symbols(bfd *bfd, int if (!lm->mod_load_symtable) { if ((lm->mod_load_symtable = (struct syment *) - malloc(symalloc * sizeof(struct syment))) == NULL) + calloc(symalloc, sizeof(struct syment))) == NULL) error(FATAL, "module syment space malloc: %s\n", strerror(errno)); @@ -9314,7 +9498,12 @@ store_load_module_symbols(bfd *bfd, int else if ((spx = kallsyms_module_symbol(lm, &syminfo))) { syminfo.value = spx->value; found = TRUE; - } else { + } else if (lm->mod_percpu && + (STREQ(secname, ".data.percpu") || + STREQ(secname, ".data..percpu"))) { + syminfo.value += lm->mod_percpu; + found = TRUE; + } else { syminfo.value += lm->mod_section_data[i].offset + lm->mod_base; found = TRUE; } @@ -9329,6 +9518,7 @@ store_load_module_symbols(bfd *bfd, int syminfo.type)) { sp->value = syminfo.value; sp->type = syminfo.type; + sp->flags |= MODULE_SYMBOL; namespace_ctl(NAMESPACE_INSTALL, &lm->mod_load_namespace, sp, name); @@ -9385,6 +9575,7 @@ store_load_module_symbols(bfd *bfd, int lm->mod_load_symend->value = spx->value; lm->mod_load_symend->type = spx->type; + lm->mod_load_symend->flags |= MODULE_SYMBOL; lm->mod_load_symend++; lm->mod_load_symcnt++; } @@ -9397,9 +9588,10 @@ store_load_module_symbols(bfd *bfd, int compare_syms); lm->mod_load_symend--; - if (!MODULE_END(lm->mod_load_symend)) - error(INFO, "%s: last symbol is not _MODULE_END_%s?\n", - lm->mod_name, lm->mod_name); + if (!MODULE_END(lm->mod_load_symend) && + !IN_MODULE_PERCPU(lm->mod_load_symend->value, lm)) + error(INFO, "%s: last symbol: %s is not _MODULE_END_%s?\n", + lm->mod_name, lm->mod_load_symend->name, lm->mod_name); lm->mod_symtable = lm->mod_load_symtable; lm->mod_symend = lm->mod_load_symend; @@ -9408,7 +9600,6 @@ store_load_module_symbols(bfd *bfd, int lm->mod_flags |= MOD_LOAD_SYMS; st->flags |= LOAD_MODULE_SYMS; - } /* @@ -9451,6 +9642,7 @@ delete_load_module(ulong base_addr) lm->mod_text_start = lm->mod_data_start = 0; lm->mod_bss_start = lm->mod_rodata_start = 0; lm->mod_sections = 0; + lm->mod_percpu_size = 0; if (lm->mod_section_data) free(lm->mod_section_data); lm->mod_section_data = (struct mod_section_data *)0; @@ -9485,6 +9677,7 @@ delete_load_module(ulong base_addr) lm->mod_load_symcnt = lm->mod_symalloc = 0; lm->mod_text_start = lm->mod_data_start = 0; lm->mod_bss_start = lm->mod_rodata_start = 0; + lm->mod_percpu_size = 0; lm->mod_sections = 0; if (lm->mod_section_data) free(lm->mod_section_data); @@ -9926,7 +10119,6 @@ clear_text_value_cache(void) * new one. */ -#define allocated pad1 #define last_sp addr2 int @@ -9962,10 +10154,10 @@ patch_kernel_symbol(struct gnu_request * sp = (struct syment *)req->last_sp; sp += sp ? 1 : 0; - if (sp && (sp->cnt == 1) && !(sp->allocated) && + if (sp && (sp->cnt == 1) && !(sp->flags & SYMBOL_NAME_USED) && STREQ(sp->name, req->name)) { *((ulong *)req->addr) = sp->value; - sp->allocated = TRUE; + sp->flags |= SYMBOL_NAME_USED; req->last_sp = (ulong)sp; } else { switch (c = get_syment_array(req->name, sp_array, 1000)) @@ -9975,16 +10167,16 @@ patch_kernel_symbol(struct gnu_request * case 1: *((ulong *)req->addr) = sp_array[0]->value; - sp_array[0]->allocated = TRUE; + sp_array[0]->flags |= SYMBOL_NAME_USED; req->last_sp = (ulong)sp_array[0]; break; default: for (i = 0; i < c; i++) { - if (sp_array[i]->allocated) + if (sp_array[i]->flags & SYMBOL_NAME_USED) continue; *((ulong *)req->addr) = sp_array[i]->value; - sp_array[i]->allocated = TRUE; + sp_array[i]->flags |= SYMBOL_NAME_USED; req->last_sp = (ulong)sp_array[i]; break; } @@ -9995,7 +10187,6 @@ patch_kernel_symbol(struct gnu_request * return TRUE; } -#undef allocated #undef last_sp /* --- crash-5.0.9/lkcd_x86_trace.c 2010-11-12 15:34:12.000000000 -0500 +++ crash/lkcd_x86_trace.c 2010-11-05 15:09:31.000000000 -0400 @@ -1716,6 +1716,7 @@ find_trace( } } else if (strstr(func_name, "call_do_IRQ") || strstr(func_name, "common_interrupt") || + strstr(func_name, "reboot_interrupt") || strstr(func_name, "call_function_interrupt")) { /* Interrupt frame */ sp = curframe->fp + 4; @@ -2581,6 +2582,7 @@ print_stack_entry(struct bt_info *bt, in { char buf[BUFSIZE]; struct syment *sp; + struct load_module *lm; if (frmp && frmp->prev && STREQ(frmp->funcname, "error_code") && (sp = x86_jmp_error_code((ulong)frmp->prev->pc))) @@ -2595,10 +2597,13 @@ print_stack_entry(struct bt_info *bt, in if ((sp = eframe_label(funcname, eip))) funcname = sp->name; - fprintf(ofp, "%s#%d [%8lx] %s%s at %lx\n", + fprintf(ofp, "%s#%d [%8lx] %s%s at %lx", level < 10 ? " " : "", level, esp, funcname_display(funcname), strlen(buf) ? buf : "", eip); + if (module_symbol(eip, NULL, &lm, NULL, 0)) + fprintf(ofp, " [%s]", lm->mod_name); + fprintf(ofp, "\n"); if (bt->flags & BT_LINE_NUMBERS) { get_line_number(eip, buf, FALSE); --- crash-5.0.9/unwind.c 2010-11-12 15:34:12.000000000 -0500 +++ crash/unwind.c 2010-11-05 17:13:23.000000000 -0400 @@ -1696,6 +1696,7 @@ unwind_v3(struct bt_info *bt) struct pt_regs *pt; int frame; char *name; + struct load_module *lm; static int unw_in_progress = FALSE; if (bt->debug) @@ -1751,9 +1752,12 @@ restart: break; } } else { - fprintf(fp, "%s#%d [BSP:%lx] %s at %lx\n", + fprintf(fp, "%s#%d [BSP:%lx] %s at %lx", frame >= 10 ? "" : " ", frame, bsp, name, ip); + if (module_symbol(ip, NULL, &lm, NULL, 0)) + fprintf(fp, " [%s]", lm->mod_name); + fprintf(fp, "\n"); if (bt->flags & BT_FULL) rse_function_params(bt, info, name); --- crash-5.0.9/defs.h 2010-11-12 15:34:12.000000000 -0500 +++ crash/defs.h 2010-11-11 17:04:27.000000000 -0500 @@ -1532,6 +1532,7 @@ struct offset_table { long unwind_idx_insn; long signal_struct_nr_threads; long module_init_size; + long module_percpu; }; struct size_table { /* stash of commonly-used sizes */ @@ -1911,6 +1912,10 @@ struct alias_data { /* c #endif /* !GDB_COMMON */ +#define SYMBOL_NAME_USED (0x1) +#define MODULE_SYMBOL (0x2) +#define IS_MODULE_SYMBOL(SYM) ((SYM)->flags & MODULE_SYMBOL) + struct syment { ulong value; char *name; @@ -1918,10 +1923,10 @@ struct syment { struct syment *name_hash_next; char type; unsigned char cnt; - unsigned char pad1; + unsigned char flags; unsigned char pad2; }; - + #define NAMESPACE_INIT (1) #define NAMESPACE_REUSE (2) #define NAMESPACE_FREE (3) @@ -2063,6 +2068,8 @@ struct load_module { ulong mod_init_size; struct syment *mod_init_symtable; struct syment *mod_init_symend; + ulong mod_percpu; + ulong mod_percpu_size; }; #define IN_MODULE(A,L) \ @@ -2071,6 +2078,11 @@ struct load_module { #define IN_MODULE_INIT(A,L) \ (((ulong)(A) >= (L)->mod_init_module_ptr) && ((ulong)(A) < ((L)->mod_init_module_ptr+(L)->mod_init_size))) +#define IN_MODULE_PERCPU(A,L) \ + (((ulong)(A) >= (L)->mod_percpu) && ((ulong)(A) < ((L)->mod_percpu+(L)->mod_percpu_size))) + +#define MODULE_PERCPU_SYMS_LOADED(L) ((L)->mod_percpu && (L)->mod_percpu_size) + #ifndef GDB_COMMON #define KVADDR (0x1) @@ -3579,6 +3591,7 @@ void show_symbol(struct syment *, ulong, #define SHOW_HEX_OFFS (0x4) #define SHOW_DEC_OFFS (0x8) #define SHOW_RADIX() (*gdb_output_radix == 16 ? SHOW_HEX_OFFS : SHOW_DEC_OFFS) +#define SHOW_MODULE (0x10) int symbol_query(char *, char *, struct syment **); struct syment *next_symbol(char *, struct syment *); struct syment *prev_symbol(char *, struct syment *);
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility