--- crash-4.0-7.7/memory.c 2009-03-20 11:22:07.000000000 -0400 +++ crash-4.0-8.8/memory.c 2009-03-16 09:32:53.000000000 -0400 @@ -185,6 +185,7 @@ static int count_free_objects(struct meminfo *, ulong); char *is_slab_page(struct meminfo *, char *); static void do_node_lists_slub(struct meminfo *, ulong, int); +static void check_devmem_is_allowed(void); /* * Memory display modes specific to this file. @@ -1766,6 +1767,10 @@ if (cnt > size) cnt = size; + if (CRASHDEBUG(8)) + fprintf(fp, " addr: %llx paddr: %llx cnt: %ld\n", + addr, (unsigned long long)paddr, cnt); + switch (READMEM(fd, bufptr, cnt, (memtype == PHYSADDR) || (memtype == XENMACHADDR) ? 0 : addr, paddr)) { @@ -1800,6 +1805,8 @@ switch (error_handle) { case (FAULT_ON_ERROR): + if (ACTIVE() && (kt->flags & IN_KERNEL_INIT)) + check_devmem_is_allowed(); case (QUIET|FAULT_ON_ERROR): if (pc->flags & IN_FOREACH) RESUME_FOREACH(); @@ -1917,6 +1924,42 @@ } /* + * The first required reads of memory are done in kernel_init(), + * so if there's a fatal read error of /dev/mem, display a warning + * message if it appears that CONFIG_STRICT_DEVMEM is in effect, + * which only allows the first 256 pages of physical memory to + * be accessed: + * + * int devmem_is_allowed(unsigned long pagenr) + * { + * if (pagenr <= 256) + * return 1; + * if (!page_is_ram(pagenr)) + * return 1; + * return 0; + * } + */ +static void +check_devmem_is_allowed(void) +{ + long tmp; + + if (STREQ(pc->live_memsrc, "/dev/mem") && + kernel_symbol_exists("devmem_is_allowed") && + readmem(256*PAGESIZE(), PHYSADDR, &tmp, + sizeof(long), "devmem_is_allowed - pfn 256", + QUIET|RETURN_ON_ERROR) && + !(readmem(257*PAGESIZE(), PHYSADDR, &tmp, + sizeof(long), "devmem_is_allowed - pfn 257", + QUIET|RETURN_ON_ERROR))) { + error(INFO, + "\nThis kernel may be configured with CONFIG_STRICT_DEVMEM," + " which\n renders /dev/mem unusable as a live memory " + "source.\n\n"); + } +} + +/* * Read from memory driver. */ int @@ -3369,7 +3412,6 @@ void get_task_mem_usage(ulong task, struct task_mem_usage *tm) { - int rdflags; struct task_context *tc; BZERO(tm, sizeof(struct task_mem_usage)); @@ -3377,8 +3419,6 @@ if (IS_ZOMBIE(task) || IS_EXITING(task)) return; - rdflags = ACTIVE() ? (QUIET|RETURN_ON_ERROR) : RETURN_ON_ERROR; - tc = task_to_context(task); if (!tc || !tc->mm_struct) /* probably a kernel thread */ --- crash-4.0-7.7/help.c 2009-03-20 11:22:07.000000000 -0400 +++ crash-4.0-8.8/help.c 2009-02-20 14:16:32.000000000 -0500 @@ -1494,6 +1494,13 @@ " one object file may be entered.", " -u shared-object unload the specified shared object file; if no file", " arguments are specified, unload all objects.", +"\n If the shared-object filename is not expressed with a fully-qualified", +" pathname, the following directories will be searched in the order shown,", +" and the first instance of the file that is found will be selected:\n", +" 1. the current working directory", +" 2. the directory specified in the CRASH_EXTENSIONS environment variable", +" 3. /usr/lib64/crash/extensions (64-bit architectures)", +" 4. /usr/lib/crash/extensions", "\n If no arguments are entered, the current set of shared object files and ", " a list of their commands will be displayed. The registered commands", " contained in each shared object file will appear automatically in the ", --- crash-4.0-7.7/kernel.c 2009-03-20 11:22:07.000000000 -0400 +++ crash-4.0-8.8/kernel.c 2009-02-18 15:33:20.000000000 -0500 @@ -67,6 +67,8 @@ if (pc->flags & KERNEL_DEBUG_QUERY) return; + kt->flags |= IN_KERNEL_INIT; + if (!(kt->cpu_flags = (ulong *)calloc(NR_CPUS, sizeof(ulong)))) error(FATAL, "cannot malloc cpu_flags array"); @@ -526,6 +528,8 @@ } BUG_bytes_init(); + + kt->flags &= ~IN_KERNEL_INIT; } /* @@ -2017,7 +2021,7 @@ if (bt->hp) { if (bt->hp->esp && !INSTACK(bt->hp->esp, bt)) error(INFO, - "invalid stack address for this task: %lx\n (valid range: %lx - %lx)\n", + "non-process stack address for this task: %lx\n (valid range: %lx - %lx)\n", bt->hp->esp, bt->stackbase, bt->stacktop); eip = bt->hp->eip; esp = bt->hp->esp; @@ -3365,7 +3369,7 @@ dump_log(int msg_level) { int i; - ulong log_buf, logged_chars; + ulong log_buf, log_end; char *buf; char last; ulong index; @@ -3392,18 +3396,16 @@ buf = GETBUF(log_buf_len); log_wrap = FALSE; - get_symbol_data("logged_chars", sizeof(ulong), &logged_chars); + get_symbol_data("log_end", sizeof(ulong), &log_end); readmem(log_buf, KVADDR, buf, log_buf_len, "log_buf contents", FAULT_ON_ERROR); - if (logged_chars < log_buf_len) { + if (log_end < log_buf_len) index = 0; - } else { - get_symbol_data("log_end", sizeof(ulong), &index); - index &= log_buf_len-1; - } + else + index = log_end & (log_buf_len - 1); - if ((logged_chars < log_buf_len) && (index == 0) && (buf[index] == '<')) + if ((log_end < log_buf_len) && (index == 0) && (buf[index] == '<')) loglevel = TRUE; else loglevel = FALSE; @@ -4000,6 +4002,8 @@ fprintf(fp, "%sRELOC_SET", others++ ? "|" : ""); if (kt->flags & RELOC_FORCE) fprintf(fp, "%sRELOC_FORCE", others++ ? "|" : ""); + if (kt->flags & IN_KERNEL_INIT) + fprintf(fp, "%sIN_KERNEL_INIT", others++ ? "|" : ""); fprintf(fp, ")\n"); fprintf(fp, " stext: %lx\n", kt->stext); fprintf(fp, " etext: %lx\n", kt->etext); --- crash-4.0-7.7/configure.c 2009-03-20 11:22:07.000000000 -0400 +++ crash-4.0-8.8/configure.c 2009-02-19 14:29:07.000000000 -0500 @@ -1187,12 +1187,25 @@ printf("netdump, diskdump and kdump packages from Red Hat Linux, the mcore kernel patch\n"); printf("offered by Mission Critical Linux, or the LKCD kernel patch.\n"); printf("\n"); + printf("%%package extensions\n"); + printf("Summary: Additional commands for the crash dump analysis tool\n"); + printf("Group: Development/Debuggers\n"); + printf("\n"); + printf("%%description extensions\n"); + printf("The extensions package contains plugins that provide additional crash\n"); + printf("commands. The extensions can be loaded in crash via the \"extend\" command.\n"); + printf("\n"); + printf("The following extensions are provided:\n"); + printf("* sial: Provides C-like language for writing dump analysis scripts\n"); + printf("* dminfo: Device-mapper target analyzer\n"); + printf("\n"); printf("%%prep\n"); printf("%%setup -n %%{name}-%%{version}-%%{release}\n"); printf("# %%patch0 -p1 -b .install (patch example)\n"); printf("\n"); printf("%%build\n"); printf("make RPMPKG=\"%%{version}-%%{release}\"\n"); + printf("make RPMPKG=\"%%{version}-%%{release}\" extensions\n"); /* printf("make crashd\n"); */ printf("\n"); printf("%%install\n"); @@ -1203,6 +1216,9 @@ printf("cp crash.8 %%{buildroot}%%{_mandir}/man8/crash.8\n"); printf("mkdir -p %%{buildroot}%%{_includedir}/crash\n"); printf("cp defs.h %%{buildroot}%%{_includedir}/crash\n"); + printf("mkdir -p %%{buildroot}%%{_libdir}/crash/extensions\n"); + printf("cp extensions/sial.so %%{buildroot}%%{_libdir}/crash/extensions\n"); + printf("cp extensions/dminfo.so %%{buildroot}%%{_libdir}/crash/extensions\n"); printf("\n"); printf("%%clean\n"); printf("rm -rf %%{buildroot}\n"); @@ -1216,6 +1232,10 @@ printf("%%files devel\n"); printf("%%defattr(-,root,root)\n"); printf("%%{_includedir}/*\n"); + printf("\n"); + printf("%%files extensions\n"); + printf("%%defattr(-,root,root)\n"); + printf("%%{_libdir}/crash/extensions/*\n"); } /* --- crash-4.0-7.7/x86_64.c 2009-03-20 11:22:07.000000000 -0400 +++ crash-4.0-8.8/x86_64.c 2009-03-11 16:39:00.000000000 -0400 @@ -2316,7 +2316,7 @@ last_process_stack_eframe = 0; bt->call_target = NULL; rsp = bt->stkptr; - if (!rsp) { + if (!rsp || !accessible(rsp)) { error(INFO, "cannot determine starting stack pointer\n"); return; } --- crash-4.0-7.7/extensions.c 2009-03-20 11:22:07.000000000 -0400 +++ crash-4.0-8.8/extensions.c 2009-02-20 14:16:38.000000000 -0500 @@ -18,6 +18,8 @@ #include "defs.h" #include +static int in_extensions_library(char *, char *); + #define DUMP_EXTENSIONS (0) #define LOAD_EXTENSION (1) #define UNLOAD_EXTENSION (2) @@ -186,18 +188,19 @@ void load_extension(char *lib) { - struct extension_table *ext; + struct extension_table *ext, *curext; char buf[BUFSIZE]; size_t size; + char *env; + int env_len; - for (ext = extension_table; ext; ext = ext->next) { - if (same_file(ext->filename, lib)) { - fprintf(fp, "%s: shared object already loaded\n", lib); - return; - } - } + if ((env = getenv("CRASH_EXTENSIONS"))) + env_len = strlen(env)+1; + else + env_len = 0; - size = sizeof(struct extension_table) + strlen(lib) + strlen("./") + 1; + size = sizeof(struct extension_table) + strlen(lib) + + MAX(env_len, strlen("/usr/lib64/crash/extensions/")) + 1; if ((ext = (struct extension_table *)malloc(size)) == NULL) error(FATAL, "cannot malloc extension_table space."); @@ -208,13 +211,39 @@ /* * If the library is not specified by an absolute pathname, dlopen() - * does not look in the current directory. + * does not look in the current directory, so modify the filename. + * If it's not in the current directory, check the extensions library + * directory. */ - if ((*lib != '.') && (*lib != '/') && is_elf_file(lib)) - sprintf(ext->filename, "./%s", lib); - else + if ((*lib != '.') && (*lib != '/')) { + if (file_exists(lib, NULL)) + sprintf(ext->filename, "./%s", lib); + else if (in_extensions_library(lib, buf)) + strcpy(ext->filename, buf); + else { + error(INFO, "%s: %s\n", lib, strerror(ENXIO)); + free(ext); + return; + } + } else strcpy(ext->filename, lib); + if (!is_elf_file(ext->filename)) { + error(INFO, "%s: not an ELF format object file\n", + ext->filename); + free(ext); + return; + } + + for (curext = extension_table; curext; curext = curext->next) { + if (same_file(curext->filename, ext->filename)) { + fprintf(fp, "%s: shared object already loaded\n", + ext->filename); + free(ext); + return; + } + } + /* * register_extension() will be called by the shared object's * _init() function before dlopen() returns below. @@ -262,12 +291,43 @@ } /* + * Check the extensions library directories. + */ +static int +in_extensions_library(char *lib, char *buf) +{ + char *env; + + if ((env = getenv("CRASH_EXTENSIONS"))) { + sprintf(buf, "%s%s%s", env, + LASTCHAR(env) == '/' ? "" : "/", + lib); + if (file_exists(buf, NULL)) + return TRUE; + } + + if (BITS64()) { + sprintf(buf, "/usr/lib64/crash/extensions/%s", lib); + if (file_exists(buf, NULL)) + return TRUE; + } + + sprintf(buf, "/usr/lib/crash/extensions/%s", lib); + if (file_exists(buf, NULL)) + return TRUE; + + return FALSE; +} + +/* * Unload all, or as specified, extension libraries. */ void unload_extension(char *lib) { struct extension_table *ext; + int found; + char buf[BUFSIZE]; if (!lib) { while (extension_table) { @@ -288,8 +348,20 @@ return; } - for (ext = extension_table; ext; ext = ext->next) { + if ((*lib != '.') && (*lib != '/')) { + if (!file_exists(lib, NULL) && + in_extensions_library(lib, buf)) + lib = buf; + } + + if (!file_exists(lib, NULL)) { + error(INFO, "%s: %s\n", lib, strerror(ENXIO)); + return; + } + + for (ext = extension_table, found = FALSE; ext; ext = ext->next) { if (same_file(lib, ext->filename)) { + found = TRUE; if (dlclose(ext->handle)) error(INFO, "dlclose: %s: shared object not open\n", @@ -313,7 +385,15 @@ help_init(); } } + if (STREQ(basename(lib), basename(ext->filename))) { + error(INFO, "%s and %s are different object files\n", + lib, ext->filename); + found = TRUE; + } } + + if (!found) + error(INFO, "%s: not loaded\n", lib); } /* --- crash-4.0-7.7/unwind.c 2009-03-20 11:22:07.000000000 -0400 +++ crash-4.0-8.8/unwind.c 2009-02-27 14:49:41.000000000 -0500 @@ -2072,7 +2072,6 @@ char *type) { unsigned long pt, sw, pid; - int processor; char *p, *q; struct task_context *tc = NULL; struct bt_info clone_bt; @@ -2118,15 +2117,19 @@ if (*p != ' ') goto find_exframe; if ((q = strchr(++p, ' '))) { - /* " " */ - if (sscanf(++q, "%d", &processor) > 0) { - tc = pid_to_context(0); - while (tc) { - if (tc != bt->tc && - tc->processor == processor) - break; - tc = tc->tc_next; - } + /* + * " " + * + * We came from one of the PID 0 swapper tasks, + * so just find the one with the same cpu as + * the passed-in INIT/MCA task. + */ + tc = pid_to_context(0); + while (tc) { + if (tc != bt->tc && + tc->processor == bt->tc->processor) + break; + tc = tc->tc_next; } } else if (sscanf(p, "%lu", &pid) > 0) /* " " */ --- crash-4.0-7.7/defs.h 2009-03-20 11:22:07.000000000 -0400 +++ crash-4.0-8.8/defs.h 2009-03-20 11:17:44.000000000 -0400 @@ -474,6 +474,7 @@ #define RELOC_FORCE (0x4000000) #define ARCH_OPENVZ (0x8000000) #define ARCH_PVOPS (0x10000000) +#define IN_KERNEL_INIT (0x20000000) #define GCC_VERSION_DEPRECATED (GCC_3_2|GCC_3_2_3|GCC_2_96|GCC_3_3_2|GCC_3_3_3)