RFC: string search for crash

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

 



Here is a patch to add string search to crash-5.1.1.

It requires the my previous patch for the parse_line routine.

It searches for the specified strings, and for half or more of the
string appearing at the start and end of search blocks (usually pages)
in case the string spans a page boundary.

It is currently invoked with the -c option to search, as in:

crash-5.1.1str> search -k -e 0xffffc90000000000 -c "getty[3895]"
ffff880123b54810: :46 getty[3895]: /dev/ttyS1: No such file or dir

or

crash-5.1.1str> search -k -c -e 0xffffc90000000000 "getty[3895]"
ffff880123b54810: :46 getty[3895]: /dev/ttyS1: No such file or dir

It reports the found string in 48 chars of context (except
at the end of pages), and it reports aligned addresses, so the found
string doesn't always appear at the beginning of the context (as in the
example above).

It could optionally use strncasecmp to do case-insensitive searches.

I simplified it :-) by combining the main and tail searches into one
loop and added a 10-15% performance degradation somewhere.

Here it searches the dump for bugs and danger :-)

crash-5.1.1str> search -k -c -e 0xffffc90000000000 "bugs" "danger"
ffff8801254c0ff8: ug:Debug
ffff880125cd4ff8: ebian/bu
ffff880125ec8870: efb: danger danger! Oopsen imminent!..<6>Mode (%
ffff880125ec8878: ger danger! Oopsen imminent!..<6>Mode (%dx%d) la
ffff880125eee518: ofb: danger danger!  Oopsen imminent!..<3>neofb:
ffff880125eee520: ger danger!  Oopsen imminent!..<3>neofb: neo2200
ffff880125f72000: ger_event.......................................
ffff880125fc3560: ice bugs (default = 0, 128kB max transfer = 0x1,

The first two hits come because half or more of "bugs" occurred at the
end of a page.  The next to the last hit is found because the last
half of "danger" appears at the beginning of a page.

Bob Montgomery




--- memory.c.orig	2011-01-25 14:26:55.000000000 -0700
+++ memory.c	2011-02-01 16:21:28.000000000 -0700
@@ -134,6 +134,7 @@ static int page_to_phys(ulong, physaddr_
 static int phys_to_page(physaddr_t, ulong *); 
 static void display_memory(ulonglong, long, ulong, int); 
 static void search(ulong, ulong, ulong, int, ulong *, int);
+static void string_search(ulong, ulong, int, char **, int);
 static int next_upage(struct task_context *, ulong, ulong *);
 static int next_kpage(ulong, ulong *);
 static ulong last_vmalloc_address(void);
@@ -11284,18 +11285,20 @@ void
 cmd_search(void)
 {
         int c;
+	int str_search = 0;
 	ulong start, end, mask, memtype, len;
 	ulong uvaddr_end;
 	int sflag;
 	struct meminfo meminfo;
 	ulong value_array[MAXARGS];
+	char *string_array[MAXARGS];
 	struct syment *sp;
 
 	start = end = mask = sflag = memtype = len = 0;
 	uvaddr_end = COMMON_VADDR_SPACE() ? (ulong)(-1) : machdep->kvbase;
 	BZERO(value_array, sizeof(ulong) * MAXARGS);
 
-        while ((c = getopt(argcnt, args, "l:uks:e:v:m:")) != EOF) {
+        while ((c = getopt(argcnt, args, "cl:uks:e:v:m:")) != EOF) {
                 switch(c)
                 {
 		case 'u':
@@ -11353,6 +11356,10 @@ cmd_search(void)
                         mask = htol(optarg, FAULT_ON_ERROR, NULL);
                         break;
 
+		case 'c':
+			str_search++;
+			break;
+
                 default:
                         argerrs++;
                         break;
@@ -11447,18 +11454,171 @@ cmd_search(void)
 
 	c = 0;
 	while (args[optind]) {
-		value_array[c] = htol(args[optind], FAULT_ON_ERROR, NULL);
+		if (str_search) 
+			string_array[c] = args[optind];
+		else
+			value_array[c] = htol(args[optind], FAULT_ON_ERROR, NULL);
 		c++;
 		optind++;
 	}
 
-	search(start, end, mask, memtype, value_array, c);
+	if (str_search)
+		string_search(start, end, memtype, string_array, c);
+	else
+		search(start, end, mask, memtype, value_array, c);
 }
 
 /*
  *  Do the work for cmd_search().
  */
 
+#define CONTEXT_SIZE 48
+static void
+string_search(ulong start, ulong end, int memtype, char **value, int vcnt)
+{
+	int i, j, k;
+	int len[MAXARGS];
+	ulong pp, next;
+	char *ubp, *prp, *lastp;
+	int charcnt, lastpage;
+	ulong page;
+	physaddr_t paddr;
+	char *pagebuf;
+
+	if (start & (sizeof(long)-1)) {
+		start &= ~(sizeof(long)-1);
+		error(INFO, "rounding down start address to: %lx\n", start);
+	}
+
+	pagebuf = GETBUF(PAGESIZE());
+	next = start;
+
+	for (pp = VIRTPAGEBASE(start); next < end; next = pp) {
+		lastpage = (VIRTPAGEBASE(next) == VIRTPAGEBASE(end));
+		if (LKCD_DUMPFILE())
+			set_lkcd_nohash();
+
+		/*
+		 *  Keep it virtual for Xen hypervisor.
+		 */
+
+		if (XEN_HYPER_MODE()) {
+                	if (!readmem(pp, KVADDR, pagebuf, PAGESIZE(),
+                    	    "search page", RETURN_ON_ERROR|QUIET)) {
+				if (CRASHDEBUG(1))
+					fprintf(fp, 
+					    "search suspended at: %lx\n", pp);
+				return;
+			}
+			goto virtual;
+		}
+
+                switch (memtype)
+                {
+                case UVADDR:
+                        if (!uvtop(CURRENT_CONTEXT(), pp, &paddr, 0) ||
+                            !phys_to_page(paddr, &page)) { 
+				if (!next_upage(CURRENT_CONTEXT(), pp, &pp)) 
+					return;
+                                continue;
+			}
+                        break;
+
+                case KVADDR:
+                        if (!kvtop(CURRENT_CONTEXT(), pp, &paddr, 0) ||
+                            !phys_to_page(paddr, &page)) {
+				if (!next_kpage(pp, &pp))
+					return;
+                                continue;
+			}
+                        break;
+                }
+
+                if (!readmem(paddr, PHYSADDR, pagebuf, PAGESIZE(),
+                    "search page", RETURN_ON_ERROR|QUIET)) {
+			pp += PAGESIZE();
+			continue;
+		}
+virtual:
+		ubp = (char *)&pagebuf[next - pp];
+		if (lastpage) {
+			if (end == (ulong)(-1))
+				charcnt = PAGESIZE();
+			else
+				charcnt = end - next;
+		} else
+			charcnt = PAGESIZE() - (next - pp);
+
+		for (j = 0; j < vcnt; j++) {
+			len[j] = strlen(value[j]);
+		}
+
+		lastp = &ubp[charcnt];
+
+		/* pre-search for the last half or more of the string at start of area */
+		for (j = 0; j < vcnt; j++) {
+			int min_len = len[j]/2 + len[j]%2;  /* need the big half of odd lengths */
+			if (min_len < 1) 
+				min_len = 1;
+			for (k = len[j] - min_len; k > 0; k--) {
+				if ((charcnt > len[j] - k) && 
+				    (strncmp(value[j]+k, ubp, len[j]-k) == 0)) {
+					int ii = 0;
+					prp = ubp;
+					/* report findings on aligned addresses */
+					if ((ulong)prp & (sizeof(long) - 1))
+						prp = (char *)
+						    ((ulong)prp & ~(sizeof(long) - 1));
+					fprintf(fp, "%lx: ", next & ~(sizeof(long) - 1));
+					while ((ii < CONTEXT_SIZE) && (&prp[ii] < lastp)) {
+						if (isprint(prp[ii]))
+							fprintf(fp, "%c", prp[ii]);
+						else
+							fprintf(fp, ".");
+						ii++;
+					}
+					fprintf(fp, "\n");
+				}
+			}
+		}
+			
+		/* search for full string, and partial string at end of search area */
+		for (i = 0; i < charcnt; i++, ubp++, next++) {
+			for (j = 0; j < vcnt; j++) {
+				int min_len = len[j]/2 + len[j]%2;  /* need the big half of odd lengths */
+				if (min_len < 1) 
+					min_len = 1;
+				if (charcnt >= (i + min_len)) {
+					int slen = (len[j] < (charcnt - i)? len[j]:(charcnt - i));
+					if (strncmp(value[j], ubp, slen) == 0) {
+						int ii = 0;
+						prp = ubp;
+						/* report findings on aligned addresses */
+						if ((ulong)prp & (sizeof(long) - 1))
+							prp = (char *)
+							    ((ulong)prp & ~(sizeof(long) - 1));
+						fprintf(fp, "%lx: ", next & ~(sizeof(long) - 1));
+						while ((ii < CONTEXT_SIZE) && (&prp[ii] < lastp)) {
+							if (isprint(prp[ii]))
+								fprintf(fp, "%c", prp[ii]);
+							else
+								fprintf(fp, ".");
+							ii++;
+						}
+						fprintf(fp, "\n");
+					}
+				} 
+			}
+		}
+
+		if (CRASHDEBUG(1))
+			if ((pp % (1024*1024)) == 0)
+				console("%lx\n", pp);
+
+		pp += PAGESIZE();
+	}
+}
+
 #define SEARCHMASK(X) ((X) | mask) 
 
 static void
--
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