[PATCH V2] Add -C option for search

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

 



Hello Dave,

I made a new patch to implement the -C option for search. This time the
patch is accomplished in a simple manner according to your advice.

Thanks.
Zhang Yanfei
>From 0cde596e587b2344948118c04ed7416d68ae5fe2 Mon Sep 17 00:00:00 2001
From: zhangyanfei <zhangyanfei@xxxxxxxxxxxxxx>
Date: Thu, 9 Feb 2012 15:32:11 +0800
Subject: [PATCH] Add option -C for sub-command search.

Signed-off-by: zhangyanfei <zhangyanfei@xxxxxxxxxxxxxx>
---
 help.c   |    5 +-
 memory.c |  271 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 261 insertions(+), 15 deletions(-)

diff --git a/help.c b/help.c
index f752283..d3317f4 100755
--- a/help.c
+++ b/help.c
@@ -2343,7 +2343,7 @@ char *help_search[] = {
 "seach",
 "search memory",
 "[-s start] [ -[kKV] | -u | -p ] [-e end | -l length] [-m mask]\n"
-"         -[cwh] value ...",
+"         [-C num] -[cwh] 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",
@@ -2374,6 +2374,9 @@ 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.",
+"     -C num  Also display memory contents just before and after value.  The size",
+"             of the memory displayed before(after) value is num * sizeof(value).",
+"             Note, this option is ignored when -c is specified.",
 "         -c  Search for character string values instead of unsigned longs.  If",
 "             the string contains any space(s), it must be encompassed by double",
 "             quotes.",
diff --git a/memory.c b/memory.c
index 55a184b..6672770 100755
--- a/memory.c
+++ b/memory.c
@@ -87,6 +87,8 @@ struct meminfo {           /* general purpose memory information structure */
 struct searchinfo {
 	int mode;
 	int vcnt;
+	int c_num;
+	ulong memtype;
 	union {
 		/* default ulong search */
 		struct {
@@ -176,6 +178,8 @@ static int dump_page_lists(struct meminfo *);
 static void dump_kmeminfo(void);
 static int page_to_phys(ulong, physaddr_t *); 
 static void display_memory(ulonglong, long, ulong, int, void *); 
+static int get_search_page(ulonglong, char *, struct searchinfo *);
+static void display_with_pre_and_post(void *, ulonglong, ulonglong, struct searchinfo *);
 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 *);
@@ -11617,7 +11621,7 @@ generic_get_kvaddr_ranges(struct vaddr_range *rp)
 void
 cmd_search(void)
 {
-        int i, c, ranges;
+        int i, c, ranges, c_num;
 	ulonglong start, end;
 	ulong mask, memtype, len;
 	ulong uvaddr_start, uvaddr_end;
@@ -11631,6 +11635,7 @@ cmd_search(void)
 
 #define vaddr_overflow(ADDR) (BITS32() && ((ADDR) > 0xffffffffULL))
 
+	c_num = 0;
 	start = end = mask = sflag = pflag = Kflag = Vflag = memtype = len = 0;
 	kvaddr_start = kvaddr_end = 0;
 	uvaddr_start = UNINITIALIZED;
@@ -11668,7 +11673,7 @@ cmd_search(void)
 
 	searchinfo.mode = SEARCH_ULONG;	/* default search */
 
-        while ((c = getopt(argcnt, args, "l:ukKVps:e:v:m:hwc")) != EOF) {
+        while ((c = getopt(argcnt, args, "l:ukKVps:e:v:m:hwcC:")) != EOF) {
                 switch(c)
                 {
 		case 'u':
@@ -11769,6 +11774,10 @@ cmd_search(void)
 			searchinfo.mode = SEARCH_CHARS;
 			break;
 
+		case 'C':
+			c_num = dtoi(optarg, FAULT_ON_ERROR, NULL);
+			break;
+
                 default:
                         argerrs++;
                         break;
@@ -11790,6 +11799,8 @@ cmd_search(void)
         if (argerrs || !sflag || !args[optind] || (len && end) || !memtype)
                 cmd_usage(pc->curcmd, SYNOPSIS);
 
+	searchinfo.memtype = memtype;
+
 	/*
 	 *  Verify starting address.
 	 */
@@ -11916,6 +11927,37 @@ cmd_search(void)
 		}
 	}
 			
+	if (c_num) {
+		switch (searchinfo.mode)
+		{
+		case SEARCH_ULONG:
+			if (c_num > PAGESIZE()/sizeof(long)) {
+				error(INFO, "WARNING: too many numbers and"
+					" -C option is ignored\n");
+				c_num = 0;
+			}
+			break;
+		case SEARCH_UINT:
+			if (c_num > PAGESIZE()/sizeof(int)) {
+				error(INFO, "WARNING: too many numbers and"
+					" -C option is ignored\n");
+				c_num = 0;
+			}
+			break;
+		case SEARCH_USHORT:
+			if (c_num > PAGESIZE()/sizeof(short)) {
+				error(INFO, "WARNING: too many numbers and"
+					" -C option is ignored\n");
+				c_num = 0;
+			}
+			break;
+		case SEARCH_CHARS:
+			error(INFO, "-C option ignored on string search\n");
+			c_num = 0;
+			break;
+		}
+	}
+	searchinfo.c_num = c_num;
 		
 	searchinfo.vcnt = 0;
 	while (args[optind]) {
@@ -12013,15 +12055,191 @@ cmd_search(void)
 
 #define SEARCHMASK(X) ((X) | mask) 
 
+static int
+get_search_page(ulonglong ppp, char *pagebuf, struct searchinfo *si)
+{
+	ulong page;
+	physaddr_t paddr;
+	ulong pp;
+	ulong memtype;
+
+	pp = (ulong)ppp;
+	memtype = si->memtype;
+
+	if (memtype == PHYSADDR) {
+		if (!phys_to_page(ppp, &page) ||
+		    !readmem(ppp, PHYSADDR, pagebuf, PAGESIZE(),
+			     "search page", RETURN_ON_ERROR|QUIET)) {
+			return 0;
+		}
+		return 1;
+	}
+
+	/*
+	 *  Keep it virtual for Xen hypervisor.
+	 */
+	if (XEN_HYPER_MODE()) {
+		if (!readmem(pp, KVADDR, pagebuf, PAGESIZE(),
+                    "search page", RETURN_ON_ERROR|QUIET)) {
+			return 0;
+		}
+		return 1;
+	}
+
+        switch (memtype)
+        {
+        case UVADDR:
+                if (!uvtop(CURRENT_CONTEXT(), pp, &paddr, 0) ||
+                    !phys_to_page(paddr, &page)) {
+			return 0;
+		}
+                break;
+
+        case KVADDR:
+                if (!kvtop(CURRENT_CONTEXT(), pp, &paddr, 0) ||
+                    !phys_to_page(paddr, &page)) {
+                        return 0;
+		}
+                break;
+        }
+
+        if (!readmem(paddr, PHYSADDR, pagebuf, PAGESIZE(),
+            "search page", RETURN_ON_ERROR|QUIET)) {
+		return 0;
+	}
+
+	return 1;
+}
+
+#define print_addr(addr, si) \
+do { \
+	if (si->memtype == PHYSADDR) \
+		fprintf(fp, "%llx: ", addr); \
+	else \
+		fprintf(fp, "%lx: ", (ulong)addr); \
+} while (0);
+
+#define print_value(bufptr, offset, si) \
+do { \
+	switch(si->mode) \
+	{ \
+	case SEARCH_ULONG: \
+		fprintf(fp, "%lx ", *((ulong *)bufptr + offset)); \
+		break; \
+	case SEARCH_UINT: \
+		fprintf(fp, "%x ", *((uint *)bufptr + offset)); \
+		break; \
+	case SEARCH_USHORT: \
+		fprintf(fp, "%x ", *((ushort *)bufptr + offset)); \
+		break; \
+	} \
+} while (0);
+
+static void
+display_with_pre_and_post(void *bufptr, ulonglong addr_base, ulonglong addr, struct searchinfo *si)
+{
+	int cnt, cnt1, cnt2, wordcnt, exist;
+	int i, c_num, t, offset;
+	char *buf;
+	ulonglong pre_addr_base, post_addr_base, tmpaddr;
+
+	switch (si->mode)
+	{
+	case SEARCH_USHORT:
+		t = sizeof(ushort);
+		break;
+	case SEARCH_UINT:
+		t = sizeof(uint);
+		break;
+	case SEARCH_ULONG:
+	default:
+		t = sizeof(ulong);
+		break;
+	}
+
+	cnt = offset = 0;
+	cnt1 = (addr - addr_base) / t;
+	cnt2 = (PAGESIZE() - (addr - addr_base)) / t - 1;
+	wordcnt = PAGESIZE() / t;
+	exist = 0;
+	c_num = si->c_num;
+	pre_addr_base = post_addr_base = addr_base;
+
+	buf = GETBUF(PAGESIZE());
+
+	if (cnt1 < c_num && addr_base >= PAGESIZE()) { /* read pre-page */
+		pre_addr_base -= PAGESIZE();
+		exist = get_search_page(pre_addr_base, buf, si);
+	}
+
+	if (exist) {
+		cnt = cnt1 - c_num + wordcnt;
+		tmpaddr = pre_addr_base + cnt * t;
+		print_addr(tmpaddr, si);
+		for (i = cnt; i < wordcnt; i++)
+			print_value(buf, i, si);
+	} else {
+		if (cnt1 >= c_num) {
+			tmpaddr = addr - c_num * t;
+			print_addr(tmpaddr, si);
+		} else if (cnt1 != 0)
+			print_addr(addr_base, si);
+	}
+
+	cnt = cnt1 < c_num ? 0 : cnt1 - c_num;
+	for (i = cnt; i < cnt1; i++) {
+		offset = i - cnt1;
+		print_value(bufptr, offset, si);
+	}
+	if (exist || cnt1 != 0)
+		fprintf(fp, "\n");
+
+	print_addr(addr, si);
+	print_value(bufptr, 0, si);
+
+	exist = 0;
+	if (cnt2 < c_num) { /* read post-page */
+		post_addr_base += PAGESIZE();
+		exist = get_search_page(post_addr_base, buf, si);
+	}
+
+	cnt = cnt2 < c_num ? cnt2 : c_num - 1;
+	for (i = 1; i <= cnt; i++)
+		print_value(bufptr, i, si);
+
+	if (cnt2 >= c_num) {
+		fprintf(fp, "\n");
+		tmpaddr = addr + c_num * t;
+		print_addr(tmpaddr, si);
+		print_value(bufptr, c_num, si);
+	} else {
+		if (exist) {
+			cnt = c_num - cnt2 - 1;
+			for (i = 0; i < cnt; i++)
+				print_value(buf, i, si);
+			fprintf(fp, "\n");
+			tmpaddr = post_addr_base + cnt * t;
+			print_addr(tmpaddr, si);
+			print_value(buf, cnt, si);
+		}
+	}
+	fprintf(fp, "\n--\n");
+}
+
 static ulong
 search_ulong(ulong *bufptr, ulong addr, int longcnt, struct searchinfo *si)
 {
 	int i, j;
+	ulong addr_base = VIRTPAGEBASE(addr);
 	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);
+			if (SEARCHMASK(*bufptr) == SEARCHMASK(si->s_parms.s_ulong.value[j])) {
+				if (si->c_num)
+					display_with_pre_and_post(bufptr, addr_base, addr, si);
+				else
+					fprintf(fp, "%lx: %lx\n", addr, *bufptr);
+			}
                 }
 	}
 	return addr;
@@ -12032,11 +12250,16 @@ static ulonglong
 search_ulong_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si)
 {
 	int i, j;
+	ulonglong addr_base = PHYSPAGEBASE(addr);
 	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);
+			if (SEARCHMASK(*bufptr) == SEARCHMASK(si->s_parms.s_ulong.value[j])) {
+				if (si->c_num)
+					display_with_pre_and_post(bufptr, addr_base, addr, si);
+				else
+					fprintf(fp, "%llx: %lx\n", addr, *bufptr);
+			}
                 }
 	}
 	return addr;
@@ -12048,12 +12271,17 @@ 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;
+	ulong addr_base = VIRTPAGEBASE(addr);
 	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);
+			if (SEARCHMASK(*ptr) == SEARCHMASK(si->s_parms.s_uint.value[j])) {
+				if (si->c_num)
+					display_with_pre_and_post(ptr, addr_base, addr, si);
+				else
+					fprintf(fp, "%lx: %x\n", addr, *ptr);
+			}
                 }
 	}
 	return addr;
@@ -12066,12 +12294,17 @@ 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;
+	ulonglong addr_base = PHYSPAGEBASE(addr);
 	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);
+			if (SEARCHMASK(*ptr) == SEARCHMASK(si->s_parms.s_uint.value[j])) {
+				if (si->c_num)
+					display_with_pre_and_post(ptr, addr_base, addr, si);
+				else
+					fprintf(fp, "%llx: %x\n", addr, *ptr);
+			}
                 }
 	}
 	return addr;
@@ -12083,12 +12316,17 @@ 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;
+	ulong addr_base = VIRTPAGEBASE(addr);
 	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);
+			if (SEARCHMASK(*ptr) == SEARCHMASK(si->s_parms.s_ushort.value[j])) {
+				if (si->c_num)
+					display_with_pre_and_post(ptr, addr_base, addr, si);
+				else
+					fprintf(fp, "%lx: %x\n", addr, *ptr);
+			}
                 }
 	}
 	return addr;
@@ -12101,12 +12339,17 @@ search_ushort_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *s
 	int i, j;
 	int cnt = longcnt * (sizeof(long)/sizeof(short));
 	ushort *ptr = (ushort *)bufptr;
+	ulonglong addr_base = PHYSPAGEBASE(addr);
 	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);
+			if (SEARCHMASK(*ptr) == SEARCHMASK(si->s_parms.s_ushort.value[j])) {
+				if (si->c_num)
+					display_with_pre_and_post(ptr, addr_base, addr, si);
+				else
+					fprintf(fp, "%llx: %x\n", addr, *ptr);
+			}
                 }
 	}
 	return addr;
-- 
1.7.1

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