--- crash-4.0-7.4/main.c 2008-11-18 13:42:54.000000000 -0500 +++ crash-4.0-7.5/main.c 2008-11-12 15:57:17.000000000 -0500 @@ -1086,6 +1086,9 @@ if (pc->flags & MINIMAL_MODE) sprintf(&buf[strlen(buf)], "%sMINIMAL_MODE", others++ ? "|" : ""); + if (pc->flags & CRASHBUILTIN) + sprintf(&buf[strlen(buf)], + "%sCRASHBUILTIN", others++ ? "|" : ""); if (pc->flags) strcat(buf, ")"); --- crash-4.0-7.4/tools.c 2008-11-18 13:42:55.000000000 -0500 +++ crash-4.0-7.5/tools.c 2008-10-24 11:19:44.000000000 -0400 @@ -2068,6 +2068,28 @@ fprintf(fp, "print_max: %d\n", print_max); return; + } else if (STREQ(args[optind], "null-stop")) { + optind++; + if (args[optind]) { + if (STREQ(args[optind], "on")) + stop_print_at_null = 1; + else if (STREQ(args[optind], "off")) + stop_print_at_null = 0; + else if (IS_A_NUMBER(args[optind])) { + value = stol(args[optind], + FAULT_ON_ERROR, NULL); + if (value) + stop_print_at_null = 1; + else + stop_print_at_null = 0; + } else + goto invalid_set_command; + } + if (runtime) + fprintf(fp, "null-stop: %s\n", + stop_print_at_null ? "on" : "off"); + return; + } else if (STREQ(args[optind], "dumpfile")) { optind++; if (!runtime && args[optind]) { @@ -2240,6 +2262,7 @@ fprintf(fp, " dumpfile: %s\n", pc->dumpfile); fprintf(fp, " unwind: %s\n", kt->flags & DWARF_UNWIND ? "on" : "off"); fprintf(fp, " zero_excluded: %s\n", *diskdump_flags & ZERO_EXCLUDED ? "on" : "off"); + fprintf(fp, " null-stop: %s\n", stop_print_at_null ? "on" : "off"); } --- crash-4.0-7.4/memory.c 2008-11-18 13:42:54.000000000 -0500 +++ crash-4.0-7.5/memory.c 2008-11-12 15:57:24.000000000 -0500 @@ -7542,12 +7542,16 @@ for (i = 0; i < vt->kmem_cache_len_nodes && start_address[i]; i++) { if (readmem(start_address[i] + OFFSET(kmem_list3_shared), KVADDR, &shared, sizeof(void *), - "kmem_list3 shared", RETURN_ON_ERROR|QUIET) && - readmem(shared + OFFSET(array_cache_limit), + "kmem_list3 shared", RETURN_ON_ERROR|QUIET)) { + if (!shared) + break; + } + if (readmem(shared + OFFSET(array_cache_limit), KVADDR, &limit, sizeof(int), "shared array_cache limit", RETURN_ON_ERROR|QUIET)) { if (limit > max_limit) max_limit = limit; + break; } } } @@ -8948,7 +8952,7 @@ static void do_slab_chain_percpu_v2_nodes(long cmd, struct meminfo *si) { - int i, tmp, s; + int i, tmp, s, node; int list_borked; char *slab_buf; ulong specified_slab; @@ -8977,6 +8981,14 @@ slab_buf = GETBUF(SIZE(slab)); for (index=0; (index < vt->kmem_cache_len_nodes) && start_address[index]; index++) { + if (vt->flags & NODES_ONLINE) { + node = next_online_node(index); + if (node < 0) + break; + if (node != index) + continue; + } + slab_chains[0] = start_address[index] + OFFSET(kmem_list3_slabs_partial); slab_chains[1] = start_address[index] + OFFSET(kmem_list3_slabs_full); slab_chains[2] = start_address[index] + OFFSET(kmem_list3_slabs_free); @@ -9078,6 +9090,14 @@ slab_buf = GETBUF(SIZE(slab)); for (index=0; (index < vt->kmem_cache_len_nodes) && start_address[index]; index++) { + if (vt->flags & NODES_ONLINE) { + node = next_online_node(index); + if (node < 0) + break; + if (node != index) + continue; + } + slab_chains[0] = start_address[index] + OFFSET(kmem_list3_slabs_partial); slab_chains[1] = start_address[index] + OFFSET(kmem_list3_slabs_full); slab_chains[2] = start_address[index] + OFFSET(kmem_list3_slabs_free); @@ -10159,7 +10179,7 @@ sizeof(ulong) * vt->kmem_cache_len_nodes , "array nodelist array", RETURN_ON_ERROR) || !readmem(start_address[index] + OFFSET(kmem_list3_shared), KVADDR, &shared, - sizeof(void *), "kmem_list3 shared", RETURN_ON_ERROR|QUIET) || + sizeof(void *), "kmem_list3 shared", RETURN_ON_ERROR|QUIET) || !shared || !readmem(shared + OFFSET(array_cache_avail), KVADDR, &avail, sizeof(int), "shared array_cache avail", RETURN_ON_ERROR|QUIET) || !avail) { FREEBUF(start_address); @@ -12332,6 +12352,7 @@ case DEVMEM: case MEMMOD: + case CRASHBUILTIN: psz = (uint)getpagesize(); break; --- crash-4.0-7.4/filesys.c 2008-11-18 13:42:55.000000000 -0500 +++ crash-4.0-7.5/filesys.c 2008-12-02 16:20:06.000000000 -0500 @@ -1755,10 +1755,10 @@ MEMBER_OFFSET_INIT(file_f_dentry, "file", "f_dentry"); MEMBER_OFFSET_INIT(file_f_vfsmnt, "file", "f_vfsmnt"); MEMBER_OFFSET_INIT(file_f_count, "file", "f_count"); + MEMBER_OFFSET_INIT(path_mnt, "path", "mnt"); + MEMBER_OFFSET_INIT(path_dentry, "path", "dentry"); if (INVALID_MEMBER(file_f_dentry)) { MEMBER_OFFSET_INIT(file_f_path, "file", "f_path"); - MEMBER_OFFSET_INIT(path_mnt, "path", "mnt"); - MEMBER_OFFSET_INIT(path_dentry, "path", "dentry"); ASSIGN_OFFSET(file_f_dentry) = OFFSET(file_f_path) + OFFSET(path_dentry); ASSIGN_OFFSET(file_f_vfsmnt) = OFFSET(file_f_path) + OFFSET(path_mnt); } @@ -2071,7 +2071,7 @@ ulong fd; ulong file; ulong value; - int i, j; + int i, j, use_path; int header_printed = 0; char root_pathname[BUFSIZE]; char pwd_pathname[BUFSIZE]; @@ -2112,7 +2112,12 @@ readmem(fs_struct_addr, KVADDR, fs_struct_buf, SIZE(fs_struct), "fs_struct buffer", FAULT_ON_ERROR); - root_dentry = ULONG(fs_struct_buf + OFFSET(fs_struct_root)); + use_path = (MEMBER_TYPE("fs_struct", "root") == TYPE_CODE_STRUCT); + if (use_path) + root_dentry = ULONG(fs_struct_buf + OFFSET(fs_struct_root) + + OFFSET(path_dentry)); + else + root_dentry = ULONG(fs_struct_buf + OFFSET(fs_struct_root)); if (root_dentry) { if (VALID_MEMBER(fs_struct_rootmnt)) { @@ -2120,13 +2125,23 @@ OFFSET(fs_struct_rootmnt)); get_pathname(root_dentry, root_pathname, BUFSIZE, 1, vfsmnt); + } else if (use_path) { + vfsmnt = ULONG(fs_struct_buf + + OFFSET(fs_struct_root) + + OFFSET(path_mnt)); + get_pathname(root_dentry, root_pathname, + BUFSIZE, 1, vfsmnt); } else { get_pathname(root_dentry, root_pathname, BUFSIZE, 1, 0); } } - pwd_dentry = ULONG(fs_struct_buf + OFFSET(fs_struct_pwd)); + if (use_path) + pwd_dentry = ULONG(fs_struct_buf + OFFSET(fs_struct_pwd) + + OFFSET(path_dentry)); + else + pwd_dentry = ULONG(fs_struct_buf + OFFSET(fs_struct_pwd)); if (pwd_dentry) { if (VALID_MEMBER(fs_struct_pwdmnt)) { @@ -2134,6 +2149,13 @@ OFFSET(fs_struct_pwdmnt)); get_pathname(pwd_dentry, pwd_pathname, BUFSIZE, 1, vfsmnt); + } else if (use_path) { + vfsmnt = ULONG(fs_struct_buf + + OFFSET(fs_struct_pwd) + + OFFSET(path_mnt)); + get_pathname(pwd_dentry, pwd_pathname, + BUFSIZE, 1, vfsmnt); + } else { get_pathname(pwd_dentry, pwd_pathname, BUFSIZE, 1, 0); @@ -3177,7 +3199,7 @@ char modname1[BUFSIZE]; char modname2[BUFSIZE]; char *name; - int use_module; + int use_module, crashbuiltin; struct stat stat1, stat2; pc->flags |= DEVMEM; @@ -3185,7 +3207,7 @@ goto live_report; pc->live_memsrc = "/dev/mem"; - use_module = FALSE; + use_module = crashbuiltin = FALSE; if (file_exists("/dev/mem", &stat1) && file_exists(pc->memory_device, &stat2) && @@ -3222,6 +3244,10 @@ } pclose(pipe); + + if (!use_module && file_exists("/dev/crash", &stat1) && + S_ISCHR(stat1.st_mode)) + crashbuiltin = TRUE; } if (use_module) { @@ -3232,6 +3258,15 @@ pc->live_memsrc = pc->memory_device; } + if (crashbuiltin) { + pc->flags &= ~DEVMEM; + pc->flags |= CRASHBUILTIN; + pc->readmem = read_memory_device; + pc->writemem = write_memory_device; + pc->live_memsrc = pc->memory_device; + pc->memory_module = NULL; + } + live_report: if (CRASHDEBUG(1)) fprintf(fp, "get_live_memory_source: %s\n", pc->live_memsrc); @@ -3413,10 +3448,11 @@ /* * If we're here, the memory driver module is being requested: * - * 1. If the module is not already loaded, insmod it. - * 2. Determine the misc driver minor device number that it was assigned. - * 3. Create (or verify) the device file. - * 4. Then just open it. + * 1. If /dev/crash is built into the kernel, just open it. + * 2. If the module is not already loaded, insmod it. + * 3. Determine the misc driver minor device number that it was assigned. + * 4. Create (or verify) the device file. + * 5. Then just open it. */ static int @@ -3424,10 +3460,14 @@ { dev_t dev; + if (pc->flags & CRASHBUILTIN) + goto open_device; + if (!memory_driver_module_loaded(NULL)) { if (!insmod_memory_driver_module()) return FALSE; - } + } else + pc->flags |= MODPRELOAD; if (!get_memory_driver_dev(&dev)) return FALSE; @@ -3435,6 +3475,7 @@ if (!create_memory_device(dev)) return FALSE; +open_device: if ((pc->mfd = open(pc->memory_device, O_RDONLY)) < 0) { error(INFO, "%s: open: %s\n", pc->memory_device, strerror(errno)); --- crash-4.0-7.4/help.c 2008-11-18 13:42:55.000000000 -0500 +++ crash-4.0-7.5/help.c 2008-12-03 14:28:12.000000000 -0500 @@ -678,6 +678,8 @@ " dumpfile filename name of core dumpfile (from .%src file only).", " zero_excluded on | off controls whether excluded pages from a dumpfile", " should return zero-filled memory.", +" null-stop on | off if on, gdb's printing of character arrays will", +" stop at the first NULL encountered.", " ", " Internal variables may be set in four manners:\n", " 1. entering the set command in $HOME/.%src.", @@ -724,6 +726,7 @@ " namelist: vmlinux", " dumpfile: vmcore", " zero_excluded: off", +" null-stop: on", " ", " Show the current context:\n", " %s> set", @@ -738,10 +741,14 @@ char *help_p[] = { "p", "print the value of an expression", -"expression", +"[-x|-d][-u] expression", " This command passes its arguments on to gdb \"print\" command for evaluation.", "", -" expression The expression to be evaluated.\n", +" expression The expression to be evaluated.", +" -x override default output format with hexadecimal format.", +" -d override default output format with decimal format.", +" -u the expression evaluates to a user address reference.", +"", " The default output format is decimal, but that can be changed at any time", " with the two built-in aliases \"hex\" and \"dec\". Alternatively, there", " are two other built-in aliases, \"px\" and \"pd\", which force the command", --- crash-4.0-7.4/kernel.c 2008-11-18 13:42:55.000000000 -0500 +++ crash-4.0-7.5/kernel.c 2008-12-03 14:08:14.000000000 -0500 @@ -102,8 +102,14 @@ } if (machine_type("X86")) get_symbol_data("max_pfn", sizeof(ulong), &kt->p2m_table_size); - if (machine_type("X86_64")) - get_symbol_data("end_pfn", sizeof(ulong), &kt->p2m_table_size); + if (machine_type("X86_64")) { + /* + * kernel version < 2.6.27 => end_pfn + * kernel version >= 2.6.27 => max_pfn + */ + if (!try_get_symbol_data("end_pfn", sizeof(ulong), &kt->p2m_table_size)) + get_symbol_data("max_pfn", sizeof(ulong), &kt->p2m_table_size); + } if ((kt->m2p_page = (char *)malloc(PAGESIZE())) == NULL) error(FATAL, "cannot malloc m2p page."); } @@ -164,7 +170,15 @@ p2++; *p2 = NULLCHAR; kt->kernel_version[2] = atoi(p1); - } + + if (CRASHDEBUG(1)) + fprintf(fp, "base kernel version: %d.%d.%d\n", + kt->kernel_version[0], + kt->kernel_version[1], + kt->kernel_version[2]); + } else + error(INFO, "cannot determine base kernel version\n"); + verify_version(); @@ -2049,8 +2063,13 @@ { case BT_HARDIRQ: btloc.hp->eip = symbol_value("do_IRQ"); - btloc.hp->esp = ULONG(bt->stackbuf + - SIZE(irq_ctx) - (sizeof(unsigned int)*2)); + if (symbol_exists("__do_IRQ")) + btloc.hp->esp = ULONG(bt->stackbuf + + OFFSET(thread_info_previous_esp)); + else + btloc.hp->esp = ULONG(bt->stackbuf + + SIZE(irq_ctx) - + (sizeof(unsigned int)*2)); fprintf(fp, "--- ---\n"); break; @@ -2504,7 +2523,10 @@ break; case KALLSYMS_V2: - numksyms = ULONG(modbuf + OFFSET(module_num_symtab)); + if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) + numksyms = UINT(modbuf + OFFSET(module_num_symtab)); + else + numksyms = ULONG(modbuf + OFFSET(module_num_symtab)); total += numksyms; break; } @@ -2617,8 +2639,12 @@ case KMOD_V2: module_name = modbuf + OFFSET(module_name); - mod_size = LONG(modbuf + - OFFSET(module_core_size)); + if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) + mod_size = UINT(modbuf + + OFFSET(module_core_size)); + else + mod_size = ULONG(modbuf + + OFFSET(module_core_size)); if (strlen(module_name) < MAX_MOD_NAME) strcpy(buf, module_name); else --- crash-4.0-7.4/gdb_interface.c 2008-11-18 13:42:54.000000000 -0500 +++ crash-4.0-7.5/gdb_interface.c 2008-12-03 14:07:59.000000000 -0500 @@ -374,6 +374,7 @@ fprintf(fp, " prettyprint_arrays: %d\n", prettyprint_arrays); fprintf(fp, " prettyprint_structs: %d\n", prettyprint_structs); fprintf(fp, "repeat_count_threshold: %x\n", repeat_count_threshold); + fprintf(fp, " stop_print_at_null: %d\n", stop_print_at_null); fprintf(fp, " print_max: %d\n", print_max); fprintf(fp, " output_radix: %d\n", output_radix); fprintf(fp, " output_format: "); @@ -687,6 +688,7 @@ cmd_gdb(void) { int c; + char buf[BUFSIZE]; while ((c = getopt(argcnt, args, "")) != EOF) { switch(c) @@ -713,14 +715,8 @@ * If the command is not restricted, pass it on. */ if (!is_restricted_command(args[1], FAULT_ON_ERROR)) { - if (pc->redirect & (REDIRECT_TO_PIPE|REDIRECT_TO_FILE)) - pc->orig_line[pc->eoc_index] = NULLCHAR; - - if (STRNEQ(pc->orig_line, "gdb") && - whitespace(pc->orig_line[3])) - shift_string_left(pc->orig_line, strlen("gdb")+1); - - gdb_pass_through(clean_line(pc->orig_line), NULL, 0); + concat_args(buf, 1, 0); + gdb_pass_through(buf, NULL, 0); } } --- crash-4.0-7.4/x86.c 2008-11-18 13:58:40.000000000 -0500 +++ crash-4.0-7.5/x86.c 2008-11-18 14:02:03.000000000 -0500 @@ -1773,13 +1773,13 @@ if (x86_omit_frame_pointer()) machdep->flags |= OMIT_FRAME_PTR; STRUCT_SIZE_INIT(user_regs_struct, "user_regs_struct"); - if (MEMBER_EXISTS("user_regs_struct", "ebp") + if (MEMBER_EXISTS("user_regs_struct", "ebp")) MEMBER_OFFSET_INIT(user_regs_struct_ebp, "user_regs_struct", "ebp"); else MEMBER_OFFSET_INIT(user_regs_struct_ebp, "user_regs_struct", "bp"); - if (MEMBER_EXISTS("user_regs_struct", "esp") + if (MEMBER_EXISTS("user_regs_struct", "esp")) MEMBER_OFFSET_INIT(user_regs_struct_esp, "user_regs_struct", "esp"); else @@ -1827,7 +1827,12 @@ } if (machdep->flags & PAE) { - machdep->section_size_bits = _SECTION_SIZE_BITS_PAE; + if (THIS_KERNEL_VERSION < LINUX(2,6,26)) + machdep->section_size_bits = + _SECTION_SIZE_BITS_PAE_ORIG; + else + machdep->section_size_bits = + _SECTION_SIZE_BITS_PAE_2_6_26; machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_PAE; } else { machdep->section_size_bits = _SECTION_SIZE_BITS; --- crash-4.0-7.4/ppc64.c 2008-11-18 13:42:55.000000000 -0500 +++ crash-4.0-7.5/ppc64.c 2008-12-05 09:56:52.000000000 -0500 @@ -693,8 +693,9 @@ ulong res, value, ppc_md, md_setup_res; ulong we_have_of, prep_setup_res; ulong node, type, name, properties; - char str_buf[16]; - uint len, mhz = 0; + char str_buf[32]; + uint len; + ulong mhz = 0; if (machdep->mhz) return(machdep->mhz); @@ -764,6 +765,23 @@ mhz /= 1000000; break; } + else if(len && (strcasecmp(str_buf, + "ibm,extended-clock-frequency") == 0)){ + /* found the right cpu property */ + + readmem(properties+ + OFFSET(property_value), + KVADDR, &value, sizeof(ulong), + "clock freqency pointer", + FAULT_ON_ERROR); + readmem(value, KVADDR, &mhz, + sizeof(ulong), + "clock frequency value", + FAULT_ON_ERROR); + mhz /= 1000000; + break; + } + /* keep looking */ readmem(properties+ --- crash-4.0-7.4/symbols.c 2008-11-18 13:42:54.000000000 -0500 +++ crash-4.0-7.5/symbols.c 2008-12-03 13:51:00.000000000 -0500 @@ -1277,8 +1277,15 @@ gpl_syms = ULONG(modbuf + OFFSET(module_gpl_syms)); nsyms = UINT(modbuf + OFFSET(module_num_syms)); ngplsyms = UINT(modbuf + OFFSET(module_num_gpl_syms)); - nksyms = ULONG(modbuf + OFFSET(module_num_symtab)); - size = ULONG(modbuf + OFFSET(module_core_size)); + + if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) { + nksyms = UINT(modbuf + OFFSET(module_num_symtab)); + size = UINT(modbuf + OFFSET(module_core_size)); + } else { + nksyms = ULONG(modbuf + OFFSET(module_num_symtab)); + size = ULONG(modbuf + OFFSET(module_core_size)); + } + mod_name = modbuf + OFFSET(module_name); lm = &st->load_modules[m++]; @@ -1301,8 +1308,12 @@ ngplsyms, nksyms); lm->mod_flags = MOD_EXT_SYMS; lm->mod_ext_symcnt = mcnt; - lm->mod_etext_guess = lm->mod_base + - ULONG(modbuf + OFFSET(module_core_text_size)); + if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) + lm->mod_etext_guess = lm->mod_base + + UINT(modbuf + OFFSET(module_core_text_size)); + else + lm->mod_etext_guess = lm->mod_base + + ULONG(modbuf + OFFSET(module_core_text_size)); lm->mod_text_start = lm->mod_base; st->ext_module_symtable[mcnt].value = lm->mod_base; @@ -1740,7 +1751,10 @@ return 0; } - nksyms = ULONG(modbuf + OFFSET(module_num_symtab)); + if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) + nksyms = UINT(modbuf + OFFSET(module_num_symtab)); + else + nksyms = ULONG(modbuf + OFFSET(module_num_symtab)); ksymtab = ULONG(modbuf + OFFSET(module_symtab)); locsymtab = module_buf + (ksymtab - lm->mod_base); kstrtab = ULONG(modbuf + OFFSET(module_strtab)); @@ -4952,7 +4966,7 @@ leader = do_load_module_filter = restore_radix = 0; - while ((c = getopt(argcnt, args, "dhx")) != EOF) { + while ((c = getopt(argcnt, args, "dhxu")) != EOF) { switch(c) { case 'd': @@ -4968,6 +4982,10 @@ output_format = (output_radix == 10) ? 0 : 'x'; break; + case 'u': + pc->curcmd_flags |= MEMTYPE_UVADDR; + break; + default: argerrs++; break; --- crash-4.0-7.4/lkcd_x86_trace.c 2008-11-18 13:42:55.000000000 -0500 +++ crash-4.0-7.5/lkcd_x86_trace.c 2008-12-05 09:22:48.000000000 -0500 @@ -1423,7 +1423,9 @@ if (XEN_HYPER_MODE()) { func_name = kl_funcname(pc); if (STREQ(func_name, "idle_loop") || STREQ(func_name, "hypercall") + || STREQ(func_name, "process_softirqs") || STREQ(func_name, "tracing_off") + || STREQ(func_name, "page_fault") || STREQ(func_name, "handle_exception")) { UPDATE_FRAME(func_name, pc, 0, sp, bp, asp, 0, 0, bp - sp, 0); return(trace->nframes); @@ -2440,12 +2442,14 @@ bt->flags |= BT_TEXT_SYMBOLS_PRINT|BT_ERROR_MASK; back_trace(bt); - bt->flags = BT_EFRAME_COUNT; - if ((cnt = machdep->eframe_search(bt))) { - error(INFO, "possible exception frame%s:\n", - cnt > 1 ? "s" : ""); - bt->flags &= ~(ulonglong)BT_EFRAME_COUNT; - machdep->eframe_search(bt); + if (!XEN_HYPER_MODE()) { + bt->flags = BT_EFRAME_COUNT; + if ((cnt = machdep->eframe_search(bt))) { + error(INFO, "possible exception frame%s:\n", + cnt > 1 ? "s" : ""); + bt->flags &= ~(ulonglong)BT_EFRAME_COUNT; + machdep->eframe_search(bt); + } } } --- crash-4.0-7.4/xen_hyper.c 2008-11-18 13:42:55.000000000 -0500 +++ crash-4.0-7.5/xen_hyper.c 2008-12-03 11:40:34.000000000 -0500 @@ -153,6 +153,17 @@ #endif XEN_HYPER_STRUCT_SIZE_INIT(cpu_user_regs, "cpu_user_regs"); + xht->idle_vcpu_size = get_array_length("idle_vcpu", NULL, 0); + xht->idle_vcpu_array = (ulong *)malloc(xht->idle_vcpu_size * sizeof(ulong)); + if (xht->idle_vcpu_array == NULL) { + error(FATAL, "cannot malloc idle_vcpu_array space.\n"); + } + if (!readmem(symbol_value("idle_vcpu"), KVADDR, xht->idle_vcpu_array, + xht->idle_vcpu_size * sizeof(ulong), "idle_vcpu_array", + RETURN_ON_ERROR)) { + error(FATAL, "cannot read idle_vcpu array.\n"); + } + /* * Do some initialization. */ @@ -188,7 +199,13 @@ XEN_HYPER_MEMBER_OFFSET_INIT(domain_is_hvm, "domain", "is_hvm"); XEN_HYPER_MEMBER_OFFSET_INIT(domain_is_privileged, "domain", "is_privileged"); XEN_HYPER_MEMBER_OFFSET_INIT(domain_debugger_attached, "domain", "debugger_attached"); + + /* + * Will be removed in Xen 4.4 (hg ae9b223a675d), + * need to check that with XEN_HYPER_VALID_MEMBER() before using + */ XEN_HYPER_MEMBER_OFFSET_INIT(domain_is_polling, "domain", "is_polling"); + XEN_HYPER_MEMBER_OFFSET_INIT(domain_is_dying, "domain", "is_dying"); XEN_HYPER_MEMBER_OFFSET_INIT(domain_is_paused_by_controller, "domain", "is_paused_by_controller"); XEN_HYPER_MEMBER_OFFSET_INIT(domain_is_shutting_down, "domain", "is_shutting_down"); @@ -895,6 +912,7 @@ ulong domain, next, dom_xen, dom_io, idle_vcpu; struct xen_hyper_domain_context *dc; struct xen_hyper_domain_context *dom0; + int i; if ((xhdt->flags & XEN_HYPER_DOMAIN_F_INIT) && !ACTIVE()) { return; @@ -925,20 +943,25 @@ dc++; /* restore an idle domain context. */ - get_symbol_data("idle_vcpu", sizeof(idle_vcpu), &idle_vcpu); - if (!readmem(idle_vcpu + MEMBER_OFFSET("vcpu", "domain"), - KVADDR, &domain, sizeof(domain), "domain", RETURN_ON_ERROR)) { - error(WARNING, "cannot read domain member in vcpu.\n"); - } - if (CRASHDEBUG(1)) { - fprintf(fp, "idle_vcpu=%lx, domain=%lx\n", idle_vcpu, domain); - } - if ((domain_struct = xen_hyper_read_domain(domain)) == NULL) { - error(FATAL, "cannot read idle domain.\n"); + for (i = 0; i < xht->idle_vcpu_size; i += XEN_HYPER_MAX_VIRT_CPUS) { + idle_vcpu = xht->idle_vcpu_array[i]; + if (idle_vcpu == 0) + break; + if (!readmem(idle_vcpu + MEMBER_OFFSET("vcpu", "domain"), + KVADDR, &domain, sizeof(domain), "domain", RETURN_ON_ERROR)) { + error(FATAL, "cannot read domain member in vcpu.\n"); + } + if (CRASHDEBUG(1)) { + fprintf(fp, "idle_vcpu=%lx, domain=%lx\n", idle_vcpu, domain); + } + if ((domain_struct = xen_hyper_read_domain(domain)) == NULL) { + error(FATAL, "cannot read idle domain.\n"); + } + xen_hyper_store_domain_context(dc, domain, domain_struct); + if (i == 0) + xhdt->idle_domain = dc; + dc++; } - xen_hyper_store_domain_context(dc, domain, domain_struct); - xhdt->idle_domain = dc; - dc++; /* restore domain contexts from dom0 symbol. */ xen_hyper_get_domain_next(XEN_HYPER_DOMAIN_READ_DOM0, &next); @@ -961,7 +984,7 @@ { ulong domain, next_in_list; long domain_next_in_list; - int i; + int i, j; get_symbol_data("dom0", sizeof(void *), &domain); domain_next_in_list = MEMBER_OFFSET("domain", "next_in_list"); @@ -974,7 +997,12 @@ error(FATAL, "cannot read domain.next_in_list.\n"); } } - i += 3; /* for dom_io, dom_xen and idle domain */ + i += 2; /* for dom_io, dom_xen */ + /* for idle domains */ + for (j = 0; j < xht->idle_vcpu_size; j += XEN_HYPER_MAX_VIRT_CPUS) { + if (xht->idle_vcpu_array[j]) + i++; + } return i; } @@ -1179,7 +1207,8 @@ dc->domain_flags |= XEN_HYPER_DOMS_privileged; } else if (*(dp + XEN_HYPER_OFFSET(domain_debugger_attached))) { dc->domain_flags |= XEN_HYPER_DOMS_debugging; - } else if (*(dp + XEN_HYPER_OFFSET(domain_is_polling))) { + } else if (XEN_HYPER_VALID_MEMBER(domain_is_polling) && + *(dp + XEN_HYPER_OFFSET(domain_is_polling))) { dc->domain_flags |= XEN_HYPER_DOMS_polling; } else if (*(dp + XEN_HYPER_OFFSET(domain_is_paused_by_controller))) { dc->domain_flags |= XEN_HYPER_DOMS_ctrl_pause; --- crash-4.0-7.4/xen_hyper_command.c 2008-11-18 13:42:55.000000000 -0500 +++ crash-4.0-7.5/xen_hyper_command.c 2008-12-03 11:40:34.000000000 -0500 @@ -1379,7 +1379,7 @@ } else if (dc->domain_id == XEN_HYPER_DOMID_XEN) { *type = XEN_HYPER_DOMAIN_TYPE_XEN; sprintf(buf, verbose ? "dom_xen" : "X"); - } else if (dc == xhdt->idle_domain) { + } else if (dc->domain_id == XEN_HYPER_DOMID_IDLE) { *type = XEN_HYPER_DOMAIN_TYPE_IDLE; sprintf(buf, verbose ? "idle domain" : "I"); } else if (dc == xhdt->dom0) { --- crash-4.0-7.4/xen_hyper_dump_tables.c 2008-11-18 13:42:55.000000000 -0500 +++ crash-4.0-7.5/xen_hyper_dump_tables.c 2008-12-02 10:31:47.000000000 -0500 @@ -775,8 +775,10 @@ (buf, "%ld\n", xen_hyper_offset_table.domain_is_privileged)); XEN_HYPER_PRI(fp, len, "domain_debugger_attached: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.domain_debugger_attached)); - XEN_HYPER_PRI(fp, len, "domain_is_polling: ", buf, flag, - (buf, "%ld\n", xen_hyper_offset_table.domain_is_polling)); + if (XEN_HYPER_VALID_MEMBER(domain_is_polling)) { + XEN_HYPER_PRI(fp, len, "domain_is_polling: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.domain_is_polling)); + } XEN_HYPER_PRI(fp, len, "domain_is_dying: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.domain_is_dying)); XEN_HYPER_PRI(fp, len, "domain_is_paused_by_controller: ", buf, flag, --- crash-4.0-7.4/defs.h 2008-11-18 13:42:55.000000000 -0500 +++ crash-4.0-7.5/defs.h 2008-12-03 16:44:47.000000000 -0500 @@ -185,10 +185,11 @@ #define IFILE_ERROR (0x400000000000000ULL) #define KERNTYPES (0x800000000000000ULL) #define MINIMAL_MODE (0x1000000000000000ULL) +#define CRASHBUILTIN (0x2000000000000000ULL) #define ACTIVE() (pc->flags & LIVE_SYSTEM) #define DUMPFILE() (!(pc->flags & LIVE_SYSTEM)) -#define MEMORY_SOURCES (NETDUMP|KDUMP|MCLXCD|LKCD|DEVMEM|S390D|MEMMOD|DISKDUMP|XENDUMP) +#define MEMORY_SOURCES (NETDUMP|KDUMP|MCLXCD|LKCD|DEVMEM|S390D|MEMMOD|DISKDUMP|XENDUMP|CRASHBUILTIN) #define DUMPFILE_TYPES (DISKDUMP|NETDUMP|KDUMP|MCLXCD|LKCD|S390D|XENDUMP) #define REMOTE() (pc->flags & REMOTE_DAEMON) #define REMOTE_ACTIVE() (pc->flags & REM_LIVE_SYSTEM) @@ -2069,7 +2070,8 @@ #define TIF_SIGPENDING (2) // CONFIG_X86_PAE -#define _SECTION_SIZE_BITS_PAE 30 +#define _SECTION_SIZE_BITS_PAE_ORIG 30 +#define _SECTION_SIZE_BITS_PAE_2_6_26 29 #define _MAX_PHYSMEM_BITS_PAE 36 // !CONFIG_X86_PAE @@ -4510,6 +4512,7 @@ extern int prettyprint_arrays; extern int repeat_count_threshold; extern unsigned int print_max; +extern int stop_print_at_null; /* * gdb/utils.c --- crash-4.0-7.4/xen_hyper_defs.h 2008-11-18 13:42:55.000000000 -0500 +++ crash-4.0-7.5/xen_hyper_defs.h 2008-12-03 11:40:34.000000000 -0500 @@ -166,6 +166,7 @@ /* Prepared domain ID. */ #define XEN_HYPER_DOMID_IO (0x7FF1U) #define XEN_HYPER_DOMID_XEN (0x7FF2U) +#define XEN_HYPER_DOMID_IDLE (0x7FFFU) /* Domain flags (domain_flags). */ /* Is this domain privileged? */ @@ -404,6 +405,8 @@ uint *cpu_idxs; ulong *__per_cpu_offset; int percpu_shift; + int idle_vcpu_size; + ulong *idle_vcpu_array; }; struct xen_hyper_dumpinfo_context { --- crash-4.0-7.4/extensions/libsial/sial_type.c 2008-11-18 13:42:55.000000000 -0500 +++ crash-4.0-7.5/extensions/libsial/sial_type.c 2008-10-22 11:03:46.000000000 -0400 @@ -278,9 +278,6 @@ int dosign=0; int vnbits=size*8; - - val = API_GET_UINT64(&val); - /* first get the value_t */ if (nbits >= 32) { int upper_bits = nbits - 32; --- crash-4.0-7.4/extensions/sial.c 2008-11-18 13:42:55.000000000 -0500 +++ crash-4.0-7.5/extensions/sial.c 2008-10-28 14:53:10.000000000 -0400 @@ -1,5 +1,5 @@ /* - * $Id: sial.c,v 1.6 2008/09/15 14:33:56 anderson Exp $ + * $Id: sial.c,v 1.7 2008/10/28 18:53:10 anderson Exp $ * * This file is part of lcrash, an analysis tool for Linux memory dumps. * @@ -363,7 +363,7 @@ sial_member_soffset(m, TYPE_FIELD_BITPOS(type, midx)/8); sial_member_ssize(m, TYPE_FIELD_TYPE(type, midx)->length); sial_member_snbits(m, TYPE_FIELD_BITSIZE(type, midx)); - sial_member_sfbit(m, TYPE_FIELD_BITSIZE(type, midx)); + sial_member_sfbit(m, TYPE_FIELD_BITPOS(type, midx)%8); sial_member_sname(m, TYPE_FIELD_NAME(type, midx)); LASTNUM=midx+1; return drilldowntype(TYPE_FIELD_TYPE(type, midx), tm);