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 <[email protected]>
Date: Thu, 9 Feb 2012 15:32:11 +0800
Subject: [PATCH] Add option -C for sub-command search.

Signed-off-by: zhangyanfei <[email protected]>
---
 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
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to