Solaris學習筆記(4)

Solaris學習筆記(4)

作者: Badcoffee
Email:
[email protected]
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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章