Chip123 科技應用創新平台

 找回密碼
 申請會員

QQ登錄

只需一步,快速開始

Login

用FB帳號登入

搜索
1 2 3 4
查看: 7805|回復: 6
打印 上一主題 下一主題

trace linux kernel source - ARM - 01

  [複製鏈接]
跳轉到指定樓層
1#
發表於 2008-8-6 14:33:07 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
昨天下載了linux-2.6.26的kernel source0 e0 D$ K$ j  b& K8 f4 b9 s0 G
打算trace一下 (以ARM為例子)
+ P3 K; u- t% Y4 K+ R( }- x3 u% J8 ^% P看看能不能多了解一下kernel booting時候的一些動作   f/ u- w, O( O0 O* N7 y
一些文章提到是從/arch/arm/boot/bootp/init.S開始
3 a2 b' Y4 e' e$ O9 U/ f( |( q所以節錄了一些下來
/ r- _) {+ s- Y) ~; l
9 @( l3 R8 p( B0 ?- r0 ^5 m! e     19         .section .start,#alloc,#execinstr
, }3 J) K2 u8 K# X* U' Y     20         .type   _start, #function
6 y) P! h" f$ U& r     21         .globl  _start4 g" P. O4 [' S1 B
     223 E; L! L$ h7 [/ t& `
     23 _start:     add lr, pc, #-0x8       @ lr = current load addr6 N0 K0 P/ @  d. W" o
     24         adr r13, data
, m6 e0 M/ \% g5 {     25         ldmia   r13!, {r4-r6}       @ r5 = dest, r6 = length" o0 `% U- m7 t  ^2 E, X
     26         add r4, r4, lr      @ r4 = initrd_start + load addr0 V; u9 m2 f1 i* j4 [% E7 e2 a
     27         bl  move            @ move the initrd. d. T# }1 \& ~3 Y% W1 `/ w( z, \4 y0 l% k
     .....
/ Q0 \3 j/ T* M% W; N0 [     76         .type   data,#object
; i5 ^9 P3 M7 e/ w5 r) m2 Y     77 data:       .word   initrd_start        @ source initrd address
. t. x8 K2 r& r5 T8 b* [, o) K9 J     78         .word   initrd_phys     @ destination initrd address
6 [. p8 ?, u; o" e0 q' V# H( |     79         .word   initrd_size     @ initrd size. k' E  R& ^; w( ~$ \1 j
     804 ]9 d$ V! q/ }  D

. f' t" N/ E, ?- D! w( fline 19,宣告了叫做.start的section
8 D! l, A! {; I4 \/ n. G* lline 20,21宣告了一個叫做_start的function2 @9 K  o) O: ~3 b- O7 ^: s, F9 s
程式碼似乎從line 23開始( v6 y; a) r: @, c$ F5 H
line 23, 『add lr, pc, #-0x8』' L  H2 h4 o/ c2 b: G9 j
add就是將pc+(-0x8)的結果放到lr之中,pc和lr都是ARM裡頭暫存器
8 ]0 m" ]% M7 p. n. e; U2 I! kpc就是program counter,CPU用來指著目前要執行的指令,執行完CPU就會自動把PC+1" y% U3 x8 K9 c; N6 j
這樣就會拿到下一道指令,lr通常是第14個register, r14,常被用來繼續function3 y, f- X% w' M; u. E
return時候的返回位置。奇怪的是為什麼要-0x8??
. V: c- j- H% n( G! q原因應該是ARM本身有pipeline的設計,prefetch->decode->execution,當指令被執行- g, Y7 ]4 k" X  r0 q& R
的時候,其實已經預先去偷偷抓下一道,所以PC值不是真的指在目前執行的地方,三級
1 y1 x  |7 D0 Vpipeline剛好多了兩個cycle所以4 bytes x 2必須要-8才是正在執行指令的位址。! ]" @+ x8 O0 ?9 Y% Z
( `3 B4 r9 G* z5 x
line 24, 『adr r13, data』! N; n3 w( M2 F7 R
adr會去讀取data所在的位址當作值,寫道r13裡頭。r13通常是用來放stack pointer,
* f4 x5 b+ @5 E: Q8 Z常縮寫成sp,所以現在r13就指到data所在的位置上去。6 X1 W1 _" j% a. Q! J3 J- K1 e
: [/ X1 O& R) m
line 25, 『ldmia   r13!, {r4-r6}』* u6 G. @7 v8 i% B; J8 w, B
ldmia, load multiple increment after,顧名思義就是可以做很多次load的動作,每此
, N; u" F; L3 ~: l) Q; ?* pload完就把位址+1,執行完之後+ E6 {; c4 S$ k5 F7 |& u
r4 = initrd_start1 y7 Z1 w& v9 A8 D% M; h% v9 q
r5 = initrd_phys1 G( Z: q: F6 c# q
r6 = initrd_size
2 k0 `: m4 H8 z6 O- g# K" C0 g# ~
line 26, 『add r4, r4, lr』
8 ?8 r! F' s( a0 ]r4 = r4+lr, lr是剛剛我們算過的,指到一開始執行指令的地方,看程式碼的解釋,被當1 ]% O2 f) f' s" d
成載入的位址,所以執行完 r4 = initrd_start+程式被載入的位置,用途不明,看看之4 f: ^5 q! {3 H6 F& f
後有沒有被用到。
' {5 a4 _( s; N& Z5 n
$ d* k% O- ]0 P* q, Kline 27, 『bl  move』
0 M5 {$ I) t9 {$ I: Ubl, b是branch,相當於C語言goto的動作,l就是goto之前,先把目前位置存放到lr裡面,/ R1 }) X( L4 V! z- l$ @
所以bl除了goto之外,也改寫了lr,應該是有利於等一下返回的時候,可以用lr的值。2 v5 V0 l" c4 {: N# a# }  q, B4 J
% N: I, F8 B8 H$ e; X. G
以上,好像還沒開始什麼重點,有空再繼續,有想錯的地方或是需要補充的地方,多多指教~
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享分享 頂2 踩 分享分享
2#
 樓主| 發表於 2008-8-6 18:23:09 | 只看該作者
上面的 code 裡面出現了一些還沒定義的symbol
7 R5 V. @  b$ t2 U3 U0 }1 k例如 initrd_start, initrd_size等等3 p  `3 N+ q- l1 E  f5 L# A
其實是被定義在另外一個檔 ./arch/arm/boot/bootp/initrd.S/ ^, t9 Q- H, i. f4 y9 u+ o

) ~  m1 U+ i% C0 _6 G      1     .type   initrd_start,#object
7 |0 k$ C4 z1 H1 k. w6 k5 ?6 q3 h      2     .globl  initrd_start
, O; a! Q; x6 Z$ D3 F$ u/ S7 B9 z      3 initrd_start:+ p& J8 \' L0 g3 ~9 G2 ^7 h
      4     .incbin INITRD
5 S% H9 K2 l1 j      5     .globl  initrd_end. ^6 r) ]- b/ g' q0 u3 N
      6 initrd_end:" u4 A# i, @& C0 h2 e

: f7 Q0 R8 u* x8 gline 2, 3, 5, 6定義了兩個symbol initrd_start和initrd_end/ `+ Z' P0 v  x/ \% O# j# N
中間還用.incbin INITRD 將 ramdisk 的 image include進來
4 c. U3 q) b7 H5 i# ~這邊有點複雜( w/ f, k: e! d: d
假如compiler kernel的時候
( z( I; N5 ~+ C" l7 I有選擇使用ramdisk當成boot device的話
- Z+ T! M" J$ [' ]會對從環境變數去設置 INITRD 9 L5 ~* y  P, x( ^
這個檔名會被帶入到MAKEFILE( n+ [0 V; q4 L7 Q
並且在做assembler動作的丟進來
  {% p3 E" Z4 e" _6 E4 J假如沒有使用initrd
% _9 L* M7 X4 A1 x/ _那就.incbin應該就包不到東西
0 c/ d; e4 [2 _: f* _9 d' rinitrd_start 和 initrd_end 就會相等7 G9 v7 p$ Y0 Y* v; M( o9 F

: ^4 Q, J3 k9 `5 v7 p1 _- _另外有個 script ./arch/arm/boot/bootp/bootp.lds
; |+ x" E8 i2 r# R1 Z8 n1 n它規範了所有link起來的object code裡面的section要怎麼編排8 q) Z: J4 B1 M( g# m1 x. a
這樣撰寫kernel的時候
! a4 H. ~8 y5 T9 F; k可以到特定的section取得想要的資料或是計算某個section的大小
  \) {* C# w' y$ j. I% ]% @& F+ ]5 J/ }
     10 OUTPUT_ARCH(arm)
/ k9 {: i' F% j' u' ]4 D     11 ENTRY(_start)9 K9 P% [# ]3 X, Q* Y; c: c- q
     12 SECTIONS% Z$ S9 W$ e: O8 _# b& e; {
     13 {
/ q8 f, A- e9 y5 k4 q9 c, q8 R     14   . = 0;( J# A. r" s. F0 L% [. j) a
     15   .text : {
" h+ @1 t, Q" Y$ m" F     16    _stext = .;% c; |3 C- k* i) q) c2 d6 z
     17    *(.start)
0 r9 V% e8 i* f" w1 Q" t% Z     18    *(.text)- u% R9 C+ U% o( J. G
     19    initrd_size = initrd_end - initrd_start;) P3 N: O6 ?" N
     20    _etext = .;" Q) T0 k, W- G! K* g0 G! T
     21   }
3 K: }4 Y" N; W2 n7 N     22
" k( Y  q7 {6 h/ e" ^7 |/ I& @3 N     23   .stab 0 : { *(.stab) }
; j) H: R. H2 W0 V     24   .stabstr 0 : { *(.stabstr) }
% l/ A. V- S" K) K     25   .stab.excl 0 : { *(.stab.excl) }
" R9 D1 j- H4 H4 q( E: c- I; ?1 }) s( V     26   .stab.exclstr 0 : { *(.stab.exclstr) }- |: t% f0 ]- a' s9 g3 ]7 W
     27   .stab.index 0 : { *(.stab.index) }5 t2 K$ S0 m* `% @. d* J
     28   .stab.indexstr 0 : { *(.stab.indexstr) }6 D0 U$ h  J8 B4 Q
     29   .comment 0 : { *(.comment) }* e  }, U, c4 U3 \4 K
     30 }
. S* G& Z7 S! N2 ]7 ]9 U# s  y3 m. O) @4 N5 o$ {) E0 u' r; T
對於object file的格式不熟悉的話1 h% u$ b: U; s) `9 g8 X
可以參考ELF format的相關文件
3#
 樓主| 發表於 2008-8-6 19:50:09 | 只看該作者
接著繼續看 init.S* U9 M6 C8 v. Z6 \
之前的code已經goto到move這邊來( I/ x$ I7 j% v" y! I
所以貼一些move的程式碼; J  u* b% F0 w  `  k: w  j

) ]! ?) }) ?- _8 K- j1 k     66 move:       ldmia   r4!, {r7 - r10}     @ move 32-bytes at a time9 S8 S1 w/ G$ r# n8 s* ^7 K
     67         stmia   r5!, {r7 - r10}9 Y$ K8 K$ P3 e+ F: E* {5 `3 d
     68         ldmia   r4!, {r7 - r10}* Z3 ~5 @+ U8 [( v5 k. Y. A
     69         stmia   r5!, {r7 - r10}
8 E  y6 Y7 _: |1 r     70         subs    r6, r6, #8 * 44 a$ q$ e; d4 Q( u7 G" n7 G
     71         bcs move+ S9 {; \- a( o
     72         mov pc, lr3 j# W5 N7 D8 }6 r7 c

& I+ o9 a5 _9 D% bline 66, 將r4所指到的位置,分別將值讀出來放到r7, r8, r9, r10, 可以發現剛剛計算過的r4這邊被2 C# Z0 O6 ?$ D% A5 f& q/ N8 I8 L
用到了,但是為什麼r4不是用initrd_start,卻還要加上load addr??$ Y+ `5 K2 w5 b; T: C
原因應該是bootp.lds的14行『. = 0;』表示最後被link好的address會從0x0開始
3 U  C  ?% x! a6 D0 m所以 initrd_start 所記錄的位置可以當成是offset7 U2 G0 _) r0 J# z, }1 [4 I
加上load到DRAM或是擺在flash上的位址後& m* h" O& G2 }) e; [% r
就剛好是initrd所在的地方; B( N: |# M1 F8 e) A: v2 v: F
" Q* u, |1 Y. Q- M1 A2 [
line 67, 『stmia   r5!, {r7 - r10}』9 v3 O4 c8 S+ j$ r9 m% t2 O9 ^
stmia, store multiple increment after, 和ldmia動作相同,只是用來寫資料。
# d4 r1 e8 g7 t  }r5是存放著initrd要擺放的位置
, \. o" O0 I6 c/ m猜測應該是為了一開始image放在flash上,但是可以將initrd拷貝到DRAM上
* O3 S% |! K) v/ Y/ P3 L; [8 tr7寫到r5指到的位置
1 r2 E) a& O) Ur8->r5+1
, ?* V0 v, j+ ur9->r5+2
8 [* `! V  E1 O- B4 fr10->r5+3
! j& R$ R; s: ]5 T所以我們發現,66,67行就是將r4所指的東西搬到r5。
% S# u1 H- ^$ x0 ~! b' `
  U0 k2 x, ]/ T' f6 oline 68, 69也是一樣copy了4x4bytes,一共是32bytes。$ `1 Q7 b9 u5 [# [3 b2 N
line 70,『subs    r6, r6, #8 * 4』,將length - 32bytes( D) n5 w; y" H$ U' _. ^7 ^7 M
line 71,『bcs move』,b是branch的意思,cs是表示condition的條件,要是條件符合的話,
6 j1 k' c, D) d) A9 Y! d: @就做branch的動作,這邊的用意是判斷前一個length是不是已經到0,如果不為零就繼續copy。
" A8 L# X$ [$ `. b4 h9 D7 N9 sline 72,『mov pc, lr』9 K% h; x- G, n+ M
接著就把剛剛bl指令預先存放好的lr 填入pc,這樣CPU就會跳回去原本的return address。
+ q- c  s% A0 C. I1 I7 W2 r' _, N  k
以上的動作,慢慢看得出來有在做些什麼事+ L4 b3 y7 V4 z* \2 J+ n
1. 找出initrd的所在位置
4 [' m  j, z! V- k7 n8 n, Q2. 將它copy到一個指定的destination去
4#
 樓主| 發表於 2008-8-7 11:25:39 | 只看該作者
程式返回之後4 Z' L" x  T0 E
我們接著看下一行
  1.      33         ldmia   r13, {r5-r9}        @ get size and addr of initrd; m0 K3 [8 l" ]
  2.      34                         @ r5 = ATAG_CORE
    . g* Z2 L) x0 I, q6 ^! l+ V; G+ l
  3.      35                         @ r6 = ATAG_INITRD26 `# g- \( V% k8 S7 e
  4.      36                         @ r7 = initrd start
    . j2 f1 f. F1 A( s3 ~$ H7 g) }  f
  5.      37                         @ r8 = initrd end6 k. C$ `4 D4 Q/ C# W
  6.      38                         @ r9 = param_struct address
    " ^+ T8 F9 i7 w$ O4 q9 O
  7.      39
    / S0 S  N# c# g
  8.      40         ldr r10, [r9, #4]       @ get first tag
    " m! j+ `( e3 v9 d5 Q8 H
  9.      41         teq r10, r5         @ is it ATAG_CORE?
複製代碼
line 33, 繼續從r13的地方取出資料到r5, r6, r7 ,r8, r9,註解的說明有提到各個資料
7 X2 z! o, n5 e1 u1 \% ^( D2 T! N的意義,注意一下這邊的r7是initrd的destination address不是source address。
" h3 y$ d8 f; K8 r2 j1 W( v: R. E
: |( v  ~+ X5 Q4 _7 xline 40, 讀入第一個tag,這邊的tag是指bootloader丟給kernel的一個boot arguments,
$ H, L8 }* _2 c9 ^, u8 b: N會被用一個叫做ATAG的structure包起來,並且放到系統的某個地方。然後kernel跑init.S,# j. B7 J( ^$ Y$ E! l' P
的時候就會去這個地方拿ATAG的資料,這些資訊包括記憶體要使用多大,螢幕的解析度多大等等。' m8 l9 ]" d. K7 q" O$ s+ z5 n

# ~4 r0 O4 }4 b1 _4 K4 G9 C1 k# ?line 41, t是test, eq是equal, 判斷拿到的第一個tag是不是等於atag core. 應該是看
3 U8 Z4 A/ Y; C) R! patag list 是不是成立的。" Z6 R) J& @+ J, W- U
: u8 V* V' ~/ ?- C* D2 ?
繼續接著看
  1.      45         movne   r10, #0         @ terminator
    $ y6 D- J4 r" e1 H! H* ?
  2.      46         movne   r4, #2          @ Size of this entry (2 words)6 V0 z+ e3 r0 @
  3.      47         stmneia r9, {r4, r5, r10}   @ Size, ATAG_CORE, terminator
複製代碼
發現45, 46, 47的指令都帶有condition "ne", not equal,表示是剛剛 line 41發現atag不成立- V1 n6 _, U% y; B
所做的事情,注釋是寫『If we didn't find a valid tag list, create a dummy ATAG_CORE entry.』
9 I/ P. v3 b; _7 l所以以上三行就是用來創造一個假的entry,假設一切順利這三行指令會bypass過去不會被執行到。
, e. ]) O$ a" L3 x9 g# e, F- Z
; K8 d' I+ y/ j2 `接著來看init.S最後一段程式碼 (終於~)
  1.      54 taglist:    ldr r10, [r9, #0]       @ tag length1 d/ ~& c1 t; {+ D: G1 ]' B
  2.      55         teq r10, #0         @ last tag (zero length)?
    - v& M1 U/ f7 M2 E5 `
  3.      56         addne   r9, r9, r10, lsl #2
    4 w1 [/ R$ d, P$ A
  4.      57         bne taglist; L# g8 `: {$ Z, `5 U  J! q
  5.      58& m+ Q- e  U5 N
  6.      59         mov r5, #4          @ Size of initrd tag (4 words)
    . {( ?, h' s$ O' G
  7.      60         stmia   r9, {r5, r6, r7, r8, r10}7 C$ S3 c  M0 u( K. z0 g; V
  8.      61         b   kernel_start        @ call kernel
複製代碼
line 54, 將r9指到的位址的offset 0x0的值載入到r10。看註解是tag length,所以這邊得要去翻翻atag的規範$ q# [, t' n* I: l4 O" C* s/ w8 h! H8 G4 T
這邊有個文章有提到 http://www.simtec.co.uk/products ... ooting_article.html ,一開
. D& {# j: O3 `2 V8 G始應該是去讀atag_header所看第一個欄位,確認一下是size,應該沒問題。
  1. struct atag_header {0 K( X6 C, J4 z' ~2 D" P: D
  2.         u32 size; /* legth of tag in words including this header */
    - P- B, M) t) Q4 T" P! g
  3.         u32 tag;  /* tag value */
    4 U5 w& c2 u* D& c9 v
  4. };
複製代碼
line 55,測試一下size是不是0。
: D7 [! v8 ^. E% Z  Z7 ?. lline 56, 57也有condition ne,表示是不為0的時候做的。將拿到的length(r10)乘以4,這邊的lsl是將r10往7 c& K7 H- U' J2 ^: X6 y% v1 |) O
左shift的意思,因為一個欄位是4bytes,所以乘4之後就跳到下一個tag,一直跳到最後沒東西。6 K2 |7 V& L# D8 s
& M8 I3 V: I3 W0 s( D
line 59, 將r5設成4
2 Q, y- K# R# I2 W5 ]0 }% Qline 60, 將r5, r6, r7, r8 ,r10存到r9所指到的位置,應該就是跟在atag list的後面。; X4 q. c- a) x4 Z4 U/ Q% l
line 61, jump 到 kernel_start ,注意這邊是用b而不是bl,因為跳過去kernel就不需要返回了。BL會用到4 i6 D! |4 U4 V* k- N5 p! m
lr紀錄返回位置。8 L: x$ p( f+ B" J5 e! q
) n" t6 D: s' @& h! i3 i- K9 O, A) e& D
以上,走過一整個init.S,接著會跳到./arch/arm/boot/compressed/head.S。, j' J% _2 e0 ]8 d7 ?/ e! ]6 J

; t# I) `8 ~2 Gkernel_start的定義方式跟initrd_start有點類似,中間有透過 kernel.S去用.incbin把kernel image包進來。

評分

參與人數 2Chipcoin +5 +2 收起 理由
card_4_girt + 2 無私分享的心更重要,希望你再接再厲
jacky002 + 5 以資鼓勵,再接再厲!

查看全部評分

5#
發表於 2008-8-9 07:44:45 | 只看該作者
好一段時間沒有碰程式了,看到你的分析讓我想起年輕時候的我 ~~~~ 還是不要透漏年齡
6#
 樓主| 發表於 2008-8-9 11:31:33 | 只看該作者
原帖由 jacky002 於 2008-8-9 07:44 AM 發表
2 {, c# [5 H' I% I; m( Q好一段時間沒有碰程式了,看到你的分析讓我想起年輕時候的我 ~~~~ 還是不要透漏年齡

0 u( U, f9 [, e* B, J7 _& H! L9 ]/ f1 g0 `( R

2 b0 O, i0 D% C有些時候  東西是越陳越香啊~~) ?+ I+ h6 P7 E! Q" g' R
...........
7#
 樓主| 發表於 2009-7-16 15:26:26 | 只看該作者
剛剛發現一個大陸網站的blog貼了我的文章! {3 X( Q3 d; M9 }
但是沒表明出處 = =
. t" l3 t; K4 o1 J$ M' x還把標題改過,感覺像是他自己寫的
6 c% C3 R; h1 ]" E5 G: i4 [0 X真是麻煩~8 H$ z( E: y( j3 O$ \# x  Y% T

% |7 |0 f7 Y5 G1 ?" f已經好幾次這樣的經驗# {  b; _; Z7 z7 C# C
以前幫忙有弄網站也是這樣: K; r7 U7 j$ I$ a; t: Q2 B' M
抄襲得很嚴重9 J( `; l) j: B4 Q, _
內地那邊到底有沒有在管啊!!
您需要登錄後才可以回帖 登錄 | 申請會員

本版積分規則

首頁|手機版|Chip123 科技應用創新平台 |新契機國際商機整合股份有限公司

GMT+8, 2024-5-22 06:02 AM , Processed in 0.134518 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表