--- crash-5.0.1/memory.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/memory.c 2010-03-26 14:37:15.000000000 -0400 @@ -7212,6 +7212,8 @@ ulong cache, cache_cache, name; long next_offset, name_offset; char *cache_buf; + int has_cache_chain; + ulong cache_chain; char buf[BUFSIZE]; if (vt->flags & KMEM_CACHE_UNAVAIL) { @@ -7224,6 +7226,14 @@ return; } + if (symbol_exists("cache_chain")) { + has_cache_chain = TRUE; + cache_chain = symbol_value("cache_chain"); + } else { + has_cache_chain = FALSE; + cache_chain = 0; + } + name_offset = vt->flags & (PERCPU_KMALLOC_V1|PERCPU_KMALLOC_V2) ? OFFSET(kmem_cache_s_name) : OFFSET(kmem_cache_s_c_name); next_offset = vt->flags & (PERCPU_KMALLOC_V1|PERCPU_KMALLOC_V2) ? @@ -7260,6 +7270,10 @@ cache = ULONG(cache_buf + next_offset); + if (has_cache_chain && (cache == cache_chain)) + readmem(cache, KVADDR, &cache, sizeof(char *), + "cache_chain", FAULT_ON_ERROR); + if (vt->flags & (PERCPU_KMALLOC_V1|PERCPU_KMALLOC_V2)) cache -= next_offset; @@ -9196,9 +9210,6 @@ tmp = INT(slab_buf + OFFSET(slab_inuse)); si->inuse += tmp; - if (ACTIVE()) - gather_cpudata_list_v2_nodes(si, index); - si->s_mem = ULONG(slab_buf + OFFSET(slab_s_mem)); gather_slab_cached_count(si); @@ -12094,8 +12105,11 @@ else node_present_pages = 0; - readmem(pgdat+OFFSET(pglist_data_bdata), KVADDR, &bdata, - sizeof(ulong), "pglist bdata", FAULT_ON_ERROR); + if (VALID_MEMBER(pglist_data_bdata)) + readmem(pgdat+OFFSET(pglist_data_bdata), KVADDR, &bdata, + sizeof(ulong), "pglist bdata", FAULT_ON_ERROR); + else + bdata = BADADDR; if (initialize) { nt->node_id = id; @@ -12140,8 +12154,9 @@ MKSTR(node_size)), mkstring(buf2, flen, CENTER|LJUST|LONG_HEX, MKSTR(pgdat)), - mkstring(buf3, flen, CENTER|LONG_HEX, - MKSTR(bdata)), + bdata == BADADDR ? + mkstring(buf3, flen, CENTER, "----") : + mkstring(buf3, flen, CENTER|LONG_HEX, MKSTR(bdata)), mkstring(buf4, flen, CENTER|LJUST|LONG_HEX, MKSTR(node_zones))); fprintf(fp, "%s", buf5); --- crash-5.0.1/help.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/help.c 2010-03-12 16:36:43.000000000 -0500 @@ -975,13 +975,13 @@ " PID PPID CPU TASK ST %MEM VSZ RSS COMM", " 21273 21256 0 ffff81003ec15080 IN 46.3 1138276 484364 firefox", " ", -" Show the time usage data for pid 18844:\n", -" %s> ps -t 18844", -" PID: 18844 TASK: c3012000 CPU: 0 COMMAND: \"bash\"", -" RUN TIME: 00:31:23", -" START TIME: 51390045", -" USER TIME: 1", -" SYSTEM TIME: 3", +" Show the time usage data for pid 10318:\n", +" %s> ps -t 10318", +" PID: 10318 TASK: f7b85550 CPU: 5 COMMAND: \"bash\"", +" RUN TIME: 1 days, 01:35:32", +" START TIME: 5209", +" UTIME: 95", +" STIME: 57", " ", " Show the process status of PID 1, task f9dec000, and all nfsd tasks:\n", " %s> ps 1 f9dec000 nfsd", --- crash-5.0.1/task.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/task.c 2010-03-12 15:59:50.000000000 -0500 @@ -300,6 +300,8 @@ MEMBER_OFFSET_INIT(task_struct_start_time, "task_struct", "start_time"); MEMBER_SIZE_INIT(task_struct_start_time, "task_struct", "start_time"); + MEMBER_SIZE_INIT(task_struct_utime, "task_struct", "utime"); + MEMBER_SIZE_INIT(task_struct_stime, "task_struct", "stime"); MEMBER_OFFSET_INIT(task_struct_times, "task_struct", "times"); MEMBER_OFFSET_INIT(tms_tms_utime, "tms", "tms_utime"); MEMBER_OFFSET_INIT(tms_tms_stime, "tms", "tms_stime"); @@ -3335,16 +3337,18 @@ ulonglong start_time; ulong tms_utime; ulong tms_stime; - struct timeval utime; - struct timeval stime; + struct timeval old_utime; + struct timeval old_stime; struct kernel_timeval kutime; struct kernel_timeval kstime; + ulonglong utime; + ulonglong stime; }; static void show_task_times(struct task_context *tcp, ulong flags) { - int i, tasks, use_kernel_timeval; + int i, tasks, use_kernel_timeval, use_utime_stime; struct task_context *tc; struct task_start_time *task_start_times, *tsp; ulong jiffies; @@ -3355,6 +3359,12 @@ GETBUF(RUNNING_TASKS() * sizeof(struct task_start_time)); use_kernel_timeval = STRUCT_EXISTS("kernel_timeval"); + if (VALID_MEMBER(task_struct_utime) && + (SIZE(task_struct_utime) == + (BITS32() ? sizeof(uint32_t) : sizeof(uint64_t)))) + use_utime_stime = TRUE; + else + use_utime_stime = FALSE; get_symbol_data("jiffies", sizeof(long), &jiffies); if (symbol_exists("jiffies_64")) get_uptime(NULL, &jiffies_64); @@ -3400,7 +3410,12 @@ OFFSET(task_struct_times) + OFFSET(tms_tms_stime)); } else if (VALID_MEMBER(task_struct_utime)) { - if (use_kernel_timeval) { + if (use_utime_stime) { + tsp->utime = ULONG(tt->task_struct + + OFFSET(task_struct_utime)); + tsp->stime = ULONG(tt->task_struct + + OFFSET(task_struct_stime)); + } else if (use_kernel_timeval) { BCOPY(tt->task_struct + OFFSET(task_struct_utime), &tsp->kutime, sizeof(struct kernel_timeval)); @@ -3418,8 +3433,8 @@ OFFSET(task_struct_stime), &stime_64, 8); /* convert from micro-sec. to sec. */ - tsp->utime.tv_sec = utime_64 / 1000000; - tsp->stime.tv_sec = stime_64 / 1000000; + tsp->old_utime.tv_sec = utime_64 / 1000000; + tsp->old_stime.tv_sec = stime_64 / 1000000; } else { uint32_t utime_32, stime_32; BCOPY(tt->task_struct + @@ -3428,8 +3443,8 @@ BCOPY(tt->task_struct + OFFSET(task_struct_stime), &stime_32, 4); - tsp->utime.tv_sec = utime_32; - tsp->stime.tv_sec = stime_32; + tsp->old_utime.tv_sec = utime_32; + tsp->old_stime.tv_sec = stime_32; } } else { BCOPY(tt->task_struct + @@ -3461,16 +3476,21 @@ fprintf(fp, " USER TIME: %ld\n", tsp->tms_utime); fprintf(fp, " SYSTEM TIME: %ld\n\n", tsp->tms_stime); } else if (VALID_MEMBER(task_struct_utime)) { - if (use_kernel_timeval) { + if (use_utime_stime) { + fprintf(fp, " UTIME: %lld\n", + (ulonglong)tsp->utime); + fprintf(fp, " STIME: %lld\n\n", + (ulonglong)tsp->stime); + } else if (use_kernel_timeval) { fprintf(fp, " USER TIME: %d\n", tsp->kutime.tv_sec); fprintf(fp, " SYSTEM TIME: %d\n\n", tsp->kstime.tv_sec); } else { fprintf(fp, " USER TIME: %ld\n", - tsp->utime.tv_sec); + tsp->old_utime.tv_sec); fprintf(fp, " SYSTEM TIME: %ld\n\n", - tsp->stime.tv_sec); + tsp->old_stime.tv_sec); } } } --- crash-5.0.1/kernel.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/kernel.c 2010-03-09 08:39:24.000000000 -0500 @@ -1535,7 +1535,7 @@ continue; if ((vaddr = htol(strip_ending_char(arglist[0], ':'), - RETURN_ON_ERROR, NULL)) >= spn->value) + RETURN_ON_ERROR|QUIET, NULL)) >= spn->value) continue; if (STREQ(arglist[2], "ud2a")) { @@ -1658,7 +1658,7 @@ } #define FRAMESIZE_DEBUG_MESSAGE \ -"\nx86 usage: bt -F [size|clear|dump|seek|noseek|validate|novalidate] [-I eip]\n If eip: set its associated framesize to size.\n \"validate/novalidate\" will turn on/off V bit for this eip entry.\n If !eip: \"clear\" will clear the framesize cache and RA seek/noseek flags.\n \"dump\" will dump the current framesize cache entries.\n \"seek/noseek\" turns on/off RA seeking.\n \"validate/novalidate\" turns on/off V bit for all current entries.\n\nx86_64 usage: bt -F [clear|dump|validate] [-I rip]\n If rip: \"validate\" will verbosely recalculate the framesize.\n If !rip: \"clear\" will clear the framesize cache.\n \"dump\" will dump the current framesize cache entries.\n" +"\nx86 usage: bt -F [size|clear|dump|seek|noseek|validate|novalidate] [-I eip]\n If eip: set its associated framesize to size.\n \"validate/novalidate\" will turn on/off V bit for this eip entry.\n If !eip: \"clear\" will clear the framesize cache and RA seek/noseek flags.\n \"dump\" will dump the current framesize cache entries.\n \"seek/noseek\" turns on/off RA seeking.\n \"validate/novalidate\" turns on/off V bit for all current entries.\n\nx86_64 usage: bt -F [clear|dump|validate|framepointer|noframepointer] [-I rip]\n If rip: \"validate\" will verbosely recalculate the framesize without\n framepointers (no stack reference).\n If !rip: \"clear\" will clear the framesize cache.\n \"dump\" will dump the current framesize cache entries.\n \"framepointer/noframepointer\" toggle the FRAMEPOINTER flag and\n clear the framesize cache." /* @@ -1858,6 +1858,10 @@ hook.esp = (ulong)-1; else if (STREQ(optarg, "novalidate")) hook.esp = (ulong)-2; + else if (STREQ(optarg, "framepointer")) + hook.esp = (ulong)-3; + else if (STREQ(optarg, "noframepointer")) + hook.esp = (ulong)-4; else if (STREQ(optarg, "clear")) { kt->flags &= ~(RA_SEEK|NO_RA_SEEK); hook.esp = 0; @@ -3870,8 +3874,8 @@ fprintf(fp, "\n"); } - - fprintf(fp, " CPUS: %d\n", kt->cpus); + fprintf(fp, " CPUS: %d\n", + machine_type("PPC64") ? get_cpus_to_display() : kt->cpus); if (ACTIVE()) get_symbol_data("xtime", sizeof(struct timespec), &kt->date); fprintf(fp, " DATE: %s\n", @@ -6257,6 +6261,18 @@ } /* + * When displaying cpus, return the number of cpus online if possible, + * otherwise kt->cpus. + */ +int +get_cpus_to_display(void) +{ + int online = get_cpus_online(); + + return (online ? online : kt->cpus); +} + +/* * Xen machine-address to pseudo-physical-page translator. */ ulonglong --- crash-5.0.1/x86.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/x86.c 2010-03-22 10:43:17.000000000 -0400 @@ -466,6 +466,7 @@ #ifndef MCLX db_read_bytes(addr, size, data); #else + BZERO(data, sizeof(int)); if (INSTACK(addr, bt)) { if (size == sizeof(ulong)) return (db_expr_t)GET_STACK_ULONG(addr); @@ -1026,7 +1027,7 @@ int INT_EFRAME_EBX = 0; int INT_EFRAME_GS = -1; -#define MAX_USER_EFRAME_SIZE (16) +#define MAX_USER_EFRAME_SIZE (17) #define KERNEL_EFRAME_SIZE (INT_EFRAME_EFLAGS+1) #define EFRAME_USER (1) @@ -1878,7 +1879,7 @@ { if (INVALID_SIZE(pt_regs)) { if (THIS_KERNEL_VERSION < LINUX(2,6,20)) - ASSIGN_SIZE(pt_regs) = (MAX_USER_EFRAME_SIZE-1)*sizeof(ulong); + ASSIGN_SIZE(pt_regs) = (MAX_USER_EFRAME_SIZE-2)*sizeof(ulong); else { ASSIGN_SIZE(pt_regs) = MAX_USER_EFRAME_SIZE*sizeof(ulong); INT_EFRAME_SS = 15; @@ -3988,6 +3989,7 @@ "E820_RESERVED", "E820_ACPI", "E820_NVS", + "E820_UNUSABLE", }; static void @@ -4014,8 +4016,11 @@ addr = ULONGLONG(e820entry_ptr + OFFSET(e820entry_addr)); size = ULONGLONG(e820entry_ptr + OFFSET(e820entry_size)); type = ULONG(e820entry_ptr + OFFSET(e820entry_type)); - fprintf(fp, "%016llx - %016llx %s\n", addr, addr+size, - e820type[type]); + fprintf(fp, "%016llx - %016llx ", addr, addr+size); + if (type >= (sizeof(e820type)/sizeof(char *))) + fprintf(fp, "type %ld\n", type); + else + fprintf(fp, "%s\n", e820type[type]); } } --- crash-5.0.1/ppc.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/ppc.c 2010-03-25 13:40:19.000000000 -0400 @@ -461,7 +461,7 @@ ppc_processor_speed(void) { ulong res, value, ppc_md, md_setup_res; - ulong we_have_of, prep_setup_res; + ulong prep_setup_res; ulong node, type, name, properties; char str_buf[16]; ulong len, mhz = 0; @@ -469,22 +469,7 @@ if (machdep->mhz) return(machdep->mhz); - /* first, check if the have_of variable a) exists, and b) is TRUE */ - if(symbol_exists("have_of")) { - get_symbol_data("have_of", sizeof(void *), &we_have_of); - } else { - we_have_of = 0; - } - - if(we_have_of) { - /* we have a machine with open firmware, so search the OF nodes - * for cpu nodes. - * Too bad we can't call kernel helper functions here :) - */ - - if(!symbol_exists("allnodes")) - return (machdep->mhz = 0); - + if(symbol_exists("allnodes")) { get_symbol_data("allnodes", sizeof(void *), &node); while(node) { readmem(node+OFFSET(device_node_type), @@ -545,54 +530,53 @@ } if(!properties) { /* didn't find the cpu speed for some reason */ - mhz = 0; + return (machdep->mhz = 0); } } - } else { - /* for machines w/o OF */ - /* untested, but in theory this should work on prep machines */ + } + /* for machines w/o OF */ + /* untested, but in theory this should work on prep machines */ - if (symbol_exists("res")) { - get_symbol_data("res", sizeof(void *), &res); + if (symbol_exists("res") && !mhz) { + get_symbol_data("res", sizeof(void *), &res); - if (symbol_exists("prep_setup_residual")) { - get_symbol_data("prep_setup_residual", - sizeof(void *), &prep_setup_res); - get_symbol_data("ppc_md", sizeof(void *), - &ppc_md); - readmem(ppc_md + - OFFSET(machdep_calls_setup_residual), - KVADDR, &md_setup_res, - sizeof(ulong), "ppc_md setup_residual", - FAULT_ON_ERROR); + if (symbol_exists("prep_setup_residual")) { + get_symbol_data("prep_setup_residual", + sizeof(void *), &prep_setup_res); + get_symbol_data("ppc_md", sizeof(void *), + &ppc_md); + readmem(ppc_md + + OFFSET(machdep_calls_setup_residual), + KVADDR, &md_setup_res, + sizeof(ulong), "ppc_md setup_residual", + FAULT_ON_ERROR); - if(prep_setup_res == md_setup_res) { - /* PREP machine */ - readmem(res+ - OFFSET(RESIDUAL_VitalProductData)+ - OFFSET(VPD_ProcessorHz), - KVADDR, &mhz, sizeof(ulong), - "res VitalProductData", - FAULT_ON_ERROR); + if(prep_setup_res == md_setup_res) { + /* PREP machine */ + readmem(res+ + OFFSET(RESIDUAL_VitalProductData)+ + OFFSET(VPD_ProcessorHz), + KVADDR, &mhz, sizeof(ulong), + "res VitalProductData", + FAULT_ON_ERROR); - mhz = (mhz > 1024) ? mhz >> 20 : mhz; - } + mhz = (mhz > 1024) ? mhz >> 20 : mhz; } + } - if(!mhz) { - /* everything else seems to do this the same way... */ - readmem(res + - OFFSET(bd_info_bi_intfreq), - KVADDR, &mhz, sizeof(ulong), - "bd_info bi_intfreq", FAULT_ON_ERROR); + if(!mhz) { + /* everything else seems to do this the same way... */ + readmem(res + + OFFSET(bd_info_bi_intfreq), + KVADDR, &mhz, sizeof(ulong), + "bd_info bi_intfreq", FAULT_ON_ERROR); - mhz /= 1000000; - } + mhz /= 1000000; } - /* else...well, we don't have OF, or a residual structure, so - * just print unknown MHz - */ } + /* else...well, we don't have OF, or a residual structure, so + * just print unknown MHz + */ return (machdep->mhz = mhz); } --- crash-5.0.1/s390.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/s390.c 2010-02-26 10:48:43.000000000 -0500 @@ -37,7 +37,7 @@ #define S390_PTE_INVALID_MASK 0x80000900 #define S390_PTE_INVALID(x) ((x) & S390_PTE_INVALID_MASK) -#define ASYNC_STACK_SIZE STACKSIZE() // can be 4096 or 8192 +#define INT_STACK_SIZE STACKSIZE() // can be 4096 or 8192 #define KERNEL_STACK_SIZE STACKSIZE() // can be 4096 or 8192 #define LOWCORE_SIZE 4096 @@ -570,20 +570,23 @@ FAULT_ON_ERROR); } -/* - * read in the async stack +/* + * Read interrupt stack (either "async_stack" or "panic_stack"); */ -static void -s390_get_async_stack(char* lowcore, char* async_stack, unsigned long* start, unsigned long* end) +static void s390_get_int_stack(char *stack_name, char* lc, char* int_stack, + unsigned long* start, unsigned long* end) { - unsigned long async_stack_ptr; + unsigned long stack_addr; - async_stack_ptr = ULONG(lowcore + - MEMBER_OFFSET("_lowcore","async_stack")); - readmem(async_stack_ptr-ASYNC_STACK_SIZE,KVADDR, async_stack, - ASYNC_STACK_SIZE, "async_stack", FAULT_ON_ERROR); - *start=async_stack_ptr-ASYNC_STACK_SIZE; - *end=async_stack_ptr; + if (!MEMBER_EXISTS("_lowcore", stack_name)) + return; + stack_addr = ULONG(lc + MEMBER_OFFSET("_lowcore", stack_name)); + if (stack_addr == 0) + return; + readmem(stack_addr - INT_STACK_SIZE, KVADDR, int_stack, + INT_STACK_SIZE, stack_name, FAULT_ON_ERROR); + *start = stack_addr - INT_STACK_SIZE; + *end = stack_addr; } /* @@ -593,16 +596,18 @@ s390_back_trace_cmd(struct bt_info *bt) { char* stack; - char async_stack[ASYNC_STACK_SIZE]; + char async_stack[INT_STACK_SIZE]; + char panic_stack[INT_STACK_SIZE]; long ksp,backchain,old_backchain; int i=0, r14_offset,bc_offset,r14, skip_first_frame=0; - unsigned long async_start,async_end, stack_end, stack_start, stack_base; + unsigned long async_start = 0, async_end = 0; + unsigned long panic_start = 0, panic_end = 0; + unsigned long stack_end, stack_start, stack_base; if (bt->hp && bt->hp->eip) { error(WARNING, "instruction pointer argument ignored on this architecture!\n"); } - async_end = async_start = 0; ksp = bt->stkptr; /* print lowcore and get async stack when task has cpu */ @@ -622,9 +627,10 @@ s390_print_lowcore(lowcore,bt,0); return; } - - s390_get_async_stack(lowcore,async_stack,&async_start, - &async_end); + s390_get_int_stack("async_stack", lowcore, async_stack, + &async_start, &async_end); + s390_get_int_stack("panic_stack", lowcore, panic_stack, + &panic_start, &panic_end); s390_print_lowcore(lowcore,bt,1); fprintf(fp,"\n"); skip_first_frame=1; @@ -653,7 +659,7 @@ unsigned long r14_stack_off; int j; - /* Find stack: Either async stack or task stack */ + /* Find stack: Either async, panic stack or task stack */ if((backchain > stack_start) && (backchain < stack_end)){ stack = bt->stackbuf; stack_base = stack_start; @@ -661,6 +667,10 @@ && s390_has_cpu(bt)){ stack = async_stack; stack_base = async_start; + } else if((backchain > panic_start) && (backchain < panic_end) + && s390_has_cpu(bt)){ + stack = panic_stack; + stack_base = panic_start; } else { /* invalid stackframe */ break; --- crash-5.0.1/s390x.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/s390x.c 2010-02-26 10:48:43.000000000 -0500 @@ -36,7 +36,7 @@ #define S390X_PTE_INVALID_MASK 0x900ULL #define S390X_PTE_INVALID(x) ((x) & S390X_PTE_INVALID_MASK) -#define ASYNC_STACK_SIZE STACKSIZE() // can be 8192 or 16384 +#define INT_STACK_SIZE STACKSIZE() // can be 8192 or 16384 #define KERNEL_STACK_SIZE STACKSIZE() // can be 8192 or 16384 #define LOWCORE_SIZE 8192 @@ -803,19 +803,22 @@ } /* - * read in the async stack + * Read interrupt stack (either "async_stack" or "panic_stack"); */ -static void -s390x_get_async_stack(char* lowcore, char* async_stack, unsigned long* start, unsigned long* end) +static void s390x_get_int_stack(char *stack_name, char* lc, char* int_stack, + unsigned long* start, unsigned long* end) { - unsigned long async_stack_ptr; + unsigned long stack_addr; - async_stack_ptr = ULONG(lowcore + - MEMBER_OFFSET("_lowcore","async_stack")); - readmem(async_stack_ptr-ASYNC_STACK_SIZE,KVADDR, async_stack, - ASYNC_STACK_SIZE, "async_stack", FAULT_ON_ERROR); - *start=async_stack_ptr-ASYNC_STACK_SIZE; - *end=async_stack_ptr; + if (!MEMBER_EXISTS("_lowcore", stack_name)) + return; + stack_addr = ULONG(lc + MEMBER_OFFSET("_lowcore", stack_name)); + if (stack_addr == 0) + return; + readmem(stack_addr - INT_STACK_SIZE, KVADDR, int_stack, + INT_STACK_SIZE, stack_name, FAULT_ON_ERROR); + *start = stack_addr - INT_STACK_SIZE; + *end = stack_addr; } /* @@ -825,11 +828,14 @@ s390x_back_trace_cmd(struct bt_info *bt) { char* stack; - char async_stack[ASYNC_STACK_SIZE]; + char async_stack[INT_STACK_SIZE]; + char panic_stack[INT_STACK_SIZE]; long ksp,backchain,old_backchain; - int i=0, r14_offset,bc_offset,r14, skip_first_frame=0; + int i=0, r14_offset,bc_offset, skip_first_frame=0; unsigned long async_start = 0, async_end = 0; + unsigned long panic_start = 0, panic_end = 0; unsigned long stack_end, stack_start, stack_base; + unsigned long r14; if (bt->hp && bt->hp->eip) { error(WARNING, @@ -854,9 +860,10 @@ s390x_print_lowcore(lowcore,bt,0); return; } - - s390x_get_async_stack(lowcore,async_stack,&async_start, - &async_end); + s390x_get_int_stack("async_stack", lowcore, async_stack, + &async_start, &async_end); + s390x_get_int_stack("panic_stack", lowcore, panic_stack, + &panic_start, &panic_end); s390x_print_lowcore(lowcore,bt,1); fprintf(fp,"\n"); skip_first_frame=1; @@ -885,7 +892,7 @@ unsigned long r14_stack_off; int j; - /* Find stack: Either async stack or task stack */ + /* Find stack: Either async, panic stack or task stack */ if((backchain > stack_start) && (backchain < stack_end)){ stack = bt->stackbuf; stack_base = stack_start; @@ -893,6 +900,10 @@ && s390x_has_cpu(bt)){ stack = async_stack; stack_base = async_start; + } else if((backchain > panic_start) && (backchain < panic_end) + && s390x_has_cpu(bt)){ + stack = panic_stack; + stack_base = panic_start; } else { /* invalid stackframe */ break; @@ -913,7 +924,7 @@ skip_first_frame=0; } else { fprintf(fp," #%i [%08lx] ",i,backchain); - fprintf(fp,"%s at %x\n", closest_symbol(r14), r14); + fprintf(fp,"%s at %lx\n", closest_symbol(r14), r14); if (bt->flags & BT_LINE_NUMBERS) s390x_dump_line_number(r14); i++; @@ -944,19 +955,20 @@ } /* Check for interrupt stackframe */ - if((backchain == 0) && (stack == async_stack)){ - unsigned long psw_flags,r15; + if((backchain == 0) && + (stack == async_stack || stack == panic_stack)) { + int pt_regs_off = old_backchain - stack_base + 160; + unsigned long psw_flags; - psw_flags = ULONG(&stack[old_backchain - stack_base - +96 +MEMBER_OFFSET("pt_regs","psw")]); + psw_flags = ULONG(&stack[pt_regs_off + + MEMBER_OFFSET("pt_regs", "psw")]); if(psw_flags & 0x1000000000000ULL){ /* User psw: should not happen */ break; } - r15 = ULONG(&stack[old_backchain - stack_base + - 96 + MEMBER_OFFSET("pt_regs", - "gprs") + 15 * S390X_WORD_SIZE]); - backchain=r15; + backchain = ULONG(&stack[pt_regs_off + + MEMBER_OFFSET("pt_regs", "gprs") + + 15 * S390X_WORD_SIZE]); fprintf(fp," - Interrupt -\n"); } } while(backchain != 0); @@ -1036,28 +1048,28 @@ fprintf(fp," -access registers:\n"); ptr = lc + MEMBER_OFFSET("_lowcore","access_regs_save_area"); - tmp[0]=ULONG(ptr); - tmp[1]=ULONG(ptr + 4); - tmp[2]=ULONG(ptr + 2 * 4); - tmp[3]=ULONG(ptr + 3 * 4); + tmp[0]=UINT(ptr); + tmp[1]=UINT(ptr + 4); + tmp[2]=UINT(ptr + 2 * 4); + tmp[3]=UINT(ptr + 3 * 4); fprintf(fp," %#010lx %#010lx %#010lx %#010lx\n", tmp[0], tmp[1], tmp[2], tmp[3]); - tmp[0]=ULONG(ptr + 4 * 4); - tmp[1]=ULONG(ptr + 5 * 4); - tmp[2]=ULONG(ptr + 6 * 4); - tmp[3]=ULONG(ptr + 7 * 4); + tmp[0]=UINT(ptr + 4 * 4); + tmp[1]=UINT(ptr + 5 * 4); + tmp[2]=UINT(ptr + 6 * 4); + tmp[3]=UINT(ptr + 7 * 4); fprintf(fp," %#010lx %#010lx %#010lx %#010lx\n", tmp[0], tmp[1], tmp[2], tmp[3]); - tmp[0]=ULONG(ptr + 8 * 4); - tmp[1]=ULONG(ptr + 9 * 4); - tmp[2]=ULONG(ptr + 10* 4); - tmp[3]=ULONG(ptr + 11* 4); + tmp[0]=UINT(ptr + 8 * 4); + tmp[1]=UINT(ptr + 9 * 4); + tmp[2]=UINT(ptr + 10 * 4); + tmp[3]=UINT(ptr + 11 * 4); fprintf(fp," %#010lx %#010lx %#010lx %#010lx\n", tmp[0], tmp[1], tmp[2], tmp[3]); - tmp[0]=ULONG(ptr + 12* 4); - tmp[1]=ULONG(ptr + 13* 4); - tmp[2]=ULONG(ptr + 14* 4); - tmp[3]=ULONG(ptr + 15* 4); + tmp[0]=UINT(ptr + 12 * 4); + tmp[1]=UINT(ptr + 13 * 4); + tmp[2]=UINT(ptr + 14 * 4); + tmp[3]=UINT(ptr + 15 * 4); fprintf(fp," %#010lx %#010lx %#010lx %#010lx\n", tmp[0], tmp[1], tmp[2], tmp[3]); --- crash-5.0.1/ppc64.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/ppc64.c 2010-03-26 10:11:27.000000000 -0400 @@ -51,6 +51,7 @@ static void parse_cmdline_args(void); static void ppc64_paca_init(void); static void ppc64_clear_machdep_cache(void); +static void ppc64_vmemmap_init(void); struct machine_specific ppc64_machine_specific = { { 0 }, 0, 0 }; @@ -137,8 +138,11 @@ machdep->line_number_hooks = ppc64_line_number_hooks; machdep->value_to_symbol = generic_machdep_value_to_symbol; machdep->init_kernel_pgd = NULL; - if (symbol_exists("vmemmap_populate")) + if (symbol_exists("vmemmap_populate")) { machdep->flags |= VMEMMAP; + machdep->machspec->vmemmap_base = + VMEMMAP_REGION_ID << REGION_SHIFT; + } break; case POST_GDB: @@ -190,6 +194,9 @@ m->l4_shift = m->l3_shift + m->l3_index_size; } + if (machdep->flags & VMEMMAP) + ppc64_vmemmap_init(); + machdep->section_size_bits = _SECTION_SIZE_BITS; machdep->max_physmem_bits = _MAX_PHYSMEM_BITS; ppc64_paca_init(); @@ -328,6 +335,8 @@ fprintf(fp, "%sVM_4_LEVEL", others++ ? "|" : ""); if (machdep->flags & VMEMMAP) fprintf(fp, "%sVMEMMAP", others++ ? "|" : ""); + if (machdep->flags & VMEMMAP_AWARE) + fprintf(fp, "%sVMEMMAP_AWARE", others++ ? "|" : ""); fprintf(fp, ")\n"); fprintf(fp, " kvbase: %lx\n", machdep->kvbase); @@ -419,6 +428,27 @@ fprintf(fp, " l1_shift: %d\n", machdep->machspec->l1_shift); fprintf(fp, " pte_shift: %d\n", machdep->machspec->pte_shift); fprintf(fp, " l2_masked_bits: %x\n", machdep->machspec->l2_masked_bits); + fprintf(fp, " vmemmap_base: "); + if (machdep->machspec->vmemmap_base) + fprintf(fp, "%lx\n", machdep->machspec->vmemmap_base); + else + fprintf(fp, "(unused)\n"); + if (machdep->machspec->vmemmap_cnt) { + fprintf(fp, " vmemmap_cnt: %d\n", + machdep->machspec->vmemmap_cnt); + fprintf(fp, " vmemmap_psize: %d\n", + machdep->machspec->vmemmap_psize); + for (i = 0; i < machdep->machspec->vmemmap_cnt; i++) { + fprintf(fp, + " vmemmap_list[%d]: virt: %lx phys: %lx\n", i, + machdep->machspec->vmemmap_list[i].virt, + machdep->machspec->vmemmap_list[i].phys); + } + } else { + fprintf(fp, " vmemmap_cnt: (unused)\n"); + fprintf(fp, " vmemmap_page_size: (unused)\n"); + fprintf(fp, " vmemmap_list[]: (unused)\n"); + } } /* @@ -653,7 +683,8 @@ if (!IS_KVADDR(kvaddr)) return FALSE; - if (REGION_ID(kvaddr) == VMEMMAP_REGION_ID) + if ((machdep->flags & VMEMMAP) && + (kvaddr >= machdep->machspec->vmemmap_base)) return ppc64_vmemmap_to_phys(kvaddr, paddr, verbose); if (!vt->vmalloc_start) { @@ -673,34 +704,135 @@ } /* + * Verify that the kernel has made the vmemmap list available, + * and if so, stash the relevant data required to make vtop + * translations. + */ +static +void ppc64_vmemmap_init(void) +{ + int i, psize, shift, cnt; + struct list_data list_data, *ld; + long backing_size, virt_addr_offset, phys_offset, list_offset; + ulong *vmemmap_list; + char *vmemmap_buf; + struct machine_specific *ms; + + if (!(kernel_symbol_exists("vmemmap_list")) || + !(kernel_symbol_exists("mmu_psize_defs")) || + !(kernel_symbol_exists("mmu_vmemmap_psize")) || + !STRUCT_EXISTS("vmemmap_backing") || + !STRUCT_EXISTS("mmu_psize_def") || + !MEMBER_EXISTS("mmu_psize_def", "shift") || + !MEMBER_EXISTS("vmemmap_backing", "phys") || + !MEMBER_EXISTS("vmemmap_backing", "virt_addr") || + !MEMBER_EXISTS("vmemmap_backing", "list")) + return; + + ms = machdep->machspec; + + backing_size = STRUCT_SIZE("vmemmap_backing"); + virt_addr_offset = MEMBER_OFFSET("vmemmap_backing", "virt_addr"); + phys_offset = MEMBER_OFFSET("vmemmap_backing", "phys"); + list_offset = MEMBER_OFFSET("vmemmap_backing", "list"); + + if (!readmem(symbol_value("mmu_vmemmap_psize"), + KVADDR, &psize, sizeof(int), "mmu_vmemmap_psize", + RETURN_ON_ERROR)) + return; + if (!readmem(symbol_value("mmu_psize_defs") + + (STRUCT_SIZE("mmu_psize_def") * psize) + + MEMBER_OFFSET("mmu_psize_def", "shift"), + KVADDR, &shift, sizeof(int), "mmu_psize_def shift", + RETURN_ON_ERROR)) + return; + + ms->vmemmap_psize = 1 << shift; + + ld = &list_data; + BZERO(ld, sizeof(struct list_data)); + if (!readmem(symbol_value("vmemmap_list")+OFFSET(list_head_next), + KVADDR, &ld->start, sizeof(void *), "vmemmap_list.next", + RETURN_ON_ERROR)) + return; + ld->end = symbol_value("vmemmap_list"); + ld->list_head_offset = list_offset; + + hq_open(); + cnt = do_list(ld); + vmemmap_list = (ulong *)GETBUF(cnt * sizeof(ulong)); + cnt = retrieve_list(vmemmap_list, cnt); + hq_close(); + + if ((ms->vmemmap_list = (struct ppc64_vmemmap *)malloc(cnt * + sizeof(struct ppc64_vmemmap))) == NULL) + error(FATAL, "cannot malloc vmemmap list space"); + + vmemmap_buf = GETBUF(backing_size); + for (i = 0; i < cnt; i++) { + if (!readmem(vmemmap_list[i], KVADDR, vmemmap_buf, + backing_size, "vmemmap_backing", RETURN_ON_ERROR)) + goto out; + + ms->vmemmap_list[i].phys = ULONG(vmemmap_buf + phys_offset); + ms->vmemmap_list[i].virt = ULONG(vmemmap_buf + virt_addr_offset); + } + + if (ms->vmemmap_base != ms->vmemmap_list[0].virt) { + ms->vmemmap_base = ms->vmemmap_list[0].virt; + if (CRASHDEBUG(1)) + fprintf(fp, + "ppc64_vmemmap_init: vmemmap base: %lx\n", + ms->vmemmap_base); + } + + ms->vmemmap_cnt = cnt; + machdep->flags |= VMEMMAP_AWARE; +out: + FREEBUF(vmemmap_buf); + FREEBUF(vmemmap_list); + machdep->flags |= VMEMMAP_AWARE; +} + +/* * If the vmemmap address translation information is stored in the kernel, * make the translation. */ static int ppc64_vmemmap_to_phys(ulong kvaddr, physaddr_t *paddr, int verbose) { - if (!(machdep->flags & VMEMMAP)) - return FALSE; - - /* - * If possible, make the translation here. - */ + int i; + ulong offset; + struct machine_specific *ms; - /* TBD -- kernel assist required */ + if (!(machdep->flags & VMEMMAP_AWARE)) { + /* + * During runtime, just fail the command. + */ + if (vt->flags & VM_INIT) + error(FATAL, "cannot translate vmemmap address: %lx\n", + kvaddr); + /* + * During vm_init() initialization, print a warning message. + */ + error(WARNING, + "cannot translate vmemmap kernel virtual addresses:\n" + " commands requiring page structure contents" + " will fail\n\n"); + + return FALSE; + } - /* - * During runtime, just fail the command. - */ - if (vt->flags & VM_INIT) - error(FATAL, "cannot translate vmemmap address: %lx\n", - kvaddr); + ms = machdep->machspec; - /* - * During vm_init() initialization, print a warning message. - */ - error(WARNING, - "cannot translate vmemmap kernel virtual addresses:\n" - " commands requiring page structure contents will fail\n\n"); + for (i = 0; i < ms->vmemmap_cnt; i++) { + if ((kvaddr >= ms->vmemmap_list[i].virt) && + (kvaddr < (ms->vmemmap_list[i].virt + ms->vmemmap_psize))) { + offset = kvaddr - ms->vmemmap_list[i].virt; + *paddr = ms->vmemmap_list[i].phys + offset; + return TRUE; + } + } return FALSE; } @@ -742,7 +874,7 @@ ppc64_processor_speed(void) { ulong res, value, ppc_md, md_setup_res; - ulong we_have_of, prep_setup_res; + ulong prep_setup_res; ulong node, type, name, properties; char str_buf[32]; uint len; @@ -751,22 +883,7 @@ if (machdep->mhz) return(machdep->mhz); - /* first, check if the have_of variable a) exists, and b) is TRUE */ - if(symbol_exists("have_of")) { - get_symbol_data("have_of", sizeof(void *), &we_have_of); - } else { - we_have_of = 0; - } - - if(we_have_of) { - /* we have a machine with open firmware, so search the OF nodes - * for cpu nodes. - * Too bad we can't call kernel helper functions here :) - */ - - if(!symbol_exists("allnodes")) - return (machdep->mhz = 0); - + if(symbol_exists("allnodes")) { get_symbol_data("allnodes", sizeof(void *), &node); while(node) { readmem(node+OFFSET(device_node_type), @@ -842,54 +959,54 @@ } if(!properties) { /* didn't find the cpu speed for some reason */ - mhz = 0; + return (machdep->mhz = 0); } } - } else { - /* for machines w/o OF */ - /* untested, but in theory this should work on prep machines */ + } - if (symbol_exists("res")) { - get_symbol_data("res", sizeof(void *), &res); + /* for machines w/o OF */ + /* untested, but in theory this should work on prep machines */ - if (symbol_exists("prep_setup_residual")) { - get_symbol_data("prep_setup_residual", - sizeof(void *), &prep_setup_res); - get_symbol_data("ppc_md", sizeof(void *), - &ppc_md); - readmem(ppc_md + - OFFSET(machdep_calls_setup_residual), - KVADDR, &md_setup_res, - sizeof(ulong), "ppc_md setup_residual", - FAULT_ON_ERROR); - - if(prep_setup_res == md_setup_res) { - /* PREP machine */ - readmem(res+ - OFFSET(RESIDUAL_VitalProductData)+ - OFFSET(VPD_ProcessorHz), - KVADDR, &mhz, sizeof(ulong), - "res VitalProductData", - FAULT_ON_ERROR); + if (symbol_exists("res") && !mhz) { + get_symbol_data("res", sizeof(void *), &res); - mhz = (mhz > 1024) ? mhz >> 20 : mhz; - } - } + if (symbol_exists("prep_setup_residual")) { + get_symbol_data("prep_setup_residual", + sizeof(void *), &prep_setup_res); + get_symbol_data("ppc_md", sizeof(void *), + &ppc_md); + readmem(ppc_md + + OFFSET(machdep_calls_setup_residual), + KVADDR, &md_setup_res, + sizeof(ulong), "ppc_md setup_residual", + FAULT_ON_ERROR); - if(!mhz) { - /* everything else seems to do this the same way... */ - readmem(res + - OFFSET(bd_info_bi_intfreq), - KVADDR, &mhz, sizeof(ulong), - "bd_info bi_intfreq", FAULT_ON_ERROR); + if(prep_setup_res == md_setup_res) { + /* PREP machine */ + readmem(res+ + OFFSET(RESIDUAL_VitalProductData)+ + OFFSET(VPD_ProcessorHz), + KVADDR, &mhz, sizeof(ulong), + "res VitalProductData", + FAULT_ON_ERROR); - mhz /= 1000000; - } - } - /* else...well, we don't have OF, or a residual structure, so - * just print unknown MHz - */ - } + mhz = (mhz > 1024) ? mhz >> 20 : mhz; + } + } + + if(!mhz) { + /* everything else seems to do this the same way... */ + readmem(res + + OFFSET(bd_info_bi_intfreq), + KVADDR, &mhz, sizeof(ulong), + "bd_info bi_intfreq", FAULT_ON_ERROR); + + mhz /= 1000000; + } + } + /* else...well, we don't have OF, or a residual structure, so + * just print unknown MHz + */ return (machdep->mhz = (ulong)mhz); } @@ -2215,7 +2332,7 @@ fprintf(fp, " MACHINE TYPE: %s\n", uts->machine); fprintf(fp, " MEMORY SIZE: %s\n", get_memory_size(buf)); - fprintf(fp, " CPUS: %d\n", kt->cpus); + fprintf(fp, " CPUS: %d\n", get_cpus_to_display()); fprintf(fp, " PROCESSOR SPEED: "); if ((mhz = machdep->processor_speed())) fprintf(fp, "%ld Mhz\n", mhz); --- crash-5.0.1/x86_64.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/x86_64.c 2010-03-09 14:26:21.000000000 -0500 @@ -80,6 +80,7 @@ static void parse_cmdline_args(void); static void x86_64_clear_machdep_cache(void); static void x86_64_irq_eframe_link_init(void); +static void x86_64_framepointer_init(void); static int x86_64_xendump_p2m_create(struct xendump_data *); static char *x86_64_xendump_load_page(ulong, struct xendump_data *); static int x86_64_xendump_page_index(ulong, struct xendump_data *); @@ -94,7 +95,8 @@ static ulong x86_64_get_stacktop_hyper(ulong); static int x86_64_framesize_cache_resize(void); static int x86_64_framesize_cache_func(int, ulong, int *, int); -static int x86_64_get_framesize(struct bt_info *, ulong); +static ulong x86_64_get_framepointer(struct bt_info *, ulong); +static int x86_64_get_framesize(struct bt_info *, ulong, ulong); static void x86_64_framesize_debug(struct bt_info *); static void x86_64_get_active_set(void); @@ -388,6 +390,7 @@ MEMBER_OFFSET("cpu_user_regs", "cs") - sizeof(ulong); } x86_64_irq_eframe_link_init(); + x86_64_framepointer_init(); break; case POST_VM: @@ -436,6 +439,8 @@ fprintf(fp, "%sPHYS_BASE", others++ ? "|" : ""); if (machdep->flags & FRAMESIZE_DEBUG) fprintf(fp, "%sFRAMESIZE_DEBUG", others++ ? "|" : ""); + if (machdep->flags & FRAMEPOINTER) + fprintf(fp, "%sFRAMEPOINTER", others++ ? "|" : ""); fprintf(fp, ")\n"); fprintf(fp, " kvbase: %lx\n", machdep->kvbase); @@ -2668,7 +2673,7 @@ bt, ofp); rsp += SIZE(pt_regs); /* guaranteed kernel mode */ if (bt->eframe_ip && ((framesize = x86_64_get_framesize(bt, - bt->eframe_ip)) >= 0)) + bt->eframe_ip, rsp)) >= 0)) rsp += framesize; level++; irq_eframe = 0; @@ -2694,7 +2699,7 @@ case BACKTRACE_ENTRY_DISPLAYED: level++; if ((framesize = x86_64_get_framesize(bt, - bt->eframe_ip ? bt->eframe_ip : *up)) >= 0) { + bt->eframe_ip ? bt->eframe_ip : *up, rsp)) >= 0) { rsp += framesize; i += framesize/sizeof(ulong); } @@ -2739,7 +2744,7 @@ bt->flags &= ~(BT_START|BT_SAVE_EFRAME_IP|BT_FRAMESIZE_DISABLE); level++; - if ((framesize = x86_64_get_framesize(bt, bt->instptr)) >= 0) + if ((framesize = x86_64_get_framesize(bt, bt->instptr, rsp)) >= 0) rsp += framesize; } } @@ -2787,7 +2792,7 @@ case BACKTRACE_ENTRY_DISPLAYED: level++; if ((framesize = x86_64_get_framesize(bt, - bt->eframe_ip ? bt->eframe_ip : *up)) >= 0) { + bt->eframe_ip ? bt->eframe_ip : *up, rsp)) >= 0) { rsp += framesize; i += framesize/sizeof(ulong); } @@ -2898,7 +2903,7 @@ rsp += SIZE(pt_regs); irq_eframe = 0; if (bt->eframe_ip && ((framesize = x86_64_get_framesize(bt, - bt->eframe_ip)) >= 0)) + bt->eframe_ip, rsp)) >= 0)) rsp += framesize; } level++; @@ -2978,7 +2983,7 @@ case BACKTRACE_ENTRY_DISPLAYED: level++; if ((framesize = x86_64_get_framesize(bt, - bt->eframe_ip ? bt->eframe_ip : *up)) >= 0) { + bt->eframe_ip ? bt->eframe_ip : *up, rsp)) >= 0) { rsp += framesize; i += framesize/sizeof(ulong); } @@ -4504,6 +4509,7 @@ "E820_RESERVED", "E820_ACPI", "E820_NVS", + "E820_UNUSABLE", }; static void @@ -4532,8 +4538,11 @@ addr = ULONGLONG(e820entry_ptr + OFFSET(e820entry_addr)); size = ULONGLONG(e820entry_ptr + OFFSET(e820entry_size)); type = UINT(e820entry_ptr + OFFSET(e820entry_type)); - fprintf(fp, "%016llx - %016llx %s\n", addr, addr+size, - e820type[type]); + fprintf(fp, "%016llx - %016llx ", addr, addr+size); + if (type >= (sizeof(e820type)/sizeof(char *))) + fprintf(fp, "type %d\n", type); + else + fprintf(fp, "%s\n", e820type[type]); } } @@ -4775,6 +4784,31 @@ machdep->machspec->last_upml_read = 0; } +#define PUSH_RBP_MOV_RSP_RBP 0xe5894855 + +static void +x86_64_framepointer_init(void) +{ + unsigned int push_rbp_mov_rsp_rbp; + int i, check; + char *checkfuncs[] = {"sys_open", "sys_fork", "sys_read"}; + + if (pc->flags & KERNEL_DEBUG_QUERY) + return; + + for (i = check = 0; i < 3; i++) { + if (!readmem(symbol_value(checkfuncs[i]), KVADDR, + &push_rbp_mov_rsp_rbp, sizeof(uint), + "framepointer check", RETURN_ON_ERROR)) + return; + if (push_rbp_mov_rsp_rbp == 0xe5894855) + check++; + } + + if (check == 3) + machdep->flags |= FRAMEPOINTER; +} + static void x86_64_irq_eframe_link_init(void) { @@ -6122,20 +6156,51 @@ return TRUE; } +ulong +x86_64_get_framepointer(struct bt_info *bt, ulong rsp) +{ + ulong stackptr, framepointer, retaddr; + + framepointer = 0; + stackptr = rsp - sizeof(ulong); + + if (!INSTACK(stackptr, bt)) + return 0; + + if (!readmem(stackptr, KVADDR, &framepointer, + sizeof(ulong), "framepointer", RETURN_ON_ERROR|QUIET)) + return 0; + + if (!INSTACK(framepointer, bt)) + return 0; + + if (framepointer <= (rsp+sizeof(ulong))) + return 0; + + if (!readmem(framepointer + sizeof(ulong), KVADDR, &retaddr, + sizeof(ulong), "return address", RETURN_ON_ERROR|QUIET)) + return 0; + + if (!is_kernel_text(retaddr)) + return 0; + + return framepointer; +} + #define BT_FRAMESIZE_IGNORE_MASK \ (BT_OLD_BACK_TRACE|BT_TEXT_SYMBOLS|BT_TEXT_SYMBOLS_ALL|BT_FRAMESIZE_DISABLE) static int -x86_64_get_framesize(struct bt_info *bt, ulong textaddr) +x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp) { - int c, framesize, instr, arg; + int c, framesize, instr, arg, max; struct syment *sp; long max_instructions; ulong offset; char buf[BUFSIZE]; char buf2[BUFSIZE]; char *arglist[MAXARGS]; - ulong locking_func, textaddr_save, current; + ulong locking_func, textaddr_save, current, framepointer; char *p1, *p2; int reterror; int arg_exists; @@ -6178,7 +6243,26 @@ } else textaddr_save = 0; - framesize = 0; + if ((machdep->flags & FRAMEPOINTER) && + rsp && !exception && !textaddr_save) { + framepointer = x86_64_get_framepointer(bt, rsp); + if (CRASHDEBUG(3)) { + if (framepointer) + fprintf(fp, + " rsp: %lx framepointer: %lx -> %ld\n", + rsp, framepointer, framepointer - rsp); + else + fprintf(fp, + " rsp: %lx framepointer: (unknown)\n", rsp); + } + if (framepointer) { + framesize = framepointer - rsp; + return (x86_64_framesize_cache_func(FRAMESIZE_ENTER, + textaddr, &framesize, 0)); + } + } + + framesize = max = 0; max_instructions = textaddr - sp->value; instr = arg = -1; @@ -6198,7 +6282,7 @@ strcpy(buf2, buf); if (CRASHDEBUG(3)) - fprintf(pc->saved_fp, buf2); + fprintf(fp, buf2); c = parse_line(buf, arglist); @@ -6237,12 +6321,15 @@ if (STRNEQ(arglist[instr], "push")) { framesize += 8; if (CRASHDEBUG(2) || (bt->flags & BT_FRAMESIZE_DEBUG)) - fprintf(pc->saved_fp, "%s\t[framesize: %d]\n", + fprintf(fp, "%s\t[framesize: %d]\n", strip_linefeeds(buf2), framesize); - } else if (STRNEQ(arglist[instr], "pop")) { - framesize -= 8; + max = framesize; + } else if (STRNEQ(arglist[instr], "pop") || + STRNEQ(arglist[instr], "leaveq")) { + if (framesize > 0) + framesize -= 8; if (CRASHDEBUG(2) || (bt->flags & BT_FRAMESIZE_DEBUG)) - fprintf(pc->saved_fp, "%s\t[framesize: %d]\n", + fprintf(fp, "%s\t[framesize: %d]\n", strip_linefeeds(buf2), framesize); } else if (arg_exists && STRNEQ(arglist[instr], "add") && (p1 = strstr(arglist[arg], ",%rsp"))) { @@ -6252,9 +6339,10 @@ offset = htol(p2+1, RETURN_ON_ERROR, &reterror); if (reterror) continue; - framesize -= offset; + if (framesize > 0) + framesize -= offset; if (CRASHDEBUG(2) || (bt->flags & BT_FRAMESIZE_DEBUG)) - fprintf(pc->saved_fp, "%s\t[framesize: %d]\n", + fprintf(fp, "%s\t[framesize: %d]\n", strip_linefeeds(buf2), framesize); } else if (arg_exists && STRNEQ(arglist[instr], "sub") && (p1 = strstr(arglist[arg], ",%rsp"))) { @@ -6265,14 +6353,22 @@ if (reterror) continue; framesize += offset; + max = framesize; if (CRASHDEBUG(2) || (bt->flags & BT_FRAMESIZE_DEBUG)) - fprintf(pc->saved_fp, "%s\t[framesize: %d]\n", + fprintf(fp, "%s\t[framesize: %d]\n", strip_linefeeds(buf2), framesize); + } else if (STRNEQ(arglist[instr], "retq")) { + if (!exception) { + framesize = max; + if (CRASHDEBUG(2) || (bt->flags & BT_FRAMESIZE_DEBUG)) + fprintf(fp, "%s\t[framesize restored to: %d]\n", + strip_linefeeds(buf2), max); + } } else if (STRNEQ(arglist[instr], "retq_NOT_CHECKED")) { bt->flags |= BT_FRAMESIZE_DISABLE; framesize = -1; if (CRASHDEBUG(2) || (bt->flags & BT_FRAMESIZE_DEBUG)) - fprintf(pc->saved_fp, "%s\t[framesize: DISABLED]\n", + fprintf(fp, "%s\t[framesize: DISABLED]\n", strip_linefeeds(buf2)); break; } @@ -6305,16 +6401,34 @@ framesize = -1; x86_64_framesize_cache_func(FRAMESIZE_ENTER, bt->hp->eip, &framesize, exception); - } else /* clear all entries */ + } else { /* clear all entries */ BZERO(&x86_64_framesize_cache[0], sizeof(struct framesize_cache)*framesize_cache_entries); + fprintf(fp, "framesize cache cleared\n"); + } break; case -1: if (!bt->hp->eip) error(INFO, "x86_64_framesize_debug: ignoring command\n"); else - x86_64_get_framesize(bt, bt->hp->eip); + x86_64_get_framesize(bt, bt->hp->eip, 0); + break; + + case -3: + machdep->flags |= FRAMEPOINTER; + BZERO(&x86_64_framesize_cache[0], + sizeof(struct framesize_cache)*framesize_cache_entries); + fprintf(fp, + "framesize cache cleared and FRAMEPOINTER turned ON\n"); + break; + + case -4: + machdep->flags &= ~FRAMEPOINTER; + BZERO(&x86_64_framesize_cache[0], + sizeof(struct framesize_cache)*framesize_cache_entries); + fprintf(fp, + "framesize cache cleared and FRAMEPOINTER turned OFF\n"); break; default: --- crash-5.0.1/symbols.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/symbols.c 2010-03-19 11:56:41.000000000 -0400 @@ -33,6 +33,7 @@ static void check_for_dups(struct load_module *); static int symbol_name_count(char *); static struct syment *symbol_search_next(char *, struct syment *); +static struct syment *kallsyms_module_symbol(struct load_module *, symbol_info *); static void store_load_module_symbols \ (bfd *, int, void *, long, uint, ulong, char *); static int load_module_index(struct syment *); @@ -2127,6 +2128,8 @@ return -1; if (STRNEQ(s2->name, "__insmod")) return 1; + if (STRNEQ(s2->name, "_MODULE_START_")) + return 1; } return (s1->value < s2->value ? -1 : @@ -7467,6 +7470,10 @@ SIZE(tss_struct)); fprintf(fp, " task_struct_start_time: %ld\n", SIZE(task_struct_start_time)); + fprintf(fp, " task_struct_utime: %ld\n", + SIZE(task_struct_utime)); + fprintf(fp, " task_struct_stime: %ld\n", + SIZE(task_struct_stime)); fprintf(fp, " cputime_t: %ld\n", SIZE(cputime_t)); fprintf(fp, " mem_section: %ld\n", @@ -8320,7 +8327,7 @@ FREEBUF(req->buf); sprintf(buf, "set complaints 0"); - gdb_pass_through(buf, NULL, 0); + gdb_pass_through(buf, NULL, GNU_RETURN_ON_ERROR); return(!(req->flags & GNU_COMMAND_FAILED)); } @@ -8547,7 +8554,7 @@ FREEBUF(req->buf); sprintf(buf, "set complaints 0"); - gdb_pass_through(buf, NULL, 0); + gdb_pass_through(buf, NULL, GNU_RETURN_ON_ERROR); return(!(req->flags & GNU_COMMAND_FAILED)); } @@ -8579,6 +8586,47 @@ sp->value, sp->name)); } +/* + * Return the syment of a kallsyms-generated module symbol. + */ +static struct syment * +kallsyms_module_symbol(struct load_module *lm, symbol_info *syminfo) +{ + struct syment *sp, *spx; + int cnt; + + if (!(lm->mod_flags & MOD_KALLSYMS)) + return NULL; + + sp = NULL; + cnt = 0; + for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++) { + if (!STREQ(spx->name, syminfo->name)) + continue; + if (spx->cnt) { + cnt++; + continue; + } + + spx->cnt++; + sp = spx; + break; + } + + if (CRASHDEBUG(2)) { + if (cnt) + fprintf(fp, "kallsyms [%s] %s: multiply defined\n", + lm->mod_name, syminfo->name); + if (sp) + fprintf(fp, "kallsyms [%s] %s: %lx\n", + lm->mod_name, syminfo->name, sp->value); + else + fprintf(fp, "kallsyms [%s] %s: NOT FOUND\n", + lm->mod_name, syminfo->name); + } + + return sp; +} /* * Replace the externally-defined module symbols found in store_load_modules() @@ -8656,6 +8704,8 @@ lm->mod_rodata_start = lm->mod_bss_start = 0; lm->mod_load_symcnt = 0; lm->mod_sections = 0; + for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++) + spx->cnt = 0; sp = lm->mod_load_symtable; if (!(lm->mod_section_data = (struct mod_section_data *) @@ -8762,11 +8812,16 @@ if ((st->flags & INSMOD_BUILTIN) && (STREQ(name, "init_module") || - STREQ(name, "cleanup_module"))) { - found = 0; + STREQ(name, "cleanup_module"))) + found = FALSE; + else if (syminfo.name[0] == '.') + found = FALSE; + else if ((spx = kallsyms_module_symbol(lm, &syminfo))) { + syminfo.value = spx->value; + found = TRUE; } else { syminfo.value += lm->mod_section_data[i].offset + lm->mod_base; - found = 1; + found = TRUE; } } } --- crash-5.0.1/cmdline.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/cmdline.c 2010-03-10 11:59:33.000000000 -0500 @@ -1056,8 +1056,10 @@ } if (pc->flags & TTY) { - if ((fd = open("/dev/tty", O_RDONLY)) < 0) - error(FATAL, "/dev/tty: %s\n", strerror(errno)); + if ((fd = open("/dev/tty", O_RDONLY)) < 0) { + console("/dev/tty: %s\n", strerror(errno)); + clean_exit(1); + } if (tcsetattr(fd, TCSANOW, &pc->termios_orig) == -1) error(FATAL, "tcsetattr /dev/tty: %s\n", --- crash-5.0.1/lkcd_x86_trace.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/lkcd_x86_trace.c 2010-03-15 15:51:57.000000000 -0400 @@ -1533,8 +1533,15 @@ pc = sp1->value + offset; flag = EX_FRAME; } else { - curframe->error = KLE_BAD_RA; - flag = 0; + if (!XEN_HYPER_MODE() && + !is_kernel_thread(bt->task) && + (bt->stacktop == machdep->get_stacktop(bt->task)) && + (((ulong)(bp+4) + SIZE(pt_regs)) > bt->stacktop)) + flag = INCOMPLETE_EX_FRAME; + else { + curframe->error = KLE_BAD_RA; + flag = 0; + } } #else curframe->error = KLE_BAD_RA; @@ -1899,6 +1906,14 @@ print_eframe(ofp, pt); } #ifdef REDHAT + if (CRASHDEBUG(1) && (frmp->flag == INCOMPLETE_EX_FRAME)) { + fprintf(ofp, " INCOMPLETE EXCEPTION FRAME:\n"); + fprintf(ofp, + " user stacktop: %lx frame #%d: %lx (+pt_regs: %lx)\n", + bt->stacktop, frmp->level, (ulong)frmp->fp, + (ulong)frmp->fp + SIZE(pt_regs)); + } + if (trace->bt->flags & BT_FULL) { fprintf(ofp, " [RA: %x SP: %x FP: %x " "SIZE: %d]\n", frmp->ra, frmp->sp, --- crash-5.0.1/netdump.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/netdump.c 2010-02-23 17:20:17.000000000 -0500 @@ -481,7 +481,8 @@ case KDUMP_ELF32: case KDUMP_ELF64: if (nd->num_pt_load_segments == 1) { - offset = (off_t)paddr + (off_t)nd->header_size; + offset = (off_t)paddr + (off_t)nd->header_size - + (off_t)nd->pt_load_segments[0].phys_start; break; } --- crash-5.0.1/defs.h 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/defs.h 2010-03-26 10:11:23.000000000 -0400 @@ -1607,6 +1607,8 @@ long kobj_map; long page_flags; long module_sect_attr; + long task_struct_utime; + long task_struct_stime; }; struct array_table { @@ -3717,6 +3719,7 @@ int get_cpus_present(void); int get_cpus_possible(void); int get_highest_cpu_online(void); +int get_cpus_to_display(void); int in_cpu_map(int, int); void paravirt_init(void); void print_stack_text_syms(struct bt_info *, ulong, ulong); @@ -3939,6 +3942,7 @@ #define SCHED_TEXT (0x40) #define PHYS_BASE (0x80) #define VM_XEN_RHEL4 (0x100) +#define FRAMEPOINTER (0x200) #define VM_FLAGS (VM_ORIG|VM_2_6_11|VM_XEN|VM_XEN_RHEL4) @@ -3984,6 +3988,11 @@ long result; /* Result of a system call */ }; +struct ppc64_vmemmap { + unsigned long phys; + unsigned long virt; +}; + /* * Used to store the HW interrupt stack. It is only for 2.4. */ @@ -4010,6 +4019,11 @@ uint pte_shift; uint l2_masked_bits; + + int vmemmap_cnt; + int vmemmap_psize; + ulong vmemmap_base; + struct ppc64_vmemmap *vmemmap_list; }; #define IS_LAST_L4_READ(l4) ((ulong)(l4) == machdep->machspec->last_level4_read) @@ -4027,6 +4041,7 @@ error(FATAL, "-d option is not applicable to PowerPC architecture\n") #define KSYMS_START (0x1) #define VM_ORIG (0x2) +#define VMEMMAP_AWARE (0x4) #define REGION_SHIFT (60UL) #define REGION_ID(addr) (((unsigned long)(addr)) >> REGION_SHIFT) --- crash-5.0.1/lkcd_x86_trace.h 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/lkcd_x86_trace.h 2010-03-15 15:51:54.000000000 -0400 @@ -467,6 +467,7 @@ #define EX_FRAME 0x1 /* this frame is an interrupt or exception frame, pt_regs field of sframe_t is valid in this case */ +#define INCOMPLETE_EX_FRAME 0x2 /* Stack segment structure */ --- crash-5.0.1/extensions/sial.c 2010-03-26 15:09:57.000000000 -0400 +++ crash-5.0.2/extensions/sial.c 2010-03-02 08:53:43.000000000 -0500 @@ -1,5 +1,5 @@ /* - * $Id: sial.c,v 1.9 2009/11/20 15:25:23 anderson Exp $ + * $Id: sial.c,v 1.10 2010/03/02 13:53:43 anderson Exp $ * * This file is part of lcrash, an analysis tool for Linux memory dumps. * @@ -292,6 +292,11 @@ type=0; break; + case TYPE_CODE_BOOL: + sial_parsetype("char", t, ref); + type=0; + break; + case TYPE_CODE_UNION: sial_type_mkunion(t); goto label;