Solaris学习笔记(4)

    技术2022-05-11  46

    Solaris学习笔记(4)

    作者: BadcoffeeEmail: blog.oliver@gmail.comBlog: http://blog.csdn.net/yayong2007年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, %g0restore

    或者

    retrestore

    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 >  ::stackregs000002a100347111 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,  % o7000002a1003472d1 intr_thread + 0x2c0 ( 0 , 1859ff8, 180c000, 1b, 10b5fd8, 1817c00)   % l0 -% l3:           1008468                 a        4414001602               80a   % l4 -% l7:                 0                  0                  0       2a10030f980mdb: failed to read instruction at  0 : no mapping  for  address000002a10030f221  0 (1817c00,  0 , 300077d4000, ffffffffffffffff,  2 1816800 )   % l0 -% l3:      60000128fe8               1b                 0  ffffffffffffffff   % l4 -% l7:      60000128fe8 ffffffffffffffff          1859ff8          106b174  thread_start + 4 :          jmpl       % i7,  % o7000002a10030f2d1 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)