書籍の記載を確認するために、VirtualBoxのデバッグ機能を使って、MINIX 1.1のブートストラップ(bootblok.s)を見てみました。
・MINIXオペレーティングシステム (ISBN4-7561-0000-7)
⇒「APPENDIX D MINIX再構築ガイド」/「D.1 はじめに」
・MINIXリファレンスマニュアル (ISBN4-535-60004-X-C3055)
⇒「Chapter 3 MINIX インプリメンターガイド」/「3.1 イントロダクション」
⇒「Chapter 3 MINIX インプリメンターガイド」/「3.5 ブートディスケットの構築」/「3.5.1 導入」
1.準備①VirtualBoxの設定
理由はわからないが、VirtualBoxのブレークポイントを利用するために、[設定]-[システム]-[アクセラレーション]-[仮想化支援機能]のチェックボックス[VT-x/AMD-Vを有効化]のチェックを外しておく。
2.準備②MINIX起動ディスクのファイル名を変更
拡張子が無いとVirtualBoxでイメージの選択ができないため、拡張子を付与する。
オリジナルファイル名 | 変更後ファイル名 | 内容(“README_1.1″より) |
---|---|---|
floppy_disk1 | floppy_disk1.img | Boot Disk |
floppy_disk2 | floppy_disk2.img | Root File System |
floppy_disk3 | floppy_disk3.img | /usr |
floppy_disk4 | floppy_disk4.img | /user |
floppy_disk5 | floppy_disk5.img | Kernel, H and Include Sources |
floppy_disk6 | floppy_disk6.img | FS and Lib Sources |
floppy_disk7 | floppy_disk7.img | MM and Tools Sources |
floppy_disk8 | floppy_disk8.img | Commands Sources |
3.VirtualBoxでイメージを選択しデバッグ起動
VirtualBoxのフロッピーデバイス0に「floppy_disk1.img」を選択し、下記コマンドを用いて起動する。
“C:\Program Files\Oracle\VirtualBox\VBoxManage.exe” startvm “Minix_v1.1” -E VBOX_GUI_DBG_AUTO_SHOW=true -E VBOX_GUI_DBG_ENABLED=true
※”Minix_v1.1″は仮想マシン名。
※起動すると一時停止状態になる。
(他の起動方法)
“C:\Program Files\Oracle\VirtualBox\VirtualBoxVM.exe” –startvm “Minix_v1.1” –dbg
※一時停止状態ではなく、動作する。
4.使用するデバッグコマンドを確認
ウィンドウ「VBox Dbg – Console」のテキストボックス「Command」へ、「help commands」と入力し[Enter]キーを押下。
※一部抜粋。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
br <address> [passes [max passes]] [cmds] Sets a recompiler specific breakpoint. db [addr] Dump memory in bytes. g Continue execution. p [count] [cmds] Step over. r [reg [[=] newval]] Show or set register(s) - active reg set. t [count] [cmds] Trace . u [addr] Unassemble. stop Stop execution. |
※ウィンドウ「VBox Dbg – Console」が表示されていない場合、仮想マシンのウィンドウのメニュー[デバッグ]-[コマンドライン]で、表示できる。
※参考 – 「help commands」の結果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
Welcome to the VirtualBox Debugger! Current VM is 09a80000, CPU #0 VBoxDbg> help commands Commands for CodeView/WinDbg emulation: ba <access> <size> <address> [passes [max passes]] [cmds] Sets a data access breakpoint. bc all | <bp#> [bp# []] Deletes a set of breakpoints. bd all | <bp#> [bp# []] Disables a set of breakpoints. be all | <bp#> [bp# []] Enables a set of breakpoints. bl Lists all the breakpoints. bp <address> [passes [max passes]] [cmds] Sets a breakpoint (int 3). br <address> [passes [max passes]] [cmds] Sets a recompiler specific breakpoint. d [addr] Dump memory using last element size and type. dF [addr] Dump memory as far 16:16. dFs [addr] Dump memory as far 16:16 with near symbols. da [addr] Dump memory as ascii string. db [addr] Dump memory in bytes. dd [addr] Dump memory in double words. dds [addr] Dump memory as double words with near symbols. da [addr] Dump memory as ascii string. dg [sel [..]] Dump the global descriptor table (GDT). dga [sel [..]] Dump the global descriptor table (GDT) including not-present entries. di [int [..]] Dump the interrupt descriptor table (IDT). dia [int [..]] Dump the interrupt descriptor table (IDT) including not-present entries. dl [sel [..]] Dump the local descriptor table (LDT). dla [sel [..]] Dump the local descriptor table (LDT) including not-present entries. dpd [addr|index] Dumps page directory entries of the default context. dpda [addr] Dumps memory at given address as a page directory. dpdb [addr|index] Dumps page directory entries of the guest and the hypervisor. dpdg [addr|index] Dumps page directory entries of the guest. dpdh [addr|index] Dumps page directory entries of the hypervisor. dph [addr [cr3 [mode]] Dumps the paging hierarchy at for specfied address range. Default context. dphg [addr [cr3 [mode]] Dumps the paging hierarchy at for specfied address range. Guest context. dphh [addr [cr3 [mode]] Dumps the paging hierarchy at for specfied address range. Hypervisor context. dp [addr] Dump memory in mode sized words. dps [addr] Dump memory in mode sized words with near symbols. dpt <addr> Dumps page table entries of the default context. dpta <addr> Dumps memory at given address as a page table. dptb <addr> Dumps page table entries of the guest and the hypervisor. dptg <addr> Dumps page table entries of the guest. dpth <addr> Dumps page table entries of the hypervisor. dq [addr] Dump memory in quad words. dqs [addr] Dump memory as quad words with near symbols. dt [tss|tss:ign|addr] Dump the task state segment (TSS). dt16 [tss|tss:ign|addr] Dump the 16-bit task state segment (TSS). dt32 [tss|tss:ign|addr] Dump the 32-bit task state segment (TSS). dt64 [tss|tss:ign|addr] Dump the 64-bit task state segment (TSS). dti <type> [levels] Dump type information. dtv <type> <addr> [levels] Dump a memory buffer using the information in the given type. du [addr] Dump memory as unicode string (little endian). dw [addr] Dump memory in words. eb <addr> <value> Write a 1-byte value to memory. ew <addr> <value> Write a 2-byte value to memory. ed <addr> <value> Write a 4-byte value to memory. eq <addr> <value> Write a 8-byte value to memory. g Continue execution. gu Go up - continue execution till after return. k Callstack. kv Verbose callstack. kg Callstack - guest. kgv Verbose callstack - guest. kh Callstack - hypervisor. lm [module [..]] List modules. lmv [module [..]] List modules, verbose. lmo [module [..]] List modules and their segments. lmov [module [..]] List modules and their segments, verbose. ln [addr/sym [..]] List symbols near to the address. Default address is CS:EIP. ls [addr] Source. m <addr> Display information about that piece of memory. p [count] [cmds] Step over. pr Toggle displaying registers for tracing & stepping (no code executed). pa <addr> [count] [cmds] Step to the given address. pc [count] [cmds] Step to the next call instruction. pt [count] [cmds] Step to the next return instruction. r [reg [[=] newval]] Show or set register(s) - active reg set. rg [reg [[=] newval]] Show or set register(s) - guest reg set. rg32 Show 32-bit guest registers. rg64 Show 64-bit guest registers. rh [reg [[=] newval]] Show or set register(s) - hypervisor reg set. rt Toggles terse / verbose register info. s [options] <range> <pattern> Continue last search. sa <range> <pattern> Search memory for an ascii string. sb <range> <pattern> Search memory for one or more bytes. sd <range> <pattern> Search memory for one or more double words. sq <range> <pattern> Search memory for one or more quad words. su <range> <pattern> Search memory for an unicode string. sw <range> <pattern> Search memory for one or more words. sx [<event> [..]] Lists settings for exceptions, exits and other events. All if no filter is specified. sx- -c <cmd> <event> [..] Modifies the command for one or more exceptions, exits or other event. 'all' addresses all. sxe [-c <cmd>] <event> [..] Enable: Break into the debugger on the specified exceptions, exits and other events. 'all' addresses all. sxn [-c <cmd>] <event> [..] Notify: Display info in the debugger and continue on the specified exceptions, exits and other events. 'all' addresses all. sxi [-c <cmd>] <event> [..] Ignore: Ignore the specified exceptions, exits and other events ('all' = all of them). Without the -c option, the guest runs like normal. sxr Reset the settings to default for exceptions, exits and other events. All if no filter is specified. t [count] [cmds] Trace . tr Toggle displaying registers for tracing & stepping (no code executed). ta <addr> [count] [cmds] Trace to the given address. tc [count] [cmds] Trace to the next call instruction. tt [count] [cmds] Trace to the next return instruction. u [addr] Unassemble. u64 [addr] Unassemble 64-bit code. u32 [addr] Unassemble 32-bit code. u16 [addr] Unassemble 16-bit code. uv86 [addr] Unassemble 16-bit code with v8086/real mode addressing. ucfg [addr] Unassemble creating a control flow graph. ucfgc [addr] Unassemble creating a control flow graph with colors. Common Commands: bye Exits the debugger. cpu [idCpu] If no argument, display the current CPU, else change to the specified CPU. echo <str1> [str2..[strN]] Displays the strings separated by one blank space and the last one followed by a newline. exit Exits the debugger. format Evaluates an expression and formats it. detect Detects or re-detects the guest os and starts the OS specific digger. dmesg [N last messages] Displays the guest os kernel messages, if available. dumpimage <addr1> [addr2..[addrN]] Dumps executable images. harakiri Kills debugger process. help [cmd/op [..]] Display help. For help about info items try 'info help'. info <info> [args] Display info register in the DBGF. For a list of info items try 'info help'. loadimage <filename> <address> [name] Loads the symbols of an executable image at the specified address. loadimage32 <filename> <address> [name] loadimage variant for selecting 32-bit images (mach-o). loadimage64 <filename> <address> [name] loadimage variant for selecting 64-bit images (mach-o). loadinmem <address> [name] Tries to load a image mapped at the given address. loadmap <filename> <address> [name] [subtrahend] [seg] Loads the symbols from a map file, usually at a specified address. loadplugin <plugin1> [plugin2..N] Loads one or more plugins loadseg <filename> <address> <seg> [name] Loads the symbols of a segment in the executable image at the specified address. loadvars <filename> Load variables from file. One per line, same as the args to the set command. log [group string] Displays or modifies the logging group settings (VBOX_LOG) logdest [dest string] Displays or modifies the logging destination (VBOX_LOG_DEST). logflags [flags string] Displays or modifies the logging flags (VBOX_LOG_FLAGS). logflush Flushes the log buffers. quit Exits the debugger. runscript <filename> Runs the command listed in the script. Lines starting with '#' (after removing blanks) are comment. blank lines are ignored. Stops on failure. set <var> <value> Sets a global variable. showvars List all the defined variables. stop Stop execution. unload <modname1> [modname2..N] Unloads one or more modules in the current address space. unloadplugin <plugin1> [plugin2..N] Unloads one or more plugins. unset <var1> [var1..[varN]] Unsets (delete) one or more global variables. writecore <filename> Write core to file. External Commands: injecterror Inject error into I/O subsystem. alliem [boolean] Enables or disabled executing ALL code in IEM, if no arguments are given it displays the current status. patmon Enable patching. patmoff Disable patching. csamon Enable CSAM code scanning. csamoff Disable CSAM code scanning. remstep [on/off] Enable or disable the single stepping with logged disassembly. If no arguments show the current state. pgmsync Sync the CR3 page. pgmerror Enables inject runtime of errors into parts of PGM. pgmerroroff Disables inject runtime errors into parts of PGM. pgmsyncalways Toggle permanent CR3 syncing. pgmphystofile Save the physical memory to file. pgmpoolcheck Check the pgm pool pages. stats [pattern] Display statistics. statsreset [pattern] Resets statistics. VBoxDbg> |
5.ブレークポイントへブートプログラムの開始番地(0x7c00)を追加
ウィンドウ「VBox Dbg – Console」のテキストボックス「Command」へ、「br 0x7c00」と入力し[Enter]キーを押下。
6.仮想マシンを再開
再開し暫くすると、設定したブレークポイントで、中断し、ウィンドウ「VBox Dbg – Console」へ、アドレス「0000:00007c00」で、中断した旨が、表示される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
Welcome to the VirtualBox Debugger! Current VM is 099d0000, CPU #0 VBoxDbg> br 0x7c00 Set REM breakpoint 28 at 0000000000007c00 VBoxDbg> dbgf event: Breakpoint 28! (rem) eax=0000aa55 ebx=00000000 ecx=00000001 edx=00000000 esi=00000000 edi=0000fff0 eip=00007c00 esp=00007800 ebp=00000000 iopl=0 nv up ei pl zr na po nc cs=0000 ds=0000 es=0000 fs=0000 gs=0000 ss=0000 eflags=00200246 Looking for 'F:\tinderbox\win-6.0\out\win.amd64\release\obj\VMMRC\VMMRC.pdb' w/ cache subdir 'B21A97ADD3DE42519576F8C1C0BD39EE1' and 0xd4000014 flags... Path list entry: 'C:\Program Files\Oracle\VirtualBox\VBoxDbgSyms/' Dir does not exist: 'C:/Program Files/Oracle/VirtualBox/VBoxDbgSyms/' Path list entry: 'C:\Program Files\Oracle\VirtualBox' Path list entry: 'C:\■■■■■■■■■■■■■■■■■\Minix_v1.1/debug/' Dir does not exist: 'C:/■■■■■■■■■■■■■■■■■/Minix_v1.1/debug/' Path list entry: 'C:\■■■■■■■■■■■■■■■■■\Minix_v1.1/' Path list entry: 'C:\■■■■■■■■■\' Looking for 'F:\tinderbox\win-6.0\out\win.amd64\release\obj\VBoxDDRC\VBoxDDRC.pdb' w/ cache subdir '29F5E12563A749D78778B99DBE9A084A1' and 0xd4000014 flags... Path list entry: 'C:\Program Files\Oracle\VirtualBox\VBoxDbgSyms/' Dir does not exist: 'C:/Program Files/Oracle/VirtualBox/VBoxDbgSyms/' Path list entry: 'C:\Program Files\Oracle\VirtualBox' Path list entry: 'C:\■■■■■■■■■■■■■■■■■\Minix_v1.1/debug/' Dir does not exist: 'C:/■■■■■■■■■■■■■■■■■/Minix_v1.1/debug/' Path list entry: 'C:\■■■■■■■■■■■■■■■■■\Minix_v1.1/' Path list entry: 'C:\■■■■■■■■■\' 0000:00007c00 b8 c0 07 mov ax, 007c0h VBoxDbg> |
7.0x7c00へロードされているプログラムとブートストラップ(bootblok.s)を比較
0x7c00へロードされているプログラムを表示するために、ウィンドウ「VBox Dbg – Console」のテキストボックス「Command」へ、「u」と入力し[Enter]キーを押下。
1 2 3 4 5 6 7 8 9 10 11 12 |
VBoxDbg> u 0000:00007c00 b8 c0 07 mov ax, 007c0h 0000:00007c03 8e d8 mov ds, ax 0000:00007c05 33 f6 xor si, si 0000:00007c07 b8 e0 2f mov ax, 02fe0h 0000:00007c0a 8e c0 mov es, ax 0000:00007c0c 33 ff xor di, di 0000:00007c0e b9 00 01 mov cx, 00100h 0000:00007c11 f3 a5 rep movsw 0000:00007c13 ea 18 00 e0 2f jmp far 02fe0h:00018h 0000:00007c18 8c ca mov dx, cs VBoxDbg> |
[ブートストラップ(bootblok.s)の抜粋]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
…省略… | Summary of the words patched into the boot block by build: | Word at 504: # sectors to load | Word at 506: # DS value for fsck | Word at 508: # PC value for fsck | Word at 510: # CS value for fsck | | This version of the boot block must be assembled without separate I & D | space. LOADSEG = 0x0060 | here the boot block will start loading BIOSSEG = 0x07C0 | here the boot block itself is loaded BOOTSEG = 0x2FE0 | here it will copy itself (192K-512b) DSKBASE = 120 | 120 = 4 * 0x1E = ptr to disk parameters final = 504 fsck_ds = 506 fsck_pc = 508 fsck_cs = 510 .globl begtext, begdata, begbss, endtext, enddata, endbss | asld needs these .text begtext: .data begdata: .bss begbss: .text | copy bootblock to bootseg mov ax,#BIOSSEG mov ds,ax xor si,si | ds:si - original block mov ax,#BOOTSEG mov es,ax xor di,di | es:di - new block mov cx,#256 | # words to move rep movw | copy loop | start boot procedure jmpi start,BOOTSEG | set cs to bootseg start: mov dx,cs mov ds,dx | set ds to cs xor ax,ax mov es,ax | set es to 0 mov ss,ax | set ss to 0 mov sp,#1024 | initialize sp (top of vector table) …省略… |
8.最後に、ブートストラップ処理を見るためにステップ実行
※「t」、「p」、「br」、「g」などを使用する。
※理由はわからないが、「g」コマンドは、「t」コマンドなどのステップ実行後でないと動作しない。
※「0000:00007c11 rep movsw」は、繰り返しのため、下記は、「0000:00007c13 jmp far 02fe0h:00018h」へブレークポイントを設定した例である。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
VBoxDbg> <strong>t</strong> VBoxDbg> dbgf event: Single step! (rem) eax=000007c0 ebx=00000000 ecx=00000001 edx=00000000 esi=00000000 edi=0000fff0 eip=00007c03 esp=00007800 ebp=00000000 iopl=0 nv up ei pl zr na po nc cs=0000 ds=0000 es=0000 fs=0000 gs=0000 ss=0000 eflags=00200246 0000:00007c03 8e d8 mov ds, ax VBoxDbg> <strong>br 0000:00007c13</strong> Set REM breakpoint 29 at 0000000000007c13 VBoxDbg> <strong>g</strong> VBoxDbg> dbgf event: Breakpoint 29! (rem) eax=00002fe0 ebx=00000000 ecx=00000000 edx=00000000 esi=00000200 edi=00000200 eip=00007c13 esp=00007800 ebp=00000000 iopl=0 nv up ei pl zr na po nc cs=0000 ds=07c0 es=2fe0 fs=0000 gs=0000 ss=0000 eflags=00200246 0000:00007c13 ea 18 00 e0 2f jmp far 02fe0h:00018h VBoxDbg> |