Signed-off-by: Kazuhito Hagio <k-hagio-ab@xxxxxxx> --- symbols.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/symbols.c b/symbols.c index a432909ff28e..62092ba7d723 100644 --- a/symbols.c +++ b/symbols.c @@ -111,6 +111,7 @@ static ulong module_mem_end(ulong, struct load_module *); static int _in_module_range(ulong, struct load_module *, int, int); struct syment *value_search_module_v2(ulong, ulong *); struct syment *next_module_symbol(char *, struct syment *, ulong); +struct syment *prev_module_symbol(struct syment *, ulong); static const char *module_start_tags[]; static const char *module_start_strs[]; @@ -6073,6 +6074,71 @@ next_symbol(char *symbol, struct syment *sp_in) return NULL; } +/* Only for 6.4 and later */ +struct syment * +prev_module_symbol(struct syment *sp_in, ulong val_in) +{ + int i, j, k; + struct load_module *lm; + struct syment *sp, *sp_end; + + if (val_in) + goto value_search; + + for (i = 0; i < st->mods_installed; i++) { + lm = &st->load_modules[i]; + + /* quick check: sp_in is not in the module range. */ + if (sp_in < lm->symtable[lm->address_order[0]] || + sp_in > lm->symend[lm->address_order[lm->nr_mems-1]]) + continue; + + for (j = 0; j < lm->nr_mems; j++) { + k = lm->address_order[j]; + if (sp_in < lm->symtable[k] || sp_in > lm->symend[k]) + continue; + + if (sp_in == lm->symtable[k]) + return prev_module_symbol(NULL, sp_in->value); + + sp = sp_in - 1; + if (MODULE_PSEUDO_SYMBOL(sp)) + return prev_module_symbol(NULL, sp->value); + + return sp; + } + } + return NULL; + +value_search: + sp = sp_end = NULL; + for (i = 0; i < st->mods_installed; i++) { + lm = &st->load_modules[i]; + + /* quick check: val_in is lower than the lowest in the module. */ + if (val_in < lm->symtable[lm->address_order[0]]->value) + continue; + + for (j = lm->nr_mems - 1; j >= 0 ; j--) { + k = lm->address_order[j]; + if (val_in > lm->symend[k]->value && + (sp == NULL || lm->symend[k]->value > sp->value)) { + sp = lm->symtable[k]; + sp_end = lm->symend[k]; + break; + } + } + } + for ( ; sp_end > sp; sp_end--) { + if (MODULE_PSEUDO_SYMBOL(sp_end)) + continue; + if (sp_end->value > val_in) + return sp_end; + } + + return NULL; +} + /* * For a given symbol, return a pointer to the previous (lower) symbol's syment. * Either a symbol name or syment pointer may be passed as an argument. @@ -6096,6 +6162,9 @@ prev_symbol(char *symbol, struct syment *sp_in) sp_prev = sp; } + if (MODULE_MEMORY()) + return prev_module_symbol(sp_in, 0); + search_init = FALSE; for (i = 0; i < st->mods_installed; i++) { -- 2.31.1 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/crash-utility Contribution Guidelines: https://github.com/crash-utility/crash/wiki