linux不可屏蔽中断异常处理函数定义

  set_trap_gate(0,&divide_error);
 set_intr_gate(1,&debug);
 set_intr_gate(2,&nmi);
 set_system_intr_gate(3, &int3); /* int3-5 can be called from all */
 set_system_gate(4,&overflow);
 set_system_gate(5,&bounds);
 set_trap_gate(6,&invalid_op);
 set_trap_gate(7,&device_not_available);
 set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS);
 set_trap_gate(9,&coprocessor_segment_overrun);
 set_trap_gate(10,&invalid_TSS);
 set_trap_gate(11,&segment_not_present);
 set_trap_gate(12,&stack_segment);
 set_trap_gate(13,&general_protection);
 set_intr_gate(14,&page_fault);
 set_trap_gate(15,&spurious_interrupt_bug);
 set_trap_gate(16,&coprocessor_error);
 set_trap_gate(17,&alignment_check);
 set_trap_gate(18,&machine_check);
 set_trap_gate(19,&simd_coprocessor_error);

divide_error等20个中断处理函数的定义一直都搜索不到,让我郁闷了好几天,今天把所有的汇编文件全部加载进工程才发现原来是在arch目录下具体处理器中的entry.s文件中定义的

 

 拿个具体的中断处理函数说下:

栈是由高地址到低地址负增长的

ENTRY(divide_error)
 pushl $0   # no error code                  //错误码  在栈低 4byte
 pushl $do_divide_error                      //异常处理函数地址  4byte
 ALIGN
error_code:
 pushl %ds                                             //数据段寄存器 压入栈
 pushl %eax                                           
 xorl %eax, %eax                                  //eax清零
 pushl %ebp
 pushl %edi
 pushl %esi
 pushl %edx
 decl %eax                                             //eax = -1
 pushl %ecx
 pushl %ebx
 cld                                                         //清除方向标志
 movl %es, %ecx                                
 movl ES(%esp), %edi                     //处理函数地址存入edi
 movl ORIG_EAX(%esp), %edx      //error code存入edx
 movl %eax, ORIG_EAX(%esp)     //原错误码位置写入-1,据ulk解释是区别于0x80异常
 movl %ecx, ES(%esp)                      //es保存在距离栈顶0x20byte的位置  ES定义等于0x20
 movl $(__USER_DS), %ecx          
 movl %ecx, %ds
 movl %ecx, %es
 movl %esp,%eax                            //栈顶位置保存在eax中,    源吗中注释的: # pt_regs pointer    不知道eax和函数调用有什么关系
 call *%edi
 jmp ret_from_exception

 

在TRap.c文件中用宏定义的 do_divide error、dp_int3等异常处理函数

#define DO_ERROR(trapnr, signr, str, name) \
fastcall void do_##name(struct pt_regs * regs, long error_code) \
{ \
 if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
      == NOTIFY_STOP) \
  return; \
 do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
}

#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
fastcall void do_##name(struct pt_regs * regs, long error_code) \
{ \
 siginfo_t info; \
 info.si_signo = signr; \
 info.si_errno = 0; \
 info.si_code = sicode; \
 info.si_addr = (void __user *)siaddr; \
 if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
      == NOTIFY_STOP) \
  return; \
 do_trap(trapnr, signr, str, 0, regs, error_code, &info); \
}

#define DO_VM86_ERROR(trapnr, signr, str, name) \
fastcall void do_##name(struct pt_regs * regs, long error_code) \
{ \
 if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
      == NOTIFY_STOP) \
  return; \
 do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
}

#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
fastcall void do_##name(struct pt_regs * regs, long error_code) \
{ \
 siginfo_t info; \
 info.si_signo = signr; \
 info.si_errno = 0; \
 info.si_code = sicode; \
 info.si_addr = (void __user *)siaddr; \
 if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
      == NOTIFY_STOP) \
  return; \
 do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
}

DO_VM86_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->eip)
#ifndef CONFIG_KPROBES
DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
#endif
DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
DO_ERROR_INFO( 6, SIGILL,  "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)

 

do_page_fault的函数定义:

fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code)

c的函数参数是通过压栈传递的,所以此时栈中原来压入的寄存器等就对应了函数的参数(参数从左到右 对应 栈顶到栈低)

 

此文章为自己继续学习、背忘用,欢迎留言指正或补充我未知的。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值