CRASH ANALYSIS of PPC440+OSE PLATFORM
Sailor_forever sailing_9806@163.com 转载请注明
【摘要】本文分析了PPC440+OSE平台下系统Crash的相关底层技术。首先介绍了PPC440的寄存器及系统crash时的基本处理流程,接着分析了PPC ABI规范,确定了函数调用时的参数传递规则和栈结构,这些都为crash时的寄存器组和栈分析奠定了基础。最后以DATA TLB MISS异常为例,详细介绍了如何根据DUMP文件分析系统死机原因。
【关键字】PPC440,OSE,CRASH,DATA TLB MISS
1 寄存器
1.1 寄存器按处理器模式分类
用户权限可以访问的寄存器
只有特权模式可以访问的寄存器
1.2 寄存器按功能类型分类
1.2.1 分支跳转
CR User CR 66
CTR User SPR 66
LR User SPR 65
CTR:Count Register
作为loop循环计数,自动递减,一些条件转移指令可以利用其进行分支转移
CR:Condition Register
条件寄存器,算术运算指令后会自动更新改寄存器,条件分支转移指令使用
LR:Link Register
函数调用时,程序的返回地址,即下一条待执行的指令的地址
1.2.2 Cache 控制
DNV0–DNV3 Supervisor SPR 94
DTV0–DTV3 Supervisor SPR 94
DVLIM Supervisor SPR 96
INV0–INV3 Supervisor SPR 94
ITV0–ITV3 Supervisor SPR 94
IVLIM Supervisor SPR 96
1.2.3 Cache Debug
DCDBTRH, DCDBTRL Supervisor, read-only SPR 121
ICDBDR, ICDBTRH, ICDBTRL Supervisor, read-only SPR 106
1.2.4 Debug
DAC1–DAC2 Supervisor SPR 242
DBCR0–DBCR2 Supervisor SPR 235
DBDR Supervisor SPR 243
DBSR Supervisor SPR 240
DVC1–DVC2 Supervisor SPR 242
IAC1–IAC4 Supervisor SPR 241
Device Control Implemented outside core Supervisor DCR 52
1.2.5 Integer Processing
GPR0–GPR31 User GPR 69
XER User SPR 69
GPR0–GPR31:通用寄存器组,R0――R31
1.2.6 Interrupt Processing
CSRR0–CSRR1 Supervisor SPR
DEAR Supervisor SPR
ESR Supervisor SPR
IVOR0–IVOR15 Supervisor SPR
IVPR Supervisor SPR
MCSR Supervisor SPR
MCSRR0-MCSRR1 Supervisor SPR
SRR0–SRR1 Supervisor SPR
CSRR0–CSRR1:Critical Save/Restore Register
CSRR0:用于产生critical中断时保存返回的PC指针
CSRR1:用于产生critical中断时保存当前的MSR
DEAR :Data Exception Addr Register
Load、store及cache管理等指令读取内存发生Alignment, Data TLB Miss, or Data Storage等错误时,将错误的地址存于DEAR
ESR:Exception Syndrome Register
当触发某种异常或者中断时,可能需要查看具体是哪种子中断,相当于中断的偏移量
IVOR0–IVOR15:Interrupt Vector Offset Registers
中断矢量偏移寄存器,CPU级共16个中断,每个中断向量的入口地址的低位由此寄存器决定
IVPR:Interrupt Vector Prefix Register
中断矢量基址寄存器,中断向量地址的高16位统一由此决定
SRR0–SRR1:Save and Restore Register
引起异常的指令地址或者中断返回的下一条指令地址
1.2.7 Processor Control
CCR0 Supervisor SPR
CCR1 Supervisor SPR
MSR Supervisor MSR
PIR, PVR Supervisor, read-only SPR
RSTCFG Supervisor, read-only SPR
SPRG0–SPRG3 Supervisor SPR
SPRG4–SPRG7 User, read-only; Supervisor SPR
USPRG0 User SPR
MSR:Machine State Register
机器状态寄存器,部分中断使能由此控制,处理器模式由此控制
1.2.8 Storage Control
MMUCR Supervisor SPR
PID Supervisor SPR
MMUCR :Memory Management Unit Control Register
1.2.9 Timer
DEC Supervisor SPR
DECAR Supervisor, write-only SPR
TBL, TBU User read, Supervisor write SPR
TCR Supervisor SPR
TSR Supervisor SPR
2 中断处理
2.1 中断概念
指令执行、收到外部信号、内部定时器、调试事件及错误事件都可能导致异常,当相应异常使能时,CPU会暂停当前的工作进入异常处理,此即为中断处理。
2.2 中断类型划分标准
除了Machine Check中断外,所有中断可以按照两种标准进行划分:
Asynchronous or synchronous
Critical or non-critical
Asynchronous中断:和当前指令的执行无关,是随机的,如外部中断
Synchronous:是指由于指令本身的执行导致的异常
Critical:必须立即处理,即使当前仍在处理某些类型的中断时也需要停下来,处理该重要的中断
non-critical:相比较而言不太重要的中断,可以被Critical事件中断
2.3 中断处理相关的寄存器
Save/Restore Registers (SRR0–SRR1)
Critical Save/Restore Registers (CSRR0–CSRR1)
Data Exception Address Register (DEAR)
Interrupt Vector Offset Registers
(IVOR0–IVOR15)
Interrupt Vector Prefix Register (IVPR)
Exception Syndrome Register (ESR)
Machine State Register (MSR)
具体意义见相关寄存器说明
2.4 中断类型
内核使用IVPR和IVORn寄存器保存中断向量。每个中断向量的入口地址是IVPR+IVORn。IVPR提供中断向量的基址,IVORn提供中断向量的偏移。IVORn与异常的对应关系如下:
IVOR0 Critical Input
IVOR1 Machine Check
IVOR2 Data Storage
用户模式下访问内核模式才能访问的内存空间,或者数据访问的字节序与定义的字节序不一致引发的异常
IVOR3 Instruction Storage
在用户模式访问内核模式下才能访问的内存空间,以及因为指令预取部件访问的字节序与定义的字节序不一致时引发此异常。
IVOR4 External Input
IVOR5 Alignment
IVOR6 Program
执行非法指令,在用户模式下执行内核模式才能执行的指令或者tw指令条件满足时,产生此异常。
IVOR7 FP Unavailable
IVOR8 System Call
执行sc指令产生此异常
IVOR9 AP Unavailable
IVOR10 Decrementer
DEC寄存器产生的定时器异常, PowerPC利用此异常实现时钟中断
IVOR11 Fixed Interval Timer
IVOR12 Watchdog Timer Watchdog
IVOR13 Data TLB Miss Error
当处理器取指时,如果访问指令的地址没有在TLB中命中时产生此异常
IVOR14 Instruction TLB Miss Error
当处理器取指时,如果访问指令的地址没有在TLB中命中时产生此异常
IVOR15 Debug
内核初始化的时候,会把所有需要初始化的IVOR赋上恰当的值。当有对应异常发生时,直接跳转到IVPR+IVORn所指向的地址即可。
2.5 中断处理的基本流程
如果当前异常使能且优先级更高,则中断处理的流程如下:
1、保存被中断程序的返回地址或者错误指令的地址到SRR0 (for non-critical class interrupts) or CSRR0 (for critical class interrupts) or MCSRR0 (for Machine Check interrupts)
根据异常类型更新ESR或者MCSR,即可获得更详细的中断类型
2、保存MSR寄存器到SRR1 (for non-critical class interrupts) or CSRR1 (for critical class interrupts) or MCSRR1 (for Machine Check interrupts),如果是地址异常还会保存错误地址到DEAR寄存器中
3、更新MSR,原则如下:
清除MSR[WE,EE,PR,FP,FE0,DWE,FE1,IS,DS]
critical class interrupts 清除MSR[CE,DE] ,non-critical class不清除,因此non-critical class interrupts可以被critical class interrupts中断
Machine Check interrupts 清除MSR[ME],其他中断不清除
4、清除PR,IS,DS位。此时,处理器运行在内核模式
5、根据IVPR和IVOR4寄存器获得中断向量,进行中断程序执行
6、中断程序执行结束后,使用rfi/rfci/rfmci指令返回。rfi/rfci/rfmci指令从SRR1/CSRR1/M CSRR1寄存器恢复MSR寄存器,从SRR0/CSRR00/MCSRR0寄存器中获得中断的返回地址,注意这两步其实是一个原子操作
3 PowerPC中的ABI规范
ABI或EABI(Extend ABI)通常是处理器体系结构的一部分,它与平台是紧密相连的。可以把ABI理解为一套规则,这套规则一般包括定义了以下内容:
1、如何使用机器的寄存器。比如用那个通用寄存器来作stack pointer和frame pointer。
2、堆栈的结构。
3、参数传递规则。
特定于那个平台的编译器和链接器实现都要遵循这些约定。
3.1 寄存器的使用规则
GPR0:随意使用,无需保存
GPR1:该寄存器保存堆栈的栈顶指针,也就是SP指针。
GPR2:专用
GPR3-GPR4:使用这两个寄存器保存程序的返回值。
GPR3-GPR10:用于传递函数参数。当参数多于8个时,使用存储器的栈传送。
GPR11-GPR12: 随意使用,无需保存
GPR13:专用,该寄存器用于保存sdata段的基地址指针。
GPR14-GPR31:程序可以自由使用这几个寄存器。
共分为三类
Volatile:随意使用,函数调用或者中断时不用保存
Nonvolatile:非易失性的,使用前需要保存,用后恢复
Dedicated:专用的,如R1作为SP,不能用于其他用途,因为中断可能随时来临
3.2 堆栈的结构
PowerPC架构没有专门的push、pop指令来实现堆栈结构,因此需要有一套规范来支持参数传递、Nonvolatile寄存器的保存以及局部变量等。将这些数据以统一的格式存放在栈中。
3.2.1 栈的增减规则
SP总是以双字对齐的方式指向当前stack frame的底部,新的SP递减增长,。
3.2.2 栈的结构
进行函数调用时,堆栈将向下增长,并按照特定的格式保存现场,以防止中断后无法返回到调用处。
Back Chain:当前栈顶指针寄存器SP保存上一个栈桢的Back Chain的地址。当函数返回时,SP指回上一个栈桢。
LR Save Word:保存LR寄存器的值,用于函数返回,即调用函数处的下一条指令地址。
Parameter Save Area:用于存放函数参数。当参数多于R3-R10 8个时才用此区域。
Local Variable Area:用于存放临时变量。首先选择GPR0/GPR11/ GPR12保存临时变量,只有当寄存器不够用时才用此区域。
CR Save Area:若函数可能更改CR,则保存CR寄存器。
32-bit General Register Save Area:保存函数用到的32位寄存器。若使用了GPR14- GPR31之间的寄存器,则需要将之上至GPR31的所有寄存器入栈保存,如使用了GPR16,则应保存GPR16- GPR31。
注意,根据具体的函数不一样,栈桢的内容是不一样的,最小的栈桢只有Back Chain和LR Save Word,共8字节,栈始终对齐在8字节边界,否则填充补齐。
Back Chain和LR Save Word紧紧相邻,且Back Chain是递减的,这些特征便于定位哪个是函数调用的边界。
3.3 函数调用示例
以下使用一VxWorks的入口函数简单分析下,中间插入部分汇编。
void usrInit (int startType)
{
stwu r1,-0x20(r1); /* 保存原先sp,同时更新sp */
mflr r0; /* LR 获取 */
stw r31, 0x1C(r1); /* 非易失性reg保存,这只保存r31 */
stw r0, 0x24(r1); /* LR存储在上个堆栈sp+4处 */
mr r31, r1 /* r31为当前sp值 */
stw r3, 0x8(r31) /* 局部变量,也就是startType */
sysStart (startType);
lwz r3, 0x8(r31)
crclr 0x6
bl 0x1E11F8BC /* 函数跳转 */
cacheLibInit (USER_I_CACHE_MODE, USER_D_CACHE_MODE);
li r3, 01
li r4, 01
bl 0x1E80EE0
excVecInit ();
sysHwInit ();
usrCacheEnable ();
usrKernelInit ();
}
lwz r11, 0x0(r1) /* SP恢复 */
lwz r0, 0x4(r1)
mtlr r0 /* LR 恢复 */
lwz r31, -0x4(r11) /* R31恢复 */
mr r1, r11
blr /* usrInit函数返回 */
4 Data TLB Miss 分析
4.1 Dump文件分析
4.1.1 错误代码解析
[POST MORTEM DUMP]
user called : 0
error code : 0x00000000
extra : 0x00000000
curr_proc : 0x00010179
[ERROR HANDLER PARAMETERS]
user called : 0 (Kernel)
error code : 0x91000113
extra : 0x002a3e58
curr_proc : 0xe2a3835a
ERROR NUMBER 0x91000113 WITH EXTRA DATA 0x002A3E58 OCCURRED IN
PROCESS irqProc
TYPE PRI-15
BLOCK CXC1727187%1_R3N02
ERROR SPECIFICATION
An unexpected exception occurred.
The exception offset is supplied in the subcode field.
The extra parameter contains a pointer to a register
dump, described in cpu.h
This error is fatal.
The exception vector = 0x1100, Data TLB Miss.
错误源user called:0内核发现的错误
错误代码:0x91000113,113的详细解释为Data TLB Miss,异常入口0x1100
错误附加值:0x002A3E58,指向dump的寄存器组
错误进程:0x00010179,代表优先级为15的进程irqProc
程序版本:可加载程序CXC1727187%1_R3N02
4.1.2 Dump寄存器分析
[REGISTERS FOR PROCESS 0x10179 irqProc]
PC = 00655304 SP = 03C87E10 MSR = 00029030 LR = 03CFD778
R0 = 00000001 R8 = 002A0000 R16 = 40220000 R24 = 42EC0000
R1 = 03C87E10 R9 = 000003D4 R17 = 40220000 R25 = 42FC4B40
R2 = 42E75C0C R10 = 00029030 R18 = 40220000 R26 = 00000001
R3 = 03C84890 R11 = 0331FDC0 R19 = 42E40000 R27 = 00000000
R4 = 00029030 R12 = 03C84740 R20 = 42E40000 R28 = 42ED0114
R5 = 00021030 R13 = 42ED1180 R21 = 42E40000 R29 = 42ED0000
R6 = 0006CB8D R14 = 40220000 R22 = 42E40000 R30 = 03C8B2A0
R7 = 00000000 R15 = 40220000 R23 = 42E40000 R31 = 03C87960
DAR = 03320194 CR = 42500002 XER = 00000000 CTR = 0062AA64
[OTHER PROCESSOR REGISTERS]
PVR = 21821820
CCR0 = 48000000 CCR1 = 00000000 CR = 22502088
CSRR0 = 005EB840 CSRR1 = 00000000 CTR = 00000000
DAC1 = 00000000 DAC2 = 00000000 DBCR0 = 00000000
DBCR1 = 00000000 DBCR2 = 60000A00 DBDR = 00000210
DBSR = 00000000 DCDBTRH= 00000000 DCDBTRL= 00040820
DCRIPR= 00000000 DEAR = 03FB4004 DEC = 0018F671
DECAR = 00000000 DNV0 = 021E1314 DNV1 = 25091031
DNV2 = 3E38242B DNV3 = 03003026 DTV0 = 00000000
DTV1 = 00000000 DTV2 = 00000000 DTV3 = 00000000
DVC1 = 88010C00 DVC2 = 40000A00 DVLIM = 00000000
ESR = 00000000 IAC1 = 00000000 IAC2 = 00000000
IAC3 = 00000000 IAC4 = 00000000 ICDBDR= FFFFFFFF
ICDBTRH= 00000000 ICDBTRL= 00000000 INV0 = 2B382F34
INV1 = 08090025 INV2 = 182B0A0F INV3 = 3839111D
ITV0 = 00000000 ITV1 = 00000000 ITV2 = 00000000
ITV3 = 00000000 IVLIM = 00000000 IVOR0 = 00000100
IVOR1 = 00000200 IVOR2 = 00000300 IVOR3 = 00000400
IVOR4 = 00000500 IVOR5 = 00000600 IVOR6 = 00000700
IVOR7 = 00000800 IVOR8 = 00000C00 IVOR9 = 00000D00
IVOR10= 00000900 IVOR11= 00000A00 IVOR12= 00000B00
IVOR13= 00001100 IVOR14= 00001200 IVOR15= 00002000
IVPR = 00000000 MCSR = 00000000 MCSRR0= 00647938
MCSRR1= 00000000 MMUCR = 00000006 PID = 00000000
PIR = 00000000 RSTCFG= 00000000 SPRG0 = 03CC0000
SPRG1 = 00244D34 SPRG2 = 0062AA64 SPRG3 = 42500002
SPRG4 = 00000000 SPRG5 = 00000000 SPRG6 = 00000000
SPRG7 = 00000000 SRR0 = 0067AF9C SRR1 = 00021030
TBL = ADDC399C TBU = 5080D45A TCR = 00000000
TSR = 00000000 USPRG0= 00000001
DDR2MC_BESR = 00000000
DDR2MC_BEARL = 00000000
DDR2MC_BEARU = 00000000
DDR2MC_ECCES = 00000000
OPB2PLB_GSTAT = 00000000
OPB2PLB_GEARL = BBB5FF9D
OPB2PLB_GEARH = 0000000E
PLB2OPB_GEAR = FFFFFFC0
PLB2OPB_GEARU = 00000000
PLB2OPB_GESR0 = 00000000
PLB2OPB_GESR1 = 00000000
EBCO0_BEAR = 00000000
EBCO0_BESR = 00000000
关键寄存器分析
PC = 00655304
下一条待执行的指令地址,由于流水线的因素,PC并不是当前执行的指令地址
SP = 03C87E10
异常时当前函数调用层次的堆栈指针,堆栈递减的,由SP及当前任务堆栈的栈顶即可知道调用的层次关系及相关变量、参数等
MSR = 00029030
机器状态字
LR = 03CFD778
待返回的函数中下一条指令的地址
IVPR = 00000000
异常入口的计算方法IVPR + IVORx = 0x1100
推算IVORx = IVOR13,根据PPC440中断向量表即可知此为Data TLB Miss异常
DEAR = 03FB4004
Data TLB Miss异常为数据访问异常,此时导致错误的虚拟地址将保存在DEAR中,错误地址为03FB4004。Data TLB Miss异常,说明未找到虚拟地址03FB4004的映射关系,可能因为为03FB4004不存在于任何一个页表范围内,或者本任务对03FB4004地址没有访问权限。
SRR0 = 0067AF9C SRR1 = 00021030
产生错误的指令地址保存在SRR0中,为0067AF9C
结合相关map表,即可知道0067AF9C所对应的文件、函数、代码行等信息。
4.1.3 内存布局分析
描述了各个Segments and regions的内存分布,结合PC、SP、LR、DEAR、SRR0即可找到错误的代码段及数据段
[MEMORY MANAGER]
MEMORY LEFT: 6455296 bytes = 6,2 Mbytes
Segments and regions
SEGMENT NAME NUMBER OWNER ID SEGMENT ID MODE
SYSTEM_SEGMENT 1 65597 0 usermode
。。。。。。。。。
VECTORS 3 0x00000000-0x00004000 0x00004000
super_wp user_wp persistant copyback physical
PBOOT 4 0x00004000-0x000416D4 0x0003D6D4
user_wp persistant copyback physical
。。。。。
OS_CODE 6 0x00500000-0x0077DC00 0x0027DC00
super_wp user_wp persistant copyback physical
OS_DATA 7 0x00200000-0x003787B1 0x001787B1
user_wp public persistant copyback physical
OS_NOVRAM 8 0x0037C000-0x003809A9 0x000049A9
user_wp persistant copyback physical
INIT_MAINPOOL 9 0x00800000-0x009A4000 0x001A4000
public persistant copyback physical
。。。。。。。。
Mainpool_Frag_1 2 0x03FD4000-0x03FF4000 0x00020000
public copyback physical
Syspool_Frag_1 19 0x03FB4000-0x03FD4000 0x00020000
copyback physical
。。。。。。。。。
Mainpool_Frag_19 50 0x03CE0000-0x03D00000 0x00020000
public copyback physical
。。。。。。
Syspool_Frag_3 53 0x03C80000-0x03CA0000 0x00020000
copyback physical
。。。。。。。。。
分析:
OS_CODE 6 0x00500000-0x0077DC00 0x0027DC00
SRR0 = 0067AF9C 在OS_CODE的范围内,说明产生异常时正在运行内核代码
Syspool_Frag_3 53 0x03C80000-0x03CA0000 0x00020000
SP = 03C87E10 在Syspool_Frag_3范围内,说明irq_proc在内核态使用了Syspool_Frag_3作为栈空间
Syspool_Frag_1 19 0x03FB4000-0x03FD4000 0x00020000
DEAR = 03FB4004 产生错误的地址位于此段,当有属性权限控制时,可能为非法内存访问导致TLB异常
4.1.4 内存池分析
[POOL INFO]
poolid frags totsize used unused used%
0x1000c 21 4341728 4278752 62976 99 Main
0x10000 4 818336 733120 85216 90 OSE
Pool: Main
Pool id 0x1000c
signal sizes 8
sig_conf 31 63 127 255 1055 4095 16383 65535
sig_alloc 1161 643 40 227 38 70 108 0
stack sizes 8
stk_conf 256 512 1024 2048 4096 8192 16384 65536
stk_alloc 0 6 6 74 62 31 6 1
fragment info
fragment baseaddr lastaddr size sigsize stksize unused used%
0 0x03ca0000 0x03cc0000 131072 68096 0 62976 51
1 0x03ce0000 0x03d00000 131072 110656 11264 9152 93
2 0x03d00000 0x03d20000 131072 79520 36864 14688 88
3 0x03d20000 0x03d40000 131072 125728 5120 224 99
4 0x03d40000 0x03d60000 131072 127968 0 3104 97
5 0x03d60000 0x03d80000 131072 127968 0 3104 97
6 0x03d80000 0x03da0000 131072 127968 0 3104 97
7 0x03da0000 0x03dc0000 131072 127968 0 3104 97
8 0x03dc0000 0x03de0000 131072 127968 0 3104 97
9 0x03de0000 0x03e00000 131072 128416 0 2656 97
10 0x03e00000 0x03e20000 131072 116128 0 14944 88
11 0x03e20000 0x03e40000 131072 115520 0 15552 88
12 0x03e40000 0x03e60000 131072 116128 0 14944 88
13 0x03e60000 0x03e80000 131072 116128 0 14944 88
14 0x03e80000 0x03ea0000 131072 116128 0 14944 88
15 0x03ea0000 0x03ec0000 131072 115520 0 15552 88
16 0x03ec0000 0x03ee0000 131072 116128 0 14944 88
17 0x03ee0000 0x03f00000 131072 116128 0 14944 88
18 0x03f84000 0x03fa4000 131072 116128 0 14944 88
19 0x03fd4000 0x03ff4000 131072 115520 0 15552 88
20 0x00800000 0x009a3fe0 1720288 902368 807936 9984 99
Pool: System pool
Pool id 0x10000
signal sizes 8
sig_conf 31 63 127 255 1023 4095 16383 65535
sig_alloc 1773 624 92 1 0 1 0 0
stack sizes 8
stk_conf 256 512 1024 2048 4096 8192 16384 65536
stk_alloc 1 0 0 4 0 0 1 0
fragment info
fragment baseaddr lastaddr size sigsize stksize unused used%
0 0x03c80000 0x03ca0000 131072 45856 0 85216 34
1 0x03cc0000 0x03ce0000 131072 131040 0 32 99
2 0x03fb4000 0x03fd4000 131072 114656 16384 32 99
3 0x00310280 0x00377f20 425120 401984 22784 352 99
共两个内存池:
OSE,系统内存池
Main,应用程序内存池
4.1.5 死机进程irq-proc的栈分析
[SUPERVISOR STACK PREAMBLE FOR PROCESS 0x10179 irqProc]
03C87860: 03fc0120 03c88260 03fb5ac0 03c86160 "... ...`..Z...a`"
03C87870: 00000000 000100ed 000100e9 028e0002 "................"
。。。。。。。。。
03C87A40: 00000000 00000000 00000000 eeeeeeee "................"
03C87A50: eeeeeeee eeeeeeee eeeeeeee eeeeeeee "................"
[SUPERVISOR STACK FOR PROCESS 0x10179 irqProc]
03C87A60: eeeeeeee eeeeeeee eeeeeeee eeeeeeee "................"
........:< Skipping empty part of the stack >
03C87BD0: eeeeeeee eeeeeeee 03c87bf8 eeeeeeee "..........{....."
03C87BE0: 03c87c00 00000000 eeeeeeee 00000000 "..|............."
。。。。。。。。。。。
03C87DE0: 00000001 03c84890 00029030 00021030 "......H....0...0"
03C87DF0: 0006cb8d 00000000 002a0000 000003d4 ".........*......"
03C87E00: 00029030 0331fdc0 03c84740 0064adfc "...0.1....G@.d.."
03C87E10: 03c87e38 00654f70 03c87e40 42fc4b40 "..~8.eOp..~@B.K@"
03C87E20: 42fc4a00 00000000 00000005 42ed0000 "B.J.........B..."
03C87E30: 42fc4a70 03cfd778 03c87e40 00649fa4 "B.Jp...x..~@.d.."
03C87E40: 03cfd778 0067a890 42da1150 0002d030 "...x.g..B..P...0"
03C87E50: eeeeeeee 42d0b440 eeeeeeee eeeeeeee "....B..@........"
[MAIN STACK PREAMBLE FOR PROCESS 0x10179 irqProc]
03CFD200: eeeeeeee eeeeeeee eeeeeeee eeeeeeee "................"
03CFD210: eeeeeeee eeeeeeee eeeeeeee eeeeeeee "................"
03CFD220: eeeeeeee eeeeeeee eeeeeeee eeeeeeee "................"
。。。。。。。。
03CFD3D0: eeeeeeee eeeeeeee eeeeeeee eeeeeeee "................"
03CFD3E0: eeeeeeee eeeeeeee eeeeeeee eeeeeeee "................"
03CFD3F0: eeeeeeee eeeeeeee eeeeeeee eeeeeeee "................"
[MAIN STACK FOR PROCESS 0x10179 irqProc]
03CFD400: eeeeeeee eeeeeeee eeeeeeee eeeeeeee "................"
........:< Skipping empty part of the stack >
03CFD640: eeeeeeee eeeeeeee 03cfd678 42dd41cc "...........xB.A."
。。。。。。。。。。。。。。。。。。
03CFD760: 42fc3490 03cfd768 03cfd788 42d0a0f8 "B.4....h....B..."
03CFD770: 03cfd788 00000000 03cfd788 42d0b440 "............B..@"
03CFD780: 42fc4a70 03cfd788 03cfd7d0 42d0b100 "B.Jp........B..."
03CFD790: 00000000 00000002 03c84640 40220000 "..........F@@".."
03CFD7A0: 40230000 40260000 40220000 000100ab "@#..@&..@"......"
03CFD7B0: 00000000 00000002 03c84640 42ec0000 "..........F@B..."
03CFD7C0: 42ed00c4 42ed0000 42fc4a00 03cfd7d0 "B...B...B.J....."
03CFD7D0: 03cfd7f0 42d097b4 03c83c40 0001007f "....B.....<@...."
03CFD7E0: 03c83c40 03c84860 03c83c40 03c84860 "..<@..H`..<@..H`"
03CFD7F0: 00000000 42da1078 eeeeeeee eeeeeeee "....B..x........"
每个进程有两个栈,用户模式的栈和supervisor模式的栈
irqProc的用户栈为03CFD200――03CFD7FF
supervisor栈 03C87860――03C87E5F
死机时的栈指针SP = 03C87E10,在内核栈空间内,说明irqProc进程当前运行在内核态模式。由于栈是递减的,因此栈中的有效数据范围为03C87E10――03C87E5F
03C87E10: 03c87e38 00654f70 03c87e40 42fc4b40 "..~8.eOp..~@B.K@"
03C87E20: 42fc4a00 00000000 00000005 42ed0000 "B.J.........B..."
03C87E30: 42fc4a70 03cfd778 03c87e40 00649fa4 "B.Jp...x..~@.d.."
03C87E40: 03cfd778 0067a890 42da1150 0002d030 "...x.g..B..P...0"
03C87E50: eeeeeeee 42d0b440 eeeeeeee eeeeeeee "....B..@........"
根据Back Chain和LR Save Word紧紧相邻且Back Chain是递减的规则,以及SP八字节对其的规则,可确定几个函数调用点:
内核态:
03c87e38 00654f70
03c87e40 00649fa4
03cfd778 0067a890
进入内核态之前用户态的栈指针为03cfd778
因此03cfd778――03CFD7FF为用户态的有效栈空间
用户态:
03cfd788 42d0b440
03cfd7d0 42d0b100
03cfd7f0 42d097b4
00000000 42da1078
根据map文件及反汇编的代码文件,即可找到每一个地址所对应的指令
4.1.6 可加载模块分析
[LOADED PROGRAMS]
Load module id: CXC1720828_RBLACK
Load module path:
Load module version: No version available, loaded from flash
Start code: 0x00500000 size: 0x0027dc00
Start data: 0x00200000 size: 0x00180a00
Image checksum: 0x6521
。。。。。。。。。。
Load module id: CXC1727187%1_R3N02
Load module path: @(#)/vobs/tdrbs/hw/trax/build trax.ppc440 ppc440 miznick_trax
Load module version: @(#)CXC1727187R3N02 2009-05-07 23:26:35 CST 96ec48c5-1195ba2b-6e4d
Program handle: 4
Entry point: 42d947a0
Start code: 42c70000 Size: 00226fa8
Start data: 42ea0000 Size: 001269f0
BSS start: 42ea0000
Image checksum: 0xa148
CXC1720828_RBLACK为内核的固件,运行地址为0x00500000
CXC1727187%1_R3N02为TRAX程序,为可加载模块,其代码及数据空间是从系统堆中动态获取的,代码段首地址42c70000,全局数据段首地址42ea0000
4.1.7 内核运行轨迹分析
[KERNEL TRACE CONTENTS]
TRACE LOG FROM KERNEL
EVENT TIME / PROCESS(pid) / SIGNAL : parameters, ...
Error at 1686789.064 ms
kernel ecode = 0x91000113, extra = 0x002A3E58
proc: CXC1727187_R3N02:irqProc(0x10179)
Swapped at 1686788.914 ms
out: Main:capi_bg(0x10069)
in: CXC1727187_R3N02:irqProc(0x10179)
Send at 1686788.907 ms
from: CXC1726374_R5D01:PARA5(0x100F5)
to: CXC1727187_R3N02:irqProc(0x10179)
00000000: 0100d509 00000001 00000001 "............"
Swapped at 1686784.048 ms
out: Main:Cs_errorManTime_proc(0x10020)
in: Main:capi_bg(0x10069)
Swapped at 1686784.007 ms
out: Main:capi_bg(0x10069)
in: Main:Cs_errorManTime_proc(0x10020)
。。。。。。。。。。。
Error at 1686789.064 ms
kernel ecode = 0x91000113, extra = 0x002A3E58
proc: CXC1727187_R3N02:irqProc(0x10179)
为系统死机事件,记录了错误值,错误程序的某个进程
Swapped at 1686788.914 ms
out: Main:capi_bg(0x10069)
in: CXC1727187_R3N02:irqProc(0x10179)
Send at 1686788.907 ms
from: CXC1726374_R5D01:PARA5(0x100F5)
to: CXC1727187_R3N02:irqProc(0x10179)
00000000: 0100d509 00000001 00000001 "............"
CXC1726374_R5D01:PARA5(0x100F5)向to: CXC1727187_R3N02:irqProc(0x10179)
发送消息,激活了irqProc(0x10179),进行任务切换,调度CXC1727187_R3N02:irqProc(0x10179)后,系统死机
4.1.8 系统堆分析
系统堆用于内核自身部分动态数据的存储,另外主要功能是用于动态加载模块的内存需求。
[HEAP SUMMARY FOR SEGMENTS]
Summary of Heap for segment 0x000200c7
Alloc from Memory manager threshold default
Annotation size 0
Endmark size 1
Wipe on free (OFF) Error on null (ON) Redundant bitmap (OFF)
Total size 741888
Total requested 187461, 25% of total
Total used 218912, 30% of total
Total used (high water-mark) 218912, 30% of total
Overhead and internal
fragmentation 31451, 17% of total requested
14% of total used
Total free 522976, 70% of total
Largest free 458512, 62% of total
External fragmentation 12% (100% - largest free / total free)
Private buffers 5
Shared buffers 142
Number of failed malloc calls (return 0) 0
Buffer Histogram
Size # of free # of used
16 0 0
16 30 0
32 6 66
48 0 49
80 1 17
128 0 1
208 0 0
336 0 1
544 1 6
880 0 3
1424 0 0
2304 1 0
3728 0 0
6032 0 0
9760 2 0
15792 0 2
25552 0 0
41344 1 0
66896 0 1
108240 0 1
175136 0 0
283376 0 0
458512 1 0
741888 0 0
1200400 0 0
1942288 0 0
3142688 0 0
5084976 0 0
8227664 0 0
Fragments:
Address 0x42f11658 size 741912
由上可知堆中每个内存块的使用情况,分配释放的次数
4.1.9 产生错误的指令分析
[FAILING INSTRUCTION]
006552E4: 880b0bcc 2c000000 41820090 38000001 "....,...A...8..."
006552F4: 980b0018 a13e001e 816b0b90 5529103a ".....>...k..U).:"
00655304: 7ca9582e a1250004 a01e001c 7c090000 "|.X..%......|..."
00655314: 40820034 801f0034 81250034 7c004b78 "@..4...4.%.4|.Kx"
00655304是即将执行的下一条指令的地址
4.1.10 进程列表
[PROCESS LIST]
NAME TYPE STATE LINE FILE MAIN STACK BASE MAIN STACK LIMIT USAGE SUPERV STACK BASE SUPERV STACK LIMIT USAGE
"CXC1727187_R3N02" BLOCK Segment-ID: 0x000200c7 Block-ID: 0x000200c8 Sigpool-ID: 0x0001000c Stackpool-ID: 0x0001000c User-mode
"irqProc" PRI-15 running 863 "receive@ose.h" 0x03cfd400 0x03cfd7ff 42 0x03c87a60 0x03c87e5f 63 0 2 0x00010179
"drvProc" PRI-15 wsig... 863 "receive@ose.h" 0x03d1b800 0x03d1bbff 24 0x03fb9a00 0x03fb9dff 32 0 5 0x000200e8 R1=03D1BBB8 RA=42D25618
"CXC1727187_R3N02" BLOCK Segment-ID: 0x000200c7 Block-ID: 0x000200c8 Sigpool-ID: 0x0001000c Stackpool-ID: 0x0001000c User-mode
"CXC1727187_R3N02"使用的Segment、Block、Sigpool及Stackpool等信息都可以获得了
"irqProc" PRI-15 running 863 "receive@ose.h" 0x03cfd400 0x03cfd7ff 42 0x03c87a60 0x03c87e5f 63 0 2 0x00010179
irqProc进程为running状态,所在行863 receive@ose.h
栈使用情况
用户栈 0x03cfd400 0x03cfd7ff 42
内核栈 0x03c87a60 0x03c87e5f 63
与“死机进程irq-proc的栈分析”章节分析的结果一致
4.1.11 异常代码的函数调用分析
[CALLTRACE FOR PROCESS 0x10179 irqProc]
Translation of address registers:
PC = 00655304 [10155304],CXC1720828_RBLACK
LR = 03cfd778
DAR = 03320194
Stacktrace :
Using stackpointer : 03c87e10
内核态的栈得到的轨迹
Back chain word : 03c87e38
00654f70 [10154f70],CXC1720828_RBLACK
Back chain word : 03c87e40
00649fa4 [10149fa4],CXC1720828_RBLACK
Back chain word : 03cfd778
0067a890 [1017a890],CXC1720828_RBLACK
用户态栈得到的轨迹
Back chain word : 03cfd788
42d0b440 [1009b440],CXC1727187%1_R3N02 ??:0 warning
1009b0bc g F .text 00000324 _ZN17CInterruptManager3runEv
1009b3e0 l F .text 0000003c _Z6senderPP6SIGNAL
1009b41c l F .text 0000003c _Z7receivePKm
1009b458 g F .text 00000388 _Z14intHandler_5msmmm
Back chain word : 03cfd7d0
42d0b100 [1009b100],CXC1727187%1_R3N02 ??:0 writezone
0x1009b0bc CInterruptManager::run()
Back chain word : 03cfd7f0
42d097b4 [100997b4],CXC1727187%1_R3N02 ??:0 yearistype
1009972c l F .text 0000013c _Z9irqProc__v
Back chain word : 00000000
42da1078 [10131078],CXC1727187%1_R3N02
1013107c g .text 00000000 zzinit_OSE
实际运行的地址和map文件中的地址有一个对应的关系
PC = 00655304 [10155304]
相当于一个线性偏移,在map中搜索的地址为10155304附近的段,结合反汇编代码可确定出错的语句
5 To be continued
MMU and TLB of PPC
Memory Management System under OSE and PPC440