>From 42998b52ae9e09eea373feb1614f56f1e62d1e84 Mon Sep 17 00:00:00 2001 From: zhangyanfei Date: Fri, 3 Feb 2012 10:42:59 +0800 Subject: [PATCH] Add option -C for sub-command search. Signed-off-by: zhangyanfei --- 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