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
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility