--- crash-4.0-6.3/main.c 2008-07-14 10:31:19.000000000 -0400 +++ crash-4.0-7.1/main.c 2008-08-18 16:35:46.000000000 -0400 @@ -57,6 +57,7 @@ {"no_scroll", 0, 0, 0}, {"reloc", required_argument, 0, 0}, {"active", 0, 0, 0}, + {"minimal", 0, 0, 0}, {0, 0, 0, 0} }; @@ -201,6 +202,9 @@ kt->flags |= RELOC_SET; } + else if (STREQ(long_options[option_index].name, "minimal")) + pc->flags |= MINIMAL_MODE; + else { error(INFO, "internal error: option %s unhandled\n", long_options[option_index].name); @@ -496,7 +500,7 @@ #else error(FATAL, XEN_HYPERVISOR_NOT_SUPPORTED); #endif - } else { + } else if (!(pc->flags & MINIMAL_MODE)) { read_in_kernel_config(IKCFG_INIT); kernel_init(); machdep_init(POST_GDB); @@ -521,16 +525,21 @@ #ifdef XEN_HYPERVISOR_ARCH xen_hyper_display_sys_stats(); xen_hyper_show_vcpu_context(XEN_HYPER_VCPU_LAST_CONTEXT()); + fprintf(fp, "\n"); #else error(FATAL, XEN_HYPERVISOR_NOT_SUPPORTED); #endif - } else { + } else if (!(pc->flags & MINIMAL_MODE)) { display_sys_stats(); show_context(CURRENT_CONTEXT()); + fprintf(fp, "\n"); } - fprintf(fp, "\n"); } + if (pc->flags & MINIMAL_MODE) + error(NOTE, + "minimal mode commands: log, dis, rd, sym, eval and exit\n\n"); + pc->flags |= RUNTIME; /* @@ -607,14 +616,22 @@ if (is_datatype_command()) goto reattempt; - if (is_gdb_command(TRUE, FAULT_ON_ERROR)) + if (!(pc->flags & MINIMAL_MODE) && + is_gdb_command(TRUE, FAULT_ON_ERROR)) goto reattempt; if (REMOTE() && remote_execute()) return; pc->curcmd = pc->program_name; - error(INFO, "command not found: %s\n", args[0]); + + if (pc->flags & MINIMAL_MODE) + error(INFO, + "%s: command not available in minimal mode\n" + "NOTE: minimal mode commands: log, dis, rd, sym, eval and exit\n", + args[0]); + else + error(INFO, "command not found: %s\n", args[0]); if (pc->curcmd_flags & REPEAT) pc->curcmd_flags &= ~REPEAT; @@ -629,6 +646,9 @@ { struct command_table_entry *cp; struct extension_table *ext; + + if ((pc->flags & MINIMAL_MODE) && !minimal_functions(name)) + return NULL; for (cp = pc->cmd_table; cp->name; cp++) { if (STREQ(cp->name, name)) @@ -1062,6 +1082,9 @@ if (pc->flags & IFILE_ERROR) sprintf(&buf[strlen(buf)], "%sIFILE_ERROR", others++ ? "|" : ""); + if (pc->flags & MINIMAL_MODE) + sprintf(&buf[strlen(buf)], + "%sMINIMAL_MODE", others++ ? "|" : ""); if (pc->flags) strcat(buf, ")"); --- crash-4.0-6.3/tools.c 2008-07-14 10:31:20.000000000 -0400 +++ crash-4.0-7.1/tools.c 2008-08-06 16:17:36.000000000 -0400 @@ -41,11 +41,11 @@ { int end_of_line, new_line; char buf[BUFSIZE]; - ulong retaddr[4] = { 0 }; + ulong retaddr[NUMBER_STACKFRAMES] = { 0 }; va_list ap; if (CRASHDEBUG(1) || (pc->flags & DROP_CORE)) { - save_return_address(retaddr); + SAVE_RETURN_ADDRESS(retaddr); console("error() trace: %lx => %lx => %lx => %lx\n", retaddr[3], retaddr[2], retaddr[1], retaddr[0]); } @@ -4436,6 +4436,11 @@ if (CRASHDEBUG(2)) error(INFO, "convert_time: %lld (%llx)\n", count, count); + if (!machdep->hz) { + sprintf(buf, "(cannot calculate: unknown HZ value)"); + return buf; + } + total = (count)/(ulonglong)machdep->hz; days = total / SEC_DAYS; --- crash-4.0-6.3/memory.c 2008-07-14 10:31:20.000000000 -0400 +++ crash-4.0-7.1/memory.c 2008-08-08 11:41:37.000000000 -0400 @@ -320,6 +320,9 @@ MEMBER_OFFSET_INIT(block_device_bd_disk, "block_device", "bd_disk"); MEMBER_OFFSET_INIT(inode_i_mapping, "inode", "i_mapping"); MEMBER_OFFSET_INIT(address_space_nrpages, "address_space", "nrpages"); + if (INVALID_MEMBER(address_space_nrpages)) + MEMBER_OFFSET_INIT(address_space_nrpages, "address_space", "__nrpages"); + MEMBER_OFFSET_INIT(gendisk_major, "gendisk", "major"); MEMBER_OFFSET_INIT(gendisk_fops, "gendisk", "fops"); MEMBER_OFFSET_INIT(gendisk_disk_name, "gendisk", "disk_name"); @@ -10379,7 +10382,10 @@ mem_map: mi->flags = orig_flags; pc->curcmd_flags &= ~HEADER_PRINTED; - dump_mem_map(mi); + if (vaddr != BADADDR) + dump_mem_map(mi); + else + mi->retval = FALSE; if (!mi->retval) fprintf(fp, "%llx: %s address not found in mem map\n", @@ -10934,6 +10940,11 @@ switch(c) { case 'u': + if (XEN_HYPER_MODE()) + error(FATAL, + "-u option is not applicable to the " + "Xen hypervisor\n"); + if (!sflag) { address_space_start(CURRENT_CONTEXT(),&start); sflag++; @@ -10943,6 +10954,11 @@ break; case 'k': + if (XEN_HYPER_MODE()) + error(FATAL, + "-k option is not applicable to the " + "Xen hypervisor\n"); + if (!sflag) { start = machdep->kvbase; if (machine_type("IA64") && @@ -10984,6 +11000,14 @@ } } + if (XEN_HYPER_MODE()) { + memtype = KVADDR; + if (!sflag) + error(FATAL, + "the \"-s start\" option is required for" + " the Xen hypervisor\n"); + } + if (argerrs || !sflag || !args[optind] || (len && end)) cmd_usage(pc->curcmd, SYNOPSIS); @@ -11023,7 +11047,9 @@ break; case KVADDR: - if (vt->vmalloc_start < machdep->identity_map_base) + if (XEN_HYPER_MODE()) + end = (ulong)(-1); + else if (vt->vmalloc_start < machdep->identity_map_base) end = (ulong)(-1); else { meminfo.memtype = KVADDR; @@ -11042,6 +11068,8 @@ switch (memtype) { case UVADDR: + if (is_kernel_thread(CURRENT_TASK()) || !task_mm(CURRENT_TASK(), TRUE)) + error(FATAL, "current context has no user address space\n"); if (end > uvaddr_end) { error(INFO, "address range starts in user space and ends kernel space\n"); @@ -11097,6 +11125,20 @@ 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: @@ -11123,7 +11165,7 @@ pp += PAGESIZE(); continue; } - +virtual: ubp = (ulong *)&pagebuf[next - pp]; if (lastpage) { if (end == (ulong)(-1)) --- crash-4.0-6.3/task.c 2008-07-14 10:31:20.000000000 -0400 +++ crash-4.0-7.1/task.c 2008-08-06 16:23:01.000000000 -0400 @@ -306,12 +306,15 @@ get_symbol_data("cfq_slice_async", sizeof(int), &cfq_slice_async); - machdep->hz = cfq_slice_async * 25; - if (CRASHDEBUG(2)) - fprintf(fp, - "cfq_slice_async exitsts: setting hz to %d\n", - machdep->hz); + if (cfq_slice_async) { + machdep->hz = cfq_slice_async * 25; + + if (CRASHDEBUG(2)) + fprintf(fp, + "cfq_slice_async exists: setting hz to %d\n", + machdep->hz); + } } if (VALID_MEMBER(runqueue_arrays)) --- crash-4.0-6.3/kernel.c 2008-07-14 10:31:20.000000000 -0400 +++ crash-4.0-7.1/kernel.c 2008-08-06 16:12:21.000000000 -0400 @@ -933,6 +933,10 @@ } if (CRASHDEBUG(1)) { + error(WARNING, + "\ncannot find matching kernel version in %s file:\n\n", + namelist); + fprintf(fp, "verify_namelist:\n"); fprintf(fp, "/proc/version:\n%s\n", kt->proc_version); fprintf(fp, "utsname version: %s\n", kt->utsname.version); --- crash-4.0-6.3/configure.c 2008-07-14 10:31:19.000000000 -0400 +++ crash-4.0-7.1/configure.c 2008-07-17 08:52:14.000000000 -0400 @@ -1156,7 +1156,7 @@ printf("Name: %s\n", lower_case(target_data.program, buf)); printf("Version: %s\n", Version); printf("Release: %s\n", Release); - printf("License: GPL\n"); + printf("License: GPLv2\n"); printf("Group: Development/Debuggers\n"); printf("Source: %%{name}-%%{version}-%%{release}.tar.gz\n"); printf("URL: http://people.redhat.com/anderson\n"); --- crash-4.0-6.3/ia64.c 2008-07-14 10:31:20.000000000 -0400 +++ crash-4.0-7.1/ia64.c 2008-05-21 08:45:49.000000000 -0400 @@ -4167,14 +4167,14 @@ if (!machdep->kvtop(NULL, addr, &paddr, 0)) return 0; - __per_cpu_mca = (ulong *)GETBUF(sizeof(ulong) * xht->pcpus); + __per_cpu_mca = (ulong *)GETBUF(sizeof(ulong) * plen); if (!readmem(symbol_value("__per_cpu_mca"), KVADDR, __per_cpu_mca, - sizeof(ulong) * xht->pcpus, "__per_cpu_mca", RETURN_ON_ERROR|QUIET)) + sizeof(ulong) * plen, "__per_cpu_mca", RETURN_ON_ERROR|QUIET)) return 0; if (CRASHDEBUG(1)) { - for (i = 0; i < xht->pcpus; i++) { + for (i = 0; i < plen; i++) { fprintf(fp, "__per_cpu_mca[%d]: %lx\n", i, __per_cpu_mca[i]); } --- crash-4.0-6.3/symbols.c 2008-07-14 10:31:20.000000000 -0400 +++ crash-4.0-7.1/symbols.c 2008-08-12 14:40:13.000000000 -0400 @@ -1312,6 +1312,14 @@ lm_mcnt = mcnt; mcnt++; + if (nsyms && !IN_MODULE(syms, lm)) { + error(WARNING, + "[%s] module.syms outside of module " + "address space (%lx)\n\n", + lm->mod_name, syms); + nsyms = 0; + } + if (nsyms) { modsymbuf = GETBUF(sizeof(struct kernel_symbol)*nsyms); readmem((ulong)syms, KVADDR, modsymbuf, @@ -8913,8 +8921,8 @@ return offset2; if (pc->flags & DATADEBUG) { - ulong retaddr[4] = { 0 }; - save_return_address(retaddr); + ulong retaddr[NUMBER_STACKFRAMES] = { 0 }; + SAVE_RETURN_ADDRESS(retaddr); sprintf(errmsg, "invalid (optional) structure member offsets: %s or %s", item1, item2); @@ -8936,8 +8944,8 @@ return size2; if (pc->flags & DATADEBUG) { - ulong retaddr[4] = { 0 }; - save_return_address(retaddr); + ulong retaddr[NUMBER_STACKFRAMES] = { 0 }; + SAVE_RETURN_ADDRESS(retaddr); sprintf(errmsg, "invalid (optional) structure sizes: %s or %s", item1, item2); datatype_error(retaddr, errmsg, func, file, line); @@ -8964,8 +8972,8 @@ return offset; if (offset < 0) { - ulong retaddr[4] = { 0 }; - save_return_address(retaddr); + ulong retaddr[NUMBER_STACKFRAMES] = { 0 }; + SAVE_RETURN_ADDRESS(retaddr); sprintf(errmsg, "invalid structure member offset: %s", item); datatype_error(retaddr, errmsg, func, file, line); @@ -8982,8 +8990,8 @@ return size; if (size < 0) { - ulong retaddr[4] = { 0 }; - save_return_address(retaddr); + ulong retaddr[NUMBER_STACKFRAMES] = { 0 }; + SAVE_RETURN_ADDRESS(retaddr); sprintf(errmsg, "invalid structure size: %s", item); datatype_error(retaddr, errmsg, func, file, line); } @@ -9051,7 +9059,7 @@ thisfile = get_thisfile(); fprintf(stderr, "[%s] error trace: ", thisfile); - for (i = 3; i >= 0; i--) { + for (i = (NUMBER_STACKFRAMES-1); i >= 0; i--) { if (retaddr[i]) fprintf(stderr, "%s%lx%s", i == 3 ? "" : "=> ", @@ -9065,7 +9073,7 @@ return; } - for (i = 0; i < 4; i++) { + for (i = 0; i < NUMBER_STACKFRAMES; i++) { if (!(lookfor = retaddr[i])) continue; --- crash-4.0-6.3/cmdline.c 2008-07-14 10:31:21.000000000 -0400 +++ crash-4.0-7.1/cmdline.c 2008-08-18 13:55:03.000000000 -0400 @@ -34,6 +34,7 @@ static void wait_for_children(ulong); #define ZOMBIES_ONLY (1) #define ALL_CHILDREN (2) +int shell_command(char *); #define READLINE_LIBRARY @@ -481,10 +482,8 @@ if (LASTCHAR(p) == '|') error(FATAL_RESTART, "pipe to nowhere?\n"); - if (pc->redirect & REDIRECT_SHELL_COMMAND) { - system(p); - return REDIRECT_SHELL_COMMAND; - } + if (pc->redirect & REDIRECT_SHELL_COMMAND) + return shell_command(p); if ((pipe = popen(p, "w")) == NULL) { error(INFO, "cannot open pipe\n"); @@ -829,16 +828,13 @@ void cmdline_init(void) { - int fd; + int fd = 0; /* * Stash a copy of the original termios setup. * Build a raw version for quick use for each command entry. */ - if (isatty(fileno(stdin))) { - if ((fd = open("/dev/tty", O_RDONLY)) < 0) - error(FATAL, "/dev/tty: %s\n", strerror(errno)); - + if (isatty(fileno(stdin)) && ((fd = open("/dev/tty", O_RDONLY)) >= 0)) { if (tcgetattr(fd, &pc->termios_orig) == -1) error(FATAL, "tcgetattr /dev/tty: %s\n", strerror(errno)); @@ -862,8 +858,10 @@ readline_init(); } else { - fprintf(fp, pc->flags & SILENT ? - "" : " NOTE: stdin: not a tty\n"); + if (fd < 0) + error(INFO, "/dev/tty: %s\n", strerror(errno)); + if (!(pc->flags & SILENT)) + fprintf(fp, "NOTE: stdin: not a tty\n\n"); fflush(fp); pc->flags &= ~TTY; } @@ -2137,3 +2135,35 @@ stall(1000); } } + +/* + * Run an escaped shell command, redirecting the output to + * the current output file. + */ +int +shell_command(char *cmd) +{ + FILE *pipe; + char buf[BUFSIZE]; + + if ((pipe = popen(cmd, "r")) == NULL) { + error(INFO, "cannot open pipe: %s\n", cmd); + pc->redirect &= ~REDIRECT_SHELL_COMMAND; + pc->redirect |= REDIRECT_FAILURE; + return REDIRECT_FAILURE; + } + + while (fgets(buf, BUFSIZE, pipe)) + fprintf(fp, buf); + pclose(pipe); + + return REDIRECT_SHELL_COMMAND; +} + +int minimal_functions(char *name) +{ + return STREQ("log", name) || STREQ("help",name) || \ + STREQ("dis", name) || STREQ("q", name) || \ + STREQ("sym", name) || STREQ("exit", name)|| \ + STREQ("rd", name) || STREQ("eval", name) ; +} --- crash-4.0-6.3/defs.h 2008-07-14 10:31:20.000000000 -0400 +++ crash-4.0-7.1/defs.h 2008-08-19 11:10:10.000000000 -0400 @@ -46,6 +46,7 @@ #include #include #include +#include /* backtrace() */ #define BASELEVEL_REVISION "4.0" @@ -183,6 +184,7 @@ #define PLEASE_WAIT (0x200000000000000ULL) #define IFILE_ERROR (0x400000000000000ULL) #define KERNTYPES (0x800000000000000ULL) +#define MINIMAL_MODE (0x1000000000000000ULL) #define ACTIVE() (pc->flags & LIVE_SYSTEM) #define DUMPFILE() (!(pc->flags & LIVE_SYSTEM)) @@ -1797,18 +1799,18 @@ char argbuf[1]; }; -static inline void -save_return_address(ulong *retaddr) -{ - retaddr[0] = (ulong) __builtin_return_address(0); -#if defined(X86) || defined(PPC) || defined(X86_64) || defined(PPC64) - if (__builtin_frame_address(1)) - retaddr[1] = (ulong) __builtin_return_address(1); - if (__builtin_frame_address(2)) - retaddr[2] = (ulong) __builtin_return_address(2); - if (__builtin_frame_address(3)) - retaddr[3] = (ulong) __builtin_return_address(3); -#endif +#define NUMBER_STACKFRAMES 4 + +#define SAVE_RETURN_ADDRESS(retaddr) \ +{ \ + int i; \ + int saved_stacks; \ + \ + saved_stacks = backtrace((void **)retaddr, NUMBER_STACKFRAMES); \ + \ + /* explicitely zero out the invalid addresses */ \ + for (i = saved_stacks; i < NUMBER_STACKFRAMES; i++) \ + retaddr[i] = 0; \ } #endif /* !GDB_COMMON */ @@ -3135,6 +3137,7 @@ void debug_redirect(char *); int CRASHPAGER_valid(void); char *setup_scroll_command(void); +int minimal_functions(char *); /* * tools.c