6.828: Operating System Engineering (3)
とりあえず Ubuntu-box な qemu では動かないのだろう、ということにて tarball を download して
$ ./configure --prefix=/opt --target-list="i386-softmmu x86_64-softmmu" $ make $ sudo make install
した後に以下。
$ /opt/bin/qemu -hda ../lab/obj/kern/kernel.img
一応以下なソレが出力されております。
Booting from Hard Disk... 6828 decimal is XXX octal! entering test_backtrace 5 entering test_backtrace 4 entering test_backtrace 3 entering test_backtrace 2 entering test_backtrace 1 entering test_backtrace 0 leaving test_backtrace 0 leaving test_backtrace 1 leaving test_backtrace 2 leaving test_backtrace 3 leaving test_backtrace 4 leaving test_backtrace 5 Welcome to the JOS kernel monitor! Type 'help' for a list of commands. K>
以下な出力も確認。
K> help help - display this list of commands kerninfo - display information about the kernel K> kerninfo Special kernel symbols: _start f010000c (virt) 0010000c (phys) etext f0101a05 (virt) 00101a05 (phys) edata f0110320 (virt) 00110320 (phys) end f0110980 (virt) 00110980 (phys) Kernel executable memory footprint: 67KB K>
ちょっと Web なテキストと違いますね。
掘削しかけてしまった件
なんとなくソース見てやれ、って思って GNUMakefile を開いて中身を確認しかけたのですが、色々ばたばたしていたので掘削には至らず。
とりあえずテキストの続きを確認入れます。メモがあれば以下に追記予定。
GNUMakefile
そういや make qemu で動くんだったか、と言いつつ実行したら駄目。下記を追加してみました。
# # This makefile system follows the structuring conventions # recommended by Peter Miller in his excellent paper: # # Recursive Make Considered Harmful # http://aegis.sourceforge.net/auug97.pdf # QEMU := /opt/bin/qemu OBJDIR := obj
で、make qemu したら -serial mon:stdio のおかげで qemu なソレだけでなく起動端末でも同様の出力を確認。
The ROM BIOS の項
デバッガで云々な話が出てます。ええと
$ make qemu-gdb
して端末をもういっこ出して lab なディレクトリ (git clone したソレ) に入って
$ gdb GNU gdb (GDB) 7.2-ubuntu Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. + target remote localhost:26000 The target architecture is assumed to be i8086 [f000:fff0] 0xffff0: ljmp $0xf000,$0xe05b 0x0000fff0 in ?? () + symbol-file obj/kern/kernel (gdb)
これはまたお手軽ですね。てか、これはどーゆーレベルで止まってるのかが分かってません。ええとコマンドラインで make qemu-gdb したソレが以下。
$ make qemu-gdb sed "s/localhost:1234/localhost:26000/" < .gdbinit.tmpl > .gdbinit *** *** Now run 'gdb'. *** /opt/bin/qemu -hda obj/kern/kernel.img -serial mon:stdio -S -gdb tcp::26000
これ GNUMakefile の以下な部分のソレだな。
qemu-gdb: $(IMAGES) .gdbinit @echo "***" @echo "*** Now run 'gdb'." 1>&2 @echo "***" $(QEMU) $(QEMUOPTS) -S $(QEMUGDB)
ちなみに .gdbinit 云々は .gdbinit という target があります。
.gdbinit: .gdbinit.tmpl sed "s/localhost:1234/localhost:$(GDBPORT)/" < $^ > $@
とりあえず
起動したソレから si してみるか。
The target architecture is assumed to be i8086 [f000:fff0] 0xffff0: ljmp $0xf000,$0xe05b 0x0000fff0 in ?? () + symbol-file obj/kern/kernel (gdb) (gdb) si [f000:e05b] 0xfe05b: jmp 0xfefdb 0x0000e05b in ?? () (gdb)
ええと 16 * 0xf000 + 0xe05b で 0xfe05b に jmp しとるんかな。また jmp してます。
(gdb) si [f000:efdb] 0xfefdb: mov %cr0,%eax 0x0000efdb in ?? () (gdb)
う。レジスタの確認の方法を忘れとる。ascii の GDB 本を引っ張り出してみたら $eax で良いのか。
(gdb) p %eax A syntax error in expression, near `%eax'. (gdb) p/x $eax $1 = 0x0 (gdb) p/x $cr0 $2 = Value can't be converted to integer. (gdb) p $cr0 $3 = void (gdb)
とほほ void って何だよ。スルーして次を見る。
(gdb) si [f000:efde] 0xfefde: and $0x9fffffff,%eax 0x0000efde in ?? () (gdb)
レジスタの中身を見てみます。
(gdb) p $eax $4 = 1610612752 (gdb) x/i $eax 0x60000010: add %al,(%bx,%si) (gdb)
うう。というかこのあたり BIOS なソレなのか。命令のアドレスを見つつとりあえず si しまくってみます。
(gdb) si [f000:efe4] 0xfefe4: mov %eax,%cr0 0x0000efe4 in ?? () (gdb) si [f000:efe7] 0xfefe7: cli 0x0000efe7 in ?? () (gdb) si [f000:efe8] 0xfefe8: cld 0x0000efe8 in ?? () (gdb) si [f000:efe9] 0xfefe9: mov $0x8f,%eax 0x0000efe9 in ?? () (gdb) si [f000:efef] 0xfefef: out %al,$0x70 0x0000efef in ?? () (gdb) si [f000:eff1] 0xfeff1: in $0x71,%al 0x0000eff1 in ?? () (gdb) si [f000:eff3] 0xfeff3: cmp $0x0,%al 0x0000eff3 in ?? () (gdb) si [f000:eff5] 0xfeff5: jne 0xff00a 0x0000eff5 in ?? () (gdb) si [f000:eff7] 0xfeff7: xor %ax,%ax 0x0000eff7 in ?? () (gdb) si [f000:eff9] 0xfeff9: mov %ax,%ss 0x0000eff9 in ?? () (gdb) si [f000:effb] 0xfeffb: mov $0x7000,%esp 0x0000effb in ?? () (gdb) si [f000:f001] 0xff001: pushl $0xf194b 0x0000f001 in ?? () (gdb) si [f000:f007] 0xff007: jmp 0xffeae 0x0000f007 in ?? () (gdb) si [f000:feae] 0xffeae: mov %eax,%ecx 0x0000feae in ?? () (gdb) si [f000:feb1] 0xffeb1: cli 0x0000feb1 in ?? () (gdb) si [f000:feb2] 0xffeb2: cld 0x0000feb2 in ?? () (gdb) si [f000:feb3] 0xffeb3: mov $0x8f,%eax 0x0000feb3 in ?? () (gdb) si [f000:feb9] 0xffeb9: out %al,$0x70 0x0000feb9 in ?? () (gdb) si [f000:febb] 0xffebb: in $0x71,%al 0x0000febb in ?? () (gdb) si [f000:febd] 0xffebd: in $0x92,%al 0x0000febd in ?? () (gdb) si [f000:febf] 0xffebf: or $0x2,%al 0x0000febf in ?? () (gdb) si [f000:fec1] 0xffec1: out %al,$0x92 0x0000fec1 in ?? () (gdb) si [f000:fec3] 0xffec3: lidtw %cs:0x7a18 0x0000fec3 in ?? () (gdb) si [f000:fec9] 0xffec9: lgdtw %cs:0x7a58 0x0000fec9 in ?? () (gdb) si [f000:fecf] 0xffecf: mov %cr0,%eax 0x0000fecf in ?? () (gdb) si [f000:fed2] 0xffed2: or $0x1,%eax 0x0000fed2 in ?? () (gdb) si [f000:fed6] 0xffed6: mov %eax,%cr0 0x0000fed6 in ?? () (gdb) si [f000:fed9] 0xffed9: ljmpl $0x8,$0xffee1 0x0000fed9 in ?? () (gdb) si The target architecture is assumed to be i386 => 0xffee1: mov $0x10,%eax 0x000ffee1 in ?? () (gdb)
なんかちょっと違うステイトになった気がします。もう少し続行。
(gdb) si => 0xffee6: mov %eax,%ds 0x000ffee6 in ?? () (gdb) si => 0xffee8: mov %eax,%es 0x000ffee8 in ?? () (gdb) si => 0xffeea: mov %eax,%ss 0x000ffeea in ?? () (gdb)
なんかセグメントレジスタに値が代入してるように見えるが。
(gdb) si => 0xffeec: mov %eax,%fs 0x000ffeec in ?? () (gdb) si => 0xffeee: mov %eax,%gs 0x000ffeee in ?? () (gdb) si => 0xffef0: mov %ecx,%eax 0x000ffef0 in ?? () (gdb) si => 0xffef2: ret 0x000ffef2 in ?? () (gdb)
む、ret したぞ。
(gdb) si => 0xf194b: push %ebp 0x000f194b in ?? () (gdb) si => 0xf194c: push %edi 0x000f194c in ?? () (gdb) si => 0xf194d: push %esi 0x000f194d in ?? () (gdb) si => 0xf194e: push %ebx 0x000f194e in ?? () (gdb) si => 0xf194f: sub $0xdc,%esp 0x000f194f in ?? () (gdb) si => 0xf1955: xor %edx,%edx 0x000f1955 in ?? () (gdb) si => 0xf1957: mov %dl,%al 0x000f1957 in ?? () (gdb) si => 0xf1959: out %al,$0xd 0x000f1959 in ?? () (gdb) si => 0xf195b: out %al,$0xda 0x000f195b in ?? () (gdb) si => 0xf195d: mov $0xc0,%al 0x000f195d in ?? () (gdb) si => 0xf195f: out %al,$0xd6 0x000f195f in ?? () (gdb)
まだ BIOS っぽい。違うのかなぁ。
(gdb) si => 0xf1961: mov %dl,%al 0x000f1961 in ?? () (gdb) si => 0xf1963: out %al,$0xd4 0x000f1963 in ?? () (gdb) si => 0xf1965: push $0xf5420 0x000f1965 in ?? () (gdb) si => 0xf196a: push $0xf4f90 0x000f196a in ?? () (gdb) si => 0xf196f: call 0xed965 0x000f196f in ?? () (gdb) si => 0xed965: lea 0x8(%esp),%ecx 0x000ed965 in ?? () (gdb)
なんだか関数呼び出してたり。
(gdb) si => 0xed969: mov 0x4(%esp),%edx 0x000ed969 in ?? () (gdb) si => 0xed96d: mov $0xf7288,%eax 0x000ed96d in ?? () (gdb) si => 0xed972: call 0xed1e0 0x000ed972 in ?? () (gdb) si => 0xed1e0: push %ebp 0x000ed1e0 in ?? () (gdb) si => 0xed1e1: push %edi 0x000ed1e1 in ?? () (gdb) si => 0xed1e2: push %esi 0x000ed1e2 in ?? () (gdb) si => 0xed1e3: push %ebx 0x000ed1e3 in ?? () (gdb)
このあたりは BIOS ROM に書いてある処理だからね、って理解で良いのかどうか。明日時間があればもうすこし地味にこのあたりを確認してみたいと思います。