[Crash-utility] invalid regs display in bt

Richard J Moore richardj_moore at uk.ibm.com
Thu Sep 27 21:51:10 UTC 2007


crash-utility-bounces at redhat.com wrote on 27/09/2007 20:03:24:

> Richard J Moore wrote:
> > 
> > 
> > crash-utility-bounces at redhat.com wrote on 27/09/2007 17:13:45:
> > 
> >  > Richard J Moore wrote:
> >  > >
> >  > > crash-utility-bounces at redhat.com wrote on 27/09/2007 15:45:21:
> >  > >
> >  > >  > Richard J Moore wrote:
> >  > >  >
> >  > >  > > On looking at the code in entry.S at page_fault and the 
other
> >  > > exception
> >  > >  > > entry points I see no attempt to save regs to create a 
pt_regs 
> > struct.
> >  > >  > > The fact that do_page_fault takes pt_regs as the first arg 
is a
> >  > > hack to
> >  > >  > > get at CS:EIP and SS:ESP at the time of exception.
> >  > >  >
> >  > >  > KPROBE_ENTRY(page_fault)
> >  > >  >    RING0_EC_FRAME
> >  > >  >    pushl $do_page_fault
> >  > >  >    CFI_ADJUST_CFA_OFFSET 4
> >  > >  >    ALIGN
> >  > >  > error_code:
> >  > >  >    /* the function address is in %fs's slot on the stack */
> >  > >  >    pushl %es
> >  > >  >    CFI_ADJUST_CFA_OFFSET 4
> >  > >  >    /*CFI_REL_OFFSET es, 0*/
> >  > >  >    pushl %ds
> >  > >  >    CFI_ADJUST_CFA_OFFSET 4
> >  > >  >    /*CFI_REL_OFFSET ds, 0*/
> >  > >  >    pushl %eax
> >  > >  >    CFI_ADJUST_CFA_OFFSET 4
> >  > >  >    CFI_REL_OFFSET eax, 0
> >  > >  >    pushl %ebp
> >  > >  >    CFI_ADJUST_CFA_OFFSET 4
> >  > >  >    CFI_REL_OFFSET ebp, 0
> >  > >  >    pushl %edi
> >  > >  >    CFI_ADJUST_CFA_OFFSET 4
> >  > >  >    CFI_REL_OFFSET edi, 0
> >  > >  >    pushl %esi
> >  > >  >    CFI_ADJUST_CFA_OFFSET 4
> >  > >  >    CFI_REL_OFFSET esi, 0
> >  > >  >    pushl %edx
> >  > >  >    CFI_ADJUST_CFA_OFFSET 4
> >  > >  >    CFI_REL_OFFSET edx, 0
> >  > >  >    pushl %ecx
> >  > >  >    CFI_ADJUST_CFA_OFFSET 4
> >  > >  >    CFI_REL_OFFSET ecx, 0
> >  > >  >    pushl %ebx
> >  > >  >    CFI_ADJUST_CFA_OFFSET 4
> >  > >  >    CFI_REL_OFFSET ebx, 0
> >  > >  >    cld
> >  > >  >    pushl %fs
> >  > >  >    CFI_ADJUST_CFA_OFFSET 4
> >  > >  >    /*CFI_REL_OFFSET fs, 0*/
> >  > >  >    movl $(__KERNEL_PERCPU), %ecx
> >  > >  >    movl %ecx, %fs
> >  > >  >    UNWIND_ESPFIX_STACK
> >  > >  >    popl %ecx
> >  > >  >    CFI_ADJUST_CFA_OFFSET -4
> >  > >  >    /*CFI_REGISTER es, ecx*/
> >  > >  >    movl PT_FS(%esp), %edi      # get the function address
> >  > >  >    movl PT_ORIG_EAX(%esp), %edx   # get the error code
> >  > >  >    movl $-1, PT_ORIG_EAX(%esp)   # no syscall to restart
> >  > >  >    mov  %ecx, PT_FS(%esp)
> >  > >  >    /*CFI_REL_OFFSET fs, ES*/
> >  > >  >    movl $(__USER_DS), %ecx
> >  > >  >    movl %ecx, %ds
> >  > >  >    movl %ecx, %es
> >  > >  >    movl %esp,%eax         # pt_regs pointer
> >  > >  >    call *%edi
> >  > >  >    jmp ret_from_exception
> >  > >  >    CFI_ENDPROC
> >  > >  > KPROBE_END(page_fault)
> >  > >  >
> >  > >
> >  > > Dave, it looks like error_code: has been change relatively 
> > recently. My
> >  > > source starts:
> >  > > error_code:
> >  > >         pushl %ds
> >  > >         pushl %eax
> >  > >         xorl  %eax,%eax
> >  > >         pushl %ebp
> >  > > 
> >  > > and so on. Clearly not a valid pt_regs struct.
> >  > > The source I'm working with is from FC5. On your version of the 
kernel
> >  > > only the ERR, SS and ESP would be invalid.
> >  > > What tree is yours taken from?
> >  > >
> >  >
> >  > My example was from upstream 2.6.22-5.  RHEL5 (2.6.18-based)
> >  > is slightly different, as the "error_code:" chunk is located
> >  > in the "divide_error" entry point, but like 2.6.22-5, all of
> >  > the other exceptions jmp to it.
> >  >
> >  > But even your code is creating the remainder of the pt_regs
> >  > after the essential registers laid down by the hardware
> >  > exception mechanism, by pushing the remaining registers,
> >  > "upwards" towards the beginning of the structure:
> >  >
> >  > struct pt_regs {
> >  >          long ebx;
> >  >          long ecx;
> >  >          long edx;
> >  >          long esi;
> >  >          long edi;
> >  >          long ebp;
> >  >          long eax;
> >  >          int  xds;
> >  >          int  xes;
> >  >          long orig_eax;
> >  >          long eip;
> >  >          int  xcs;
> >  >          long eflags;
> >  >          long esp;
> >  >          int  xss;
> >  > };
> >  >
> >  > Right?
> >  >
> >  > Dave
> >  >
> > 
> > I don't think so. Am I misreading this:
> > 
> > we take a page fault at ring 0. The cpu pushes eflags, cs, eip, 
error-code
> > we enter the kernel at:
> > ENTRY(page_fault)
> >         pushl $do_page_fault
> >         jmp error_code
> > 
> > we have errror code in orig_eax
> > 
> > 
> > error_code:
> >         pushl %ds
> >         pushl %eax
> >         xorl %eax, %eax
> >         pushl %ebp
> >         pushl %edi
> >         pushl %esi
> >         pushl %edx
> >         decl %eax                        # eax = -1
> >         pushl %ecx
> >         pushl %ebx
> >         cld
> >         pushl %es
> >         UNWIND_ESPFIX_STACK
> >         popl %ecx
> >         movl ES(%esp), %edi                # get the function address
> >         movl ORIG_EAX(%esp), %edx        # get the error code
> >         movl %eax, ORIG_EAX(%esp)
> >         movl %ecx, ES(%esp)
> >         movl $(__USER_DS), %ecx
> >         movl %ecx, %ds
> >         movl %ecx, %es
> >         movl %esp,%eax                        # pt_regs pointer
> >         call *%edi
> >         jmp ret_from_exception
> > 
> > 
> > Aren't we sorting ds in the pt_regs.ES ? and therefore one register 
out?
> > 
> > Maybe I'm missing something?
> 
> This code piece does seem to change from version to version,
> but I think it gets the ES register into the proper pt_regs
> location by pushing it here:
> 
>  >         pushl %es
> 
> and then popping it into %ecx here:
> 
>  >         popl %ecx
> 
> and then later storing it in the pt_regs here:
> 
>  >         movl %ecx, ES(%esp)
> 
> I think...
> 
> Dave
> 

Everything is still one word out apart from ES. All this does (I think - 
and it is confusing code) is replace DS with ES instead of inserting ES by 
moving all the other regs, previously stored, down the stack 4 bytes then 
storing ES. I think we are shifted by one register wrt pt_regs from ebx to 
xds in the earlier versions of error_code. Certainly the later version of 
error_code from 2.6.22 is correct in terms of pt_regs. 

But even in that case, ERR is not correct ever and SS:ESP are not correct 
for kernel exceptions as formatted in bt. I guess this comes down to a 
wrong assumption on my part: that regs formatted by bt were meant to be 
the regs at time of exception rather than a verbatim formatting of 
pt_regs. The problem is we don't yet have a comprehensive register logout 
capability for fatal exceptions. I think there is a case for adding some 
additional capability to panic. Especially the saving of the control regs, 
the system selector regs, the debug regs and possibly a few MSRs 
(sysenter/exit, machine check, debugging )

Richard

> 
> 
> 
> --
> Crash-utility mailing list
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility






Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number 
741598. 
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU





-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/crash-utility/attachments/20070927/21413ddf/attachment.htm>


More information about the Crash-utility mailing list