[Crash-utility] invalid regs display in bt

Dave Anderson anderson at redhat.com
Thu Sep 27 19:03:24 UTC 2007


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









More information about the Crash-utility mailing list