Qemu中翻译的主要框架位于cpu-exec.c中的cpu_exec()函数。For (;;) { If (setjmp(env->jmp_env) == 0) { // exception handling For (;;) { // longjmp if there is an exception has been requested Tb_find_fast() // Look up translation block. ... Tb_add_jump() // Chaining ... Tcg_qemu_tb_exec() // Execute the translation block } } }外循环一开始设jump context为了将来中断处理作准备,内循环中检查是否有中断,有的话跳到前面设置的jump context处,另外内循环中主要做翻译和执行翻译的code。tb_find_fast()用于找要执行的code是否已经被翻译:Tb_find_fast() // search the fast lookup table(env->tb_jmp_cache) If not found Tb_find_slow() // search the slow lookup table(physical page table – tb_phys_hash) If not found Tb_gen_code() // do translation else // add to fast lookup table else return其中tb_gen_code开始翻译:Tb_gen_code() // alloc translation block Cpu_gen_code() // add to slow lookup tableCpu_gen_code() Gen_intermediate_code() // phase 1 Gen_intermediate_code_internal() Disas_insn() Tcg_gen_code // phase 2 Tcg_gen_code_common() 翻译分为两个阶段: 阶段1:guest代码到中间表示(称为micro operation)。这个阶段的实现代码主要在target-ARCH这个目录下,产生结果放在gen_opc_buf(TCG opcode)和gen_opparam_buf(TCG operand)中。 阶段2:中间表示到host代码。这个阶段的实现代码主要在tcg目录下。产生结果放在gen_code_buf中。翻译完了该执行翻译的代码了:Tcg_qemu_tb_exec() Code_gen_prologue // generated by tcg_target_qemu_prologue() when initialization.Code_gen_prologue // prologue: callee saved registers, reserve stack space, etc. // jump to translated code // epilogue: restore register and stack, etc. 在Android的emulator中,Qemu为我们提供了一些有力的调试工具,如1. Monitor,这个工具可以让用户在Qemu运行过程中与之交互并且加以控制。首先加启动参数: $ Emulator.exe –avd test –qemu -monitor telnet::1235,server,nowait接着用telnet连上: (telnet) o localhost 1235然后就应该能看到Qemu shell提示符了。之后就可以运行monitor提供的命令了。2. Log。启动时加参数-qemu -d可以根据需要打出log:Log items (comma separated): out_asm show generated host assembly code for each compiled TB in_asm show target assembly code for each compiled TB op show micro ops for each compiled TB op_opt show micro ops before eflags optimization and after liveness analysis int show interrupts/exceptions in short format exec show trace before each executed TB (lots of logs) cpu show CPU state before block translation pcall show protected mode far calls/returns/exceptions cpu_reset show CPU state before CPU resets比如加in_asm,out_asm就能把guest code和翻译好的host code打印出来:IN: 0xfffffff0: ljmp $0xf000,$0xe05bOUT: [size=32] 0x06614020: mov $0xf000,%eax 0x06614025: movzwl %ax,%eax 0x06614028: mov %eax,0x50(%ebp) 0x0661402b: shl $0x4,%eax 0x0661402e: mov %eax,0x54(%ebp) 0x06614031: mov $0xe05b,%eax 0x06614036: mov %eax,0x20(%ebp) 0x06614039: xor %eax,%eax 0x0661403b: jmp 0x844548