Dave Anderson wrote:
Richard J Moore wrote:
>
>
> crash-utility-bounces(a)redhat.com wrote on 27/09/2007 17:13:45:
>
> > Richard J Moore wrote:
> > >
> > > crash-utility-bounces(a)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...
Yeah -- that's exactly it, before jumping to error_code,
it pushes the address of the fault handler onto the stack,
essentially into the "pt_regs.xes" location:
> ENTRY(page_fault)
> pushl $do_page_fault
> jmp error_code
Then it pushes the remaining pt_regs register values,
but with the pt_regs.xes still needing to be set up.
So then later after the popl of the ES value into %ecx,
it grabs the exception handler address from the pt_regs.xes
location, and puts it into %edi:
> popl %ecx
> movl ES(%esp), %edi # get the function address
and then puts the ES value from %ecx into the pt_regs location:
> movl %ecx, ES(%esp)
and later calls the handler:
> call *%edi
Dave