Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2036738
  • 博文数量: 610
  • 博客积分: 11499
  • 博客等级: 上将
  • 技术积分: 5511
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-12 19:27
文章分类

全部博文(610)

文章存档

2016年(5)

2015年(18)

2014年(12)

2013年(16)

2012年(297)

2011年(45)

2010年(37)

2009年(79)

2008年(101)

分类:

2012-07-27 10:49:29

之前做了向内核添加系统调用的实验,突发奇想,想能不能添加异常处理程序,发现其实也比较简单,和添加系统调用差不多,下面是我做的实验的基本步骤, 与大家分享:

=============================================================

  异常向量号范围:0-31,其中0-19已经被使用,20-31被保留

任务:为异常向量号22添加异常处理程序,初步设置为与int3有相同的功能

1、编辑/usr/src/linux-source-3.2.0/arch/x86/kernel/traps.c
void __init early_trap_init(void)
{
        set_intr_gate_ist(1, &debug, DEBUG_STACK);
        /* int3 can be called from all */
        set_system_intr_gate_ist(3, &int3, DEBUG_STACK);
        set_system_intr_gate_ist(22, &int22, DEBUG_STACK);  //新增系统中断门, 不能设置为陷阱门和任务门了
        set_intr_gate(14, &page_fault);
        load_idt(&idt_descr);
}
 
2、编辑/usr/src/linux-source-3.2.0/arch/x86/include/asm/traps.h
    ..........
     asmlinkage void int3(void);
     asmlinkage void int22(void);          //新增声明

3、编辑/usr/src/linux-source-3.2.0/arch/x86/kernel/entry_32.s
ENTRY(int3)
       ......
END(int3)
//仿照int3,新增int22 异常处理程序
ENTRY(int22)
        RING0_INT_FRAME
        pushl_cfi $-1                   # mark this as an int
        SAVE_ALL
        TRACE_IRQS_OFF
        xorl %edx,%edx          # zero error code
        movl %esp,%eax          # pt_regs pointer,即SAVE_ALL保存的寄存器组指针
        call do_int22
        jmp ret_from_exception
        CFI_ENDPROC
END(int22)

 

4、编辑/usr/src/linux-source-3.2.0/arch/x86/kernel/traps.c
//仿照do_int3,新增do_int22 异常服务程序
          //这里完全借鉴了int3的处理逻辑
dotraplinkage void __kprobes do_int22(struct pt_regs *regs, long error_code)
{
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
        if (kgdb_ll_trap(DIE_INT3, "int22", regs, error_code, 3, SIGTRAP)
                        == NOTIFY_STOP)
                return;
#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
#ifdef CONFIG_KPROBES
        if (notify_die(DIE_INT3, "int22", regs, error_code, 3, SIGTRAP)
                        == NOTIFY_STOP)
                return;
#else
        if (notify_die(DIE_TRAP, "int22", regs, error_code, 3, SIGTRAP)
                        == NOTIFY_STOP)
                return;
#endif

        preempt_conditional_sti(regs);
        do_trap(22, SIGTRAP, "int22", regs, error_code, NULL);  //先借用,以后再修改
        preempt_conditional_cli(regs);
}

5、编写应用程序测试
================测试程序 1=================
int
main(){
        asm("int $22");    //插入一条 int $22 汇编指令
}
编译运行结果:Trace/breakpoint trap

================测试程序 2=================
#include
#include
void sigtrap_handler(int signo){
        printf("catch SITTRAP, signo = %d\n",signo);
}
int
main(){
        signal(SIGTRAP,sigtrap_handler);
        asm("int $22");
}
编译运行结果:catch SITTRAP, signo = 5
阅读(457) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~