Hello Dave,

I add a new option -C for sub-command search to display memory contents
just before and after the search target.  The number of the memory unit
displayed is specified by -C.

for example,
crash> search -p -C 3 dddd
17b5100: dddddddddddddddd dddddddddddddddd dddddddddddddddd
17b5118: dddd cdcdcdcdcdcdcdcd cdcdcdcdcdcdcdcd
17b5130: cdcdcdcdcdcdcdcd
--
85d04f818: 29 ffff88085d04f818 ffffea001d3f7e30
85d04f830: dddd 1000 ffff88085b48a000
85d04f848: ffff880876383b80
--
8752cfec8: ddd9 dddb dddb
8752cfee0: dddd dddd dddf
8752cfef8: dddf
--
8752cfed0: dddb dddb dddd
8752cfee8: dddd dddf dddf
8752cff00: dde1
--
crash>


Thanks.
Zhang Yanfei
>From 42998b52ae9e09eea373feb1614f56f1e62d1e84 Mon Sep 17 00:00:00 2001
From: zhangyanfei <[email protected]>
Date: Fri, 3 Feb 2012 10:42:59 +0800
Subject: [PATCH] Add option -C for sub-command search.

Signed-off-by: zhangyanfei <[email protected]>
---
 help.c   |    5 +-
 memory.c |  657 ++++++++++++++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 534 insertions(+), 128 deletions(-)

diff --git a/help.c b/help.c
index bb552d9..addd88d 100755
--- a/help.c
+++ b/help.c
@@ -2327,7 +2327,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",
@@ -2358,6 +2358,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 ea4c6a0..7571dfa 100755
--- a/memory.c
+++ b/memory.c
@@ -87,6 +87,7 @@ struct meminfo {           /* general purpose memory 
information structure */
 struct searchinfo {
        int mode;
        int vcnt;
+       int c_num;
        union {
                /* default ulong search */
                struct {
@@ -115,6 +116,22 @@ struct searchinfo {
        } s_parms;
 };
 
+/*
+ * buf_handled - contains the page that has been searched
+ * buf_handling - contains the page that is been searching
+ * buf_to_handle - contains the page that is to be searched
+ */
+struct pagebuf_t {
+       int exist; /* equals 0 if buf == NULL */
+       int wordcnt; /* num of search unit in one page */
+       char *buf; /* buffer of the page for searching */
+       ulong *ubp; /* the starting searching address in buf */
+       union {
+               ulonglong paddr; /* physical address of the searching page */
+               ulong vaddr; /* virtual address of the searching page */
+       } next;
+} buf_handled, buf_handling, buf_to_handle;
+
 static char *memtype_string(int, int);
 static char *error_handle_string(ulong);
 static void dump_mem_map(struct meminfo *);
@@ -176,15 +193,19 @@ 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 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 ulong search_ulong(struct searchinfo *);
+static ulong search_uint(struct searchinfo *);
+static ulong search_ushort(struct searchinfo *);
+static ulong search_chars(struct searchinfo *);
+static ulonglong search_ulong_p(struct searchinfo *);
+static ulonglong search_uint_p(struct searchinfo *);
+static ulonglong search_ushort_p(struct searchinfo *);
+static ulonglong search_chars_p(struct searchinfo *);
+static void make_pagebuf(struct pagebuf_t *, int, int, char *, ulong *, ulong);
+static int get_search_page(ulong *, ulong, ulong, int);
 static void search_virtual(ulong, ulong, int, struct searchinfo *);
+static void make_pagebuf_p(struct pagebuf_t *, int, int, char *, ulong *, 
ulonglong);
+static int get_search_page_p(ulonglong *, ulonglong, ulonglong);
 static void search_physical(ulonglong, ulonglong, struct searchinfo *);
 static int next_upage(struct task_context *, ulong, ulong *);
 static int next_kpage(ulong, ulong *);
@@ -11585,7 +11606,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;
@@ -11599,6 +11620,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;
@@ -11636,7 +11658,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':
@@ -11737,6 +11759,10 @@ cmd_search(void)
                        searchinfo.mode = SEARCH_CHARS;
                        break;
 
+               case 'C':
+                       c_num = dtoi(optarg, FAULT_ON_ERROR, NULL);
+                       break;
+
                 default:
                         argerrs++;
                         break;
@@ -11884,6 +11910,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]) {
@@ -11981,15 +12038,96 @@ cmd_search(void)
 
 #define SEARCHMASK(X) ((X) | mask) 
 
+#define report_hex_match_pre(type, addr_mark, value_mark, \
+               c_num, addr_base, addr, addr1_base, addr1, bufptr) \
+do { \
+       int cnt1 = PAGESIZE() / sizeof(type); \
+       int cnt2 = (addr - addr_base) / sizeof(type); \
+       int cnt3 = (addr1 - addr1_base) / sizeof(type); \
+       int dis = cnt2 - c_num; \
+       int t, k; \
+       if (c_num) { \
+               if (dis < 0 && buf_handled.exist && \
+                       (addr1_base+cnt1*sizeof(type) == addr_base)) { \
+                       t = (cnt1 + dis) > 0 ? (cnt1 + dis) : 0; \
+                       fprintf(fp, addr_mark, addr1_base + t * sizeof(type)); \
+                       for (k = t; k < cnt1; k++) \
+                               fprintf(fp, value_mark, \
+                                       *(((type *)buf_handled.ubp)-cnt3+k)); \
+               } else { \
+                       t = dis < 0 ? cnt2 : c_num; \
+                       if (t > 0) \
+                               fprintf(fp, addr_mark, addr-t*sizeof(type)); \
+               } \
+               t = dis < 0 ? 0 : dis; \
+               for (k = t; k < cnt2; k++) \
+                       fprintf(fp, value_mark, *(bufptr - cnt2 + k)); \
+               fprintf(fp, "\n"); \
+       } \
+} while (0);
+
+#define report_hex_match_post(type, addr_mark, value_mark, \
+               c_num, addr_base, addr, addr2_base, addr2, bufptr) \
+do { \
+       int cnt1 = (PAGESIZE() - (addr - addr_base)) / sizeof(type) - 1; \
+       int cnt2 = PAGESIZE() / sizeof(type); \
+       int cnt3 = (addr2 - addr2_base) / sizeof(type); \
+       int dis = cnt1 - c_num; \
+       int t, k; \
+       if (c_num) { \
+               t = dis < 0 ? cnt1 : c_num - 1; \
+               fprintf(fp, " "); \
+               for (k = 1; k <= t; k++) \
+                       fprintf(fp, value_mark, *(bufptr + k)); \
+               if (dis >= 0) { \
+                       fprintf(fp, "\n"); \
+                       fprintf(fp, addr_mark, addr + c_num * sizeof(type)); \
+                       fprintf(fp, value_mark, *(bufptr + c_num)); \
+               } else { \
+                       if (buf_to_handle.exist && addr2_base == \
+                               ((addr+(cnt1+1)*sizeof(type)))) { \
+                               t = (cnt2 + dis) > 0 ? -dis : cnt2; \
+                               for (k = 0; k < t; k++) { \
+                                       if (k == t - 1) { \
+                                               fprintf(fp, "\n"); \
+                                               fprintf(fp, addr_mark, \
+                                                       (addr2_base + k * 
sizeof(type))); \
+                                       } \
+                                       fprintf(fp, value_mark, \
+                                               *(((type 
*)buf_to_handle.ubp)-cnt3+k)); \
+                               } \
+                       } \
+               } \
+               fprintf(fp, "\n--\n"); \
+       } else { \
+               fprintf(fp, "\n"); \
+       } \
+} while (0);
+
 static ulong
-search_ulong(ulong *bufptr, ulong addr, int longcnt, struct searchinfo *si)
+search_ulong(struct searchinfo *si)
 {
        int i, j;
+       int cnt = buf_handling.wordcnt;
+       ulong *bufptr = buf_handling.ubp;
+       ulong addr = buf_handling.next.vaddr;
+       ulong addr_base = VIRTPAGEBASE(addr);
+       ulong addr1 = buf_handled.next.vaddr;
+       ulong addr1_base = VIRTPAGEBASE(addr1);
+       ulong addr2 = buf_to_handle.next.vaddr;
+       ulong addr2_base = VIRTPAGEBASE(addr2);
        ulong mask = si->s_parms.s_ulong.mask;
-       for (i = 0; i < longcnt; i++, bufptr++, addr += sizeof(long)) {
+       int c_num = si->c_num;
+
+       for (i = 0; i < cnt; 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])) {
+                               report_hex_match_pre(ulong, "%lx: ", "%lx ", 
c_num, \
+                                               addr_base, addr, addr1_base, 
addr1, bufptr);
+                               fprintf(fp, "%lx: %lx", addr, *bufptr);
+                               report_hex_match_post(ulong, "%lx: ", "%lx ", 
c_num, \
+                                               addr_base, addr, addr2_base, 
addr2, bufptr);
+                       }
                 }
        }
        return addr;
@@ -11997,31 +12135,58 @@ search_ulong(ulong *bufptr, ulong addr, int longcnt, 
struct searchinfo *si)
 
 /* phys search uses ulonglong address representation */
 static ulonglong
-search_ulong_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo 
*si)
+search_ulong_p(struct searchinfo *si)
 {
        int i, j;
+       int cnt = buf_handling.wordcnt;
+       ulong *bufptr = buf_handling.ubp;
+       ulonglong addr = buf_handling.next.paddr;
+       ulonglong addr_base = PHYSPAGEBASE(addr);
+       ulonglong addr1 = buf_handled.next.paddr;
+       ulonglong addr1_base = PHYSPAGEBASE(addr1);
+       ulonglong addr2 = buf_to_handle.next.paddr;
+       ulonglong addr2_base = PHYSPAGEBASE(addr2);
        ulong mask = si->s_parms.s_ulong.mask;
-       for (i = 0; i < longcnt; i++, bufptr++, addr += sizeof(long)) {
+       int c_num = si->c_num;
+
+       for (i = 0; i < cnt; 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])) {
+                               report_hex_match_pre(ulong, "%llx: ", "%lx ", 
c_num, \
+                                               addr_base, addr, addr1_base, 
addr1, bufptr);
+                               fprintf(fp, "%llx: %lx", addr, *bufptr);
+                               report_hex_match_post(ulong, "%llx: ", "%lx ", 
c_num, \
+                                               addr_base, addr, addr2_base, 
addr2, bufptr);
+                       }
                 }
        }
        return addr;
 }
 
 static ulong
-search_uint(ulong *bufptr, ulong addr, int longcnt, struct searchinfo *si)
+search_uint(struct searchinfo *si)
 {
        int i, j;
-       int cnt = longcnt * (sizeof(long)/sizeof(int));
-       uint *ptr = (uint *)bufptr;
+       int cnt = buf_handling.wordcnt * (sizeof(long)/sizeof(int));
+       uint *bufptr = (uint *)(buf_handling.ubp);
+       ulong addr = buf_handling.next.vaddr;
+       ulong addr_base = VIRTPAGEBASE(addr);
+       ulong addr1 = buf_handled.next.vaddr;
+       ulong addr1_base = VIRTPAGEBASE(addr1);
+       ulong addr2 = buf_to_handle.next.vaddr;
+       ulong addr2_base = VIRTPAGEBASE(addr2);
        uint mask = si->s_parms.s_uint.mask;
+       int c_num = si->c_num;
 
-       for (i = 0; i < cnt; i++, ptr++, addr += sizeof(int)) {
+       for (i = 0; i < cnt; i++, bufptr++, 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(*bufptr) == 
SEARCHMASK(si->s_parms.s_uint.value[j])) {
+                               report_hex_match_pre(uint, "%lx: ", "%x ", 
c_num, \
+                                               addr_base, addr, addr1_base, 
addr1, bufptr);
+                               fprintf(fp, "%lx: %x", addr, *bufptr);
+                               report_hex_match_post(uint, "%lx: ", "%x ", 
c_num, \
+                                               addr_base, addr, addr2_base, 
addr2, bufptr);
+                       }
                 }
        }
        return addr;
@@ -12029,34 +12194,58 @@ search_uint(ulong *bufptr, ulong addr, int longcnt, 
struct searchinfo *si)
 
 /* phys search uses ulonglong address representation */
 static ulonglong
-search_uint_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo 
*si)
+search_uint_p(struct searchinfo *si)
 {
        int i, j;
-       int cnt = longcnt * (sizeof(long)/sizeof(int));
-       uint *ptr = (uint *)bufptr;
+       int cnt = buf_handling.wordcnt * (sizeof(long)/sizeof(int));
+       uint *bufptr = (uint *)(buf_handling.ubp);
+       ulonglong addr = buf_handling.next.paddr;
+       ulonglong addr_base = PHYSPAGEBASE(addr);
+       ulonglong addr1 = buf_handled.next.paddr;
+       ulonglong addr1_base = PHYSPAGEBASE(addr1);
+       ulonglong addr2 = buf_to_handle.next.paddr;
+       ulonglong addr2_base = PHYSPAGEBASE(addr2);
        uint mask = si->s_parms.s_uint.mask;
+       int c_num = si->c_num;
 
-       for (i = 0; i < cnt; i++, ptr++, addr += sizeof(int)) {
+       for (i = 0; i < cnt; i++, bufptr++, 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(*bufptr) == 
SEARCHMASK(si->s_parms.s_uint.value[j])) {
+                               report_hex_match_pre(uint, "%llx: ", "%x ", 
c_num, \
+                                               addr_base, addr, addr1_base, 
addr1, bufptr);
+                               fprintf(fp, "%llx: %x", addr, *bufptr);
+                               report_hex_match_post(uint, "%llx: ", "%x ", 
c_num, \
+                                               addr_base, addr, addr2_base, 
addr2, bufptr);
+                       }
                 }
        }
        return addr;
 }
 
 static ulong
-search_ushort(ulong *bufptr, ulong addr, int longcnt, struct searchinfo *si)
+search_ushort(struct searchinfo *si)
 {
        int i, j;
-       int cnt = longcnt * (sizeof(long)/sizeof(short));
-       ushort *ptr = (ushort *)bufptr;
+       int cnt = buf_handling.wordcnt * (sizeof(long)/sizeof(short));
+       ushort *bufptr = (ushort *)(buf_handling.ubp);
+       ulong addr = buf_handling.next.vaddr;
+       ulong addr_base = VIRTPAGEBASE(addr);
+       ulong addr1 = buf_handled.next.vaddr;
+       ulong addr1_base = VIRTPAGEBASE(addr1);
+       ulong addr2 = buf_to_handle.next.vaddr;
+       ulong addr2_base = VIRTPAGEBASE(addr2);
        ushort mask = si->s_parms.s_ushort.mask;
+       int c_num = si->c_num;
 
-       for (i = 0; i < cnt; i++, ptr++, addr += sizeof(short)) {
+       for (i = 0; i < cnt; i++, bufptr++, 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(*bufptr) == 
SEARCHMASK(si->s_parms.s_ushort.value[j])) {
+                               report_hex_match_pre(ushort, "%lx: ", "%x ", 
c_num, \
+                                               addr_base, addr, addr1_base, 
addr1, bufptr);
+                               fprintf(fp, "%lx: %x", addr, *bufptr);
+                               report_hex_match_post(ushort, "%lx: ", "%x ", 
c_num, \
+                                               addr_base, addr, addr2_base, 
addr2, bufptr);
+                       }
                 }
        }
        return addr;
@@ -12064,17 +12253,29 @@ search_ushort(ulong *bufptr, ulong addr, int longcnt, 
struct searchinfo *si)
 
 /* phys search uses ulonglong address representation */
 static ulonglong
-search_ushort_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo 
*si)
+search_ushort_p(struct searchinfo *si)
 {
        int i, j;
-       int cnt = longcnt * (sizeof(long)/sizeof(short));
-       ushort *ptr = (ushort *)bufptr;
+       int cnt = buf_handling.wordcnt * (sizeof(long)/sizeof(short));
+       ushort *bufptr = (ushort *)(buf_handling.ubp);
+       ulonglong addr = buf_handling.next.paddr;
+       ulonglong addr_base = PHYSPAGEBASE(addr);
+       ulonglong addr1 = buf_handled.next.paddr;
+       ulonglong addr1_base = PHYSPAGEBASE(addr1);
+       ulonglong addr2 = buf_to_handle.next.paddr;
+       ulonglong addr2_base = PHYSPAGEBASE(addr2);
        ushort mask = si->s_parms.s_ushort.mask;
+       int c_num = si->c_num;
 
-       for (i = 0; i < cnt; i++, ptr++, addr += sizeof(short)) {
+       for (i = 0; i < cnt; i++, bufptr++, 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(*bufptr) == 
SEARCHMASK(si->s_parms.s_ushort.value[j])) {
+                               report_hex_match_pre(ushort, "%llx: ", "%x ", 
c_num, \
+                                               addr_base, addr, addr1_base, 
addr1, bufptr);
+                               fprintf(fp, "%llx: %x", addr, *bufptr);
+                               report_hex_match_post(ushort, "%llx: ", "%x ", 
c_num, \
+                                               addr_base, addr, addr2_base, 
addr2, bufptr);
+                       }
                 }
        }
        return addr;
@@ -12122,13 +12323,15 @@ report_match(ulong addr, char *ptr1, int len1, char 
*ptr2, int len2)
 }
        
 static ulong
-search_chars(ulong *bufptr, ulong addr, int longcnt, struct searchinfo *si)
+search_chars(struct searchinfo *si)
 {
        int i, j;
        int len;
        char *target;
+       int longcnt = buf_handling.wordcnt;
        int charcnt = longcnt * sizeof(long);
-       char *ptr = (char *)bufptr;
+       char *ptr = (char *)(buf_handling.ubp);
+       ulong addr = buf_handling.next.vaddr;
 
        /* is this the first page of this search? */
        if (si->s_parms.s_chars.started_flag == 0) {
@@ -12211,13 +12414,15 @@ report_match_p(ulonglong addr, char *ptr1, int len1, 
char *ptr2, int len2)
 }
 
 static ulonglong
-search_chars_p(ulong *bufptr, ulonglong addr_p, int longcnt, struct searchinfo 
*si)
+search_chars_p(struct searchinfo *si)
 {
        int i, j;
        int len;
        char *target;
+       int longcnt = buf_handling.wordcnt;
        int charcnt = longcnt * sizeof(long);
-       char *ptr = (char *)bufptr;
+       char *ptr = (char *)(buf_handling.ubp);
+       ulonglong addr_p = buf_handling.next.paddr;
 
        /* is this the first page of this search? */
        if (si->s_parms.s_chars.started_flag == 0) {
@@ -12279,20 +12484,121 @@ search_chars_p(ulong *bufptr, ulonglong addr_p, int 
longcnt, struct searchinfo *
 }
 
 static void
-search_virtual(ulong start, ulong end, int memtype, struct searchinfo *si)
+make_pagebuf(struct pagebuf_t *pb, int exist, int wordcnt, char *buf, ulong 
*ubp, ulong vaddr)
 {
-       ulong pp, next, *ubp;
+       pb->exist = exist;
+       pb->wordcnt = wordcnt;
+       pb->buf = buf;
+       pb->ubp = ubp;
+       pb->next.vaddr = vaddr;
+}
+
+#define OK 0
+#define DONE 1
+#define DO_SEARCH 2
+#define IGNORE 3
+
+static int
+get_search_page(ulong *pp, ulong next, ulong end, int memtype)
+{
+       char *pagebuf;
+       ulong *ubp;
        int wordcnt, lastpage;
        ulong page;
-       physaddr_t paddr; 
-       char *pagebuf;
+       physaddr_t paddr;
+
+       pagebuf = buf_to_handle.buf;
+       lastpage = (VIRTPAGEBASE(next) == VIRTPAGEBASE(end));
+
+       /*
+        *  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 DONE;
+               }
+               goto make_pagebuf;
+       }
+
+        switch (memtype)
+        {
+        case UVADDR:
+                if (!uvtop(CURRENT_CONTEXT(), *pp, &paddr, 0) ||
+                    !phys_to_page(paddr, &page)) {
+                       if (!next_upage(CURRENT_CONTEXT(), *pp, pp)) {
+                               return DONE;
+                       }
+                       return IGNORE;
+               }
+                break;
+
+        case KVADDR:
+                if (!kvtop(CURRENT_CONTEXT(), *pp, &paddr, 0) ||
+                    !phys_to_page(paddr, &page)) {
+                       if (!next_kpage(*pp, pp)) {
+                               return DONE;
+                       }
+                        return IGNORE;
+               }
+                break;
+        }
+
+        if (!readmem(paddr, PHYSADDR, pagebuf, PAGESIZE(),
+            "search page", RETURN_ON_ERROR|QUIET)) {
+               return DO_SEARCH;
+       }
+
+make_pagebuf:
+       ubp = (ulong *)&(pagebuf[next - *pp]);
+       if (lastpage) {
+               if (end == (ulong)(-1))
+                       wordcnt = PAGESIZE()/sizeof(long);
+               else
+                       wordcnt = (end - next)/sizeof(long);
+       } else
+               wordcnt = (PAGESIZE() - (next - *pp))/sizeof(long);
+
+       make_pagebuf(&buf_to_handle, 1, wordcnt, pagebuf, ubp, next);
+
+       return OK;
+}
+
+static void
+search_virtual(ulong start, ulong end, int memtype, struct searchinfo *si)
+{
+       ulong pp, next, tmppp;
+       int tmp, over;
+       char *tmpbuf;
        ulong pct, pages_read, pages_checked;
        time_t begin, finish;
 
+       over = 0;
        pages_read = pages_checked = 0;
        begin = finish = 0;
 
-       pagebuf = GETBUF(PAGESIZE());
+       buf_handled.buf = GETBUF(PAGESIZE());
+       buf_handled.exist = 0;
+       buf_handling.buf = GETBUF(PAGESIZE());
+       buf_handling.exist = 0;
+       buf_to_handle.buf = GETBUF(PAGESIZE());
+       buf_to_handle.exist = 0;
+
+       tmppp = VIRTPAGEBASE(start);
+       if (tmppp >= PAGESIZE()) {
+               tmppp -= PAGESIZE();
+               tmp = get_search_page(&tmppp, tmppp, -1, memtype);
+               if (tmp == OK) {
+                       tmpbuf = buf_handled.buf;
+                       memcpy(&buf_handled, &buf_to_handle,
+                                       sizeof(struct pagebuf_t));
+                       buf_to_handle.exist = 0;
+                       buf_to_handle.buf = tmpbuf;
+               }
+       }
 
        if (start & (sizeof(long)-1)) {
                start &= ~(sizeof(long)-1);
@@ -12309,79 +12615,66 @@ search_virtual(ulong start, ulong end, int memtype, 
struct searchinfo *si)
 
        for (pp = VIRTPAGEBASE(start); next < end; next = pp) {
                pages_checked++;
-               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);
-                               goto done;
-                       }
-                       goto virtual;
+               tmp = get_search_page(&pp, next, end, memtype);
+               switch (tmp)
+               {
+               case OK:
+                       pages_read++;
+                       break;
+               case DONE:
+                       goto done;
+                       break;
+               case DO_SEARCH:
+                       goto do_search;
+                       break;
+               case IGNORE:
+                       continue;
+                       break;
                }
 
-                switch (memtype)
-                {
-                case UVADDR:
-                        if (!uvtop(CURRENT_CONTEXT(), pp, &paddr, 0) ||
-                            !phys_to_page(paddr, &page)) { 
-                               if (!next_upage(CURRENT_CONTEXT(), pp, &pp)) 
-                                       goto done;
-                                continue;
-                       }
-                        break;
-
-                case KVADDR:
-                        if (!kvtop(CURRENT_CONTEXT(), pp, &paddr, 0) ||
-                            !phys_to_page(paddr, &page)) {
-                               if (!next_kpage(pp, &pp))
-                                       goto done;
-                                continue;
+               if (!buf_handling.exist) {
+                       tmpbuf = buf_handling.buf;
+                       memcpy(&buf_handling, &buf_to_handle, sizeof(struct 
pagebuf_t));
+                       buf_to_handle.buf = tmpbuf;
+                       buf_to_handle.exist = 0;
+                       if (pp + PAGESIZE() < end) {
+                               pp += PAGESIZE();
+                               continue;
+                       } else {
+                               over = 1;
+                               tmppp = pp + PAGESIZE();
+                               if (tmppp > pp)
+                                       get_search_page(&tmppp, tmppp,
+                                                       (ulong)(-1), memtype);
                        }
-                        break;
-                }
+               }
 
-                if (!readmem(paddr, PHYSADDR, pagebuf, PAGESIZE(),
-                    "search page", RETURN_ON_ERROR|QUIET)) {
+do_search:
+               if (!buf_handling.exist) {
                        pp += PAGESIZE();
                        continue;
                }
-virtual:
-               pages_read++;
-
-               ubp = (ulong *)&pagebuf[next - pp];
-               if (lastpage) {
-                       if (end == (ulong)(-1))
-                               wordcnt = PAGESIZE()/sizeof(long);
-                       else
-                               wordcnt = (end - next)/sizeof(long);
-               } else
-                       wordcnt = (PAGESIZE() - (next - pp))/sizeof(long);
 
                switch (si->mode)
                {
                case SEARCH_ULONG:
-                       next = search_ulong(ubp, next, wordcnt, si);
+                       next = search_ulong(si);
                        break;
                case SEARCH_UINT:
-                       next = search_uint(ubp, next, wordcnt, si);
+                       next = search_uint(si);
                        break;
                case SEARCH_USHORT:
-                       next = search_ushort(ubp, next, wordcnt, si);
+                       next = search_ushort(si);
                        break;
                case SEARCH_CHARS:
-                       next = search_chars(ubp, next, wordcnt, si);
+                       next = search_chars(si);
                        break;
                default:
                        /* unimplemented search type */
-                       next += wordcnt * (sizeof(long));
+                       next += buf_handling.wordcnt * (sizeof(long));
                        break;
                }
 
@@ -12389,6 +12682,24 @@ virtual:
                        if ((pp % (1024*1024)) == 0)
                                console("%lx\n", pp);
 
+               buf_handling.exist = 0;
+               if (!over && buf_to_handle.exist) {
+                       tmpbuf = buf_handled.buf;
+                       buf_handling.exist = 1;
+                       memcpy(&buf_handled, &buf_handling, sizeof(struct 
pagebuf_t));
+                       memcpy(&buf_handling, &buf_to_handle, sizeof(struct 
pagebuf_t));
+
+                       buf_to_handle.exist = 0;
+                       buf_to_handle.buf = tmpbuf;
+                       if (pp + PAGESIZE() >= end) {
+                               over = 1;
+                               tmppp = pp + PAGESIZE();
+                               if (tmppp > pp)
+                                       get_search_page(&tmppp, tmppp,
+                                                       (ulong)(-1), memtype);
+                               goto do_search;
+                       }
+               }
                pp += PAGESIZE();
        }
 
@@ -12402,22 +12713,81 @@ done:
        }
 }
 
-
 static void
-search_physical(ulonglong start_in, ulonglong end_in, struct searchinfo *si)
+make_pagebuf_p(struct pagebuf_t *pb, int exist, int wordcnt, char *buf, ulong 
*ubp, ulonglong paddr)
 {
+       pb->exist = exist;
+       pb->wordcnt = wordcnt;
+       pb->buf = buf;
+       pb->ubp = ubp;
+       pb->next.paddr = paddr;
+}
+
+static int
+get_search_page_p(ulonglong *ppp, ulonglong pnext, ulonglong end_in)
+{
+       char *pagebuf;
        ulong *ubp;
        int wordcnt, lastpage;
-       ulonglong pnext, ppp;
-       char *pagebuf;
+       ulong page;
+
+       pagebuf = buf_to_handle.buf;
+        lastpage = (PHYSPAGEBASE(pnext) == PHYSPAGEBASE(end_in));
+
+       if (!phys_to_page(*ppp, &page) ||
+           !readmem(*ppp, PHYSADDR, pagebuf, PAGESIZE(),
+            "search page", RETURN_ON_ERROR|QUIET)) {
+               if (!next_physpage(*ppp, ppp))
+                       return DO_SEARCH;
+               return IGNORE;
+       }
+
+       ubp = (ulong *)&(pagebuf[pnext - *ppp]);
+        if (lastpage) {
+                if (end_in == (ulonglong)(-1))
+                        wordcnt = PAGESIZE()/sizeof(long);
+                else
+                        wordcnt = (end_in - pnext)/sizeof(long);
+        } else
+                wordcnt = (PAGESIZE() - (pnext - *ppp))/sizeof(long);
+
+       make_pagebuf_p(&buf_to_handle, 1, wordcnt, pagebuf, ubp, pnext);
+
+       return OK;
+}
+
+static void
+search_physical(ulonglong start_in, ulonglong end_in, struct searchinfo *si)
+{
+       ulonglong pnext, ppp, tmpppp;
        ulong pct, pages_read, pages_checked;
        time_t begin, finish;
-       ulong page;
+       char *tmpbuf;
+       int tmp, over;
 
        pages_read = pages_checked = 0;
        begin = finish = 0;
-
-       pagebuf = GETBUF(PAGESIZE());
+       over = 0;
+
+       buf_handled.buf = GETBUF(PAGESIZE());
+       buf_handled.exist = 0;
+       buf_handling.buf = GETBUF(PAGESIZE());
+       buf_handling.exist = 0;
+       buf_to_handle.buf = GETBUF(PAGESIZE());
+       buf_to_handle.exist = 0;
+
+       tmpppp = PHYSPAGEBASE(start_in);
+       if (tmpppp >= PAGESIZE()) {
+               tmpppp -= PAGESIZE();
+               tmp = get_search_page_p(&tmpppp, tmpppp, (ulonglong)(-1));
+               if (tmp == OK) {
+                       tmpbuf = buf_handled.buf;
+                       memcpy(&buf_handled, &buf_to_handle,
+                                       sizeof(struct pagebuf_t));
+                       buf_to_handle.exist = 0;
+                       buf_to_handle.buf = tmpbuf;
+               }
+       }
 
         if (start_in & (sizeof(ulonglong)-1)) {
                 start_in &= ~(sizeof(ulonglong)-1);
@@ -12434,48 +12804,81 @@ search_physical(ulonglong start_in, ulonglong end_in, 
struct searchinfo *si)
         pnext = start_in;
         for (ppp = PHYSPAGEBASE(start_in); pnext < end_in; pnext = ppp) {
                pages_checked++;
-                lastpage = (PHYSPAGEBASE(pnext) == PHYSPAGEBASE(end_in));
                 if (LKCD_DUMPFILE())
                         set_lkcd_nohash();
 
-                if (!phys_to_page(ppp, &page) || 
-                   !readmem(ppp, PHYSADDR, pagebuf, PAGESIZE(),
-                       "search page", RETURN_ON_ERROR|QUIET)) {
-                       if (!next_physpage(ppp, &ppp))
-                               break;
+               tmp = get_search_page_p(&ppp, pnext, end_in);
+               switch (tmp)
+               {
+               case OK:
+                       pages_read++;
+                       break;
+               case DO_SEARCH:
+                       goto do_search;
+                       break;
+               case IGNORE:
                        continue;
+                       break;
                }
 
-               pages_read++;
-                ubp = (ulong *)&pagebuf[pnext - ppp];
-                if (lastpage) {
-                        if (end_in == (ulonglong)(-1))
-                                wordcnt = PAGESIZE()/sizeof(long);
-                        else
-                                wordcnt = (end_in - pnext)/sizeof(long);
-                } else
-                        wordcnt = (PAGESIZE() - (pnext - ppp))/sizeof(long);
+               if (!buf_handling.exist) {
+                       tmpbuf = buf_handling.buf;
+                       memcpy(&buf_handling, &buf_to_handle, sizeof(struct 
pagebuf_t));
+                       buf_to_handle.buf = tmpbuf;
+                       buf_to_handle.exist = 0;
+                       if (ppp + PAGESIZE() < end_in) {
+                               ppp += PAGESIZE();
+                               continue;
+                       } else {
+                               over = 1;
+                               tmpppp = ppp + PAGESIZE();
+                               if (tmpppp > ppp)
+                                       get_search_page_p(&tmpppp, tmpppp,
+                                                       (ulonglong)(-1));
+                       }
+               }
+
+do_search:
+               if (!buf_handling.exist)
+                       break;
 
                switch (si->mode)
                {
                case SEARCH_ULONG:
-                       pnext = search_ulong_p(ubp, pnext, wordcnt, si);
+                       pnext = search_ulong_p(si);
                        break;
                case SEARCH_UINT:
-                       pnext = search_uint_p(ubp, pnext, wordcnt, si);
+                       pnext = search_uint_p(si);
                        break;
                case SEARCH_USHORT:
-                       pnext = search_ushort_p(ubp, pnext, wordcnt, si);
+                       pnext = search_ushort_p(si);
                        break;
                case SEARCH_CHARS:
-                       pnext = search_chars_p(ubp, pnext, wordcnt, si);
+                       pnext = search_chars_p(si);
                        break;
                default:
                        /* unimplemented search type */
-                       pnext += wordcnt * (sizeof(long));
+                       pnext += buf_handling.wordcnt * (sizeof(long));
                        break;
                }
 
+               buf_handling.exist = 0;
+               if (!over && buf_to_handle.exist) {
+                       tmpbuf = buf_handled.buf;
+                       buf_handling.exist = 1;
+                       memcpy(&buf_handled, &buf_handling, sizeof(struct 
pagebuf_t));
+                       memcpy(&buf_handling, &buf_to_handle, sizeof(struct 
pagebuf_t));
+
+                       buf_to_handle.buf = tmpbuf;
+                       buf_to_handle.exist = 0;
+                       if (ppp + PAGESIZE() >= end_in) {
+                               over = 1;
+                               tmpppp = ppp + PAGESIZE();
+                               if (tmpppp > ppp)
+                                       get_search_page_p(&tmpppp, tmpppp, -1);
+                               goto do_search;
+                       }
+               }
                ppp += PAGESIZE();
        }
 
-- 
1.7.1

--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to