Solaris学习笔记(4)
Solaris学习笔记(4)
作者: Badcoffee
Email: blog.oliver@gmail.com
Blog: http://blog.csdn.net/yayong
2007年2月
很久没有写blog了,工作越来越忙,生活中琐事也不少,一天中的时间所剩无几了。当初很想写出精品的技术文章来,到后来才发现,要写一篇精品真的很难。从基础理论到实际案例,想深入潜出又要有一定水准,真的是太难了,这中间得花费写作者的多少心智?现在才能体会到成为一名出色的技术作家,需要的不仅仅是技术功底而已。所以,还是先做好工程师这份没有前途的职业再说吧:)
关键词:RISC/CISC/SPARC/ABI/MDB/KMDB/Solaris/OpenSolaris
本文介绍Solaris SPARC系统上Crashdump分析所需的基础知识:寄存器窗口,ABI等;Solaris的内核调试工具已经可以很好地读取出函数的入口参数,但是,在一些情况下,仍旧需要通过读取线程栈的内容来确定函数参数的值。再次说明,本文仅用于学习交流目的,错误再所难免,如果有勘误或疑问请与作者联系。
RISC 与 CISC
关于RISC与CISC的争论由来以久,相关文章到处都是,不明白可以Google一下。似乎两者已经互相借鉴,互相融合了,如果有时间,应该深入了解一下CPU和体系结构方面的知识。
SPARC体系结构的文档,可以从下面的网站得到,本文只涉及到crash dump分析的基础。
SPARC的特点
1. 精简指令集;
2. 指令和操作基于寄存器,内存访问需要专门的load/store操作;
3. 有很多寄存器(几百个),通过寄存器窗口来访问;
4. 函数参数传递也通过寄存器,而不是通过栈;
5. 指令编码定长;
6. 地址对齐,不对齐的地址会引发bad trap;例如,各种数据类型必须与其自然边界对齐;
7. 字节序缺省是大端的(也可支持小端,需要页表项的特殊设置);
SPARC寄存器
Processor Status Register (PSR):用来指示kernel/user mode, condition codes, CPU priority level等。
Program Counter (PC): 当前正在执行的指令地址;
next Program Counter (nPC):下条要执行指令的地址;
General-purpose registers:通用寄存器,实际上SPARC有数百个寄存器,但对每个程序仅可见32个,这是通过寄存器窗口实现的。
寄存器窗口中的通用寄存器分类
General-purpose registers %r0 … %r31
1. 全局寄存器(8个) - 对所有程序可见
General-purpose global registers %g0 … %g7 Same as %r0 … %r7
2. 输出寄存器(8个) -函数返回值,输出寄存器是下一个窗口的输入寄存器
General-purpose out registers %o0 … %o7 Same as %r8 … %r15
3. 局部寄存器(8个) - 仅本函数可见
General-purpose local registers %l0 … %l7 Same as %r16 … %r23
4. 输入寄存器(8个) -本函数的输入参数,来自于上一窗口的输出寄存器
General-purpose in registers %i0 … %i7 Same as %r24 … %r31
寄存器窗口
SPARCv9寄存器窗口的数量范围从 2 到 32,具体取决于处理器实现。每个寄存器窗口对应一个函数,当每个函数被调用时,函数开始会调用save指令分配相应的栈空间;
函数的调用必然引起一次窗口的切换和一次栈空间的预先分配,但寄存器在下列情况时才被保存在栈上,
1. 寄存器窗口用尽时
2. 上下文切换
3. flushw指令
这时会引发一个硬件的溢出trap,将寄存器窗口中的16个寄存器(8个局部寄存器和8个输入寄存器)保存到栈上;
寄存器窗口还有underflow trap,可以把保存在栈里的值恢复;restore指令用于切回上级调用的寄存器窗口,并取释放栈空间;
相关的指令
1. 函数调用:
call address
或者
jmpl address, %o7
2. 函数入场:
save %sp, -0x78, %sp
3. 函数返回:
jmpl %i7+8, %g0
restore
或者
ret
restore
SPARC的ABI
函数的调用者传递参数到本窗口的o寄存器,被掉函数从本窗口的i寄存器读到;
%o0到%o5 - 用于函数返回值或者传递给下一个函数参数,第一个参数是%o0 ,参数多于6个还会用栈传递;
%o6 - %sp栈顶指针;
%o7 -函数返回地址;
%i6 -%fp栈框架指针(SFP)
%i0到%i5 -入口参数,第一个参数是%i0,来自于上一窗口的输出参数;
%g0永远是0,特殊用途;
SPARC V9的 stack bias:
%o6 is still referred to as the stack pointer register %sp, and %i6 is the frame pointer register %fp. However, the %sp and %fp registers are offset by a constant, known as the stack bias, from the actual memory location of the stack. The size of the stack bias is 2047 bytes.
栈框架的定义
Solaris中,stack frame的格式定义在体系结构相关的头文件中:
http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/sparc/sys/frame.h#36
* Definition of the sparc stack frame (when it is pushed on the stack).
*/
struct frame {
long fr_local[8]; /* saved locals */
long fr_arg[6]; /* saved arguments [0 - 5] */
struct frame *fr_savfp; /* saved frame pointer */
long fr_savpc; /* saved program counter */
#if !defined(__sparcv9)
char *fr_stret; /* struct return addr */
#endif /* __sparcv9 */
long fr_argd[6]; /* arg dump area */
long fr_argx[1]; /* array of args past the sixth */
};
实际验证
在console上激活kmdb,用$<systemdump产生一个crashdump。可以根据上面的
头文件验证栈内寄存器窗口值的保存是与上面定义一致的。之所以产生一个crash dump来验证,
是为防止寄存器窗口还没有保存在栈里。
000002a100347111 abort_seq_softintr+0x94(1814400, 18cc800, 300077d4000, 3f70, 1, 1870400)
%l0-%l3: 1821d40 22d3188da0893 0 0
%l4-%l7: 0 18cc800 191bc00 1010184
intr_thread+0x2c0: jmpl %o5, %o7
000002a1003472d1 intr_thread+0x2c0(0, 1859ff8, 180c000, 1b, 10b5fd8, 1817c00)
%l0-%l3: 1008468 a 4414001602 80a
%l4-%l7: 0 0 0 2a10030f980
mdb: failed to read instruction at 0: no mapping for address
000002a10030f221 0(1817c00, 0, 300077d4000, ffffffffffffffff, 2, 1816800)
%l0-%l3: 60000128fe8 1b 0 ffffffffffffffff
%l4-%l7: 60000128fe8 ffffffffffffffff 1859ff8 106b174
thread_start+4: jmpl %i7, %o7
000002a10030f2d1 thread_start+4(0, 0, 0, 0, 0, 0)
%l0-%l3: 0 0 0 0
%l4-%l7: 0 0 0 0
> ::regs
%g0 = 0x0000000000000000 %l0 = 0x000006000013c200
%g1 = 0x0000000000000000 %l1 = 0x0000000000000001
%g2 = 0x0000000000000000 %l2 = 0x0000000000000001
%g3 = 0x0000000001853400 cpunodes+0x1140 %l3 = 0x00000600002b4a10
%g4 = 0x0000000000000000 %l4 = 0x000000000191c040
pci_intr_dma_sync
%g5 = 0x000000000109a800 %l5 = 0x0000000000000001
%g6 = 0x0000000000000010 %l6 = 0x0000000000000002
%g7 = 0x000002a100347cc0 %l7 = 0x0000000000000001
%o0 = 0x0000000000000000 %i0 = 0x0000000000000000
%o1 = 0x0000000000020040 %i1 = 0x000000000000000a
%o2 = 0x0000000001851000 lgrp_stats+0x12f8 %i2 = 0x000000000000000a
%o3 = 0x0000000000000001 %i3 = 0x0000000001814400
%o4 = 0x00000000013446a4 kmdbmod`kaif_enter %i4 = 0x0000000000000000
%o5 = 0x00000000018ea2b8 kmdbmod`kaif_dvec %i5 = 0x0000000001853400
cpunodes+0x1140
%o6 = 0x000002a100347041 %i6 = 0x000002a100347111
%o7 = 0x000000000101028c debug_enter+0x108 %i7 = 0x000000000100ff38
abort_seq_softintr+0x94
%ccr = 0x00 xcc=nzvc icc=nzvc
%fprs = 0x00 fef=0 du=0 dl=0
%asi = 0x00
%y = 0x0000000000000000
%pc = 0x0000000000000000
%npc = 0x0000000000000004
%sp = 0x000002a100347041 unbiased=0x000002a100347840
%fp = 0x000002a100347111
%tick = 0x000006b00af1f9fe
%tba = 0x0000000000000000
%tt = 0x9
%tl = 0x0
%pil = 0xc
%pstate = 0x016 cle=0 tle=0 mm=TSO red=0 pef=1 am=0 priv=1 ie=1 ag=0
%cwp = 0x05 %cansave = 0x00
%canrestore = 0x00 %otherwin = 0x00
%wstate = 0x00 %cleanwin = 0x00
> 0x000002a100347111+0t2047,24/naJ
0x2a100347910:
0x2a100347910: 1821d40
0x2a100347918: 22d3188da0893
0x2a100347920: 0
0x2a100347928: 0
0x2a100347930: 0
0x2a100347938: 18cc800
0x2a100347940: 191bc00
0x2a100347948: 1010184
0x2a100347950: 1814400
0x2a100347958: 18cc800
0x2a100347960: 300077d4000
0x2a100347968: 3f70
0x2a100347970: 1
0x2a100347978: 1870400
0x2a100347980: 2a1003472d1
0x2a100347988: 100c714
0x2a100347990: 3000793e0b8
0x2a100347998: 0
0x2a1003479a0: 0
0x2a1003479a8: 0
0x2a1003479b0: 3000793e028
0x2a1003479b8: 3000793e030
0x2a1003479c0: 1fafdd
0x2a1003479c8: 3000793e030
0x2a1003479d0: 0
0x2a1003479d8: 6000003b6e0
0x2a1003479e0: 300347221
0x2a1003479e8: 1fafdd
0x2a1003479f0: 1297538
0x2a1003479f8: 413
0x2a100347a00: 1297518
0x2a100347a08: 6000003b6e0
0x2a100347a10: 13c200
0x2a100347a18: 0
0x2a100347a20: 0
0x2a100347a28: 600002b4a10
> 2a1003472d1+0t2047,24/naJ
0x2a100347ad0:
0x2a100347ad0: 1008468
0x2a100347ad8: a
0x2a100347ae0: 4414001602
0x2a100347ae8: 80a
0x2a100347af0: 0
0x2a100347af8: 0
0x2a100347b00: 0
0x2a100347b08: 2a10030f980
0x2a100347b10: 0
0x2a100347b18: 1859ff8
0x2a100347b20: 180c000
0x2a100347b28: 1b
0x2a100347b30: 10b5fd8
0x2a100347b38: 1817c00
0x2a100347b40: 2a10030f221
0x2a100347b48: 0
0x2a100347b50: baddcafebaddcafe
0x2a100347b58: baddcafebaddcafe
0x2a100347b60: baddcafebaddcafe
0x2a100347b68: baddcafebaddcafe
0x2a100347b70: baddcafebaddcafe
0x2a100347b78: baddcafebaddcafe
0x2a100347b80: baddcafebaddcafe
0x2a100347b88: baddcafebaddcafe
0x2a100347b90: baddcafebaddcafe
0x2a100347b98: baddcafebaddcafe
0x2a100347ba0: baddcafebaddcafe
0x2a100347ba8: baddcafebaddcafe
0x2a100347bb0: baddcafebaddcafe
0x2a100347bb8: baddcafebaddcafe
0x2a100347bc0: baddcafebaddcafe
0x2a100347bc8: baddcafebaddcafe
0x2a100347bd0: baddcafebaddcafe
0x2a100347bd8: baddcafebaddcafe
0x2a100347be0: baddcafebaddcafe
0x2a100347be8: baddcafebaddcafe
相关文档:
Solaris学习笔记(3)
Solaris学习笔记(2)
Solaris学习笔记(1)
X86汇编语言学习手记(3)
X86汇编语言学习手记(2)
X86汇编语言学习手记(1)
Technorati Tag: OpenSolaris
Technorati Tag: Solaris