This problem has been reported before, but the discussion on it seemed to move off track and I don't think that anyone really found the root cause. The problem is that the x86 backtrace functionality in crash is dependent upon the struct pt_regs taken from <asm/ptrace.h> at compile time. struct pt_regs changed in 2.6.20. The result of this is that if crash is compiled on 2.6.20 or later and subsequently used to look at a 2.6.19 or earlier dump, then exception frames are incorrectly displayed and backtraces stop at them. Here is an example of a 2.6.22-compiled crash displaying a trace from a RHEL5 (2.6.18) dump: crash> bt PID: 3490 TASK: f7f5a000 CPU: 0 COMMAND: "insmod" #0 [f664ddd0] crash_kexec at c0441c78 #1 [f664de14] die at c04064a4 #2 [f664de44] do_page_fault at c0605eea #3 [f664de94] error_code (via page_fault) at c0405a6f EAX: 00000000 EBX: f8dd3400 ECX: 00200082 EDX: 00200000 DS: 007b ESI: f7bbeab0 ES: 007b EDI: f7bbe800 SS: ffffe800 ESP: 00000000 EBP: f7bbead8 CS: 0060 EIP: f8dd300d ERR: ffffffff EFLAGS: 00210296 crash> Note that in the above, crash thinks that the exception frame is a user mode one and not a kernel frame. If crash was compiled on RHEL5 (2.6.18), then the trace looks like this: crash> bt PID: 3490 TASK: f7f5a000 CPU: 0 COMMAND: "insmod" #0 [f664ddd0] crash_kexec at c0441c78 #1 [f664de14] die at c04064a4 #2 [f664de44] do_page_fault at c0605eea #3 [f664de94] error_code (via page_fault) at c0405a6f EAX: 00000000 EBX: f8dd3400 ECX: 00200082 EDX: 00200000 EBP: f7bbead8 DS: 007b ESI: f7bbeab0 ES: 007b EDI: f7bbe800 CS: 0060 EIP: f8dd300d ERR: ffffffff EFLAGS: 00210296 #4 [f664dec8] function2 at f8dd300d #5 [f664dee0] sys_init_module at c043e717 #6 [f664dfb8] system_call at c0404ef8 EAX: ffffffda EBX: 0861a028 ECX: 00010144 EDX: 0861a018 DS: 007b ESI: 00000000 ES: 007b EDI: 00307ff4 SS: 007b ESP: bfe5695c EBP: bfe569a8 CS: 0073 EIP: 00d37402 ERR: 00000080 EFLAGS: 00200206 crash> A similar problem happens if crash is compiled on pre-2.6.20 and then used to analyse a 2.6.20 or later dump. Dave, I have attached a patch to this e-mail which removes the dependence upon <asm/prtrace.h> from lkcd_x86_trace.c (which is used for non-LKCD dumps as well as LKCD dumps by the way). I notice that eframe_init() in x86.c initialises several variables which correspond to the struct pt_regs so I've had to make these external for lkcd_x86_trace.c's use. I have no problem in this being reworked if you feel that these symbols really should be in defs.h (or any other rework that you think is fit, for that matter). Regards, Alan Tyson, HP.
--- crash-4.0-4.12-orig/x86.c 2007-12-12 18:48:09.000000000 +0000 +++ crash-4.0-4.12/x86.c 2007-12-17 10:43:07.000000000 +0000 @@ -1009,22 +1009,22 @@ static void x86_init_hyper(int); static ulong x86_get_stackbase_hyper(ulong); static ulong x86_get_stacktop_hyper(ulong); -static int INT_EFRAME_SS = 14; -static int INT_EFRAME_ESP = 13; -static int INT_EFRAME_EFLAGS = 12; /* CS lcall7 */ -static int INT_EFRAME_CS = 11; /* EIP lcall7 */ -static int INT_EFRAME_EIP = 10; /* EFLAGS lcall7 */ -static int INT_EFRAME_ERR = 9; -static int INT_EFRAME_ES = 8; -static int INT_EFRAME_DS = 7; -static int INT_EFRAME_EAX = 6; -static int INT_EFRAME_EBP = 5; -static int INT_EFRAME_EDI = 4; -static int INT_EFRAME_ESI = 3; -static int INT_EFRAME_EDX = 2; -static int INT_EFRAME_ECX = 1; -static int INT_EFRAME_EBX = 0; -static int INT_EFRAME_GS = -1; + int INT_EFRAME_SS = 14; + int INT_EFRAME_ESP = 13; + int INT_EFRAME_EFLAGS = 12; /* CS lcall7 */ + int INT_EFRAME_CS = 11; /* EIP lcall7 */ + int INT_EFRAME_EIP = 10; /* EFLAGS lcall7 */ + int INT_EFRAME_ERR = 9; + int INT_EFRAME_ES = 8; + int INT_EFRAME_DS = 7; + int INT_EFRAME_EAX = 6; + int INT_EFRAME_EBP = 5; + int INT_EFRAME_EDI = 4; + int INT_EFRAME_ESI = 3; + int INT_EFRAME_EDX = 2; + int INT_EFRAME_ECX = 1; + int INT_EFRAME_EBX = 0; + int INT_EFRAME_GS = -1; #define MAX_USER_EFRAME_SIZE (16) #define KERNEL_EFRAME_SIZE (INT_EFRAME_EFLAGS+1) --- crash-4.0-4.12-orig/lkcd_x86_trace.c 2007-12-12 18:48:09.000000000 +0000 +++ crash-4.0-4.12/lkcd_x86_trace.c 2007-12-17 10:49:15.000000000 +0000 @@ -54,10 +54,9 @@ static int eframe_incr(kaddr_t, char *); static int find_trace(kaddr_t, kaddr_t, kaddr_t, kaddr_t, trace_t *, int); static void dump_stack_frame(trace_t *, sframe_t *, FILE *); static void print_trace(trace_t *, int, FILE *); -struct pt_regs; -static int eframe_type(struct pt_regs *); +static int eframe_type(uaddr_t *); char *funcname_display(char *); -static void print_eframe(FILE *, struct pt_regs *); +static void print_eframe(FILE *, uaddr_t *); static void trace_banner(FILE *); static void print_kaddr(kaddr_t, FILE *, int); int do_text_list(kaddr_t, int, FILE *); @@ -1122,7 +1121,6 @@ valid_ra_function(kaddr_t ra, char *func return(0); } -#include <asm/ptrace.h> #ifndef REDHAT #include <asm/segment.h> #endif @@ -1144,52 +1142,79 @@ valid_ra_function(kaddr_t ra, char *func #define __USER_DS 0x2B #endif +extern int INT_EFRAME_SS; +extern int INT_EFRAME_ESP; +extern int INT_EFRAME_EFLAGS; +extern int INT_EFRAME_CS; +extern int INT_EFRAME_EIP; +extern int INT_EFRAME_ERR; +extern int INT_EFRAME_ES; +extern int INT_EFRAME_DS; +extern int INT_EFRAME_EAX; +extern int INT_EFRAME_EBP; +extern int INT_EFRAME_EDI; +extern int INT_EFRAME_ESI; +extern int INT_EFRAME_EDX; +extern int INT_EFRAME_ECX; +extern int INT_EFRAME_EBX; +extern int INT_EFRAME_GS; + /* * Check if the exception frame is of kernel or user type * Is checking only DS and CS values sufficient ? */ -int eframe_type(struct pt_regs *regs) + +int eframe_type(uaddr_t *int_eframe) { - if (((regs->xcs & 0xffff) == __KERNEL_CS) && - ((regs->xds & 0xffff) == __KERNEL_DS)) + short xcs = (short)int_eframe[INT_EFRAME_CS]; + short xds = (short)int_eframe[INT_EFRAME_DS]; + + if (((xcs & 0xffff) == __KERNEL_CS) && + ((xds & 0xffff) == __KERNEL_DS)) return KERNEL_EFRAME; #ifdef REDHAT - else if (((regs->xcs & 0xffff) == 0x60) && - ((regs->xds & 0xffff) == 0x68)) + else if (((xcs & 0xffff) == 0x60) && + ((xds & 0xffff) == 0x68)) return KERNEL_EFRAME; - else if (((regs->xcs & 0xffff) == 0x60) && - ((regs->xds & 0xffff) == 0x7b)) - return KERNEL_EFRAME; - else if (XEN() && ((regs->xcs & 0xffff) == 0x61) && - ((regs->xds & 0xffff) == 0x7b)) + else if (((xcs & 0xffff) == 0x60) && + ((xds & 0xffff) == 0x7b)) + return KERNEL_EFRAME; + else if (XEN() && ((xcs & 0xffff) == 0x61) && + ((xds & 0xffff) == 0x7b)) return KERNEL_EFRAME; #endif - else if (((regs->xcs & 0xffff) == __USER_CS) && - ((regs->xds & 0xffff) == __USER_DS)) + else if (((xcs & 0xffff) == __USER_CS) && + ((xds & 0xffff) == __USER_DS)) return USER_EFRAME; #ifdef REDHAT - else if (((regs->xcs & 0xffff) == 0x73) && - ((regs->xds & 0xffff) == 0x7b)) + else if (((xcs & 0xffff) == 0x73) && + ((xds & 0xffff) == 0x7b)) return USER_EFRAME; #endif return -1; } -void print_eframe(FILE *ofp, struct pt_regs *regs) +void print_eframe(FILE *ofp, uaddr_t *regs) { int type = eframe_type(regs); #ifdef REDHAT x86_dump_eframe_common(NULL, (ulong *)regs, (type == KERNEL_EFRAME)); #else - fprintf(ofp, " ebx: %08lx ecx: %08lx edx: %08lx esi: %08lx\n", - regs->ebx, regs->ecx, regs->edx, regs->esi); - fprintf(ofp, " edi: %08lx ebp: %08lx eax: %08lx ds: %04x\n", - regs->edi, regs->ebp, regs->eax, regs->xds & 0xffff); - fprintf(ofp, " es: %04x eip: %08lx cs: %04x eflags: %08lx\n", - regs->xes & 0xffff, regs->eip, regs->xcs & 0xffff, regs->eflags); + + fprintf(ofp, " ebx: %08x ecx: %08x edx: %08x esi: %08x\n", + regs[INT_EFRAME_EBX], regs[INT_EFRAME_ECX], + regs[INT_EFRAME_EDX], regs[INT_EFRAME_ESI]); + fprintf(ofp, " edi: %08x ebp: %08x eax: %08x ds: %04x\n", + regs[INT_EFRAME_EDI], regs[INT_EFRAME_EBP], + regs[INT_EFRAME_EAX], regs[INT_EFRAME_DS] & 0xffff); + fprintf(ofp, " es: %04x eip: %08x cs: %04x eflags: %08x\n", + regs[INT_EFRAME_ES] & 0xffff, regs[INT_EFRAME_EIP], + regs[INT_EFRAME_CS] & 0xffff, regs[INT_EFRAME_EFLAGS]); if (type == USER_EFRAME) - fprintf(ofp, " esp: %08lx ss: %04x\n", regs->esp, regs->xss); + fprintf(ofp, " esp: %08x ss: %04x\n", + regs[INT_EFRAME_ESP], regs[INT_EFRAME_SS]); + #endif } @@ -1350,7 +1375,7 @@ find_trace( int flag; int interrupted_system_call = FALSE; struct bt_info *bt = trace->bt; - struct pt_regs *pt; + uaddr_t *pt; #endif sbp = trace->stack[curstkidx].ptr; sbase = trace->stack[curstkidx].addr; @@ -1624,14 +1649,14 @@ find_trace( asp = (uaddr_t*)((uaddr_t)sbp + (STACK_SIZE - (saddr - sp))); curframe = alloc_sframe(trace, flags); - ra = ((struct pt_regs *)asp)->eip; - frame_type = eframe_type((struct pt_regs*)asp); + ra = asp[INT_EFRAME_EIP]; + frame_type = eframe_type(asp); UPDATE_FRAME(func_name, pc, ra, sp, bp, asp, 0, 0, (bp - sp + 4), EX_FRAME); /* prepare for next kernel frame, if present */ if (frame_type == KERNEL_EFRAME) { - pc = ((struct pt_regs *)asp)->eip; + pc = asp[INT_EFRAME_EIP]; sp = curframe->fp+4; #ifdef REDHAT bp = sp + get_framesize(pc, bt); @@ -1650,20 +1675,20 @@ find_trace( sp = curframe->fp + 4; asp = (uaddr_t*)((uaddr_t)sbp + (STACK_SIZE - (saddr - sp))); - frame_type = eframe_type((struct pt_regs*)asp); + frame_type = eframe_type(asp); if (frame_type == KERNEL_EFRAME) bp = curframe->fp+(KERNEL_EFRAME_SZ-1)*4; else bp = curframe->fp+(USER_EFRAME_SZ-1)*4; curframe = alloc_sframe(trace, flags); - ra = ((struct pt_regs *)asp)->eip; + ra = asp[INT_EFRAME_EIP]; UPDATE_FRAME(func_name, pc, ra, sp, bp + 4, asp, 0, 0, curframe->fp - curframe->sp+4, EX_FRAME); /* prepare for next kernel frame, if present */ if (frame_type == KERNEL_EFRAME) { sp = curframe->fp + 4; - pc = ((struct pt_regs *)asp)->eip; + pc = asp[INT_EFRAME_EIP]; #ifdef REDHAT bp = sp + get_framesize(pc, bt); #else @@ -1711,7 +1736,7 @@ find_trace( */ if ((bt->flags & BT_XEN_STOP_THIS_CPU) && bt->tc->mm_struct && STREQ(kl_funcname(curframe->pc), "hypervisor_callback")) { - pt = (struct pt_regs *)(curframe->asp+1); + pt = curframe->asp+1; if (eframe_type(pt) == USER_EFRAME) { if (program_context.debug >= 1) /* pc above */ error(INFO, @@ -1803,7 +1828,7 @@ print_trace(trace_t *trace, int flags, F #ifdef REDHAT kaddr_t fp = 0; kaddr_t last_fp, last_pc, next_fp, next_pc; - struct pt_regs *pt; + uaddr_t *pt; struct bt_info *bt; bt = trace->bt; @@ -1864,7 +1889,7 @@ print_trace(trace_t *trace, int flags, F fprintf(ofp, " [0x%x]\n", frmp->pc); #endif if (frmp->flag & EX_FRAME) { - pt = (struct pt_regs *)frmp->asp; + pt = frmp->asp; if (CRASHDEBUG(1)) fprintf(ofp, " EXCEPTION FRAME: %lx\n", @@ -2259,7 +2284,7 @@ do_bt_reference_check(struct bt_info *bt (sp && (bt->ref->hexval == sp->value))) bt->ref->cmdflags |= BT_REF_FOUND; if (frmp->flag & EX_FRAME) { - type = eframe_type((struct pt_regs *)frmp->asp); + type = eframe_type(frmp->asp); x86_dump_eframe_common(bt, (ulong *)frmp->asp, (type == KERNEL_EFRAME)); }
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility