Hi Aaron, I was revisiting your v1 patch, and realized that the duplicate symbol check also needs to apply to the "can_eval()" section as well, because a user could enter "dis symbol+<offset>". So I extracted your do-while loop into a discrete function, and beefed it up to handle the entry of symbols with multiple text and data symbols, as well as some other possibilities. In so doing, things got a bit murkier than your original patch. I've attached what I've come up with so far. Tell me what you think. Thanks, Dave
--- crash-7.1.1/defs.h.orig +++ crash-7.1.1/defs.h @@ -4569,6 +4569,7 @@ void show_symbol(struct syment *, ulong, #define SHOW_DEC_OFFS (0x8) #define SHOW_RADIX() (*gdb_output_radix == 16 ? SHOW_HEX_OFFS : SHOW_DEC_OFFS) #define SHOW_MODULE (0x10) +int symbol_name_count(char *); int symbol_query(char *, char *, struct syment **); struct syment *next_symbol(char *, struct syment *); struct syment *prev_symbol(char *, struct syment *); --- crash-7.1.1/kernel.c.orig +++ crash-7.1.1/kernel.c @@ -1306,8 +1306,97 @@ verify_namelist() program_usage(SHORT_FORM); } +/* + * From either a syment pointer or a virtual address, determine + * whether there are multiple text symbols with the same name, + * and if so, display each symbol's information, and return FALSE. + * + * All of the remaining possibilities return TRUE: + * + * (1) if an evaluated address cannot be resolved to any symbol. + * (2) if there is only one possible symbol resolution. + * (3) if there are multiple data symbols, just use the first symbol + * or the address that was passed in. + * (4) if there is one text symbol and one or more data symbols with + * the same name, pick the text symbol, (re)set the incoming address, + * and return TRUE. + */ +static int +resolve_text_symbol(char *arg, struct syment *sp_in, struct gnu_request *req, int radix) +{ + int text_symbols, count; + struct syment *sp, *sp_orig, *first_text; + ulong offset, radix_flag; + + if (sp_in) { + sp_orig = sp_in; + offset = 0; + } else if ((sp_orig = value_search(req->addr, &offset))) + radix_flag = radix == 10 ? SHOW_DEC_OFFS : SHOW_HEX_OFFS; + else { + if (CRASHDEBUG(1)) + error(INFO, "%s: no text symbol found\n", arg); + return TRUE; + } + + if (symbol_name_count(sp_orig->name) <= 1) + return TRUE; + + text_symbols = 0; + first_text = NULL; + sp = sp_orig; + + do { + if ((sp->type == 't') || (sp->type == 'T')) { + if (!first_text) + first_text = sp; + text_symbols++; + } + } while ((sp = symbol_search_next(sp->name, sp))); + + /* + * Whatever the symbol or address is, there are not two text + * symbols with the same name. Let it be... + */ + if (!text_symbols) { + if (CRASHDEBUG(1)) + error(INFO, "%s: no text symbol found\n", arg); + return TRUE; + } + /* + * Only one of multiple symbols with the same name was text, + * so (re)set the req->addr as appropriate. + */ + if (text_symbols == 1) { + if (sp_in) + req->addr = first_text->value; + else + req->addr = first_text->value + offset; + return TRUE; + } + + /* + * Multiple text symbols with the same name exist. + * Display them all and return FALSE. + */ + count = 0; + sp = sp_orig; + do { + if ((sp->type == 't') || (sp->type == 'T')) { + if (++count == 1) + fprintf(fp, + "duplicate text symbols found: %s\n", + sp->name); + if (module_symbol(sp->value, NULL, NULL, NULL, 0)) + show_symbol(sp, offset, SHOW_LINENUM|SHOW_MODULE|radix_flag); + else + show_symbol(sp, offset, SHOW_LINENUM|radix_flag); + } + } while ((sp = symbol_search_next(sp->name, sp))); + return FALSE; +} /* * This routine disassembles text in one of four manners. A starting @@ -1363,7 +1452,7 @@ cmd_dis(void) unfiltered = user_mode = do_machdep_filter = do_load_module_filter = 0; radix = 0; - req = (struct gnu_request *)getbuf(sizeof(struct gnu_request)); + req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request)); req->buf = GETBUF(BUFSIZE); req->flags |= GNU_FROM_TTY_OFF|GNU_RETURN_ON_ERROR; req->count = 1; @@ -1425,9 +1514,14 @@ cmd_dis(void) radix = pc->output_radix; if (args[optind]) { - if (can_eval(args[optind])) + if (can_eval(args[optind])) { req->addr = eval(args[optind], FAULT_ON_ERROR, NULL); - else if (hexadecimal(args[optind], 0)) { + if (!resolve_text_symbol(args[optind], NULL, req, radix)) { + FREEBUF(req->buf); + FREEBUF(req); + return; + } + } else if (hexadecimal(args[optind], 0)) { req->addr = htol(args[optind], FAULT_ON_ERROR, NULL); if (!user_mode && !(sp = value_search(req->addr, &offset))) { @@ -1440,6 +1534,11 @@ cmd_dis(void) req->flags |= GNU_FUNCTION_ONLY; } else if ((sp = symbol_search(args[optind]))) { req->addr = sp->value; + if (!resolve_text_symbol(NULL, sp, req, radix)) { + FREEBUF(req->buf); + FREEBUF(req); + return; + } req->flags |= GNU_FUNCTION_ONLY; } else { fprintf(fp, "symbol not found: %s\n", args[optind]); --- crash-7.1.1/symbols.c.orig +++ crash-7.1.1/symbols.c @@ -37,7 +37,6 @@ static asection *get_kernel_section(char static char * get_section(ulong vaddr, char *buf); static void symbol_dump(ulong, char *); static void check_for_dups(struct load_module *); -static int symbol_name_count(char *); static struct syment *kallsyms_module_symbol(struct load_module *, symbol_info *); static void store_load_module_symbols \ (bfd *, int, void *, long, uint, ulong, char *); @@ -4161,7 +4160,7 @@ symbol_search(char *s) /* * Count the number of instances of a symbol name. */ -static int +int symbol_name_count(char *s) { int i;
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility