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分析的基础。

http://www.sparc.org/

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,用$

头文件验证栈内寄存器窗口值的保存是与上面定义一致的。之所以产生一个crash dump来验证,

是为防止寄存器窗口还没有保存在栈里。

# mdb 0
> ::stackregs
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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值