Here is a patch to add string search to crash-5.1.1. It requires the my previous patch for the parse_line routine. It searches for the specified strings, and for half or more of the string appearing at the start and end of search blocks (usually pages) in case the string spans a page boundary. It is currently invoked with the -c option to search, as in: crash-5.1.1str> search -k -e 0xffffc90000000000 -c "getty[3895]" ffff880123b54810: :46 getty[3895]: /dev/ttyS1: No such file or dir or crash-5.1.1str> search -k -c -e 0xffffc90000000000 "getty[3895]" ffff880123b54810: :46 getty[3895]: /dev/ttyS1: No such file or dir It reports the found string in 48 chars of context (except at the end of pages), and it reports aligned addresses, so the found string doesn't always appear at the beginning of the context (as in the example above). It could optionally use strncasecmp to do case-insensitive searches. I simplified it :-) by combining the main and tail searches into one loop and added a 10-15% performance degradation somewhere. Here it searches the dump for bugs and danger :-) crash-5.1.1str> search -k -c -e 0xffffc90000000000 "bugs" "danger" ffff8801254c0ff8: ug:Debug ffff880125cd4ff8: ebian/bu ffff880125ec8870: efb: danger danger! Oopsen imminent!..<6>Mode (% ffff880125ec8878: ger danger! Oopsen imminent!..<6>Mode (%dx%d) la ffff880125eee518: ofb: danger danger! Oopsen imminent!..<3>neofb: ffff880125eee520: ger danger! Oopsen imminent!..<3>neofb: neo2200 ffff880125f72000: ger_event....................................... ffff880125fc3560: ice bugs (default = 0, 128kB max transfer = 0x1, The first two hits come because half or more of "bugs" occurred at the end of a page. The next to the last hit is found because the last half of "danger" appears at the beginning of a page. Bob Montgomery
--- memory.c.orig 2011-01-25 14:26:55.000000000 -0700 +++ memory.c 2011-02-01 16:21:28.000000000 -0700 @@ -134,6 +134,7 @@ static int page_to_phys(ulong, physaddr_ static int phys_to_page(physaddr_t, ulong *); static void display_memory(ulonglong, long, ulong, int); static void search(ulong, ulong, ulong, int, ulong *, int); +static void string_search(ulong, ulong, int, char **, int); static int next_upage(struct task_context *, ulong, ulong *); static int next_kpage(ulong, ulong *); static ulong last_vmalloc_address(void); @@ -11284,18 +11285,20 @@ void cmd_search(void) { int c; + int str_search = 0; ulong start, end, mask, memtype, len; ulong uvaddr_end; int sflag; struct meminfo meminfo; ulong value_array[MAXARGS]; + char *string_array[MAXARGS]; struct syment *sp; start = end = mask = sflag = memtype = len = 0; uvaddr_end = COMMON_VADDR_SPACE() ? (ulong)(-1) : machdep->kvbase; BZERO(value_array, sizeof(ulong) * MAXARGS); - while ((c = getopt(argcnt, args, "l:uks:e:v:m:")) != EOF) { + while ((c = getopt(argcnt, args, "cl:uks:e:v:m:")) != EOF) { switch(c) { case 'u': @@ -11353,6 +11356,10 @@ cmd_search(void) mask = htol(optarg, FAULT_ON_ERROR, NULL); break; + case 'c': + str_search++; + break; + default: argerrs++; break; @@ -11447,18 +11454,171 @@ cmd_search(void) c = 0; while (args[optind]) { - value_array[c] = htol(args[optind], FAULT_ON_ERROR, NULL); + if (str_search) + string_array[c] = args[optind]; + else + value_array[c] = htol(args[optind], FAULT_ON_ERROR, NULL); c++; optind++; } - search(start, end, mask, memtype, value_array, c); + if (str_search) + string_search(start, end, memtype, string_array, c); + else + search(start, end, mask, memtype, value_array, c); } /* * Do the work for cmd_search(). */ +#define CONTEXT_SIZE 48 +static void +string_search(ulong start, ulong end, int memtype, char **value, int vcnt) +{ + int i, j, k; + int len[MAXARGS]; + ulong pp, next; + char *ubp, *prp, *lastp; + int charcnt, lastpage; + ulong page; + physaddr_t paddr; + char *pagebuf; + + if (start & (sizeof(long)-1)) { + start &= ~(sizeof(long)-1); + error(INFO, "rounding down start address to: %lx\n", start); + } + + pagebuf = GETBUF(PAGESIZE()); + next = start; + + for (pp = VIRTPAGEBASE(start); next < end; next = pp) { + 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); + return; + } + goto virtual; + } + + switch (memtype) + { + case UVADDR: + if (!uvtop(CURRENT_CONTEXT(), pp, &paddr, 0) || + !phys_to_page(paddr, &page)) { + if (!next_upage(CURRENT_CONTEXT(), pp, &pp)) + return; + continue; + } + break; + + case KVADDR: + if (!kvtop(CURRENT_CONTEXT(), pp, &paddr, 0) || + !phys_to_page(paddr, &page)) { + if (!next_kpage(pp, &pp)) + return; + continue; + } + break; + } + + if (!readmem(paddr, PHYSADDR, pagebuf, PAGESIZE(), + "search page", RETURN_ON_ERROR|QUIET)) { + pp += PAGESIZE(); + continue; + } +virtual: + ubp = (char *)&pagebuf[next - pp]; + if (lastpage) { + if (end == (ulong)(-1)) + charcnt = PAGESIZE(); + else + charcnt = end - next; + } else + charcnt = PAGESIZE() - (next - pp); + + for (j = 0; j < vcnt; j++) { + len[j] = strlen(value[j]); + } + + lastp = &ubp[charcnt]; + + /* pre-search for the last half or more of the string at start of area */ + for (j = 0; j < vcnt; j++) { + int min_len = len[j]/2 + len[j]%2; /* need the big half of odd lengths */ + if (min_len < 1) + min_len = 1; + for (k = len[j] - min_len; k > 0; k--) { + if ((charcnt > len[j] - k) && + (strncmp(value[j]+k, ubp, len[j]-k) == 0)) { + int ii = 0; + prp = ubp; + /* report findings on aligned addresses */ + if ((ulong)prp & (sizeof(long) - 1)) + prp = (char *) + ((ulong)prp & ~(sizeof(long) - 1)); + fprintf(fp, "%lx: ", next & ~(sizeof(long) - 1)); + while ((ii < CONTEXT_SIZE) && (&prp[ii] < lastp)) { + if (isprint(prp[ii])) + fprintf(fp, "%c", prp[ii]); + else + fprintf(fp, "."); + ii++; + } + fprintf(fp, "\n"); + } + } + } + + /* search for full string, and partial string at end of search area */ + for (i = 0; i < charcnt; i++, ubp++, next++) { + for (j = 0; j < vcnt; j++) { + int min_len = len[j]/2 + len[j]%2; /* need the big half of odd lengths */ + if (min_len < 1) + min_len = 1; + if (charcnt >= (i + min_len)) { + int slen = (len[j] < (charcnt - i)? len[j]:(charcnt - i)); + if (strncmp(value[j], ubp, slen) == 0) { + int ii = 0; + prp = ubp; + /* report findings on aligned addresses */ + if ((ulong)prp & (sizeof(long) - 1)) + prp = (char *) + ((ulong)prp & ~(sizeof(long) - 1)); + fprintf(fp, "%lx: ", next & ~(sizeof(long) - 1)); + while ((ii < CONTEXT_SIZE) && (&prp[ii] < lastp)) { + if (isprint(prp[ii])) + fprintf(fp, "%c", prp[ii]); + else + fprintf(fp, "."); + ii++; + } + fprintf(fp, "\n"); + } + } + } + } + + if (CRASHDEBUG(1)) + if ((pp % (1024*1024)) == 0) + console("%lx\n", pp); + + pp += PAGESIZE(); + } +} + #define SEARCHMASK(X) ((X) | mask) static void
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility