linux 内核die函数,内核异常分析方法

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

内核异常分析方法

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

-------------------------------------------------------------

1 总体方法

-------------------------------------------------------------

1.1 确定出错函数地址

1.2 确定出错地址在函数中的偏移

-------------------------------------------------------------

2 oops信息(由die函数产生)

-------------------------------------------------------------

/* This is gone through when something in the kernel

* has done something bad and is about to be terminated.

*/

void die(const char * str, struct pt_regs * regs, long err)

{

static struct {

spinlock_t lock;

u32 lock_owner;

int lock_owner_depth;

} die = {

.lock =     SPIN_LOCK_UNLOCKED,

.lock_owner =    -1,

.lock_owner_depth = 0

};

static int die_counter;

unsigned long flags;

oops_enter();

if (die.lock_owner != raw_smp_processor_id()) {

console_verbose();

spin_lock_irqsave(&die.lock, flags);

die.lock_owner = smp_processor_id();

die.lock_owner_depth = 0;

bust_spinlocks(1);

}

else

local_save_flags(flags);

if (++die.lock_owner_depth < 3) {

int nl = 0;

unsigned long esp;

unsigned short ss;

handle_BUG(regs); //对应oops信息的第一二行,指出出错位置所在的文件,以及行号,有了这个信息,就可以直接找到c源代码

printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);//这里的str对应invalid opcode,是在调用die时传入的值,表示错误类型,err表示这类型具体的错误号,die_counter表示调用die的次数

#ifdef CONFIG_PREEMPT

printk(KERN_EMERG "PREEMPT "); //抢占版本内核

nl = 1;

#endif

#ifdef CONFIG_SMP

if (!nl)

printk(KERN_EMERG);

printk("SMP ");          //多核版本内核

nl = 1;

#endif

#ifdef CONFIG_DEBUG_PAGEALLOC

if (!nl)

printk(KERN_EMERG);

printk("DEBUG_PAGEALLOC");

nl = 1;

#endif

if (nl)

printk("\n");

#ifdef CONFIG_SYSFS

printk(KERN_ALERT "last sysfs file: %s\n", last_sysfs_file);

#endif

if (notify_die(DIE_OOPS, str, regs, err,

current->thread.trap_no, SIGSEGV) !=

NOTIFY_STOP) {

show_registers(regs); //打印了图中的大部分信息

/* Executive summary in case the oops scrolled away */

esp = (unsigned long) (&regs->esp);

savesegment(ss, ss);

if (user_mode(regs)) {

esp = regs->esp;

ss = regs->xss & 0xffff;

}

printk(KERN_EMERG "EIP: [] ", regs->eip);

print_symbol("%s", regs->eip);

printk(" SS:ESP %04x:%08lx\n", ss, esp);  //这三行打印最后一行

}

else

regs = NULL;

} else

printk(KERN_EMERG "Recursive die() failure, output suppressed\n");

bust_spinlocks(0);

die.lock_owner = -1;

spin_unlock_irqrestore(&die.lock, flags);

if (!regs)

return;

if (kexec_should_crash(current))

crash_kexec(regs);

if (in_interrupt())

panic("Fatal exception in interrupt");

if (panic_on_oops)

panic("Fatal exception");

oops_exit();

do_exit(SIGSEGV);

}

void show_registers(struct pt_regs *regs

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值