--- crash-4.0-4.1/main.c 2007-06-04 14:03:44.000000000 -0400 +++ crash-4.0-4.2/main.c 2007-05-15 15:03:48.000000000 -0400 @@ -49,6 +49,7 @@ {"hyper", 0, 0, 0}, {"p2m_mfn", 1, 0, 0}, {"zero_excluded", 0, 0, 0}, + {"no_panic", 0, 0, 0}, {0, 0, 0, 0} }; @@ -156,6 +157,8 @@ if (STREQ(long_options[option_index].name, "zero_excluded")) *diskdump_flags |= ZERO_EXCLUDED; + if (STREQ(long_options[option_index].name, "no_panic")) + tt->flags |= PANIC_TASK_NOT_FOUND; break; case 'f': @@ -302,8 +305,14 @@ } pc->flags |= NETDUMP; pc->dumpfile = argv[optind]; - pc->readmem = read_netdump; - pc->writemem = write_netdump; + + if (is_sadump_xen()) { + pc->readmem = read_kdump; + pc->writemem = write_kdump; + } else { + pc->readmem = read_netdump; + pc->writemem = write_netdump; + } } else if (is_kdump(argv[optind], KDUMP_LOCAL)) { if (pc->flags & MEMORY_SOURCES) { --- crash-4.0-4.1/memory.c 2007-06-04 14:03:44.000000000 -0400 +++ crash-4.0-4.2/memory.c 2007-05-02 10:01:57.000000000 -0400 @@ -11673,8 +11673,12 @@ } } - if (n != vt->numnodes) - error(FATAL, "numnodes out of sync with pgdat_list?\n"); + if (n != vt->numnodes) { + if (CRASHDEBUG(2)) + error(NOTE, "changing numnodes from %d to %d\n", + vt->numnodes, n); + vt->numnodes = n; + } if (!initialize && IS_SPARSEMEM()) dump_mem_sections(); --- crash-4.0-4.1/help.c 2007-06-04 14:03:44.000000000 -0400 +++ crash-4.0-4.2/help.c 2007-05-24 17:11:04.000000000 -0400 @@ -152,8 +152,10 @@ } for (ext = extension_table; ext; ext = ext->next) { - for (cp = ext->command_table; cp->name; cp++) - pc->ncmds++; + for (cp = ext->command_table; cp->name; cp++) { + if (!(cp->flags & (CLEANUP|HIDDEN_COMMAND))) + pc->ncmds++; + } } if (!pc->cmdlist) { @@ -193,8 +195,10 @@ } for (ext = extension_table; ext; ext = ext->next) { - for (cp = ext->command_table; cp->name; cp++) - pc->cmdlist[cnt++] = cp->name; + for (cp = ext->command_table; cp->name; cp++) { + if (!(cp->flags & (CLEANUP|HIDDEN_COMMAND))) + pc->cmdlist[cnt++] = cp->name; + } } if (cnt > pc->cmdlistsz) @@ -794,7 +798,7 @@ char *help_ps[] = { "ps", "display process status information", -"[-k|-u][-s][-p|-c|-t|-l|-a|-g] [pid | taskp | command] ...", +"[-k|-u][-s][-p|-c|-t|-l|-a|-g|-r] [pid | taskp | command] ...", " This command displays process status for selected, or all, processes" , " in the system. If no arguments are entered, the process data is", " is displayed for all processes. Selected process identifiers can be", @@ -830,8 +834,8 @@ " angle bracket (\">\") preceding its information.", " ", " Alternatively, information regarding parent-child relationships,", -" per-task time usage data, argument/environment data, or thread groups", -" may be displayed:", +" per-task time usage data, argument/environment data, thread groups,", +" or resource limits may be displayed:", " ", " -p display the parental hierarchy of selected, or all, tasks.", " -c display the children of selected, or all, tasks.", @@ -843,6 +847,7 @@ " -a display the command line arguments and environment strings of", " selected, or all, user-mode tasks.", " -g display tasks by thread group, of selected, or all, tasks.", +" -r display resource limits (rlimits) of selected, or all, tasks.", "\nEXAMPLES", " Show the process status of all current tasks:\n", " %s> ps", @@ -1086,6 +1091,22 @@ " PID: 2529 TASK: 1003f0c37f0 CPU: 1 COMMAND: \"multi-thread\"", " PID: 2530 TASK: 10035597030 CPU: 1 COMMAND: \"multi-thread\"", " PID: 2531 TASK: 100184be7f0 CPU: 1 COMMAND: \"multi-thread\"", +" ", +" Display the resource limits of \"bash\" task 13896:\n", +" %s> ps -r 13896", +" PID: 13896 TASK: cf402000 CPU: 0 COMMAND: \"bash\"", +" RLIMIT CURRENT MAXIMUM", +" CPU (unlimited) (unlimited)", +" FSIZE (unlimited) (unlimited)", +" DATA (unlimited) (unlimited)", +" STACK 10485760 (unlimited)", +" CORE (unlimited) (unlimited)", +" RSS (unlimited) (unlimited)", +" NPROC 4091 4091", +" NOFILE 1024 1024", +" MEMLOCK 4096 4096", +" AS (unlimited) (unlimited)", +" LOCKS (unlimited) (unlimited)", NULL }; --- crash-4.0-4.1/task.c 2007-06-04 14:03:44.000000000 -0400 +++ crash-4.0-4.2/task.c 2007-05-24 16:56:39.000000000 -0400 @@ -34,6 +34,7 @@ static void child_list(ulong); static void show_task_times(struct task_context *, ulong); static void show_task_args(struct task_context *); +static void show_task_rlimit(struct task_context *); static void show_tgid_list(ulong); static int compare_start_time(const void *, const void *); static int start_time_timespec(void); @@ -160,8 +161,15 @@ get_idle_threads(&tt->idle_threads[0], kt->cpus); } - MEMBER_OFFSET_INIT(task_struct_thread_info, "task_struct", - "thread_info"); + if (MEMBER_EXISTS("task_struct", "thread_info")) + MEMBER_OFFSET_INIT(task_struct_thread_info, "task_struct", + "thread_info"); + else if (MEMBER_EXISTS("task_struct", "stack")) + MEMBER_OFFSET_INIT(task_struct_thread_info, "task_struct", + "stack"); + else + ASSIGN_OFFSET(task_struct_thread_info) = INVALID_OFFSET; + if (VALID_MEMBER(task_struct_thread_info)) { MEMBER_OFFSET_INIT(thread_info_task, "thread_info", "task"); MEMBER_OFFSET_INIT(thread_info_cpu, "thread_info", "cpu"); @@ -2173,7 +2181,7 @@ BZERO(&psinfo, sizeof(struct psinfo)); flag = 0; - while ((c = getopt(argcnt, args, "gstcpkula")) != EOF) { + while ((c = getopt(argcnt, args, "gstcpkular")) != EOF) { switch(c) { case 'k': @@ -2230,6 +2238,11 @@ flag |= PS_KSTACKP; break; + case 'r': + flag &= ~(PS_EXCLUSIVE); + flag |= PS_RLIMIT; + break; + default: argerrs++; break; @@ -2314,6 +2327,10 @@ show_task_args(tc); \ continue; \ } \ + if (flag & PS_RLIMIT) { \ + show_task_rlimit(tc); \ + continue; \ + } \ if (flag & PS_TGID_LIST) { \ show_tgid_list(tc->task); \ continue; \ @@ -2560,6 +2577,120 @@ FREEBUF(buf); } +char *rlim_names[] = { + /* 0 */ "CPU", + /* 1 */ "FSIZE", + /* 2 */ "DATA", + /* 3 */ "STACK", + /* 4 */ "CORE", + /* 5 */ "RSS", + /* 6 */ "NPROC", + /* 7 */ "NOFILE", + /* 8 */ "MEMLOCK", + /* 9 */ "AS", + /* 10 */ "LOCKS", + /* 11 */ "SIGPENDING", + /* 12 */ "MSGQUEUE", + /* 13 */ "NICE", + /* 14 */ "RTPRIO", + NULL, +}; + +#ifndef RLIM_INFINITY +#define RLIM_INFINITY (~0UL) +#endif + +/* + * Show the current and maximum rlimit values. + */ +static void +show_task_rlimit(struct task_context *tc) +{ + int i, j, len1, len2, rlimit_index; + int in_task_struct, in_signal_struct; + char *rlimit_buffer; + ulong *p1, rlim_addr; + char buf1[BUFSIZE]; + char buf2[BUFSIZE]; + char buf3[BUFSIZE]; + + if (!VALID_MEMBER(task_struct_rlim) && !VALID_MEMBER(signal_struct_rlim)) { + MEMBER_OFFSET_INIT(task_struct_rlim, "task_struct", "rlim"); + MEMBER_OFFSET_INIT(signal_struct_rlim, "signal_struct", "rlim"); + STRUCT_SIZE_INIT(rlimit, "rlimit"); + if (!VALID_MEMBER(task_struct_rlim) && + !VALID_MEMBER(signal_struct_rlim)) + error(FATAL, "cannot determine rlimit array location\n"); + } else if (!VALID_STRUCT(rlimit)) + error(FATAL, "cannot determine rlimit structure definition\n"); + + in_task_struct = in_signal_struct = FALSE; + + if (VALID_MEMBER(task_struct_rlim)) { + rlimit_index = get_array_length("task_struct.rlim", NULL, 0); + in_task_struct = TRUE; + } else if (VALID_MEMBER(signal_struct_rlim)) { + if (!VALID_MEMBER(task_struct_signal)) + error(FATAL, "cannot determine rlimit array location\n"); + rlimit_index = get_array_length("signal_struct.rlim", NULL, 0); + in_signal_struct = TRUE; + } + + if (!rlimit_index) + error(FATAL, "cannot determine rlimit array size\n"); + + for (i = len1 = 0; i < rlimit_index; i++) { + if ((j = strlen(rlim_names[i])) > len1) + len1 = j; + } + len2 = strlen("(unlimited)"); + + rlimit_buffer = GETBUF(rlimit_index * SIZE(rlimit)); + + print_task_header(fp, tc, 0); + + fill_task_struct(tc->task); + + if (in_task_struct) { + BCOPY(tt->task_struct + OFFSET(task_struct_rlim), + rlimit_buffer, rlimit_index * SIZE(rlimit)); + } else if (in_signal_struct) { + rlim_addr = ULONG(tt->task_struct + OFFSET(task_struct_signal)); + if (!readmem(rlim_addr + OFFSET(signal_struct_rlim), + KVADDR, rlimit_buffer, rlimit_index * SIZE(rlimit), + "signal_struct rlimit array", RETURN_ON_ERROR)) { + FREEBUF(rlimit_buffer); + return; + } + } + + fprintf(fp, " %s %s %s\n", + mkstring(buf1, len1, RJUST, "RLIMIT"), + mkstring(buf2, len2, CENTER|RJUST, "CURRENT"), + mkstring(buf3, len2, CENTER|RJUST, "MAXIMUM")); + + for (p1 = (ulong *)rlimit_buffer, i = 0; i < rlimit_index; i++) { + fprintf(fp, " %s ", mkstring(buf1, len1, RJUST, + rlim_names[i] ? rlim_names[i] : "(unknown)")); + if (*p1 == (ulong)RLIM_INFINITY) + fprintf(fp, "(unlimited) "); + else + fprintf(fp, "%s ", mkstring(buf1, len2, + CENTER|LJUST|LONG_DEC, MKSTR(*p1))); + p1++; + if (*p1 == (ulong)RLIM_INFINITY) + fprintf(fp, "(unlimited)\n"); + else + fprintf(fp, "%s\n", mkstring(buf1, len2, + CENTER|LJUST|LONG_DEC, MKSTR(*p1))); + p1++; + } + + fprintf(fp, "\n"); + + FREEBUF(rlimit_buffer); +} + /* * Put either the task_struct address or kernel stack pointer into a string. * If the kernel stack pointer is requested, piggy-back on top of the @@ -3459,7 +3590,8 @@ fprintf(fp, "(ACTIVE)"); } - if (!(pc->flags & RUNTIME) && (tt->flags & PANIC_TASK_NOT_FOUND) && + if (!(pc->flags & RUNTIME) && !ACTIVE() && + (tt->flags & PANIC_TASK_NOT_FOUND) && !SYSRQ_TASK(tc->task)) { fprintf(fp, "\n"); INDENT(indent); if (machine_type("S390") || machine_type("S390X")) @@ -3893,6 +4025,12 @@ task = NO_TASK; tc = FIRST_CONTEXT(); + /* + * --no_panic command line option + */ + if (tt->flags & PANIC_TASK_NOT_FOUND) + goto use_task_0; + if (symbol_exists("panic_threads") && symbol_exists("panicmsg") && symbol_exists("panic_processor")) { --- crash-4.0-4.1/configure.c 2007-06-04 14:03:44.000000000 -0400 +++ crash-4.0-4.2/configure.c 2007-06-04 11:58:33.000000000 -0400 @@ -1175,6 +1175,17 @@ printf("netdump, diskdump and kdump facilities 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 devel\n"); + printf("Requires: %%{name} = %%{version}\n"); + printf("Summary: crash utility for live systems; netdump, diskdump, kdump, LKCD or mcore dumpfiles\n"); + printf("Group: Development/Debuggers\n"); + printf("\n"); + printf("%%description devel\n"); + printf("The core analysis suite is a self-contained tool that can be used to\n"); + printf("investigate either live systems, kernel core dumps created from the\n"); + 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("%%prep\n"); printf("%%setup -n %%{name}-%%{version}-%%{release}\n"); printf("# %%patch0 -p1 -b .install (patch example)\n"); @@ -1189,6 +1200,8 @@ printf("make DESTDIR=%%{buildroot} install\n"); printf("mkdir -p %%{buildroot}%%{_mandir}/man8\n"); 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("\n"); printf("%%clean\n"); printf("rm -rf %%{buildroot}\n"); @@ -1198,6 +1211,10 @@ printf("%%{_mandir}/man8/crash.8*\n"); /* printf("/usr/bin/crashd\n"); */ printf("%%doc README\n"); + printf("\n"); + printf("%%files devel\n"); + printf("%%defattr(-,root,root)\n"); + printf("%%{_includedir}/*\n"); } /* --- crash-4.0-4.1/ia64.c 2007-06-04 14:03:44.000000000 -0400 +++ crash-4.0-4.2/ia64.c 2007-05-17 12:03:55.000000000 -0400 @@ -71,8 +71,6 @@ static int ia64_vtop_4l_xen_wpt(ulong, physaddr_t *paddr, ulong *pgd, int, int); static int ia64_vtop_xen_wpt(ulong, physaddr_t *paddr, ulong *pgd, int, int); static int ia64_xen_kdump_p2m_create(struct xen_kdump_data *); -static char *ia64_xen_kdump_load_page(ulong, char *); -static ulong ia64_xen_kdump_page_mfn(ulong); static int ia64_xendump_p2m_create(struct xendump_data *); static void ia64_debug_dump_page(FILE *, char *, char *); static char *ia64_xendump_load_page(ulong, struct xendump_data *); @@ -3855,32 +3853,97 @@ * From the xen vmcore, create an index of mfns for each page that makes * up the dom0 kernel's complete phys_to_machine_mapping[max_pfn] array. */ - static int ia64_xen_kdump_p2m_create(struct xen_kdump_data *xkd) { - error(FATAL, "ia64_xen_kdump_p2m_create: TBD\n"); + /* + * Temporarily read physical (machine) addresses from vmcore by + * going directly to read_netdump() instead of via read_kdump(). + */ + pc->readmem = read_netdump; - /* dummy calls for clean "make [wW]arn" */ - ia64_xen_kdump_load_page(0, NULL); - ia64_xen_kdump_page_mfn(0); - ia64_debug_dump_page(NULL, NULL, NULL); + if (CRASHDEBUG(1)) + fprintf(fp, "ia64_xen_kdump_p2m_create: p2m_mfn: %lx\n", xkd->p2m_mfn); - return FALSE; -} + if ((xkd->p2m_mfn_frame_list = (ulong *)malloc(PAGESIZE())) == NULL) + error(FATAL, "cannot malloc p2m_frame_list"); -static char * -ia64_xen_kdump_load_page(ulong kvaddr, char *pgbuf) -{ - error(FATAL, "ia64_xen_kdump_load_page: TBD\n"); - return NULL; + if (!readmem(PTOB(xkd->p2m_mfn), PHYSADDR, xkd->p2m_mfn_frame_list, PAGESIZE(), + "xen kdump p2m mfn page", RETURN_ON_ERROR)) + error(FATAL, "cannot read xen kdump p2m mfn page\n"); + + xkd->p2m_frames = PAGESIZE()/sizeof(ulong); + + pc->readmem = read_kdump; + + return TRUE; } -static ulong -ia64_xen_kdump_page_mfn(ulong kvaddr) +physaddr_t +ia64_xen_kdump_p2m(struct xen_kdump_data *xkd, physaddr_t pseudo) { - error(FATAL, "ia64_xen_kdump_page_mfn: TBD\n"); - return 0; + ulong pgd_idx, pte_idx; + ulong pmd, pte; + physaddr_t paddr; + + /* + * Temporarily read physical (machine) addresses from vmcore by + * going directly to read_netdump() instead of via read_kdump(). + */ + pc->readmem = read_netdump; + + xkd->accesses += 2; + + pgd_idx = (pseudo >> PGDIR_SHIFT_3L) & (PTRS_PER_PGD - 1); + pmd = xkd->p2m_mfn_frame_list[pgd_idx] & _PFN_MASK; + if (!pmd) { + paddr = P2M_FAILURE; + goto out; + } + + pmd += ((pseudo >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) * sizeof(ulong); + if (pmd != xkd->last_pmd_read) { + if (!readmem(pmd, PHYSADDR, &pte, sizeof(ulong), + "ia64_xen_kdump_p2m pmd", RETURN_ON_ERROR)) { + xkd->last_pmd_read = BADADDR; + xkd->last_mfn_read = BADADDR; + paddr = P2M_FAILURE; + goto out; + } + xkd->last_pmd_read = pmd; + } else { + pte = xkd->last_mfn_read; + xkd->cache_hits++; + } + pte = pte & _PFN_MASK; + if (!pte) { + paddr = P2M_FAILURE; + goto out; + } + + if (pte != xkd->last_mfn_read) { + if (!readmem(pte, PHYSADDR, xkd->page, PAGESIZE(), + "ia64_xen_kdump_p2m pte page", RETURN_ON_ERROR)) { + xkd->last_pmd_read = BADADDR; + xkd->last_mfn_read = BADADDR; + paddr = P2M_FAILURE; + goto out; + } + xkd->last_mfn_read = pte; + } else + xkd->cache_hits++; + + pte_idx = (pseudo >> PAGESHIFT()) & (PTRS_PER_PTE - 1); + paddr = *(((ulong *)xkd->page) + pte_idx); + if (!(paddr & _PAGE_P)) { + paddr = P2M_FAILURE; + goto out; + } + paddr = (paddr & _PFN_MASK) | PAGEOFFSET(pseudo); + +out: + pc->readmem = read_kdump; + return paddr; } #include "xendump.h" --- crash-4.0-4.1/extensions.c 2007-06-04 14:03:44.000000000 -0400 +++ crash-4.0-4.2/extensions.c 2007-05-24 16:26:41.000000000 -0400 @@ -107,6 +107,7 @@ void dump_extension_table(int verbose) { + int i; struct extension_table *ext; struct command_table_entry *cp; char buf[BUFSIZE]; @@ -117,23 +118,37 @@ if (verbose) { for (ext = extension_table; ext; ext = ext->next) { - fprintf(fp, " filename: %s\n", ext->filename); - fprintf(fp, " handle: %lx\n", (ulong)ext->handle); - fprintf(fp, "command_table: %lx (", - (ulong)ext->command_table); - for (others = 0, cp = ext->command_table; cp->name;cp++) - fprintf(fp, "%s%s%s", others++ ? " " : "", - cp->name, cp->help_data ? "*" : ""); - fprintf(fp, ")\n"); - fprintf(fp, " flags: %lx (", ext->flags); + fprintf(fp, " filename: %s\n", ext->filename); + fprintf(fp, " handle: %lx\n", (ulong)ext->handle); + + + fprintf(fp, " flags: %lx (", ext->flags); others = 0; if (ext->flags & REGISTERED) fprintf(fp, "%sREGISTERED", others++ ? "|" : ""); fprintf(fp, ")\n"); - fprintf(fp, " next: %lx\n", (ulong)ext->next); - fprintf(fp, " prev: %lx\n%s", - (ulong)ext->prev, ext->next ? "\n" : ""); + fprintf(fp, " next: %lx\n", (ulong)ext->next); + fprintf(fp, " prev: %lx\n", (ulong)ext->prev); + + for (i = 0, cp = ext->command_table; cp->name; cp++, i++) { + fprintf(fp, "command_table[%d]: %lx\n", i, (ulong)cp); + fprintf(fp, " name: %s\n", cp->name); + fprintf(fp, " func: %lx\n", (ulong)cp->func); + fprintf(fp, " help_data: %lx\n", (ulong)cp->help_data); + fprintf(fp, " flags: %lx (", cp->flags); + others = 0; + if (cp->flags & CLEANUP) + fprintf(fp, "%sCLEANUP", others++ ? "|" : ""); + if (cp->flags & REFRESH_TASK_TABLE) + fprintf(fp, "%sREFRESH_TASK_TABLE", others++ ? "|" : ""); + if (cp->flags & HIDDEN_COMMAND) + fprintf(fp, "%sHIDDEN_COMMAND", others++ ? "|" : ""); + fprintf(fp, ")\n"); + } + + if (ext->next) + fprintf(fp, "\n"); } return; } --- crash-4.0-4.1/symbols.c 2007-06-04 14:03:44.000000000 -0400 +++ crash-4.0-4.2/symbols.c 2007-05-24 16:47:45.000000000 -0400 @@ -3507,6 +3507,34 @@ } /* + * Return the value of a symbol from a specific module. + */ +ulong +symbol_value_module(char *symbol, char *module) +{ + int i; + struct syment *sp, *sp_end; + struct load_module *lm; + + for (i = 0; i < st->mods_installed; i++) { + lm = &st->load_modules[i]; + + if (!STREQ(module, lm->mod_name)) + continue; + + sp = lm->mod_symtable; + sp_end = lm->mod_symend; + + for ( ; sp < sp_end; sp++) { + if (STREQ(symbol, sp->name)) + return(sp->value); + } + } + + return 0; +} + +/* * Return the symbol name of a given value, with no allowance for offsets. * Returns NULL on failure to allow for testing of a value. */ @@ -5615,6 +5643,8 @@ OFFSET(task_struct_thread_info)); fprintf(fp, " task_struct_nsproxy: %ld\n", OFFSET(task_struct_nsproxy)); + fprintf(fp, " task_struct_rlim: %ld\n", + OFFSET(task_struct_rlim)); fprintf(fp, " thread_info_task: %ld\n", OFFSET(thread_info_task)); @@ -5663,6 +5693,9 @@ OFFSET(signal_struct_action)); fprintf(fp, " signal_struct_shared_pending: %ld\n", OFFSET(signal_struct_shared_pending)); + fprintf(fp, " signal_struct_rlim: %ld\n", + OFFSET(signal_struct_rlim)); + fprintf(fp, " task_struct_start_time: %ld\n", OFFSET(task_struct_start_time)); fprintf(fp, " task_struct_times: %ld\n", @@ -6731,6 +6764,8 @@ SIZE(pid_link)); fprintf(fp, " unwind_table: %ld\n", SIZE(unwind_table)); + fprintf(fp, " rlimit: %ld\n", + SIZE(rlimit)); fprintf(fp, "\n array_table:\n"); /* --- crash-4.0-4.1/cmdline.c 2007-06-04 14:03:45.000000000 -0400 +++ crash-4.0-4.2/cmdline.c 2007-05-24 17:10:05.000000000 -0400 @@ -842,6 +842,8 @@ restore_sanity(void) { int fd, waitstatus; + struct extension_table *ext; + struct command_table_entry *cp; if (pc->stdpipe) { close(fileno(pc->stdpipe)); @@ -952,6 +954,16 @@ clear_vma_cache(); clear_active_set(); + /* + * Call the cleanup() function of any extension. + */ + for (ext = extension_table; ext; ext = ext->next) { + for (cp = ext->command_table; cp->name; cp++) { + if (cp->flags & CLEANUP) + (*cp->func)(); + } + } + if (CRASHDEBUG(4)) { dump_filesys_table(0); dump_vma_cache(0); --- crash-4.0-4.1/netdump.c 2007-06-04 14:03:45.000000000 -0400 +++ crash-4.0-4.2/netdump.c 2007-05-17 12:02:51.000000000 -0400 @@ -755,11 +755,13 @@ nd->xen_kdump_data->cr3); netdump_print(" last_mfn_read: %lx\n", nd->xen_kdump_data->last_mfn_read); + netdump_print(" last_pmd_read: %lx\n", + nd->xen_kdump_data->last_pmd_read); netdump_print(" page: %lx\n", nd->xen_kdump_data->page); - netdump_print(" accesses: %lx\n", + netdump_print(" accesses: %ld\n", nd->xen_kdump_data->accesses); - netdump_print(" cache_hits: %lx ", + netdump_print(" cache_hits: %ld ", nd->xen_kdump_data->cache_hits); if (nd->xen_kdump_data->accesses) netdump_print("(%ld%%)", @@ -1386,7 +1388,8 @@ if (store) { pc->flags |= XEN_CORE; nd->xen_kdump_data = &xen_kdump_data; - nd->xen_kdump_data->last_mfn_read = BADVAL; + nd->xen_kdump_data->last_mfn_read = UNINITIALIZED; + nd->xen_kdump_data->last_pmd_read = UNINITIALIZED; if ((note->n_type == NT_XEN_KDUMP_CR3) && ((note->n_descsz/sizeof(ulong)) == 1)) { @@ -1574,7 +1577,8 @@ if (store) { pc->flags |= XEN_CORE; nd->xen_kdump_data = &xen_kdump_data; - nd->xen_kdump_data->last_mfn_read = BADVAL; + nd->xen_kdump_data->last_mfn_read = UNINITIALIZED; + nd->xen_kdump_data->last_pmd_read = UNINITIALIZED; if ((note->n_type == NT_XEN_KDUMP_CR3) && ((note->n_descsz/sizeof(ulong)) == 1)) { @@ -2091,11 +2095,17 @@ if (pc->curcmd_flags & XEN_MACHINE_ADDR) return pseudo; +#ifdef IA64 + return ia64_xen_kdump_p2m(xkd, pseudo); +#endif + xkd->accesses++; pfn = (ulong)BTOP(pseudo); mfn_idx = pfn / (PAGESIZE()/sizeof(ulong)); frame_idx = pfn % (PAGESIZE()/sizeof(ulong)); + if (mfn_idx >= xkd->p2m_frames) + return P2M_FAILURE; mfn_frame = xkd->p2m_mfn_frame_list[mfn_idx]; if (mfn_frame == xkd->last_mfn_read) @@ -2150,3 +2160,24 @@ } else error(WARNING, "invalid p2m_mfn argument: %s\n", arg); } + +/* + * Fujitsu dom0/HV sadump-generated dumpfile, which requires + * the --p2m_mfn command line argument. + */ +int +is_sadump_xen(void) +{ + if (xen_kdump_data.p2m_mfn) { + if (!XEN_CORE_DUMPFILE()) { + pc->flags |= XEN_CORE; + nd->xen_kdump_data = &xen_kdump_data; + nd->xen_kdump_data->last_mfn_read = UNINITIALIZED; + nd->xen_kdump_data->last_pmd_read = UNINITIALIZED; + nd->xen_kdump_data->flags |= KDUMP_MFN_LIST; + } + return TRUE; + } + + return FALSE; +} --- crash-4.0-4.1/defs.h 2007-06-04 14:03:45.000000000 -0400 +++ crash-4.0-4.2/defs.h 2007-05-24 16:03:07.000000000 -0400 @@ -400,6 +400,7 @@ #define REFRESH_TASK_TABLE (0x1) /* command_table_entry flags */ #define HIDDEN_COMMAND (0x2) +#define CLEANUP (0x4) /* for extensions only */ /* * A linked list of extension table structures keeps track of the current @@ -921,6 +922,7 @@ long task_struct_timestamp; long task_struct_thread_info; long task_struct_nsproxy; + long task_struct_rlim; long thread_info_task; long thread_info_cpu; long thread_info_previous_esp; @@ -945,6 +947,7 @@ long signal_struct_count; long signal_struct_action; long signal_struct_shared_pending; + long signal_struct_rlim; long k_sigaction_sa; long sigaction_sa_handler; long sigaction_sa_flags; @@ -1469,6 +1472,7 @@ long mem_section; long pid_link; long unwind_table; + long rlimit; }; struct array_table { @@ -2602,6 +2606,8 @@ #define BADVAL ((ulong)(-1)) #define UNUSED (-1) +#define UNINITIALIZED (BADVAL) + #define BITS_PER_BYTE (8) #define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long)) @@ -2850,8 +2856,9 @@ #define PS_LAST_RUN (0x400) #define PS_ARGV_ENVP (0x800) #define PS_TGID_LIST (0x1000) +#define PS_RLIMIT (0x2000) -#define PS_EXCLUSIVE (PS_TGID_LIST|PS_ARGV_ENVP|PS_TIMES|PS_CHILD_LIST|PS_PPID_LIST|PS_LAST_RUN) +#define PS_EXCLUSIVE (PS_TGID_LIST|PS_ARGV_ENVP|PS_TIMES|PS_CHILD_LIST|PS_PPID_LIST|PS_LAST_RUN|PS_RLIMIT) #define MAX_PS_ARGS (100) /* maximum command-line specific requests */ @@ -3154,6 +3161,7 @@ char *value_to_symstr(ulong, char *, ulong); char *value_symbol(ulong); ulong symbol_value(char *); +ulong symbol_value_module(char *, char *); int symbol_exists(char *s); int kernel_symbol_exists(char *s); int get_syment_array(char *, struct syment **, int); @@ -3685,8 +3693,6 @@ #define _2MB_PAGE_MASK (~((MEGABYTES(2))-1)) -#define UNINITIALIZED (BADVAL) - #endif #if defined(X86) || defined(X86_64) @@ -3809,6 +3815,7 @@ error(FATAL, "-d option TBD on ia64 architecture\n"); int ia64_in_init_stack(ulong addr); int ia64_in_mca_stack_hyper(ulong addr, struct bt_info *bt); +physaddr_t ia64_xen_kdump_p2m(struct xen_kdump_data *xkd, physaddr_t pseudo); #define OLD_UNWIND (0x1) /* CONFIG_IA64_NEW_UNWIND not turned on */ #define NEW_UNWIND (0x2) /* CONFIG_IA64_NEW_UNWIND turned on */ @@ -3941,6 +3948,7 @@ int kdump_memory_dump(FILE *); void get_kdump_regs(struct bt_info *, ulong *, ulong *); void xen_kdump_p2m_mfn(char *); +int is_sadump_xen(void); /* * diskdump.c --- crash-4.0-4.1/netdump.h 2007-06-04 14:03:45.000000000 -0400 +++ crash-4.0-4.2/netdump.h 2007-05-15 15:04:36.000000000 -0400 @@ -104,6 +104,7 @@ ulong p2m_mfn; char *page; ulong last_mfn_read; + ulong last_pmd_read; ulong cache_hits; ulong accesses; int p2m_frames; --- crash-4.0-4.1/Makefile 2007-06-04 14:05:13.000000000 -0400 +++ crash-4.0-4.2/Makefile 2007-06-04 14:05:12.000000000 -0400 @@ -543,4 +543,5 @@ @make --no-print-directory do_extensions do_extensions: - @(cd extensions; make -i OBJECTS="$(EXTENSION_OBJECT_FILES)" TARGET=$(TARGET)) + @(cd extensions; make -i OBJECTS="$(EXTENSION_OBJECT_FILES)" \ + TARGET=$(TARGET) TARGET_CFLAGS=$(TARGET_CFLAGS)) --- crash-4.0-4.1/extensions/Makefile 2007-06-04 14:03:45.000000000 -0400 +++ crash-4.0-4.2/extensions/Makefile 2007-05-29 10:16:56.000000000 -0400 @@ -34,8 +34,10 @@ ln -s ../defs.h; fi echo.so: ../defs.h echo.c - gcc -nostartfiles -shared -rdynamic -o echo.so echo.c -fPIC -D$(TARGET) + gcc -nostartfiles -shared -rdynamic -o echo.so echo.c -fPIC \ + -D$(TARGET) $(TARGET_CFLAGS) dminfo.so: ../defs.h dminfo.c - gcc -nostartfiles -shared -rdynamic -o dminfo.so dminfo.c -fPIC -D$(TARGET) + gcc -nostartfiles -shared -rdynamic -o dminfo.so dminfo.c -fPIC \ + -D$(TARGET) $(TARGET_CFLAGS)