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,用$<systemdump产生一个crashdump。可以根据上面的

头文件验证栈内寄存器窗口值的保存是与上面定义一致的。之所以产生一个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                           
   
% =   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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值