----- Original Message -----
> An updated patch is attached.
--- 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,98 @@ 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 an evaluated address argument did not contain a symbol name.
+ * (3) if there is only one possible symbol resolution.
+ * (4) if there are multiple data symbols, just use the first symbol
+ * or evaluated address that was passed in.
+ * (5) 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;
+ struct syment *sp, *sp_orig, *first_text_sp;
+ ulong offset, radix_flag;
+
+ if (sp_in) {
+ sp_orig = sp_in;
+ offset = 0;
+ } else if ((sp_orig = value_search(req->addr, &offset))) {
+ if (!strstr(arg, sp_orig->name))
+ return TRUE;
+ } 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_sp = NULL;
+ sp = sp_orig;
+
+ do {
+ if ((sp->type == 't') || (sp->type == 'T')) {
+ if (!first_text_sp)
+ first_text_sp = 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_sp->value;
+ else
+ req->addr = first_text_sp->value + offset;
+ return TRUE;
+ }
+
+ /*
+ * Multiple text symbols with the same name exist.
+ * Display them all and return FALSE.
+ */
+ error(INFO, "duplicate text symbols found: %s\n", sp->name);
+
+ radix_flag = radix == 10 ? SHOW_DEC_OFFS : SHOW_HEX_OFFS;
+ sp = sp_orig;
+
+ do {
+ if ((sp->type == 't') || (sp->type == 'T')) {
+ 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 +1453,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,21 +1515,33 @@ 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 (!user_mode &&
+ !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))) {
+ sp = value_search(req->addr, &offset);
+ if (!user_mode && !sp) {
error(WARNING,
"%lx: no associated kernel symbol found\n",
req->addr);
unfiltered = TRUE;
}
- if (!offset)
+ if (!offset && sp &&
+ ((sp->type == 't') || (sp->type == 'T')))
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