Saturday 25 May 2019

QEMU 読み会

QEMU は以下のVMの中で作られていて、誰でも gdb で trace できます。

なぜか ARM emulation を読むことに。I/O で止めれば良いんじゃないかと思ったんですが、write とかで停まらない。

  QEMU はARMをX86に変換して実行されて
  system call もそのまま system call に変換される

な、なるほど。今日はユーザモードの方を読むことに。

#0 disas_arm_insn (s=0x7fffffffd3e0, insn=3852271616) at /home/syster_clown/src/qemu-4.0.0/target/arm/translate.c:9180
#1 0x000055555569cc7b in arm_tr_translate_insn (dcbase=0x7fffffffd3e0, cpu=0x555557a94f30)
  at /home/syster_clown/src/qemu-4.0.0/target/arm/translate.c:13483
#2 0x00005555556200eb in translator_loop (ops=0x5555559d8ba0 <arm_translator_ops>, db=0x7fffffffd3e0, cpu=0x555557a94f30,
  tb=0x555555a77040 <static_code_gen_buffer+2272>) at /home/syster_clown/src/qemu-4.0.0/accel/tcg/translator.c:107
#3 0x000055555569d3e4 in gen_intermediate_code (cpu=0x555557a94f30, tb=0x555555a77040 <static_code_gen_buffer+2272>)
  at /home/syster_clown/src/qemu-4.0.0/target/arm/translate.c:13772
#4 0x000055555561e699 in tb_gen_code (cpu=0x555557a94f30, pc=415056, cs_base=0, flags=128, cflags=-16777216)
  at /home/syster_clown/src/qemu-4.0.0/accel/tcg/translate-all.c:1723
#5 0x000055555561bbbe in tb_find (cpu=0x555557a94f30, last_tb=0x0, tb_exit=0, cf_mask=0)
  at /home/syster_clown/src/qemu-4.0.0/accel/tcg/cpu-exec.c:407
#6 0x000055555561c328 in cpu_exec (cpu=0x555557a94f30) at /home/syster_clown/src/qemu-4.0.0/accel/tcg/cpu-exec.c:728
#7 0x000055555565bcf6 in cpu_loop (env=0x555557a9d1f0) at /home/syster_clown/src/qemu-4.0.0/linux-user/arm/cpu_loop.c:218
#8 0x000055555562a725 in main (argc=2, argv=0x7fffffffdea8, envp=0x7fffffffdec0)
  at /home/syster_clown/src/qemu-4.0.0/linux-user/main.c:819

disas_arm_insn で QEMU の中間コード(TCG tiny code generator)に変換します。TB (translation buffer) で管理されてる。

これを、host (この場合はx86)に変換します。

#0 tcg_reg_alloc_op (s=0x555555a5d640 <tcg_init_ctx>, op=0x555557b697e0) at /home/syster_clown/src/qemu-4.0.0/tcg/tcg.c:3471
#1 0x00005555555db4f0 in tcg_gen_code (s=0x555555a5d640 <tcg_init_ctx>, tb=0x555555a77040 <static_code_gen_buffer+2272>)
  at /home/syster_clown/src/qemu-4.0.0/tcg/tcg.c:3981
#2 0x000055555561e733 in tb_gen_code (cpu=0x555557a94f10, pc=415056, cs_base=0, flags=128, cflags=-16777216)
  at /home/syster_clown/src/qemu-4.0.0/accel/tcg/translate-all.c:1751
#3 0x000055555561bbbe in tb_find (cpu=0x555557a94f10, last_tb=0x0, tb_exit=0, cf_mask=0)
  at /home/syster_clown/src/qemu-4.0.0/accel/tcg/cpu-exec.c:407
#4 0x000055555561c328 in cpu_exec (cpu=0x555557a94f10) at /home/syster_clown/src/qemu-4.0.0/accel/tcg/cpu-exec.c:728
#5 0x000055555565bcf6 in cpu_loop (env=0x555557a9d1d0) at /home/syster_clown/src/qemu-4.0.0/linux-user/arm/cpu_loop.c:218
#6 0x000055555562a725 in main (argc=2, argv=0x7fffffffde78,

tcg_reg_alloc_op とかで、s->code_ptr に書出してます。

(gdb) x/20i s->code_ptr - 20
  0x555555a77240 <static_code_gen_buffer+2784>: mov  -0x28(%rbp),%ebx
  0x555555a77243 <static_code_gen_buffer+2787>: test  %ebx,%ebx
  0x555555a77245 <static_code_gen_buffer+2789>: jl   0x555555a7724b <static_code_gen_buffer+2795>
  0x555555a7724b <static_code_gen_buffer+2795>: mov  0x34(%rbp),%ebx
  0x555555a7724e <static_code_gen_buffer+2798>: add  $0xfffffff8,%ebx
  0x555555a77251 <static_code_gen_buffer+2801>: mov  %ebx,%r12d
  0x555555a77254 <static_code_gen_buffer+2804>: add  %al,(%rax)
  0x555555a77256 <static_code_gen_buffer+2806>: add  %al,(%rax

名前のセンスの良い「昔風のANSI-C」で書かれていて超読みやすい。コメントは少なめ。やってることは簡単だし。しかし、

  translate.c は1万4千行

です。明日は paging / TLB を読みたいが...

VM image はここ。2GB くらい。

http://ie.u-ryukyu.ac.jp/~k198584/srcread.vdi

No comments: