调试分析Linux 0.00引导程序
Bochs虛擬機(jī)的配置文件
簡(jiǎn)介 Bochs 虛擬機(jī)的配置文件
描述待啟動(dòng)的虛擬機(jī)的配置,例如內(nèi)存大小、啟動(dòng)鏡像、網(wǎng)絡(luò)功能、存儲(chǔ)配置。
Bochs運(yùn)行后,會(huì)先查找配置文件,解析模擬器要虛擬的系統(tǒng)相關(guān)信息后啟動(dòng)系統(tǒng)。
如何設(shè)置從軟驅(qū)啟動(dòng)
floppya: 1_44="Image", status=inserted
boot: a
如何設(shè)置從硬盤啟動(dòng)
ata0-master: type=disk, path="30M.sample", cylinders=615, heads=6, spt=17
boot: disk
如何設(shè)置調(diào)試選項(xiàng)
-
log: bochsout.txt:設(shè)置日志生成文件。 -
config_interface:配置界面,一系列菜單和對(duì)話框。根據(jù)平臺(tái)的不同,有3種配置界面可供選擇。 -
display_library:這一行指定了Bochs如何渲染模擬機(jī)的顯示輸出。
# windows
config_interface: win32config
display_library: win32, options="gui_debug"
# Linux
# display_library: x, options="gui_debug"
# MacOS
# display_library: sdl2
-
win32表示它將使用Windows原生的GUI庫。options="gui_debug"表示在GUI中啟用調(diào)試功能。
Bochs虛擬機(jī)的調(diào)試技巧
如何單步跟蹤?
命令s,或點(diǎn)擊Step(s)。
如何設(shè)置斷點(diǎn)進(jìn)行調(diào)試?
-
vb / vbreak seg:0ffset在虛擬地址上設(shè)置指令斷點(diǎn)。 -
lb / lbreak addr在線性地址上設(shè)置斷點(diǎn)。 -
b / break / pb / pbreak addr在物理地址上設(shè)置斷點(diǎn)。 -
info break顯示當(dāng)前所有斷點(diǎn)的信息。 -
d / del / delete n刪除斷點(diǎn) n。(斷點(diǎn)是從1開始編號(hào)的)
如何查看通用寄存器的值?
registers / reg / r
如何查看系統(tǒng)寄存器的值?
-
sreg查看段寄存器 -
info flags查看標(biāo)志寄存器 -
cr查看控制寄存器
如何查看內(nèi)存指定位置的值?
-
x /nuf addr檢查位于線性地址addr處的內(nèi)存內(nèi)容 -
xp /nuf addr檢查位于物理地址addr處的內(nèi)存內(nèi)容 - 參數(shù)
n:顯示內(nèi)存單元的計(jì)數(shù)值,默認(rèn)為1 - 參數(shù)
u:?jiǎn)卧笮。J(rèn)為w-
b:bytes 1字節(jié) -
h:halfwords 2字節(jié) -
w:words 4字節(jié) -
g:giantwords 8字節(jié)
-
- 參數(shù)
f:顯示格式,默認(rèn)為x-
x:hex 十六進(jìn)制數(shù) -
d:decimal 十進(jìn)制數(shù) -
u:unsigned 無符號(hào)十進(jìn)制 -
o:octal 八進(jìn)制 -
t:binary 二進(jìn)制數(shù) -
c:char 對(duì)應(yīng)的字符
-
如何查看各種表,如 gdt ,idt ,ldt 等?
-
info gdt-
info gdt [num]顯示第num項(xiàng)
-
info idtinfo ldt
如何查看 TSS?
info tss
如何查看棧中的內(nèi)容?
print-stack
如何在內(nèi)存指定地方進(jìn)行反匯編?
u/disasm/disassemble start end-
u /10:反匯編從當(dāng)前地址開始的10條指令
計(jì)算機(jī)引導(dǎo)程序
如何查看 0x7c00 處被裝載了什么?
查看數(shù)據(jù): View -> Linear Dump 輸入 0x7c00。
反匯編:u/disasm/disassemble 0x7c00 end
如何把真正的內(nèi)核程序從硬盤或軟驅(qū)裝載到自己想要放的地方;
調(diào)用BIOS中斷int 0x13功能2從啟動(dòng)盤讀取代碼。
如何查看實(shí)模式的中斷程序?
實(shí)模式的中斷向量表處于內(nèi)存0開始的地方。中斷向量表中中斷向量保存著中斷程序的入口地址。
如何靜態(tài)創(chuàng)建 gdt 與 idt ?
在程序中定義數(shù)據(jù),靜態(tài)輸入對(duì)應(yīng)的gdt與idt的值。
如何從實(shí)模式切換到保護(hù)模式?
控制寄存器CR0位0,為標(biāo)志PE。置位時(shí)為保護(hù)模式,復(fù)位時(shí)為實(shí)模式。
利用lmsw指令,Load Machine State Word,將PE置為1,切換到保護(hù)模式。
調(diào)試跟蹤 jmpi 0,8 ,解釋如何尋址?
此時(shí)不是實(shí)模式下的段基址與偏移地址的尋址方式了。段值已經(jīng)是段選擇子。
0為偏移量,8為段選擇子,對(duì)應(yīng)GDT中的段描述符2。
即從GDT中找到段選擇子為 8的段描述符,然后從段描述符中,取出基地址(base address),與偏移量合成線性地址。
該指令執(zhí)行后,CS:IP即變?yōu)?code>0x8:0x0。
實(shí)驗(yàn)報(bào)告
請(qǐng)簡(jiǎn)述 head.s 的工作原理
- 初始化GDT和IDT,設(shè)置GDHR和IDTR。
- 設(shè)置8253定時(shí)芯片。
- 設(shè)置定時(shí)中斷門描述符和系統(tǒng)調(diào)用陷阱門描述符,分別在IDT表的第8項(xiàng)和第128項(xiàng)。
- 利用
iret命令,跳轉(zhuǎn)到程序 任務(wù)0。
記錄head.s的內(nèi)存分布狀況
簡(jiǎn)述head.s 57至62行在做什么
57至62行:
<57> pushl $0x17 # 堆棧段選擇符(SS)入棧
<58> pushl $init_stack # 堆棧段偏移(SP)入棧
<59> pushfl # 標(biāo)志寄存器入棧
<60> pushl $0x0f # 代碼段選擇符(CS)入棧
<61> pushl $task0 # 代碼段偏移(IP)入棧
<62> iret
因?yàn)楫?dāng)前head.s 程序是內(nèi)核程序,特權(quán)級(jí)別為 0。
由于處于特權(quán)級(jí)0的代碼不能直接把控制權(quán)轉(zhuǎn)移到特權(quán)級(jí)3的代碼中執(zhí)行,但中斷返回操作可以。因此,可以利用中斷返回指令 iret來啟動(dòng)任務(wù)0。
具體操作是,在初始堆棧init_stack中人工設(shè)置一個(gè)返回環(huán)境(初始堆棧也是任務(wù)0的用戶棧):
- 任務(wù)0的 TSS段選擇符加載到任務(wù)寄存器
LTR。 - 任務(wù)0的 LDT段選擇符加載到
LDTR。 - 任務(wù)0的用戶棧指針(
SS:SP),代碼指針(CS:IP)以及標(biāo)志寄存器壓入棧中。 - 執(zhí)行返回中斷指令
iret。彈出棧中內(nèi)容,對(duì)應(yīng)到任務(wù)0的堆棧指針、代碼指針、標(biāo)志寄存器。
簡(jiǎn)述iret執(zhí)行后,pc如何找到下一條指令?
由于在iret前,棧中壓入了代碼指針,即代碼段的段選擇符和偏移量(CS:IP),所以iret后,彈出代碼指針,pc根據(jù)當(dāng)前代碼指針執(zhí)行下一條指令。
記錄 iret 執(zhí)行前后,棧是如何變化的?
執(zhí)行前:可以看到,棧頂自下的5個(gè)內(nèi)容(雙字)分別為 IP、CS、EFLAGS、SP、SS。對(duì)應(yīng)壓棧的順序。
執(zhí)行后:可見,彈出5個(gè)雙字,
當(dāng)任務(wù)進(jìn)行系統(tǒng)調(diào)用時(shí),即 int 0x80 時(shí),記錄棧的變化情況。
任務(wù)0進(jìn)行系統(tǒng)調(diào)用int 0x80前:
SS:0x17 ESP:0x0bd8
CS:0x0F EIP:0x10E9
棧空間為任務(wù)0的用戶棧,即init_stack。
系統(tǒng)調(diào)用后:
SS:0x10 ESP:0x0e4c
CS:0x08 EIP:0x166
棧空間為任務(wù)0的內(nèi)核棧。ESP不為0x0e60,可知棧中壓入了內(nèi)容。
觀察圖,發(fā)現(xiàn)棧中壓入了5個(gè)雙字,由棧頂自下分別為 調(diào)用前的EIP、調(diào)用前的CS、調(diào)用前的EFLAGS、調(diào)用前的ESP、調(diào)用前的SS。
可知,在調(diào)用中斷時(shí),指令int 0x80,會(huì)將當(dāng)前任務(wù)的該 5個(gè)寄存器內(nèi)容壓入調(diào)用后的棧空間中。也就是被調(diào)用者保存。
總結(jié)
以上是生活随笔為你收集整理的调试分析Linux 0.00引导程序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从像素到洞见:图像分类技术的全方位解读
- 下一篇: MyBatis—Spring 动态数据源