----- "Hu Tao" <hutao@xxxxxxxxxxxxxx> wrote: > Hi Dave, > > When I was investigating the backtrace problem(crash doesn't show > some functions from backtrace output), I found the reason was that > there was a dead-looping(or anything that would block module init > function) in module init function, in which case kernel had no chance > to update mod->symtab from mod->core_symtab, and mod->symtab was > still referring into the module init section which was not freed > until the end of module init function. > > Since crash never searches module init function for symbols, in the > case we can't see any symbol from module from the backtrace output. > > Following patch makes crash search the module init section for > symbols too if the section is not null. This is a pretty adventurous patch, but it looks pretty good. Given that your new module init code is pretty much segregated based upon the setting of lm->mod_init_size, it shouldn't break the handling of normal "post-init" modules. A few minor issues: # touch symbols.c # make warn cc -c -g -DX86_64 symbols.c -DGDB_7_0 -I./gdb-7.0/bfd -I./gdb-7.0/include -Wall -O2 -Wstrict-prototypes -Wmissing-prototypes -fstack-protector -Wp,-D_FORTIFY_SOURCE=2 symbols.c:3651: warning: no previous prototype for âvalue_search_moduleâ symbols.c: In function âvalue_searchâ: symbols.c:3734: warning: unused variable âlmâ symbols.c:3733: warning: unused variable âsplastâ symbols.c:3733: warning: unused variable âsp_endâ symbols.c:3732: warning: unused variable âiâ # Also, I'm wondering why you felt it necessary to make two calls to the new value_search_module() function here in value_search(): check_modules: sp = value_search_module(value, offset, 0); if (!sp) sp = value_search_module(value, offset, 1); What I would suggest is this: (1) If during initialization it is seen that a module's init symbols are still in place, then set a new "MOD_INIT" flag in lm->mod_flags. (2) Then, if value_search_module() cannot find a symbol in the lm->mod_symtable, it could check lm->mod_flags for the MOD_INIT flag, and then go back and retry the search in the lm->mod_init_symtable. If it were done that way, I can envision making value_search_module() exportable, and it would not require the caller to make the "0/1" argument decision. Dave > > -- > Thanks, > Hu Tao > > diff --git a/defs.h b/defs.h > index d431d6e..0fe9d48 100755 > --- a/defs.h > +++ b/defs.h > @@ -1515,6 +1515,7 @@ struct offset_table { /* > stash of commonly-used offsets */ > long mm_struct_rss_stat; > long mm_rss_stat_count; > long module_module_init; > + long module_init_size; > long module_init_text_size; > long cpu_context_save_fp; > long cpu_context_save_sp; > @@ -2038,6 +2039,8 @@ struct load_module { > ulong mod_flags; > struct syment *mod_symtable; > struct syment *mod_symend; > + struct syment *mod_init_symtable; > + struct syment *mod_init_symend; > long mod_ext_symcnt; > struct syment *mod_ext_symtable; > struct syment *mod_ext_symend; > @@ -2054,6 +2057,7 @@ struct load_module { > ulong mod_bss_start; > int mod_sections; > struct mod_section_data *mod_section_data; > + ulong mod_init_size; > ulong mod_init_text_size; > ulong mod_init_module_ptr; > }; > @@ -2061,6 +2065,9 @@ struct load_module { > #define IN_MODULE(A,L) \ > (((ulong)(A) >= (L)->mod_base) && ((ulong)(A) < > ((L)->mod_base+(L)->mod_size))) > > +#define IN_MODULE_INIT(A,L) \ > + (((ulong)(A) >= (L)->mod_init_module_ptr) && ((ulong)(A) < > ((L)->mod_init_module_ptr+(L)->mod_init_size))) > + > #ifndef GDB_COMMON > > #define KVADDR (0x1) > diff --git a/kernel.c b/kernel.c > index 5dc2c45..a50882a 100755 > --- a/kernel.c > +++ b/kernel.c > @@ -2691,6 +2691,7 @@ module_init(void) > MEMBER_OFFSET_INIT(module_core_text_size, "module", > "core_text_size"); > MEMBER_OFFSET_INIT(module_module_init, "module", "module_init"); > + MEMBER_OFFSET_INIT(module_init_size, "module", "init_size"); > MEMBER_OFFSET_INIT(module_init_text_size, "module", > "init_text_size"); > > diff --git a/symbols.c b/symbols.c > index c373668..f1c308e 100755 > --- a/symbols.c > +++ b/symbols.c > @@ -884,10 +884,13 @@ symname_hash_search(char *name) > */ > > #define MODULE_PSEUDO_SYMBOL(sp) \ > - (STRNEQ((sp)->name, "_MODULE_START_") || STRNEQ((sp)->name, > "_MODULE_END_")) > + ((STRNEQ((sp)->name, "_MODULE_START_") || STRNEQ((sp)->name, > "_MODULE_END_")) || \ > + (STRNEQ((sp)->name, "_MODULE_INIT_START_") || STRNEQ((sp)->name, > "_MODULE_INIT_END_"))) > > #define MODULE_START(sp) (STRNEQ((sp)->name, "_MODULE_START_")) > #define MODULE_END(sp) (STRNEQ((sp)->name, "_MODULE_END_")) > +#define MODULE_INIT_START(sp) (STRNEQ((sp)->name, > "_MODULE_INIT_START_")) > +#define MODULE_INIT_END(sp) (STRNEQ((sp)->name, > "_MODULE_INIT_END_")) > > static void > symbol_dump(ulong flags, char *module) > @@ -927,6 +930,26 @@ symbol_dump(ulong flags, char *module) > } else > show_symbol(sp, 0, SHOW_RADIX()); > } > + > + if (lm->mod_init_symtable) { > + sp = lm->mod_init_symtable; > + sp_end = lm->mod_init_symend; > + > + for ( ; sp <= sp_end; sp++) { > + if (MODULE_PSEUDO_SYMBOL(sp)) { > + if (MODULE_INIT_START(sp)) { > + p1 = "MODULE INIT START"; > + p2 = sp->name+strlen("_MODULE_INIT_START_"); > + } else { > + p1 = "MODULE INIT END"; > + p2 = sp->name+strlen("_MODULE_INIT_END_"); > + } > + fprintf(fp, "%lx %s: %s\n", sp->value, p1, p2); > + } else > + show_symbol(sp, 0, SHOW_RADIX()); > + } > + } > + > } > } > > @@ -1244,6 +1267,8 @@ store_module_symbols_v2(ulong total, int > mods_installed) > struct load_module *lm; > char buf1[BUFSIZE]; > char buf2[BUFSIZE]; > + char buf3[BUFSIZE]; > + char buf4[BUFSIZE]; > char *strbuf, *modbuf, *modsymbuf; > struct syment *sp; > ulong first, last; > @@ -1326,11 +1351,15 @@ store_module_symbols_v2(ulong total, int > mods_installed) > if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) { > lm->mod_etext_guess = lm->mod_base + > UINT(modbuf + OFFSET(module_core_text_size)); > + lm->mod_init_size = > + UINT(modbuf + OFFSET(module_init_size)); > lm->mod_init_text_size = > UINT(modbuf + OFFSET(module_init_text_size)); > } else { > lm->mod_etext_guess = lm->mod_base + > ULONG(modbuf + OFFSET(module_core_text_size)); > + lm->mod_init_size = > + ULONG(modbuf + OFFSET(module_init_size)); > lm->mod_init_text_size = > ULONG(modbuf + OFFSET(module_init_text_size)); > } > @@ -1344,6 +1373,18 @@ store_module_symbols_v2(ulong total, int > mods_installed) > lm_mcnt = mcnt; > mcnt++; > > + if (lm->mod_init_size > 0) { > + st->ext_module_symtable[mcnt].value = lm->mod_init_module_ptr; > + st->ext_module_symtable[mcnt].type = 'm'; > + sprintf(buf3, "%s%s", "_MODULE_INIT_START_", mod_name); > + namespace_ctl(NAMESPACE_INSTALL, > + &st->ext_module_namespace, > + &st->ext_module_symtable[mcnt], buf3); > + lm_mcnt = mcnt; > + mcnt++; > + } > + > + > if (nsyms && !IN_MODULE(syms, lm)) { > error(WARNING, > "[%s] module.syms outside of module " > @@ -1520,6 +1561,16 @@ store_module_symbols_v2(ulong total, int > mods_installed) > &st->ext_module_symtable[mcnt], buf2); > mcnt++; > > + 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'; > + sprintf(buf4, "%s%s", "_MODULE_INIT_END_", mod_name); > + namespace_ctl(NAMESPACE_INSTALL, > + &st->ext_module_namespace, > + &st->ext_module_symtable[mcnt], buf4); > + mcnt++; > + } > + > lm->mod_ext_symcnt = mcnt - lm->mod_ext_symcnt; > > if (!lm->mod_etext_guess) > @@ -1545,6 +1596,8 @@ store_module_symbols_v2(ulong total, int > mods_installed) > lm = &st->load_modules[m]; > sprintf(buf1, "_MODULE_START_%s", lm->mod_name); > sprintf(buf2, "_MODULE_END_%s", lm->mod_name); > + sprintf(buf3, "_MODULE_INIT_START_%s", lm->mod_name); > + sprintf(buf4, "_MODULE_INIT_END_%s", lm->mod_name); > > for (sp = st->ext_module_symtable; > sp < st->ext_module_symend; sp++) { > @@ -1556,6 +1609,12 @@ store_module_symbols_v2(ulong total, int > mods_installed) > lm->mod_ext_symend = sp; > lm->mod_symend = sp; > } > + if (STREQ(sp->name, buf3)) { > + lm->mod_init_symtable = sp; > + } > + if (STREQ(sp->name, buf4)) { > + lm->mod_init_symend = sp; > + } > } > } > > @@ -1750,6 +1809,7 @@ store_module_kallsyms_v2(struct load_module *lm, > int start, int curr, > struct namespace *ns; > int mcnt; > int mcnt_idx; > + char *module_buf_init = NULL; > > if (!(kt->flags & KALLSYMS_V2)) > return 0; > @@ -1772,30 +1832,50 @@ store_module_kallsyms_v2(struct load_module > *lm, int start, int curr, > return 0; > } > > + if (lm->mod_init_size > 0) { > + module_buf_init = GETBUF(lm->mod_init_size); > + > + if (!readmem(lm->mod_init_module_ptr, KVADDR, module_buf_init, > lm->mod_init_size, > + "module init (kallsyms)", RETURN_ON_ERROR|QUIET)) { > + error(WARNING,"cannot access module init kallsyms\n"); > + FREEBUF(module_buf_init); > + } > + } > + > if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) > nksyms = UINT(modbuf + OFFSET(module_num_symtab)); > else > nksyms = ULONG(modbuf + OFFSET(module_num_symtab)); > > ksymtab = ULONG(modbuf + OFFSET(module_symtab)); > - if (!IN_MODULE(ksymtab, lm)) { > + if (!IN_MODULE(ksymtab, lm) && !IN_MODULE_INIT(ksymtab, lm)) { > error(WARNING, > "%s: module.symtab outside of module address space\n", > lm->mod_name); > FREEBUF(module_buf); > + if (module_buf_init) > + FREEBUF(module_buf_init); > return 0; > } > - locsymtab = module_buf + (ksymtab - lm->mod_base); > + if (IN_MODULE(ksymtab, lm)) > + locsymtab = module_buf + (ksymtab - lm->mod_base); > + else > + locsymtab = module_buf_init + (ksymtab - lm->mod_init_module_ptr); > > kstrtab = ULONG(modbuf + OFFSET(module_strtab)); > - if (!IN_MODULE(kstrtab, lm)) { > + if (!IN_MODULE(kstrtab, lm) && !IN_MODULE_INIT(kstrtab, lm)) { > error(WARNING, > "%s: module.strtab outside of module address space\n", > lm->mod_name); > FREEBUF(module_buf); > + if (module_buf_init) > + FREEBUF(module_buf_init); > return 0; > } > - locstrtab = module_buf + (kstrtab - lm->mod_base); > + if (IN_MODULE(kstrtab, lm)) > + locstrtab = module_buf + (kstrtab - lm->mod_base); > + else > + locstrtab = module_buf_init + (kstrtab - lm->mod_init_module_ptr); > > for (i = 1; i < nksyms; i++) { /* ELF starts real symbols at 1 */ > switch (BITS()) > @@ -1810,14 +1890,16 @@ store_module_kallsyms_v2(struct load_module > *lm, int start, int curr, > break; > } > > - if ((ec->st_value < lm->mod_base) || > - (ec->st_value > (lm->mod_base + lm->mod_size))) > + if (((ec->st_value < lm->mod_base) || > + (ec->st_value > (lm->mod_base + lm->mod_size))) > + && (ec->st_value < lm->mod_init_module_ptr || > + ec->st_value > (lm->mod_init_module_ptr + lm->mod_init_size))) > continue; > > if (ec->st_shndx == SHN_UNDEF) > continue; > > - if (!IN_MODULE(kstrtab + ec->st_name, lm)) { > + if (!IN_MODULE(kstrtab + ec->st_name, lm) && > !IN_MODULE_INIT(kstrtab + ec->st_name, lm)) { > if (CRASHDEBUG(3)) { > error(WARNING, > "%s: bad st_name index: %lx -> %lx\n " > @@ -1869,6 +1951,8 @@ store_module_kallsyms_v2(struct load_module *lm, > int start, int curr, > > lm->mod_flags |= MOD_KALLSYMS; > FREEBUF(module_buf); > + if (module_buf_init) > + FREEBUF(module_buf_init); > > return mcnt; > } > @@ -2211,7 +2295,7 @@ is_kernel_text(ulong value) > for (i = 0; i < st->mods_installed; i++) { > lm = &st->load_modules[i]; > > - if (!IN_MODULE(value, lm)) > + if (!IN_MODULE(value, lm) && !IN_MODULE_INIT(value, lm)) > continue; > > if (lm->mod_flags & MOD_LOAD_SYMS) { > @@ -2233,10 +2317,15 @@ is_kernel_text(ulong value) > start = lm->mod_base + lm->mod_size_of_struct; > break; > case KMOD_V2: > - start = lm->mod_base; > + if (IN_MODULE(value, lm)) > + start = lm->mod_base; > + else > + start = lm->mod_init_module_ptr; > break; > } > end = lm->mod_etext_guess; > + if (IN_MODULE_INIT(value, lm) && end < lm->mod_init_module_ptr + > lm->mod_init_size) > + end = lm->mod_init_module_ptr + lm->mod_init_size; > > if ((value >= start) && (value < end)) > return TRUE; > @@ -2524,6 +2613,8 @@ dump_symbol_table(void) > lm->mod_bss_start, > lm->mod_bss_start ? > lm->mod_bss_start - lm->mod_base : 0); > + fprintf(fp, " mod_init_size: %ld\n", > + lm->mod_init_size); > fprintf(fp, " mod_init_text_size: %ld\n", > lm->mod_init_text_size); > fprintf(fp, " mod_init_module_ptr: %lx\n", > @@ -3493,6 +3584,7 @@ module_symbol(ulong value, > long mcnt; > char buf[BUFSIZE]; > ulong offs, offset; > + ulong base, end; > > if (NO_MODULES()) > return FALSE; > @@ -3506,13 +3598,20 @@ module_symbol(ulong value, > for (i = 0; i < st->mods_installed; i++) { > lm = &st->load_modules[i]; > > - if ((value >= lm->mod_base) && > - (value < (lm->mod_base + lm->mod_size))) { > + if (IN_MODULE(value, lm)) { > + base = lm->mod_base; > + end = lm->mod_base + lm->mod_size; > + } else { > + base = lm->mod_init_module_ptr; > + end = lm->mod_init_module_ptr + lm->mod_init_size; > + } > + > + if ((value >= base) && (value < end)) { > if (lmp) > *lmp = lm; > > if (name) { > - offs = value - lm->mod_base; > + offs = value - base; > if ((sp = value_search(value, &offset))) { > if (offset) > sprintf(buf, radix == 16 ? > @@ -3541,54 +3640,26 @@ module_symbol(ulong value, > return FALSE; > } > > -/* > - * Return the syment of the symbol closest to the value, along with > - * the offset from the symbol value if requested. > - */ > struct syment * > -value_search(ulong value, ulong *offset) > +value_search_module(ulong value, ulong *offset, int > search_init_section) > { > int i; > struct syment *sp, *sp_end, *spnext, *splast; > struct load_module *lm; > > - if (!in_ksymbol_range(value)) > - return((struct syment *)NULL); > - > - if ((sp = machdep->value_to_symbol(value, offset))) > - return sp; > - > - if (IS_VMALLOC_ADDR(value)) > - goto check_modules; > - > - if ((sp = symval_hash_search(value)) == NULL) > - sp = st->symtable; > - > - for ( ; sp < st->symend; sp++) { > - if (value == sp->value) { > -#ifdef GDB_7_0 > - if (STRNEQ(sp->name, ".text.")) { > - spnext = sp+1; > - if (spnext->value == value) > - sp = spnext; > - } > -#endif > - if (offset) > - *offset = 0; > - return((struct syment *)sp); > - } > - if (sp->value > value) { > - if (offset) > - *offset = value - ((sp-1)->value); > - return((struct syment *)(sp-1)); > - } > - } > - > -check_modules: > for (i = 0; i < st->mods_installed; i++) { > lm = &st->load_modules[i]; > - sp = lm->mod_symtable; > - sp_end = lm->mod_symend; > + > + if (!search_init_section) { > + sp = lm->mod_symtable; > + sp_end = lm->mod_symend; > + } else { > + if (lm->mod_init_symtable) { > + sp = lm->mod_init_symtable; > + sp_end = lm->mod_init_symend; > + } else > + continue; > + } > > if (sp->value > value) /* invalid -- between modules */ > break; > @@ -3599,7 +3670,7 @@ check_modules: > * when they have unique values. > */ > splast = NULL; > - for ( ; sp < sp_end; sp++) { > + for ( ; sp <= sp_end; sp++) { > if (value == sp->value) { > if (MODULE_START(sp)) { > spnext = sp+1; > @@ -3644,6 +3715,57 @@ check_modules: > return((struct syment *)NULL); > } > > +/* > + * Return the syment of the symbol closest to the value, along with > + * the offset from the symbol value if requested. > + */ > +struct syment * > +value_search(ulong value, ulong *offset) > +{ > + int i; > + struct syment *sp, *sp_end, *spnext, *splast; > + struct load_module *lm; > + > + if (!in_ksymbol_range(value)) > + return((struct syment *)NULL); > + > + if ((sp = machdep->value_to_symbol(value, offset))) > + return sp; > + > + if (IS_VMALLOC_ADDR(value)) > + goto check_modules; > + > + if ((sp = symval_hash_search(value)) == NULL) > + sp = st->symtable; > + > + for ( ; sp < st->symend; sp++) { > + if (value == sp->value) { > +#ifdef GDB_7_0 > + if (STRNEQ(sp->name, ".text.")) { > + spnext = sp+1; > + if (spnext->value == value) > + sp = spnext; > + } > +#endif > + if (offset) > + *offset = 0; > + return((struct syment *)sp); > + } > + if (sp->value > value) { > + if (offset) > + *offset = value - ((sp-1)->value); > + return((struct syment *)(sp-1)); > + } > + } > + > +check_modules: > + sp = value_search_module(value, offset, 0); > + if (!sp) > + sp = value_search_module(value, offset, 1); > + > + return sp; > +} > + > ulong > highest_bss_symbol(void) > { > @@ -6536,6 +6658,8 @@ dump_offset_table(char *spec, ulong makestruct) > OFFSET(module_core_size)); > fprintf(fp, " module_core_text_size: %ld\n", > OFFSET(module_core_text_size)); > + fprintf(fp, " module_init_size: %ld\n", > + OFFSET(module_init_size)); > fprintf(fp, " module_init_text_size: %ld\n", > OFFSET(module_init_text_size)); > fprintf(fp, " module_module_init: %ld\n", -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility