Re: [PATCH 2/2] dis: Report duplicate symbols

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




----- 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

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux