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.
Yeah, that thread was more a discussion on how the pt_regs
actually get saved on the kernel stack in entry.S.
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).
Right -- that file was originally adapted from the LKCD lcrash
sources, and I was simply trying to give credit where credit
was due...
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).
Yeah, I'll probably do that, and the changes you made in the
non-REDHAT section of lkcd_x86_trace.c:print_eframe() are
irrelevant since they don't get compiled. But it looks
good -- I appreciate the leg-work you've done here.
Thanks,
Dave
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(a)redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility