diff -Nau -X ignorepat crash-4.0-2.10/Makefile crash-4.0-2.10-new/Makefile --- crash-4.0-2.10/Makefile 2005-11-08 17:28:54 -08:00 +++ crash-4.0-2.10-new/Makefile 2005-11-09 11:29:50 -08:00 @@ -75,7 +75,8 @@ extensions.c remote.c va_server.c va_server_v1.c symbols.c cmdline.c \ lkcd_common.c lkcd_v1.c lkcd_v2_v3.c lkcd_v5.c lkcd_v7.c lkcd_v8.c\ lkcd_fix_mem.c s390_dump.c lkcd_x86_trace.c \ - netdump.c diskdump.c unwind.c unwind_decoder.c + netdump.c diskdump.c unwind.c unwind_decoder.c \ + kw.c SOURCE_FILES=${CFILES} ${GENERIC_HFILES} ${MCORE_HFILES} \ ${REDHAT_CFILES} ${REDHAT_HFILES} ${UNWIND_HFILES} \ @@ -87,7 +88,8 @@ extensions.o remote.o va_server.o va_server_v1.o symbols.o cmdline.o \ lkcd_common.o lkcd_v1.o lkcd_v2_v3.o lkcd_v5.o lkcd_v7.o lkcd_v8.o \ lkcd_fix_mem.o s390_dump.o netdump.o diskdump.o \ - lkcd_x86_trace.o unwind_v1.o unwind_v2.o unwind_v3.o + lkcd_x86_trace.o unwind_v1.o unwind_v2.o unwind_v3.o \ + kw.o DAEMON_OBJECT_FILES=remote_daemon.o va_server.o va_server_v1.o \ lkcd_common.o lkcd_v1.o lkcd_v2_v3.o lkcd_v5.o lkcd_v7.o lkcd_v8.o \ diff -Nau -X ignorepat crash-4.0-2.10/defs.h crash-4.0-2.10-new/defs.h --- crash-4.0-2.10/defs.h 2005-11-07 07:44:06 -08:00 +++ crash-4.0-2.10-new/defs.h 2005-11-08 17:28:46 -08:00 @@ -3619,6 +3619,7 @@ #define LKCD_DUMP_V7 (0x7) /* DUMP_VERSION_NUMBER */ #define LKCD_DUMP_V8 (0x8) /* DUMP_VERSION_NUMBER */ #define LKCD_DUMP_V9 (0x9) /* DUMP_VERSION_NUMBER */ +#define LKCD_DUMP_V10 (0xa) /* DUMP_VERSION_NUMBER */ #define LKCD_DUMP_VERSION_NUMBER_MASK (0xf) #define LKCD_DUMP_RAW (0x1) /* DUMP_[DH_]RAW */ @@ -3772,6 +3773,16 @@ #define BITS64() (lkcd->bits == 64) #endif /* LKCD_COMMON */ + +/* kw.c */ +typedef char *(*kwr_func_t)(char *, char *); + +struct kwr_ruleset; +typedef struct kwr_ruleset *kwr_ruleset_t; + +kwr_ruleset_t kwr_create(char *separator); +kwr_ruleset_t kwr_add(kwr_ruleset_t ruleset, char *str, kwr_func_t kwr_func); +int kwr_expand(kwr_ruleset_t rules, char *instring, char *outstring, int len); /* * gdb_interface.c diff -Nau -X ignorepat crash-4.0-2.10/extensions.c crash-4.0-2.10-new/extensions.c --- crash-4.0-2.10/extensions.c 2005-11-07 07:44:06 -08:00 +++ crash-4.0-2.10-new/extensions.c 2005-11-07 18:57:19 -08:00 @@ -21,6 +21,9 @@ static void load_extension(char *); static void unload_extension(char *); +static kwr_ruleset_t ext_kwrule = NULL; +static void init_ext_kwrule(void); + #define DUMP_EXTENSIONS (0) #define LOAD_EXTENSION (1) #define UNLOAD_EXTENSION (2) @@ -36,6 +39,10 @@ flag = DUMP_EXTENSIONS; + if (ext_kwrule == NULL) { + init_ext_kwrule(); + } + while ((c = getopt(argcnt, args, "lu")) != EOF) { switch(c) { @@ -177,6 +184,7 @@ struct extension_table *ext; char buf[BUFSIZE]; size_t size; + int rc; for (ext = extension_table; ext; ext = ext->next) { if (same_file(ext->filename, lib)) { @@ -194,14 +202,18 @@ ext->filename = (char *)((ulong)ext + sizeof(struct extension_table)); + if ((rc = kwr_expand(ext_kwrule, lib, buf, BUFSIZE)) != 0) { + error(FATAL, "Syntax error %d in extension spec %s", rc, lib); + } + /* * If the library is not specified by an absolute pathname, dlopen() * does not look in the current directory. */ - if ((*lib != '.') && (*lib != '/') && is_elf_file(lib)) - sprintf(ext->filename, "./%s", lib); + if ((*buf != '.') && (*buf != '/') && is_elf_file(buf)) + sprintf(ext->filename, "./%s", buf); else - strcpy(ext->filename, lib); + strcpy(ext->filename, buf); /* * register_extension() will be called by the shared object's @@ -343,3 +355,48 @@ } +char * +extrule_version(char *kw, char *arg) +{ + return(strdup(pc->program_version)); +} + +char * +extrule_corestr(char *kw, char *arg) +{ + char buf[8192]; + if (symbol_exists(arg)) { + ulong kvaddr; + if (get_symbol_type(arg, NULL, NULL) == TYPE_CODE_PTR) { + get_symbol_data(arg, sizeof(kvaddr), &kvaddr); + } else { + kvaddr = symbol_value(arg); + } + read_string(kvaddr, buf, sizeof(buf)); + return (strdup(buf)); + } else { + return strdup(""); + } +} + +char * +extrule_builddir(char *kw, char *arg) +{ + char *rv; + rv = malloc(PATH_MAX); + if (!rv) { + return (NULL); + } + if (get_build_directory(rv) == NULL) { + rv[0] = '\0'; + } + return rv; +} + +static void init_ext_kwrule(void) +{ + ext_kwrule = kwr_create("-"); + kwr_add(ext_kwrule, "crash_version", extrule_version); + kwr_add(ext_kwrule, "corestr", extrule_corestr); + kwr_add(ext_kwrule, "builddir", extrule_builddir); +} Common subdirectories: crash-4.0-2.10/gdb-6.1 and crash-4.0-2.10-new/gdb-6.1 diff -Nau -X ignorepat crash-4.0-2.10/help.c crash-4.0-2.10-new/help.c --- crash-4.0-2.10/help.c 2005-11-07 07:44:06 -08:00 +++ crash-4.0-2.10-new/help.c 2005-11-09 11:28:01 -08:00 @@ -1398,6 +1398,11 @@ " \"help\" command screen.", "\n An example of a shared object prototype file, and how to compile it", " into a shared object, is appended below.", +"\n The named is subjected to a simple keyword expansion", +" scheme with the following rules:", +" $(crash_version) version of crash", +" $(corestr-) string named taken from the core file", +" $(builddir) build directory for the kernel", "\nEXAMPLES", " Load two shared object files:\n", " %s> extend extlib1.so extlib2.so", diff -Nau -X ignorepat crash-4.0-2.10/kernel.c crash-4.0-2.10-new/kernel.c --- crash-4.0-2.10/kernel.c 2005-11-07 07:44:06 -08:00 +++ crash-4.0-2.10-new/kernel.c 2005-11-07 18:57:19 -08:00 @@ -52,7 +52,7 @@ kernel_init(int when) { int i; - char *p1, *p2, buf[BUFSIZE];; + char *p1, *p2, buf[BUFSIZE]; struct syment *sp1, *sp2; if (pc->flags & KERNEL_DEBUG_QUERY) @@ -1465,8 +1465,8 @@ if (bt->hp) { if (bt->hp->esp && !INSTACK(bt->hp->esp, bt)) error(INFO, - "invalid stack address for this task: %lx\n", - bt->hp->esp); + "invalid stack address for this task ( %lx .. %lx ) : %lx\n", + bt->stackbase, bt->stacktop, bt->hp->esp); eip = bt->hp->eip; esp = bt->hp->esp; diff -Nau -X ignorepat crash-4.0-2.10/kw.c crash-4.0-2.10-new/kw.c --- crash-4.0-2.10/kw.c 1969-12-31 16:00:00 -08:00 +++ crash-4.0-2.10-new/kw.c 2005-11-07 18:57:19 -08:00 @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +/* + * Keyword ruleset library. + * + */ + +// #define TEST + + +typedef char *(*kwr_func_t)(const char *, const char *); + +struct kwr_ruleset; +typedef struct kwr_ruleset *kwr_ruleset_t; + +kwr_ruleset_t kwr_create(char *separator); +kwr_ruleset_t kwr_add(kwr_ruleset_t ruleset, char *str, kwr_func_t kwr_func); +int kwr_expand(kwr_ruleset_t rules, const char *instring, char *outstring, int len); + +struct kwr_rule { + char *kwr_kw; + kwr_func_t kwr_func; + struct kwr_rule *kwr_next; +}; + +struct kwr_ruleset { + struct kwr_rule *krs_rules; + char krs_kwend[25]; + char krs_argbeg[25]; +}; + + +/* + * Create a new ruleset + */ +kwr_ruleset_t kwr_create(char *separator) +{ + kwr_ruleset_t rv; + + rv = malloc(sizeof *rv); + if (rv == NULL) { + return NULL; + } + sprintf(rv->krs_kwend, ")%s", separator); + sprintf(rv->krs_argbeg, "%s", separator); + rv->krs_rules = NULL; + return (rv); +} + +/* + * Add a rule to a ruleset + */ +kwr_ruleset_t kwr_add(kwr_ruleset_t kwr, char *str, kwr_func_t kwr_func) +{ + struct kwr_rule *q = kwr->krs_rules, *p; + + p = malloc(sizeof(*p)); + if (p == NULL) { + return (NULL); + } + p->kwr_kw = str; + p->kwr_func = kwr_func; + p->kwr_next = kwr->krs_rules; + kwr->krs_rules = p; + return (kwr); +} + +static char *expand_kw(kwr_ruleset_t kwr, const char *kw, const char *kwargs) +{ + char *rv = NULL; + struct kwr_rule *p; + + for (p = kwr->krs_rules; p; p = p->kwr_next) { + if (strcmp(kw, p->kwr_kw) == 0) { + rv = (p->kwr_func)( kw, kwargs); + return (rv); + } + } + return (rv); +} + +int +kwr_expand(kwr_ruleset_t kwr, const char *instring, char *outstring, int len) +{ + const char *ip, *nextkey, *closepos, *argstart; + char *keyword, *kwargs, *kwval; + char *op; + int nc, kw_chars, arglen; + + ip = instring; + op = outstring; + outstring[len - 1] = '\0'; /* Terminate to be safe */ + + while (*ip != '\0') { + nextkey = strchr(ip, '$'); + if (nextkey == 0) { + strncpy(op, ip, len - (op - outstring)); + return (0); + } else { + nc = nextkey - ip; + memcpy(op, ip, nc); + op += nc; + ip += nc; + if (nextkey[1] != '(') { + return (-1); + } + closepos = strchr(ip, ')'); + if (closepos == 0) { + return (-2); + } + kw_chars = strcspn(nextkey + 2, kwr->krs_kwend); + if (kw_chars <= 0) { + return (-3); + } + keyword = alloca(kw_chars + 1); + memcpy(keyword, nextkey + 2, kw_chars); + keyword[kw_chars] = '\0'; + + argstart = nextkey + 2 + kw_chars + strspn(nextkey + 2 + kw_chars, kwr->krs_argbeg); + arglen = closepos - argstart; + assert(arglen >= 0); + kwargs = alloca(arglen + 1); + memcpy(kwargs, argstart, arglen); + kwargs[arglen] = '\0'; + kwval = expand_kw(kwr, keyword, kwargs); + if (kwval == 0) { + return (-5); + } else { + nc = strlen(kwval); + if (op + nc + 1 - outstring > len) { + free(kwval); + return (-6); + } else { + memcpy(op, kwval, nc); + op += nc; + free(kwval); + } + } + ip = closepos + 1; + } + } + *op = '\0'; + return (0); +} + +#ifdef TEST +#include +char *teststr[] = { + "Hello", + "Hello$(a b)", + "Hello$(a)", + "noargs$", + "noclose$(", + "a b $(env HOME) c d", + "a b $(version HOME) c d", + NULL +}; + +char *kwr_version(const char *kw, const char *args) +{ + return (strdup("2.1")); +} + +char *kwr_env(const char *kw, const char *args) +{ + char *p; + char *rv = NULL; + if (strcmp(kw, "env") != 0) { + return rv; + } + p = getenv(args); + if (p) { + rv = strdup(p); + } else { + rv = strdup(""); + } + return (rv); +} + +int +main(int argc, char **argv) +{ + int i = 0; + char obuf[512]; + int rc; + char *str; + kwr_ruleset_t rules; + + + rules = kwr_create(" "); + kwr_add(rules, "env", kwr_env); + kwr_add(rules, "version", kwr_version); + while ((str = teststr[i++])) { + printf("Trying :%s:\n", str); + rc = kwr_expand(rules, str, obuf, sizeof(obuf)); + if (rc == 0) { + printf("ok in:%s: out :%s:\n", str, obuf); + } else { + printf("err %d in:%s: out :%s:\n", rc, str, obuf); + } + } + return (0); +} +#endif /* TEST*/ diff -Nau -X ignorepat crash-4.0-2.10/lkcd_common.c crash-4.0-2.10-new/lkcd_common.c --- crash-4.0-2.10/lkcd_common.c 2005-11-07 07:44:06 -08:00 +++ crash-4.0-2.10-new/lkcd_common.c 2005-11-08 17:28:11 -08:00 @@ -53,6 +53,7 @@ struct lkcd_environment lkcd_environment = { 0 }; struct lkcd_environment *lkcd = &lkcd_environment; +static int uncompress_errloc; ulonglong fix_lkcd_address(ulonglong addr) @@ -208,6 +209,7 @@ case LKCD_DUMP_V8: case LKCD_DUMP_V9: + case LKCD_DUMP_V10: lkcd->version = LKCD_DUMP_V8; return TRUE; @@ -1164,40 +1166,103 @@ return 1; } +/* Returns the bit offset if it's able to correct, or negative if not */ +int +uncompress_recover(unsigned char *dest, ulong destlen, + unsigned char *source, ulong sourcelen) +{ + int byte, bit; + ulong retlen = destlen; + int good_decomp = 0, good_rv = -1; + + /* Generate all single bit errors */ + if (sourcelen > 16384) { + lkcd_print("uncompress_recover: sourcelen %ld too long\n", + sourcelen); + return(-1); + } + for (byte = 0; byte < sourcelen; byte++) { + for (bit = 0; bit < 8; bit++) { + source[byte] ^= (1 << bit); + + if (uncompress(dest, &retlen, source, sourcelen) == Z_OK && + retlen == destlen) { + good_decomp++; + lkcd_print("good for flipping byte %d bit %d\n", + byte, bit); + good_rv = bit + byte * 8; + } + + /* Put it back */ + source[byte] ^= (1 << bit); + } + } + if (good_decomp == 0) { + lkcd_print("Could not correct gzip errors.\n"); + return -2; + } else if (good_decomp > 1) { + lkcd_print("Too many valid gzip decompressions: %d.\n", good_decomp); + return -3; + } else { + source[good_rv >> 8] ^= 1 << (good_rv % 8); + uncompress(dest, &retlen, source, sourcelen); + source[good_rv >> 8] ^= 1 << (good_rv % 8); + return good_rv; + } +} + + /* * Uncompress a gzip'd buffer. + * + * Returns FALSE on error. If set, then + * a non-negative value of uncompress_errloc indicates the location of + * a single-bit error, and the data may be used. */ static int lkcd_uncompress_gzip(unsigned char *dest, ulong destlen, unsigned char *source, ulong sourcelen) { ulong retlen = destlen; + int rc; switch (uncompress(dest, &retlen, source, sourcelen)) { case Z_OK: if (retlen == destlen) - return TRUE; + rc = TRUE; + break; lkcd_print("uncompress: returned length not page size: %ld\n", retlen); - return FALSE; + rc = FALSE; + break; case Z_MEM_ERROR: lkcd_print("uncompress: Z_MEM_ERROR (not enough memory)\n"); - return FALSE; + rc = FALSE; + break; case Z_BUF_ERROR: lkcd_print("uncompress: " "Z_BUF_ERROR (not enough room in output buffer)\n"); - return FALSE; + rc = FALSE; + break; case Z_DATA_ERROR: lkcd_print("uncompress: Z_DATA_ERROR (input data corrupted)\n"); - return FALSE; + rc = FALSE; + break; + default: + rc = FALSE; + break; } - return FALSE; + if (rc == FALSE) { + uncompress_errloc = + uncompress_recover(dest, destlen, source, sourcelen); + } + return rc; } @@ -1252,8 +1317,9 @@ dp_flags = lkcd->get_dp_flags(); dp_address = lkcd->get_dp_address(); - if (dp_flags & LKCD_DUMP_END) + if (dp_flags & LKCD_DUMP_END) { return LKCD_DUMPFILE_END; + } if ((lkcd->flags & LKCD_VALID) && (page > lkcd->total_pages)) lkcd->total_pages = page; diff -Nau -X ignorepat crash-4.0-2.10/lkcd_v7.c crash-4.0-2.10-new/lkcd_v7.c --- crash-4.0-2.10/lkcd_v7.c 2005-11-07 07:44:06 -08:00 +++ crash-4.0-2.10-new/lkcd_v7.c 2005-11-07 18:57:19 -08:00 @@ -89,7 +89,11 @@ ifd = 0; #ifdef LKCD_INDEX_FILE - lkcd->memory_pages = (dh->dh_memory_size * (getpagesize()/lkcd->page_size)) * 2; + if (dh->dh_memory_end < 0x1000000000LL) { + lkcd->memory_pages = dh->dh_memory_end / lkcd->page_size + 1; + } else { + lkcd->memory_pages = (dh->dh_memory_size * (getpagesize()/lkcd->page_size)) * 2; + } dump_index_size = (lkcd->memory_pages * sizeof(off_t)); lkcd->page_offsets = 0; strcpy(dumpfile_index_name, dumpfile); diff -Nau -X ignorepat crash-4.0-2.10/task.c crash-4.0-2.10-new/task.c --- crash-4.0-2.10/task.c 2005-11-07 07:44:06 -08:00 +++ crash-4.0-2.10-new/task.c 2005-11-07 18:57:19 -08:00 @@ -2942,7 +2942,7 @@ fprintf(fp, "(SYSRQ)"); else if (machdep->flags & INIT) fprintf(fp, "(INIT)"); - else if (kt->cpu_flags[tc->processor] & NMI) + else if (verify_task(tc, 2) && kt->cpu_flags[tc->processor] & NMI) fprintf(fp, "(NMI)"); else if (tc->task == tt->panic_task) fprintf(fp, "(PANIC)"); @@ -3460,7 +3460,10 @@ get_lkcd_panicmsg(buf); msg_found = TRUE; } - + + if (msg_found == TRUE) + return(buf); + open_tmpfile(); dump_log(FALSE); @@ -4337,7 +4340,8 @@ tc = FIRST_CONTEXT(); for (i = 0; i < RUNNING_TASKS(); i++, tc++) { - if (task_has_cpu(tc->task, NULL)) { + if (task_has_cpu(tc->task, NULL) + && tc->processor >= 0 && tc->processor < NR_CPUS) { tt->panic_threads[tc->processor] = tc->task; found++; } diff -Nau -X ignorepat crash-4.0-2.10/x86.c crash-4.0-2.10-new/x86.c --- crash-4.0-2.10/x86.c 2005-11-07 07:44:06 -08:00 +++ crash-4.0-2.10-new/x86.c 2005-11-07 18:57:19 -08:00 @@ -683,8 +683,7 @@ if ((machdep->flags & OMIT_FRAME_PTR) || bt->debug || - (bt->flags & BT_FRAMESIZE_DEBUG) || - !(bt->flags & BT_OLD_BACK_TRACE)) { + (bt->flags & BT_FRAMESIZE_DEBUG)) { lkcd_x86_back_trace(bt, 0, fp); return; } @@ -3104,31 +3103,31 @@ * with the -fomit-frame-pointer flag. */ #define PUSH_BP_MOV_ESP_BP 0xe58955 +#define PUSH_BP_CLR_EAX_MOV_ESP_BP 0xe589c03155LL static int x86_omit_frame_pointer(void) { - ulong push_bp_mov_esp_bp[3]; + ulonglong push_bp_mov_esp_bp; + int i; + char *checkfuncs[] = {"sys_open", "sys_fork", "sys_read"}; if (pc->flags & KERNEL_DEBUG_QUERY) return FALSE; - if (!readmem(symbol_value("sys_open"), KVADDR, &push_bp_mov_esp_bp[0], - sizeof(ulong), "x86_omit_frame_pointer", RETURN_ON_ERROR)) - return TRUE; - if (!readmem(symbol_value("sys_fork"), KVADDR, &push_bp_mov_esp_bp[1], - sizeof(ulong), "x86_omit_frame_pointer", RETURN_ON_ERROR)) - return TRUE; - if (!readmem(symbol_value("sys_read"), KVADDR, &push_bp_mov_esp_bp[2], - sizeof(ulong), "x86_omit_frame_pointer", RETURN_ON_ERROR)) - return TRUE; - - if (((push_bp_mov_esp_bp[0] & 0xffffff) == PUSH_BP_MOV_ESP_BP) && - ((push_bp_mov_esp_bp[1] & 0xffffff) == PUSH_BP_MOV_ESP_BP) && - ((push_bp_mov_esp_bp[2] & 0xffffff) == PUSH_BP_MOV_ESP_BP)) - return FALSE; + for (i = 0; i < 2; i++) { + if (!readmem(symbol_value(checkfuncs[i]), KVADDR, + &push_bp_mov_esp_bp, sizeof(ulonglong), + "x86_omit_frame_pointer", RETURN_ON_ERROR)) + return TRUE; + if ( !((push_bp_mov_esp_bp & 0x0000ffffff) == PUSH_BP_MOV_ESP_BP + || (push_bp_mov_esp_bp & 0xffffffffffLL) == + PUSH_BP_CLR_EAX_MOV_ESP_BP)) { + return TRUE; + } + } - return TRUE; + return FALSE; } /*