linux内核剖析之traps.c

traps的主要功能:其函数被asm.s中调用打印中断信息,通过set_trap_gate设置中断向量(如:set_trap_gate(0,&divide_error);),c语言中写汇编。

寄存器变量:register定义一个寄存器变量,他可以在汇编中跟寄存器一样操作,是链接c语言和汇编的桥梁。

如:register char __res;
 

定义的die函数打印信息,其他的中断调用该函数打印中断信息:

如:void do_divide_error(long esp, long error_code)
       {
            die("divide error",esp,error_code);
       }

下面几个函数是读取寄存器数据和die函数

_inline char get_seg_byte(unsigned short segm, void *addr)
{
    register char __res;
    _asm{
    push fs
    mov ax,segm
    mov fs,ax
    mov ebx,addr
    mov al,byte ptr fs:[ebx]
    mov __res,al
    pop fs
    }
    return __res;
}

// 取段seg 中地址addr 处的一个长字(4 字节)。
_inline long
get_seg_long(unsigned short segm,long *addr) {
    register unsigned long __res;
    _asm{
        push fs
        mov ax,segm
        mov fs,ax
        mov ebx,addr
        mov eax,fs:[ebx]
        mov __res,eax
        pop fs
    }
    return __res;
}
//#define get_seg_long(seg,addr) ({ \
//register unsigned long __res; \
//__asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \
//    :"=a" (__res):"0" (seg),"m" (*(addr))); \
//__res;})

// 取fs 段寄存器的值(选择符)。
_inline unsigned short _fs() {
    register unsigned short __res;
    _asm mov ax,fs
    _asm mov __res,ax
    return __res;
}

// 该子程序用来打印出错中断的名称、出错号、调用程序的EIP、EFLAGS、ESP、fs 段寄存器值、
// 段的基址、段的长度、进程号pid、任务号、10 字节指令码。如果堆栈在用户数据段,则还
// 打印16 字节的堆栈内容。
static void die(char * str,long esp_ptr,long nr)
{
    long * esp = (long *) esp_ptr;
    int i;

    printk("%s: %04x\n\r",str,nr&0xffff);
    printk("EIP:\t%04x:%p\nEFLAGS:\t%p\nESP:\t%04x:%p\n",
        esp[1],esp[0],esp[2],esp[4],esp[3]);
    printk("fs: %04x\n",_fs());
    printk("base: %p, limit: %p\n",get_base(current->ldt[1]),get_limit(0x17));
    if (esp[4] == 0x17) {
        printk("Stack: ");
        for (i=0;i<4;i++)
            printk("%p ",get_seg_long(0x17,i+(long *)esp[3]));
        printk("\n");
    }
    str(i);
    printk("Pid: %d, process nr: %d\n\r",current->pid,0xffff & i);
    for(i=0;i<10;i++)
        printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0])));
    printk("\n\r");
    do_exit(11);        /* play segment exception */
}

猜你喜欢

转载自blog.csdn.net/wyyy2088511/article/details/108367725
今日推荐