[PATCH] Expanded search capability for crash

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

 



This patch adds options to crash's search command that allow searches
for character strings (-c), unsigned hexadecimal integer values (-w),
and unsigned hexadecimal short values (-h).   The integer and short
values are searched on integer and short alignments respectively.

Strings are searched across contiguous page boundaries, which can cause
possibly confusing behavior since contiguity is affected by the type of
search.  For example, a page-crossing string found in a user virtual
address search might not be found in a kernel virtual address search if
the kernel pages mapped to the user address space are not contiguous.

The patch is for crash-5.1.2 and has been tested on an x86_64 system.


Some last minute caveats on with search due to the parser (worth putting
in help?):

All numbers are interpreted as hex numbers, regardless of starting
character.

Double quotes are magic to crash's parser, so strings of almost anything
can be enclosed in "", for example: "can't".

Single quotes mean nothing, so searching for 'dog' is the same as
searching for "'dog'".


Bob Montgomery
--- memory.c.orig	2011-02-14 16:43:57.000000000 -0700
+++ memory.c	2011-02-23 14:05:52.000000000 -0700
@@ -18,6 +18,7 @@
 
 #include "defs.h"
 #include <sys/mman.h>
+#include <ctype.h>
 
 struct meminfo {           /* general purpose memory information structure */
         ulong cache;       /* used by the various memory searching/dumping */
@@ -71,6 +72,48 @@ struct meminfo {           /* general pu
 	ulong container;
 };
 
+/*
+ * Search modes
+ */
+
+#define SEARCH_ULONG	(0)
+#define SEARCH_UINT	(1)
+#define SEARCH_USHORT	(2)
+#define SEARCH_CHARS	(3)
+#define SEARCH_DEFAULT	(SEARCH_ULONG)
+
+/* search mode information */
+struct searchinfo {
+	int mode;
+	int vcnt;
+	union {
+		/* default ulong search */
+		struct {
+			ulong value[MAXARGS];
+			ulong mask;
+		} s_ulong;
+
+		/* uint search */
+		struct {
+			uint value[MAXARGS];
+			uint mask;
+		} s_uint;
+
+		/* ushort search */
+		struct {
+			ushort value[MAXARGS];
+			ushort mask;
+		} s_ushort;
+
+		/* string (chars) search */
+		struct {
+			char *value[MAXARGS];
+			int len[MAXARGS];
+			int started_flag;  /* string search needs history */
+		} s_chars;
+	} s_parms;
+};
+
 static char *memtype_string(int, int);
 static char *error_handle_string(ulong);
 static void dump_mem_map(struct meminfo *);
@@ -132,8 +175,16 @@ static int dump_page_lists(struct meminf
 static void dump_kmeminfo(void);
 static int page_to_phys(ulong, physaddr_t *); 
 static void display_memory(ulonglong, long, ulong, int); 
-static void search_virtual(ulong, ulong, ulong, int, ulong *, int);
-static void search_physical(ulonglong, ulonglong, ulong, ulong *, int);
+static ulong search_ulong(ulong *, ulong, int, struct searchinfo *);
+static ulong search_uint(ulong *, ulong, int, struct searchinfo *);
+static ulong search_ushort(ulong *, ulong, int, struct searchinfo *);
+static ulong search_chars(ulong *, ulong, int, struct searchinfo *);
+static ulonglong search_ulong_p(ulong *, ulonglong, int, struct searchinfo *);
+static ulonglong search_uint_p(ulong *, ulonglong, int, struct searchinfo *);
+static ulonglong search_ushort_p(ulong *, ulonglong, int, struct searchinfo *);
+static ulonglong search_chars_p(ulong *, ulonglong, int, struct searchinfo *);
+static void search_virtual(ulong, ulong, int, struct searchinfo *);
+static void search_physical(ulonglong, ulonglong, struct searchinfo *);
 static int next_upage(struct task_context *, ulong, ulong *);
 static int next_kpage(ulong, ulong *);
 static int next_physpage(ulonglong, ulonglong *);
@@ -11322,6 +11373,8 @@ generic_get_kvaddr_ranges(struct vaddr_r
  *  space".  For processors with ambiguous user/kernel address spaces,
  *  -u or -k must be used (with or without -s) as a differentiator.
  */
+
+
 void
 cmd_search(void)
 {
@@ -11331,7 +11384,7 @@ cmd_search(void)
 	ulong uvaddr_start, uvaddr_end;
 	ulong kvaddr_start, kvaddr_end, range_start, range_end;
 	int sflag, Kflag, Vflag, pflag;
-	ulong value_array[MAXARGS];
+	struct searchinfo searchinfo;
 	struct syment *sp;
 	struct node_table *nt;
 	struct vaddr_range vaddr_ranges[MAX_KVADDR_RANGES];
@@ -11343,7 +11396,7 @@ cmd_search(void)
 	kvaddr_start = kvaddr_end = 0;
 	uvaddr_start = UNINITIALIZED;
 	uvaddr_end = COMMON_VADDR_SPACE() ? (ulong)(-1) : machdep->kvbase;
-	BZERO(value_array, sizeof(ulong) * MAXARGS);
+	BZERO(&searchinfo, sizeof(struct searchinfo));
 
 	vrp = &vaddr_ranges[0];
 	ranges = machdep->get_kvaddr_ranges(vrp);
@@ -11374,7 +11427,9 @@ cmd_search(void)
 		}
 	}
 
-        while ((c = getopt(argcnt, args, "l:ukKVps:e:v:m:")) != EOF) {
+	searchinfo.mode = SEARCH_ULONG;	/* default search */
+
+        while ((c = getopt(argcnt, args, "l:ukKVps:e:v:m:hwc")) != EOF) {
                 switch(c)
                 {
 		case 'u':
@@ -11454,6 +11509,27 @@ cmd_search(void)
                         mask = htol(optarg, FAULT_ON_ERROR, NULL);
                         break;
 
+		case 'h':
+			if (searchinfo.mode != SEARCH_DEFAULT)
+				error(INFO, "WARNING: overriding previously"
+					" set search mode with \"h\"\n");
+			searchinfo.mode = SEARCH_USHORT;
+			break;
+
+		case 'w':
+			if (searchinfo.mode != SEARCH_DEFAULT)
+				error(INFO, "WARNING: overriding previously"
+					" set search mode with \"w\"\n");
+			searchinfo.mode = SEARCH_UINT;
+			break;
+
+		case 'c':
+			if (searchinfo.mode != SEARCH_DEFAULT)
+				error(INFO, "WARNING: overriding previously"
+					" set search type with \"c\"\n");
+			searchinfo.mode = SEARCH_CHARS;
+			break;
+
                 default:
                         argerrs++;
                         break;
@@ -11583,28 +11659,76 @@ cmd_search(void)
 		break;
 	}
 
-	c = 0;
+	if (mask) {
+		switch (searchinfo.mode) 
+		{
+		case SEARCH_ULONG:
+			searchinfo.s_parms.s_ulong.mask = mask;
+			break;
+		case SEARCH_UINT:
+			searchinfo.s_parms.s_uint.mask = mask;
+			break;
+		case SEARCH_USHORT:
+			searchinfo.s_parms.s_ushort.mask = mask;
+			break;
+		case SEARCH_CHARS:
+			error(INFO, "mask ignored on string search\n");
+			break;
+		}
+	}
+			
+		
+	searchinfo.vcnt = 0;
 	while (args[optind]) {
-		value_array[c] = htol(args[optind], FAULT_ON_ERROR, NULL);
-		c++;
+		switch (searchinfo.mode) 
+		{
+		case SEARCH_ULONG:
+			searchinfo.s_parms.s_ulong.value[searchinfo.vcnt] = 
+				htol(args[optind], FAULT_ON_ERROR, NULL);
+			searchinfo.vcnt++;
+			break;
+		case SEARCH_UINT:
+			searchinfo.s_parms.s_uint.value[searchinfo.vcnt] = 
+				htol(args[optind], FAULT_ON_ERROR, NULL);
+			searchinfo.vcnt++;
+			break;
+		case SEARCH_USHORT:
+			searchinfo.s_parms.s_ushort.value[searchinfo.vcnt] = 
+				htol(args[optind], FAULT_ON_ERROR, NULL);
+			searchinfo.vcnt++;
+			break;
+		case SEARCH_CHARS:
+			/* parser can deliver empty strings */
+			if (strlen(args[optind])) { 
+				searchinfo.s_parms.s_chars.value[searchinfo.vcnt] = 
+					args[optind];
+				searchinfo.s_parms.s_chars.len[searchinfo.vcnt] = 
+					strlen(args[optind]);
+				searchinfo.vcnt++;
+			}
+			break;
+		}
 		optind++;
 	}
 
+	if (!searchinfo.vcnt)
+                cmd_usage(pc->curcmd, SYNOPSIS);
+	
 	switch (memtype)
 	{
 	case PHYSADDR:
-		search_physical(start, end, mask, value_array, c);
+		search_physical(start, end, &searchinfo);
 		break;
 
 	case UVADDR:
-		search_virtual(uvaddr_start, uvaddr_end, mask, memtype, 
-			value_array, c);
+		search_virtual(uvaddr_start, uvaddr_end, memtype, 
+			&searchinfo);
 		break;
 
 	case KVADDR:
 		if (XEN_HYPER_MODE()) {
-			search_virtual(kvaddr_start, kvaddr_end, mask, 
-				memtype, value_array, c);
+			search_virtual(kvaddr_start, kvaddr_end, memtype, 
+				&searchinfo);
 			break;
 		}
 
@@ -11637,8 +11761,8 @@ cmd_search(void)
 				break;
 			}
 
-			search_virtual(range_start, range_end, mask,
-                                        memtype, value_array, c);
+			search_virtual(range_start, range_end, memtype,
+					 &searchinfo);
 		}
 		break;
 	}
@@ -11650,10 +11774,306 @@ cmd_search(void)
 
 #define SEARCHMASK(X) ((X) | mask) 
 
+static ulong
+search_ulong(ulong *bufptr, ulong addr, int longcnt, struct searchinfo *si)
+{
+	int i, j;
+	ulong mask = si->s_parms.s_ulong.mask;
+	for (i = 0; i < longcnt; i++, bufptr++, addr += sizeof(long)) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (SEARCHMASK(*bufptr) == SEARCHMASK(si->s_parms.s_ulong.value[j]))
+				fprintf(fp, "%lx: %lx\n", addr, *bufptr);
+                }
+	}
+	return addr;
+}
+
+/* phys search uses ulonglong address representation */
+static ulonglong
+search_ulong_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si)
+{
+	int i, j;
+	ulong mask = si->s_parms.s_ulong.mask;
+	for (i = 0; i < longcnt; i++, bufptr++, addr += sizeof(long)) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (SEARCHMASK(*bufptr) == SEARCHMASK(si->s_parms.s_ulong.value[j]))
+				fprintf(fp, "%llx: %lx\n", addr, *bufptr);
+                }
+	}
+	return addr;
+}
+
+static ulong
+search_uint(ulong *bufptr, ulong addr, int longcnt, struct searchinfo *si)
+{
+	int i, j;
+	int cnt = longcnt * (sizeof(long)/sizeof(int));
+	uint *ptr = (uint *)bufptr;
+	uint mask = si->s_parms.s_uint.mask;
+
+	for (i = 0; i < cnt; i++, ptr++, addr += sizeof(int)) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (SEARCHMASK(*ptr) == SEARCHMASK(si->s_parms.s_uint.value[j]))
+				fprintf(fp, "%lx: %x\n", addr, *ptr);
+                }
+	}
+	return addr;
+}
+
+/* phys search uses ulonglong address representation */
+static ulonglong
+search_uint_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si)
+{
+	int i, j;
+	int cnt = longcnt * (sizeof(long)/sizeof(int));
+	uint *ptr = (uint *)bufptr;
+	uint mask = si->s_parms.s_uint.mask;
+
+	for (i = 0; i < cnt; i++, ptr++, addr += sizeof(int)) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (SEARCHMASK(*ptr) == SEARCHMASK(si->s_parms.s_uint.value[j]))
+				fprintf(fp, "%llx: %x\n", addr, *ptr);
+                }
+	}
+	return addr;
+}
+
+static ulong
+search_ushort(ulong *bufptr, ulong addr, int longcnt, struct searchinfo *si)
+{
+	int i, j;
+	int cnt = longcnt * (sizeof(long)/sizeof(short));
+	ushort *ptr = (ushort *)bufptr;
+	ushort mask = si->s_parms.s_ushort.mask;
+
+	for (i = 0; i < cnt; i++, ptr++, addr += sizeof(short)) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (SEARCHMASK(*ptr) == SEARCHMASK(si->s_parms.s_ushort.value[j]))
+				fprintf(fp, "%lx: %x\n", addr, *ptr);
+                }
+	}
+	return addr;
+}
+
+/* phys search uses ulonglong address representation */
+static ulonglong
+search_ushort_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si)
+{
+	int i, j;
+	int cnt = longcnt * (sizeof(long)/sizeof(short));
+	ushort *ptr = (ushort *)bufptr;
+	ushort mask = si->s_parms.s_ushort.mask;
+
+	for (i = 0; i < cnt; i++, ptr++, addr += sizeof(short)) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (SEARCHMASK(*ptr) == SEARCHMASK(si->s_parms.s_ushort.value[j]))
+				fprintf(fp, "%llx: %x\n", addr, *ptr);
+                }
+	}
+	return addr;
+}
+
+/*
+ * String search "memory" to remember possible matches that cross
+ * page (or search buffer) boundaries.
+ * The cross_match zone is the last strlen-1 chars of the page for
+ * each of the possible targets.
+ */
+struct cross_match {
+	int cnt;	/* possible hits in the cross_match zone */
+	ulong addr; 	/* starting addr of crossing match zone for this target */
+	ulonglong addr_p; /* for physical search */
+	char hit[BUFSIZE]; /* array of hit locations in the crossing match zone */
+			/* This should really be the much-smaller MAXARGLEN, but
+			 * no one seems to be enforcing that in the parser.
+			 */
+} cross[MAXARGS];
+
+ulong cross_match_next_addr; /* the expected starting value of the next page */
+ulong cross_match_next_addr_p; /* the expected starting value of the next physical page */
+	
+#define CHARS_CTX 56
+
 static void
-search_virtual(ulong start, ulong end, ulong mask, int memtype, ulong *value, int vcnt)
+report_match(ulong addr, char *ptr1, int len1, char *ptr2, int len2)
+{
+	int i;
+	fprintf(fp, "%lx: ", addr);
+	for (i = 0; i < len1; i++) {
+		if (isprint(ptr1[i]))
+			fprintf(fp, "%c", ptr1[i]);
+		else
+			fprintf(fp, ".");
+	}
+	for (i = 0; i < len2; i++) {
+		if (isprint(ptr2[i]))
+			fprintf(fp, "%c", ptr2[i]);
+		else
+			fprintf(fp, ".");
+	}
+	fprintf(fp, "\n");	
+}
+	
+static ulong
+search_chars(ulong *bufptr, ulong addr, int longcnt, struct searchinfo *si)
+{
+	int i, j;
+	int len;
+	char *target;
+	int charcnt = longcnt * sizeof(long);
+	char *ptr = (char *)bufptr;
+
+	/* is this the first page of this search? */
+	if (si->s_parms.s_chars.started_flag == 0) {
+		for (j = 0; j < si->vcnt; j++) {
+			cross[j].cnt = 0;   /* no hits */
+		}
+		cross_match_next_addr = (ulong)-1; /* no page match for first page */
+		si->s_parms.s_chars.started_flag++;
+	}
+
+	if (cross_match_next_addr == addr) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (cross[j].cnt) {
+				target = si->s_parms.s_chars.value[j];
+				len = si->s_parms.s_chars.len[j];
+				for (i = 0; i < len - 1; i++) {
+					if (cross[j].hit[i] &&
+						!strncmp(&target[len - 1 - i], ptr, i + 1)) 
+							report_match(cross[j].addr + i, 
+									target, len,
+									&ptr[i+1], 
+									CHARS_CTX - len);
+				}
+			}
+		}
+	}
+
+	/* set up for possible cross matches on this page */
+	cross_match_next_addr = addr + charcnt;
+	for (j = 0; j < si->vcnt; j++) {
+		len = si->s_parms.s_chars.len[j];
+		cross[j].cnt = 0;
+		cross[j].addr = addr + longcnt * sizeof(long) - (len - 1);
+		for (i = 0; i < len - 1; i++) 
+			cross[j].hit[i] = 0;
+	}
+	
+	for (i = 0; i < charcnt; i++, ptr++, addr++) {
+		for (j = 0; j < si->vcnt; j++) {
+			target = si->s_parms.s_chars.value[j];
+			len = si->s_parms.s_chars.len[j];
+			if ((i + len) > charcnt) {
+				/* check for cross match */
+				if (!strncmp(target, ptr, charcnt - i)) {
+					cross[j].hit[len + i - charcnt - 1] = 1;
+					cross[j].cnt++;
+				} 
+			} else {
+				if (!strncmp(target, ptr, len)) {
+					int slen = CHARS_CTX;
+					if ((i + CHARS_CTX) > charcnt) 
+						slen = charcnt - i;
+					report_match(addr, ptr, slen, (char *)0, 0);
+				}
+			}
+		}
+	}
+	return addr;
+}
+						
+
+static void
+report_match_p(ulonglong addr, char *ptr1, int len1, char *ptr2, int len2)
+{
+	int i;
+	fprintf(fp, "%llx: ", addr);
+	for (i = 0; i < len1; i++) {
+		if (isprint(ptr1[i]))
+			fprintf(fp, "%c", ptr1[i]);
+		else
+			fprintf(fp, ".");
+	}
+	for (i = 0; i < len2; i++) {
+		if (isprint(ptr2[i]))
+			fprintf(fp, "%c", ptr2[i]);
+		else
+			fprintf(fp, ".");
+	}
+	fprintf(fp, "\n");	
+}
+
+static ulonglong
+search_chars_p(ulong *bufptr, ulonglong addr_p, int longcnt, struct searchinfo *si)
 {
 	int i, j;
+	int len;
+	char *target;
+	int charcnt = longcnt * sizeof(long);
+	char *ptr = (char *)bufptr;
+
+	/* is this the first page of this search? */
+	if (si->s_parms.s_chars.started_flag == 0) {
+		for (j = 0; j < si->vcnt; j++) {
+			cross[j].cnt = 0;   /* no hits */
+		}
+		cross_match_next_addr_p = (ulonglong)-1; /* no page match for first page */
+		si->s_parms.s_chars.started_flag++;
+	}
+
+	if (cross_match_next_addr_p == addr_p) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (cross[j].cnt) {
+				target = si->s_parms.s_chars.value[j];
+				len = si->s_parms.s_chars.len[j];
+				for (i = 0; i < len - 1; i++) {
+					if (cross[j].hit[i] &&
+						!strncmp(&target[len - 1 - i], ptr, i + 1)) 
+							report_match_p(cross[j].addr_p + i, 
+									target, len,
+									&ptr[i+1], 
+									CHARS_CTX - len);
+				}
+			}
+		}
+	}
+
+	/* set up for possible cross matches on this page */
+	cross_match_next_addr_p = addr_p + charcnt;
+	for (j = 0; j < si->vcnt; j++) {
+		len = si->s_parms.s_chars.len[j];
+		cross[j].cnt = 0;
+		cross[j].addr_p = addr_p + longcnt * sizeof(long) - (len - 1);
+		for (i = 0; i < len - 1; i++) 
+			cross[j].hit[i] = 0;
+	}
+	
+	for (i = 0; i < charcnt; i++, ptr++, addr_p++) {
+		for (j = 0; j < si->vcnt; j++) {
+			target = si->s_parms.s_chars.value[j];
+			len = si->s_parms.s_chars.len[j];
+			if ((i + len) > charcnt) {
+				/* check for cross match */
+				if (!strncmp(target, ptr, charcnt - i)) {
+					cross[j].hit[len + i - charcnt - 1] = 1;
+					cross[j].cnt++;
+				} 
+			} else {
+				if (!strncmp(target, ptr, len)) {
+					int slen = CHARS_CTX;
+					if ((i + CHARS_CTX) > charcnt) 
+						slen = charcnt - i;
+					report_match_p(addr_p, ptr, slen, (char *)0, 0);
+				}
+			}
+		}
+	}
+	return addr_p;
+}
+
+static void
+search_virtual(ulong start, ulong end, int memtype, struct searchinfo *si)
+{
 	ulong pp, next, *ubp;
 	int wordcnt, lastpage;
 	ulong page;
@@ -11738,11 +12158,24 @@ virtual:
 		} else
 			wordcnt = (PAGESIZE() - (next - pp))/sizeof(long);
 
-		for (i = 0; i < wordcnt; i++, ubp++, next += sizeof(long)) {
-			for (j = 0; j < vcnt; j++) {
-				if (SEARCHMASK(*ubp) == SEARCHMASK(value[j])) 
-					fprintf(fp, "%lx: %lx\n", next, *ubp);
-			}
+		switch (si->mode)
+		{
+		case SEARCH_ULONG:
+			next = search_ulong(ubp, next, wordcnt, si);
+			break;
+		case SEARCH_UINT:
+			next = search_uint(ubp, next, wordcnt, si);
+			break;
+		case SEARCH_USHORT:
+			next = search_ushort(ubp, next, wordcnt, si);
+			break;
+		case SEARCH_CHARS:
+			next = search_chars(ubp, next, wordcnt, si);
+			break;
+		default:
+			/* unimplemented search type */
+			next += wordcnt * (sizeof(long));
+			break;
 		}
 
 		if (CRASHDEBUG(1))
@@ -11764,9 +12197,8 @@ done:
 
 
 static void
-search_physical(ulonglong start_in, ulonglong end_in, ulong mask, ulong *value, int vcnt)
+search_physical(ulonglong start_in, ulonglong end_in, struct searchinfo *si)
 {
-	int i, j;
 	ulong *ubp;
 	int wordcnt, lastpage;
 	ulonglong pnext, ppp;
@@ -11815,12 +12247,25 @@ search_physical(ulonglong start_in, ulon
                 } else
                         wordcnt = (PAGESIZE() - (pnext - ppp))/sizeof(long);
 
-                for (i = 0; i < wordcnt; i++, ubp++, pnext += sizeof(long)) {
-                        for (j = 0; j < vcnt; j++) {
-                                if (SEARCHMASK(*ubp) == SEARCHMASK(value[j]))
-					fprintf(fp, "%llx: %lx\n", pnext, *ubp);
-                        }
-                }
+		switch (si->mode)
+		{
+		case SEARCH_ULONG:
+			pnext = search_ulong_p(ubp, pnext, wordcnt, si);
+			break;
+		case SEARCH_UINT:
+			pnext = search_uint_p(ubp, pnext, wordcnt, si);
+			break;
+		case SEARCH_USHORT:
+			pnext = search_ushort_p(ubp, pnext, wordcnt, si);
+			break;
+		case SEARCH_CHARS:
+			pnext = search_chars_p(ubp, pnext, wordcnt, si);
+			break;
+		default:
+			/* unimplemented search type */
+			pnext += wordcnt * (sizeof(long));
+			break;
+		}
 
 		ppp += PAGESIZE();
 	}
--- help.c.orig	2011-02-18 12:11:54.000000000 -0700
+++ help.c	2011-02-23 14:48:05.000000000 -0700
@@ -2100,7 +2100,8 @@ NULL               
 char *help_search[] = {
 "seach",
 "search memory",
-"[-s start | -[kKV] | -u | -p ] [-e end | -l length] [-m mask] value ...",
+"[-s start] [ -[kKV] | -u | -p ] [-e end | -l length] [-m mask]"
+"                 [ -c | -w | -h ] value ...",
 "  This command searches for a given value within a range of user virtual, kernel",
 "  virtual, or physical memory space.  If no end nor length value is entered, ",
 "  then the search stops at the end of user virtual, kernel virtual, or physical",
@@ -2131,7 +2132,10 @@ char *help_search[] = {
 "             appropriate for the memory type specified.",
 "  -l length  Length in bytes of address range to search.",
 "    -m mask  Ignore the bits that are set in the hexadecimal mask value.",
-"      value  Search for this hexadecimal value.",
+"         -c  Search for character string values instead of unsigned longs",
+"         -w  Search for unsigned hexadecimal ints instead of unsigned longs",
+"         -h  Search for unsigned hexadecimal shorts instead of unsigned longs",
+"      value  Search for a hexadecimal long unless modified by -c, -w, or -h",
 " ",
 "  If -k, -K, -V, -u or -p are not used, then the search defaults to kernel",
 "  virtual address space.  The starting address must be long-word aligned. ",
@@ -2197,6 +2201,28 @@ char *help_search[] = {
 "    48579a4: babe2600",
 "    4864a68: babe2600",
 "    ...",
+"\n  Search physical memory for all instances of 0xbabe occuring in the",
+"  upper 16 bits of each 32-bit word on a 64-bit system:\n",
+"    %s> search -p babe0000 -m ffff -w",
+"    102e248: babe1174",
+"    11d2f90: babe813d",
+"    122d3ad70: babe6b27",
+"    124d8cd30: babe3dc8",
+"    124d8eefc: babef981",
+"    124d8f060: babe3dc8",
+"    124d8f17c: babefc81",
+"    ...",
+"\n  Search kernel memory for all instances of 32-bit value 0xbabe1174",
+"  on a 64-bit system:\n",
+"    %s> search -k -w babe1174",
+"    ffff88000102e248: babe1174",
+"    ffffffff8102e248: babe1174",
+"\n  Search kernel memory for two strings:\n",
+"    %s> search -k -c \"can\'t allocate memory\" \"Failure to\"",
+"    ffff8800013ddec1: can\'t allocate memory for key lists..<3>%%s %%s: error con",
+"    ffff8801258be748: Failure to install fence: %%d..<3>[drm:%%s] *ERROR* Failed",
+"    ffff880125f07ec9: can\'t allocate memory..<3>ACPI: Invalid data..Too many d",
+"    ffffffff813ddec1: can\'t allocate memory for key lists..<3>%%s %%s: error con",
 NULL               
 };
 
--- tools.c.orig	2011-02-18 12:19:16.000000000 -0700
+++ tools.c	2011-02-18 12:21:11.000000000 -0700
@@ -182,7 +182,7 @@ parse_line(char *str, char *argv[])
 	                i++;
 	            }
 
-                    if (str[i] == '(') {     
+                    if (!string && str[i] == '(') {     
                         expression = TRUE;
                     }
 	
--
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