kernel panic , Oops 等cpu异常的分析与定位

一、kernel panic

二、mips异常机制

三、linuxkernel 对mips异常的处理

四、kernel panic 实例分析

Kernel  panic

内核代码,相比用户层代码更难以调试,在内核程序开发上更要加倍小心和注意:有的BUG在内核或内核模块运行时会导致系统崩溃。当崩溃发生时,收集尽可能多的信息将有助于问题的解决。这就是内核OOPS诞生的目的。

OOPS会显示出CPU在崩溃时的状态,包括CPU寄存器和其它一些看起来难懂的信息。其实现代码在内核的arch\xxx\kernel\traps.c中。

在linux中对mips体系结构代码中,主要是通过异常处理的方式,在产生异常时将当前的寄存器状态,线程状态,加载的模块及函数调用信息,打印处理,为内核debug提供尽可能多的信息。

mips异常机制

图1
图2

Exception 2/3:TLB Miss Load/Write

Miss Load/Write,如果试图访问没有在MMU的TLB中映射的内存地址,会触发这个异常。在支持虚拟内存的操作系统中,这会触发内存的页面倒换,系统的Exception Handler会将所需要的内存页从虚拟内存中调入物理内存,并更新相应的TLB表项。

Exception 4/5:Address Error Load/Write

如果试图访问一个非对齐的地址,例如lw/sw指令的地址非4字节对齐,或lh/sh的地址非2字节对齐,就会触发这个异常。一般地,操作系统在Exception Handler中对这个异常的处理,是分开两次读取/写入这个地址。虽然一般的操作系统内核都处理了这个异常,最后能够完成期待的操作,但是由于会引起用户态到内核态的切换,以及异常的退出,当这样非对齐操作较多时会严重影响程序的运行效率。因此,编译器在定义局部和全局变量时,都会自动考虑到对齐的情况,而程序员在设计数据结构时,则需要对对齐做特别的斟酌。

Exception 9:Break Point

绝对断点指令。和syscall指令类似,它也是由专用指令break触发的。它指示了系统的一些异常情况,编程人员可以在某些不应当出现的异常分支里面加入这个指令,便于及早发现问题和调试。我们可以用高级语言中的assert机制来类比理解它。最常见的Break异常的子类型为0x07,它是编译器在编译除法运算时自动加入的。如果除数为0则执行一条break 0x07指令。这样,当出现被0除的情况时,系统就会抛出一个异常,并执行Coredump,以便于程序员定位除0错误的根因。

内核中的BUG()函数使用break指指令产生断点异常

Mips 通用寄存器定义

图3

Linux kernel 对mips异常的处理

/arch/mips/kernel/trap.c

/* 异常向量初始化 */
void __init trap_init(void)
/* 设置异常向量 */
void *set_except_vector(int n, void *addr)

异常向量的处理函数:

TLBL/TLBS:

do_page_fault()
{
        printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at ""virtual address %0*lx, epc ==                      %0*lx, ra == %0*lx\n",raw_smp_processor_id(), field, address, field, regs->cp0_epc,      field,  regs-                    >regs[31]);
        die("Oops", regs);

ADEL/ADES

Arch/mips/unaligned.c
do_ade(struct pt_regs *regs)
 {     …
       sigbus:
       die_if_kernel("Kernel unaligned instruction access", regs);
       force_sig(SIGBUS, current);
        …
}

BP

Arch/mips/kernel/trap.c
do_bp(struct pt_regs *regs)
 {
     do_trap_or_bp(regs, bcode, "Break");
}
do_trap_or_bp()
 {
     case BRK_BUG:
     die_if_kernel("Kernel bug detected", regs);
     force_sig(SIGTRAP, current);
      break;
}

die_if_kernel

 static inline void die_if_kernel(const char *str, const struct pt_regs *regs)
 {         
       if (unlikely(!user_mode(regs)))
                    die(str, regs);

}

die()

图4

show_register

图5

kernel panic 实例分析

epc:产生异常时的PC指针的值

ra:子程序的返回地址

cp0 cause

BadVA

我们重点看下epc的分析过程,工具链中提供了一系列的工具可以用于二进制的文件的分析,通过这些工具的使用我们可以定位到产生异常的代码:

内核需要开启CFG_KALLSYM,在产生异常时,能够打印出对应的函数及相应的偏移。函数地址加上偏移就是对应的汇编指令地址。

由于EPC和堆栈中的函数地址信息都是装载之后的地址,所以可以使用objdump -S 将相应的.o文件反汇编获取到函数在编译时的静态地址,从而确定函数地址。

addr2line 命令可以从.o文件中通过指令在代码段中的偏移来确定对应的C程序所在的行(需要在gcc编译时加上-g选项)。

实例(实际信息比这多,当前截取一部分):

图6

我们看到当前epc指针指向的地址为:xxx_state_context+0xb0/0x5624(偏移为0xb0),使用上面步骤:

1)反汇编命令:你的编译工具链路径/objdump -S 你的内核vmlinx或模块.ko >dump.txt

2)获取函数地址:在dump.txt中查找xxx_state_context,找到该函数地址,假如为00000034<xxx_state_context>

3)获取pc指针地址:00000034+0xb0=0x000000e4

4)定位到具体函数某一行,命令:

你的编译工具链路径/addr2line 0x000000e4 -e 你的内核vmlinx或模块.ko -f xxx_state_context

后续

1)找到产生异常的代码仅仅只是开始,因为产生异常的原因有很多,kernel panic打印处理的系统信息能提供的仅仅是当前的一些状态,更具体的分析需要结合代码进行分析。

2)假如编译工具链中有gdb的话,可以更快捷的定位到具体代码,执行命令:

#你的编译工具链gdb路径/gdb 你的内核vmlinx或模块.ko

(gdb) b *xxx_state_context+0xb0

该指令将同样可以定位到具体文件的某一行,有兴趣的朋友可以试一下。

3)该文章提到的具体命令用法,请自行查阅文档。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,711评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,079评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,194评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,089评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,197评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,306评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,338评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,119评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,541评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,846评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,014评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,694评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,322评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,026评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,257评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,863评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,895评论 2 351

推荐阅读更多精彩内容