推荐给好友 上一篇 | 下一篇

/sys/i386/i386/locore.s分析笔记

BSD爱好者乐园1| { B._+e1}9db:z:[Q2V

kernel的入口地址是/sys/i386/i386/locore.s中定义的btext:
Ff[jP'y9\5M;Q"Z
.Ws9?/^*p"D5Pv&s200  /**********************************************************************
4pN_2`Mc201   *
E7]4}:@$RC(t~2K202   * This is where the bootblocks start us, set the ball rolling...BSD爱好者乐园"~? SG_2u
203   *
g#z-P9_} _6A204   */
rf/NCsv2e205  NON_GPROF_ENTRY(btext)
E4K*c1g)J*G,qBSD爱好者乐园nm}oca0wtH
从/boot/kernel/kernel中可以读出btext的链接地址:BSD爱好者乐园8X;~FZM^~

$Krlp t/oA!Y0N3]#iC# readelf -a /boot/kernel/kernel | grep btext
] h7`N(L!_Lkt  6870: c0458a30     0 FUNC    GLOBAL DEFAULT    5 btextBSD爱好者乐园:m nGM#zo D;c`
26381: c0458a30     0 FUNC    GLOBAL DEFAULT    5 btextBSD爱好者乐园gqXi,V ^4rX{
BSD爱好者乐园4} ]*y*s1E0S9R
因此,在物理地址0x458a30处设置断点,单步跟踪locore.s中的初始化代码。程序运行至此BSD爱好者乐园#}4Y7}4Sx5W{)zZ-~i
的cpu主要寄存器的内容如下:
8n-v-{6j'Z}oz9fY"b
!E/ZbR+t%trax: 0x00000000:00458a30 rcx: 0x00000000:a0200000BSD爱好者乐园V)L!{6N-B
rdx: 0x00000000:000488a0 rbx: 0x00000000:00458a30BSD爱好者乐园R+_0o7pG3@*@8S"e3L
rsp: 0x00000000:0009e844 rbp: 0x00000000:00094884BSD爱好者乐园ZP;HA0y ^!M
rsi: 0x00000000:000610e4 rdi: 0x00000000:0005b9ccBSD爱好者乐园M9Z l t"N n:Zq,I
r8 : 0x00000000:00000000 r9 : 0x00000000:00000000BSD爱好者乐园 m/f?d ?el
r10: 0x00000000:00000000 r11: 0x00000000:00000000BSD爱好者乐园8g)}d kdL-j2IK
r12: 0x00000000:00000000 r13: 0x00000000:00000000BSD爱好者乐园_!G,U!`)s:O&`/I
r14: 0x00000000:00000000 r15: 0x00000000:00000000BSD爱好者乐园~"v/e"p%w
rip: 0x00000000:00458a30BSD爱好者乐园FTDO$c|
eflags 0x00000002
J \ ~t ?"?'i(R
8T,U-rwq/e:M首先是向0x472写入0x1234,告知bios下次为热引导:BSD爱好者乐园"oH)x[!E SH*v U u

VWY)vq,jR!ud216  /* Tell the bios to warmboot next time */
7Wy;P+LP217          movw    $0x1234,0x472BSD爱好者乐园 i;pqZ S.L
BSD爱好者乐园 e5E9\ ],d0z q*|D*Va H;x
构建一个新的帧:BSD爱好者乐园 D3_f,V^Oz$g
BSD爱好者乐园c? _wz9|CZ
220  /* Set up a real frame in case the double return in newboot is executed. */BSD爱好者乐园c$z6NXs&XE
221          pushl   %ebpBSD爱好者乐园g%H$?#K5mR
222          movl    %esp, %ebp
#QI(Jb{Xu;_BSD爱好者乐园6pnp] h
此时cpu主要寄存器的内容如下:BSD爱好者乐园C#f-LT&h G
BSD爱好者乐园5HY |{jzS)b
rax: 0x00000000:00458a30 rcx: 0x00000000:a0200000BSD爱好者乐园?$m bDK a+v
rdx: 0x00000000:000488a0 rbx: 0x00000000:00458a30
}!jIAVT x9BErsp: 0x00000000:0009e840 rbp: 0x00000000:0009e840BSD爱好者乐园k;nN+T S4M1~
rsi: 0x00000000:000610e4 rdi: 0x00000000:0005b9cc
D:q2L8G!O&y,oMr8 : 0x00000000:00000000 r9 : 0x00000000:00000000
L1}uL4u5H ^+z3Er10: 0x00000000:00000000 r11: 0x00000000:00000000BSD爱好者乐园GuxL(T/O&I*A*|
r12: 0x00000000:00000000 r13: 0x00000000:00000000
4_&e;]C u*Er14: 0x00000000:00000000 r15: 0x00000000:00000000BSD爱好者乐园/\,\?gR xEq
rip: 0x00000000:00458a3c
7M-C'G(u;X;O${eflags 0x00000002BSD爱好者乐园1Aon%_8i
BSD爱好者乐园 mKH_)~O,_r
将PSL_KRENEL赋给eflags:
+?9^#w*z8G1~$@O
|B*NM knM:l f s9f%h224  /* Don't trust what the BIOS gives for eflags. */
(HwG6L({Ma225          pushl   $PSL_KERNELBSD爱好者乐园V-d(Q'tr yqz
226          popfl
A8L9_4NLCBSD爱好者乐园8v`t&@+Aj"C|
PSL_KERNEL是在/sys/i386/include/psl.h中定义的:BSD爱好者乐园ISy}K&l1bh%R

1D ySG w60  /*BSD爱好者乐园\(\\#~#{AK0O
61   * The i486 manual says that we are not supposed to change reserved flags,BSD爱好者乐园o$YA9U:vO
62   * but this is too much trouble since the reserved flags depend on the cpuBSD爱好者乐园.[/B8bOPg:l
63   * and setting them to their historical values works in practice.BSD爱好者乐园Q#o,DW3I(I8A"[)y
64   */BSD爱好者乐园"h1tCUhN`,[#nx
65  #define PSL_RESERVED_DEFAULT    0x00000002BSD爱好者乐园#UZ_3r9s3d9XD
66
]m0xD-]8M TV;v67  /*
L0d+g;AoPU68   * Initial flags for kernel and user mode.  The kernel later inherits
U&kmSR(YTC1S7w69   * PSL_I and some other flags from user mode.BSD爱好者乐园 |I&zi }Dv*p/S^
70   */BSD爱好者乐园2I/| ` h+?y7W Rp
71  #define PSL_KERNEL      PSL_RESERVED_DEFAULTBSD爱好者乐园/SR/l6@*@P
72  #define PSL_USER        (PSL_RESERVED_DEFAULT | PSL_I)BSD爱好者乐园Kt Z*c:PZ l

^8L7a fe f'i将ds的内容赋给fs和gs:BSD爱好者乐园A-u(IO es%R9g
BSD爱好者乐园?9r[1F\U:R2V:B
228  /*
cU!^f }qd;F u229   * Don't trust what the BIOS gives for %fs and %gs.  Trust the bootstrapBSD爱好者乐园(r]fnZ6S Ke
230   * to set %cs, %ds, %es and %ss.
S-d&wZ(z4f+\Z231   */
,}9^&u8V6l Qp"yz232          mov     %ds, %ax
!c[+z*VA_233          mov     %ax, %fsBSD爱好者乐园'P+d%Jtl7w{,gF
234          mov     %ax, %gsBSD爱好者乐园nU}TK2kIn

m;m/~ v{9}BSD爱好者乐园 CAs4a|a],n/qKW
236  /*BSD爱好者乐园%HtY6Bp~;Y
237   * Clear the bss.  Not all boot programs do it, and it is our job anyway.
xY@ G!z k2[ H238   *
~,[7Is%@239   * XXX we don't check that there is memory for our bss and page tables
*TZBK&s2l!O:Lm`240   * before using it.
N.i;UE0b241   *BSD爱好者乐园k*Wj?[0n
242   * Note: we must be careful to not overwrite an active gdt or idt.  They
f A8^7gu XL t@W%~243   * inactive from now until we switch to new ones, since we don't load any
T!||yYZJ244   * more segment registers or permit interrupts until after the switch.BSD爱好者乐园\{ GqAH;F;u#E
245   */BSD爱好者乐园-F4s dqBq(u t6y
246          movl    $R(end),%ecx
J-Q}}7] D247          movl    $R(edata),%ediBSD爱好者乐园Gmzgw
248          subl    %edi,%ecx
G&^/`3O+F*R249          xorl    %eax,%eax
\ bn'v Q J,xA5C250          cldBSD爱好者乐园2j)j3k5P4Nq4}L
251          repBSD爱好者乐园 T)o N2?n~X
252          stosbBSD爱好者乐园 cF?Q Q&Q4d(XI
BSD爱好者乐园 PFdq,bpL:mB;pE
根据readelf -a kernel的结果,end的地址是0xc0c06020,由于KERNBASE是
J#k*p\b*o*]0xc0000000,此处赋给ecx的就是0xc06020。edata的地址是0xc0bab9a0,这实际上就是BSD爱好者乐园 kqCv?*P
.bss段的起始地址,此处赋给edi的就是0xbab9a0。ecx减去edi之后的内容是0x5a680,BSD爱好者乐园Ga3[y*a"X
这是从.bss段起始地址到end地址之间的字节数。随后将eax清0,作为后续清0操作的
's'{9?b}7F xQ写入值。cld保证edi递增变化。stosb将al的内容写入edi指向的位置。这段代码从BSD爱好者乐园d vW2IJ
0xc0bab9a0开始连续写入0x5a680个字节的0,从而实现将.bss段清0的目的。
.a3lT+r3}f3[BSD爱好者乐园L }:n8^(a0U)U]5|e
253
;mPrVk!l ~254          call    recover_bootinfo
?a2p({ kK p!kG x255BSD爱好者乐园QXS7]'A
BSD爱好者乐园Gx2A@z:jjW
调用recover_bootinfo获取由loader传入的引导信息。
I*tF5o8R2J ?~6[%m(m.dBSD爱好者乐园C:BY4A5B i
487          movl    28(%ebp),%ebx           /* &bootinfo.version */BSD爱好者乐园T0wMj y;xR
488          movl    BI_VERSION(%ebx),%eax
;}0IR;^I489          cmpl    $1,%eax                 /* We only understand version 1 */BSD爱好者乐园4r4L j bo [ Q1F&l(Ga
490          je      1f
i%TtL-Ku$q%^491          movl    $1,%eax                 /* Return status */
_*a"WyA+oV492          leaveBSD爱好者乐园,?b n-W(v{
493          /*
qsz8q#P9}Y494           * XXX this returns to our caller's caller (as is required) since
[0X wJ3dX5g.XD_495           * we didn't set up a frame and our caller did.BSD爱好者乐园Pj-x Bw,rf'a
496           */BSD爱好者乐园0Y1E\ b)l1r
497          retBSD爱好者乐园3D/D6j_g
BSD爱好者乐园*heoZiQg:Y
locore.s入口btext的调用格式为(*btext)(howto, bootdev, 0, 0, 0, &bootinfo),在bootinfoBSD爱好者乐园;I9n5s$fm/OV
之后压栈的有5个参数,占20个字节,在加上返回地址和在调用recover_bootinfo之前压栈的ebp,BSD爱好者乐园 Iv q1y W5W
一共有28个字节,因此从当前ebp位置上溯28个字节就是bootinfo结构体的起始地址。上述代码BSD爱好者乐园:F@$H3E%b7? J)l`N
从bootinfo结构体中取出bi_version字段的内容,判断其是否为1,仅当版本为1时才继续处理。
PE"w8X i/vBSD爱好者乐园*wa6J|%J7R
500          /*BSD爱好者乐园 B!hQs"l q%c}
501           * If we have a kernelname copy it in
N@r8}j;^#m502           */BSD爱好者乐园`,m*Z\(aeO6Z8\
503          movl    BI_KERNELNAME(%ebx),%esi
U-@)L Nvd%POq f504          cmpl    $0,%esiBSD爱好者乐园6z n jK*\ ^
505          je      2f                      /* No kernelname */
JR3qQ)Ld*X;i506          movl    $MAXPATHLEN,%ecx        /* Brute force!!! */
gmV4U |/WC507          movl    $R(kernelname),%edi
'{$e1vqX&XkJ O508          cmpb    $'/',(%esi)             /* Make sure it starts with a slash */
Suk p @L"F&d509          je      1f
|Mt0i])a&G;y3k3R#mJ510          movb    $'/',(%edi)BSD爱好者乐园h8g W hM,X!G[O
511          incl    %edi
u~Nz[f+T512          decl    %ecxBSD爱好者乐园9Fx Z,v$}&E
BSD爱好者乐园$g"K7_\j
从bootinfo结构体中取出bi_kernelname字段,写入esi。MAXPATHLEN是最大路径长度,定义为1024,
)?+D-j| QH R这是kernel中的kernelname数组的尺寸。将该数组相对于KERNBASE偏移地址写入edi,并判断由BSD爱好者乐园L(n@9n.FJV PC
bootinfo传入的bi_kernelname是否以"/"开始,若是,则将剩余部分拷入kernelname数组。BSD爱好者乐园5sG h7H E Oq)C QC
BSD爱好者乐园!B8U r+J?#Z+Q }!{@s d7C
519          /*
/b2G$_0|wK520           * Determine the size of the boot loader's copy of the bootinfoBSD爱好者乐园 e _1XGo(Ay {(RN1^oD
521           * struct.  This is impossible to do properly because old versions
7xS"H L"qPt522           * of the struct don't contain a size field and there are 2 oldBSD爱好者乐园K!s!ocV
523           * versions with the same version number.BSD爱好者乐园 B#@%[.PqG Z9p
524           */
Oz?%Bh pL#e s9v.f525          movl    $BI_ENDCOMMON,%ecx      /* prepare for sizeless version */
]j,~6L Qu;SV526          testl   $RB_BOOTINFO,8(%ebp)    /* bi_size (and bootinfo) valid? */BSD爱好者乐园M4e%W$CKygLU)X
527          je      got_bi_size             /* no, sizeless version */
)A H*\wm \528          movl    BI_SIZE(%ebx),%ecxBSD爱好者乐园U8{2E R0};Rq1]b

R"s8~V$?6X6l.p$L:]8V将bootinfo中肯定会存在的字段的结束位置取出,写入ecx,实际上就是前三个字段,12个字节。BSD爱好者乐园 ? | z0jK\ Z
RB_BOOTINFO在/sys/sys/reboot.h中定义为0x80000000,是一个表示是否传入了完整的bootinfoBSD爱好者乐园 ^Ii N{KY
结构体信息的标志。若传入了完整的bootinfo结构体信息,则将bi_size字段的内容赋给ecx。
%@*Oq;NT|:P3a"HBSD爱好者乐园Z0Q,@%r0n|1n9oe u!W
531          /*
#Z'@+v ^[*ZO0X532           * Copy the common part of the bootinfo struct
6Zdd!JX Fh&z-G@T533           */BSD爱好者乐园!r P Xh o1r
534          movl    %ebx,%esi
9m`-b4s/m%w@X|535          movl    $R(bootinfo),%ediBSD爱好者乐园+c4^Y YLwDT
536          cmpl    $BOOTINFO_SIZE,%ecxBSD爱好者乐园9Pw D\"b
537          jbe     got_common_bi_size
!XDEZ8I Lh538          movl    $BOOTINFO_SIZE,%ecx
9a(|R U9Z8i,V6OZLc539  got_common_bi_size:BSD爱好者乐园)PD[T$Z0Xu ad
540          cldBSD爱好者乐园u&X5F+CT)m/Mv
541          repBSD爱好者乐园 C%W"kK|"O#aE*F
542          movsb
*g/elPu1f4[&Z|BSD爱好者乐园Kl l S/glE8p@G:Q
比较传入的bi_size字段的内容与bootinfo结构体的大小是否一致,若传入bi_size小于等于bootinfoBSD爱好者乐园qz#X&nu)g0u f I
结构体的大小,则以bi_size为准,否则以bootinfo结构体的大小为准。将传入的bootinfo信息拷贝
)^9lY i_u+V到bootinfo结构体中。BSD爱好者乐园u}O:X w'A

oX:S*m1D o"C.G562          /*
F)cb P*TA563           * The old style disk boot.
;[Fj*dz#X+O ? `564           *      (*btext)(howto, bootdev, cyloffset, esym);BSD爱好者乐园5q8xO#bpeo;dl
565           * Note that the newer boot code just falls into here to pickBSD爱好者乐园7j"sl.B[jb#c
566           * up howto and bootdev, cyloffset and esym are no longer used
F6DrZs-p4R567           */
J.|9w F1j:v'CI;w@568  olddiskboot:
EL ]4U)W9a x[+H],L569          movl    8(%ebp),%eaxBSD爱好者乐园2k bC2m1u:Nz6h4N
570          movl    %eax,R(boothowto)BSD爱好者乐园 W b4L9`t @*HY]
571          movl    12(%ebp),%eaxBSD爱好者乐园$|2yP`)oF D5I^:L
572          movl    %eax,R(bootdev)BSD爱好者乐园Y V:PW.dS5}
573BSD爱好者乐园G"Ig9ugA
574          ret
7ZGg;O-@(g;h7a9aKBSD爱好者乐园)P8W`0Scj%^+E
分别从入参中取出相关信息存入boothowto和bootdev变量。返回btext。
8d3NU~uBSD爱好者乐园qX{kd
256  /* Get onto a stack that we can trust. */BSD爱好者乐园rh)R'e:F
257  /*
Y}5B2JrP'M:`258   * XXX this step is delayed in case recover_bootinfo needs to return viaBSD爱好者乐园@Xy^~9Y8r
259   * the old stack, but it need not be, since recover_bootinfo actuallyBSD爱好者乐园D$l0Cg9We%S0n
260   * returns via the old frame.BSD爱好者乐园@L8JhA;f#L$[ I-k B
261   */
2K:R L1{z t#s262          movl    $R(tmpstk),%esp
%kP@.`U?BSD爱好者乐园;L5y!RM*r{+m:l
tmpstk是在本文件中定义的一块8192字节的连续空间,此处将esp指向这块空间。
He`ryu.UW实际上,这块空间就紧邻在bootinfo结构体的下面。BSD爱好者乐园:SvV"h [

.\a+y1Xp%hjs;D^b291          call    identify_cpu
/h [^4M2b |Z
?NH ND9p#MaT9j,{获取cpu识别信息。BSD爱好者乐园(L#y}h:@ N d
BSD爱好者乐园d$n(@.GR^
292          call    create_pagetablesBSD爱好者乐园-r`6@ h5mO{[-l

'G1P0b6t*\3W创建第一个页面目录及其页表。BSD爱好者乐园EGmF'|:H

4z2SW2w2E0sM

u,RUNw因为使用范围的限制,BSD方面文章更新速度不快,站长会坚持每天更新博客,欢迎访问!
[版权声明]BSD爱好者乐园站内文章,如来源不是互联网,则均系原创或翻译之作,可随意转载,或以此为基础进行演译,但务必以链接形式注明原始出处和作者信息,否则属于侵权行为。另对本站转载他处文章,俱有说明,如有侵权请联系本人,本人将会在第一时间删除侵权文章。

TAG: 分析 源代码
61/6123456>
 

评分:0

我来说两句

seccode