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.
--
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)))
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 (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
",
OFFSET(module_core_text_size));
+ fprintf(fp, " module_init_size: %ld
",
+ OFFSET(module_init_size));
fprintf(fp, " module_init_text_size: %ld
",
OFFSET(module_init_text_size));
fprintf(fp, " module_module_init: %ld
",
--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility