[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