前の記事ではあまりにも中身が無かったが、今回も作業ログで中身が無い。
xv6のコンパイル結果のバイナリ
調べてみると、xv6でコンパイルしたコードの中で、オブジェクトとして残っているもので一番多きなものはkernelだった。 kernelをobjdumpしているものとして、kernel.asmが残っている。つまり、これをロードしてシミュレータで流してみると、一応ブートプロセスが辿れるかもしれない。
kernel: file format elf32-littlemips Disassembly of section .text: 80100000 <_start>: .align 2 # By convention, the _start symbol specifies the ELF entry point. .globl _start _start: mfc0 $t0, $COP0_STATUS 80100000: 00 60 08 40 01 00 09 24 25 40 29 01 26 40 09 01 .`.@...$%@).&@.. # Disable interrput li $t1, STATUS_IE or $t0, $t1, $t1 xor $t0, $t0, $t1 # Setup IM registers preparing for enabling interrput ori $t0, $t0, STATUS_IM 80100010: 00 ff 08 35 00 10 09 3c 25 40 09 01 00 60 88 40 ...5...<%@...`.@ lui $t1, STATUS_CU0 >> 16 or $t0, $t0, $t1 mtc0 $t0, $COP0_STATUS # Set up the stack pointer. la $sp, stack + KSTACKSIZE 80100020: 51 80 1d 3c e0 d6 bd 27 10 80 08 3c 84 50 08 25 Q..<...'...<.P.% # Jump to main() la $t0, main jr $t0 80100030: 08 00 00 01 00 00 00 00 00 00 00 00 ............ 8010003c <binit>: struct buf head; } bcache; void binit(void) { 8010003c: 27bdffe0 addiu sp,sp,-32 80100040: afbf001c sw ra,28(sp) 80100044: afbe0018 sw s8,24(sp) 80100048: 03a0f021 move s8,sp struct buf *b; initlock(&bcache.lock, "bcache"); 8010004c: 3c028051 lui v0,0x8051 80100050: 2444d6e0 addiu a0,v0,-10528 80100054: 3c028011 lui v0,0x8011 80100058: 2445b500 addiu a1,v0,-19200 ...
あ、mfc0とmtc0をシミュレータに実装してないや。とりあえず空っぽでいいから実装してみる。 こういう時に、命令の追加を自動化しておくと楽だ。
コンパイルされたバイナリを実行してみる。
さて、実行してみると、何が起きるだろう。PCはとりあえず0x8010_0000を設定して実行してみた。
swimmer_mips --binfile ./kernel --max 10000 --init_pc 80100000 --out debug.log --debug --debug_func --debug_gvar
おお、何となく実行されている。 命令の詳細は表示せずに、通過する関数だけ表示していってみよう。
swimmer_mips --binfile ./kernel --max 10000 --init_pc 80100000 --out debug.log --debug_func > swimmer.log <Finish loading global variable table> <Func: main> <Func: kinit1> <Func: initlock> <Func: freerange> <Func: kvmalloc> <Func: setupkvm> <Func: kalloc> <Func: switchkvm> <Func: mpinit> <Func: cprintf> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: printint> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: consputc> <Func: uartputc> <Func: picinit> <Func: outb> <Info: NewMemory Region is defined. <Func: outb> <Func: outb> <Func: outb> <Func: outb> <Func: outb> <Func: outb> <Func: outb> <Func: outb> ...
うーん、これ本当に合ってるのかな。ソースコード見ながら追い掛けるしかないか。これも勉強だ。 xv6の資料を見ながら、これが本当に正しい動作なのかを確かめる。そして、Swimmerのログ表記が分かりにくかったので、後で直す。