[Crash-utility] [PATCH] Also search module init section for symbols
Hu Tao
hutao at cn.fujitsu.com
Wed Oct 6 03:10:10 UTC 2010
Sorry for late reply but I'm just back from vacation.
On Thu, Sep 30, 2010 at 10:54:34AM -0400, Dave Anderson wrote:
>
> ----- "Hu Tao" <hutao at cn.fujitsu.com> 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.
Thanks for suggestion. Attached files are two patches that:
1. remove compile warnings.
2. add a flag MOD_INIT if module init symbols are present.
These two patches are in order and on top of previous patch I sent.
>
> 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",
--
Thanks,
Hu Tao
-------------- next part --------------
diff --git a/symbols.c b/symbols.c
index f1c308e..ad3c32d 100755
--- a/symbols.c
+++ b/symbols.c
@@ -3640,7 +3640,7 @@ module_symbol(ulong value,
return FALSE;
}
-struct syment *
+static struct syment *
value_search_module(ulong value, ulong *offset, int search_init_section)
{
int i;
@@ -3722,9 +3722,7 @@ value_search_module(ulong value, ulong *offset, int search_init_section)
struct syment *
value_search(ulong value, ulong *offset)
{
- int i;
- struct syment *sp, *sp_end, *spnext, *splast;
- struct load_module *lm;
+ struct syment *sp, *spnext;
if (!in_ksymbol_range(value))
return((struct syment *)NULL);
-------------- next part --------------
diff --git a/defs.h b/defs.h
index 0fe9d48..18546eb 100755
--- a/defs.h
+++ b/defs.h
@@ -2014,6 +2014,7 @@ struct symbol_table_data {
#define MOD_KALLSYMS (0x8)
#define MOD_INITRD (0x10)
#define MOD_NOPATCH (0x20)
+#define MOD_INIT (0x40)
#define SEC_FOUND (0x10000)
diff --git a/symbols.c b/symbols.c
index ad3c32d..ac4ba98 100755
--- a/symbols.c
+++ b/symbols.c
@@ -1950,6 +1950,8 @@ store_module_kallsyms_v2(struct load_module *lm, int start, int curr,
}
lm->mod_flags |= MOD_KALLSYMS;
+ if (lm->mod_init_size > 0)
+ lm->mod_flags |= MOD_INIT;
FREEBUF(module_buf);
if (module_buf_init)
FREEBUF(module_buf_init);
@@ -3641,26 +3643,20 @@ module_symbol(ulong value,
}
static struct syment *
-value_search_module(ulong value, ulong *offset, int search_init_section)
+value_search_module(ulong value, ulong *offset)
{
int i;
+ int retry;
struct syment *sp, *sp_end, *spnext, *splast;
struct load_module *lm;
for (i = 0; i < st->mods_installed; i++) {
+ retry = 1;
lm = &st->load_modules[i];
- 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;
- }
-
+ sp = lm->mod_symtable;
+ sp_end = lm->mod_symend;
+retry:
if (sp->value > value) /* invalid -- between modules */
break;
@@ -3710,6 +3706,13 @@ value_search_module(ulong value, ulong *offset, int search_init_section)
splast = sp;
}
}
+
+ if (retry && (lm->mod_flags & MOD_INIT)) {
+ retry = 0;
+ sp = lm->mod_init_symtable;
+ sp_end = lm->mod_init_symend;
+ goto retry;
+ }
}
return((struct syment *)NULL);
@@ -3731,7 +3734,7 @@ value_search(ulong value, ulong *offset)
return sp;
if (IS_VMALLOC_ADDR(value))
- goto check_modules;
+ return value_search_module(value, offset);
if ((sp = symval_hash_search(value)) == NULL)
sp = st->symtable;
@@ -3756,11 +3759,6 @@ value_search(ulong value, ulong *offset)
}
}
-check_modules:
- sp = value_search_module(value, offset, 0);
- if (!sp)
- sp = value_search_module(value, offset, 1);
-
return sp;
}
More information about the Crash-utility
mailing list