Closed tomoyuki-nakabayashi closed 5 years ago
まず形式をどうしようかな。JSONで良いかね?
{"ram":[0,0,0,0,248,0,0,0]}
こんな感じで出力してくれる。
Bochsのコードを眺める。まぁ簡単に出力機能は追加できそうだけど、全体的にコードがひどいな。
http://rkx1209.hatenablog.com/entry/2015/11/20/203511
るくすさんが居なければつらかったな。
cpu-exec.cのcpu_tb_exec()が実質命令実行している(ぽい)。
qom/cpu.c
void cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
if (cc->dump_state) {
cpu_synchronize_state(cpu);
cc->dump_state(cpu, f, cpu_fprintf, flags);
}
}
#define X86_CPU_CLASS(klass) \
OBJECT_CLASS_CHECK(X86CPUClass, (klass), TYPE_X86_CPU)
#define X86_CPU(obj) \
OBJECT_CHECK(X86CPU, (obj), TYPE_X86_CPU)
#define X86_CPU_GET_CLASS(obj) \
OBJECT_GET_CLASS(X86CPUClass, (obj), TYPE_X86_CPU)
CPUClassでdumpを実装している箇所があるはず。
CPUClassの中にdump_stateが関数ポインタとして定義されている。 後はこれがどこで登録されているか、かな。
target/i386/helper.c
void x86_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env;
int eflags, i, nb;
char cc_op_name[32];
static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
eflags = cpu_compute_eflags(env);
#ifdef TARGET_X86_64
...
おったおった。
#if defined(DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)
&& qemu_log_in_addr_range(itb->pc)) {
qemu_log_lock();
int flags = 0;
if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
flags |= CPU_DUMP_FPU;
}
#if defined(TARGET_I386)
flags |= CPU_DUMP_CCOP;
#endif
log_cpu_state(cpu, flags);
qemu_log_unlock();
}
#endif /* DEBUG_DISAS */
ここに戻ると、何がどこまで定義されているんだろう?
DEBUG_DISASは定義されている。
exec-all.h
/* allow to see translation results - the slowdown should be negligible, so we leave it */
#define DEBUG_DISAS
-dオプションで色々吐ける。
$ qemu-system-x86_64 -d ./qemu.log -drive format=raw,file=target/x86_64-blog_os/debug/bootimage-blog_os.bin
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 (x86 only: 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
mmu log MMU-related activities
pcall x86 only: show protected mode far calls/returns/exceptions
cpu_reset show CPU state before CPU resets
unimp log unimplemented functionality
guest_errors log when the guest OS does something invalid (eg accessing a
non-existent register)
nochain do not chain compiled TBs so that "exec" and "cpu" show
complete traces
-d cpu
EAX=0000fe7e EBX=00000000 ECX=00009135 EDX=0000e000
ESI=00000000 EDI=00000000 EBP=00000000 ESP=0000fe6c
EIP=00007824 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0040 00000400 ffffffff 008f9300
CS =f000 000f0000 ffffffff 008f9b00
SS =e000 000e0000 ffffffff 008f9300
DS =e000 000e0000 ffffffff 008f9300
FS =0000 00000000 ffffffff 008f9300
GS =0000 00000000 ffffffff 008f9300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT= 000f6c00 00000037
IDT= 00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000f6e0 CCD=00000001 CCO=LOGICL
EFER=0000000000000000
-Dでログファイルが指定できる。
一瞬で870MBか…。厳しいなぁ。
まぁいいか。
あーBIOSから動くから…。
BIOS(相当のものを)を作るか。 で、0x7c00に飛ぶところからエミュレータを開始しよう。
なるほど。qemuのdumpって毎サイクル吐き出されているわけじゃないみたいだな。 うまく使う必要がありそう。
checkpointとして使うか。
qemu-fromが仕上がってきた。 ↓で公開していないcrateも取ってこれる。
[dependencies]
qemu-from = { git = "https://github.com/tomoyuki-nakabayashi/qemu-from.git" }
自動化はできていないけど、一旦close。
qemuとかなんでもいいんだけど、命令実行後のレジスタやメモリの状態を確認できるようにする必要がある。