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