在前面的文章里面有说过,我在qemu的源码根目录建了个新路径专门来作为分析源码和debug之用。
好了,现在我们打开这个新路径:qemu/bin/debug/native
看过之前文章 关于qemu的二三事(4)————qemu源码的下载与编译,以及fdt 就知道,我再这个路径之下编译了qemu的源码。本来空空如也的文件夹,现在里面已经被填塞了一堆东西:
[root@localhost qemu]# ls bin/debug/native/
chardev hmp.d pc-bios qemu-bridge-helper qmp-commands.h tests
accel.d config-all-devices.mak hmp.o po qemu-bridge-helper.d qmp.d tpm.d
accel.o config-all-disas.mak hw qapi qemu-bridge-helper.o qmp-introspect.c tpm.o
audio config-host.h io qapi-event.c qemu-ga qmp-introspect.d trace
backends config-host.h-timestamp iothread.d qapi-event.d qemu-img qmp-introspect.h trace-events-all
block config-host.mak iothread.o qapi-event.h qemu-img-cmds.h qmp-introspect.o trace-root.c
block.d config.log ivshmem-client qapi-event.o qemu-img.d qmp-marshal.c trace-root.c-timestamp
blockdev.d config.status ivshmem-server qapi-generated qemu-img.o qmp-marshal.d trace-root.d
blockdev-nbd.d contrib libqemustub.a qapi-types.c qemu-io qmp-marshal.o trace-root.h
blockdev-nbd.o cpus-common.d libqemuutil.a qapi-types.d qemu-io-cmds.d qmp.o trace-root.h-timestamp
blockdev.o cpus-common.o linux-headers qapi-types.h qemu-io-cmds.o qobject trace-root.o
blockjob.d crypto linux-user qapi-types.o qemu-io.d qom ui
blockjob.o device-hotplug.d Makefile qapi-visit.c qemu-io.o replay util
block.o device-hotplug.o migration qapi-visit.d qemu-nbd replication.d vl.d
disas module_block.h qapi-visit.h qemu-nbd.d replication.o vl.o
bt-host.d dma-helpers.d nbd qapi-visit.o qemu-nbd.o roms x86_64-softmmu
bt-host.o dma-helpers.o net qdev-monitor.d qemu-options.def slirp x86_64-softmmu-config-devices.mak.d
bt-vhci.d docs os-posix.d qdev-monitor.o qemu-version.h stubs
bt-vhci.o fsdev os-posix.o qdict-test-data.txt qga target
[root@localhost qemu]#
首先看到的就是vl.c文件里面的main函数,main函数是在2971行:
2968 return 0;
2969 }
2970
2971 int main(int argc, char **argv, char **envp)
2972 {
2973 int i;
2974 int snapshot, linux_boot;
2975 const char *initrd_filename;
2976 const char *kernel_filename, *kernel_cmdline;
2977 const char *boot_order = NULL;
2978 const char *boot_once = NULL;
2979 DisplayState *ds;
2980 int cyls, heads, secs, translation;
2981 QemuOpts *opts, *machine_opts;
2982 QemuOpts *hda_opts = NULL, *icount_opts = NULL, *accel_opts = NULL;
2983 QemuOptsList *olist;
... ...
gdb来调试首先要干的事是什么?
打断点啊!
断点打在哪里是门学问。合理的设置断点有助于提高程序调试的效率和速度,闲话少说,我们的第一个断点该设在哪里?
把vl.c里面main函数里面的内容大致过一遍,发现前面很大篇幅都是一些变量、数组、结构体的初始化、一些函数的注册,参数的解析,一直到4082行总算初步参数解析完了,这里只是初步,因为带有子选项的参数还没解析好,或者是说还没有做更进一步的处理,举个简单例子就是后面4201行的smp的参数解析和处理:
4201 smp_parse(qemu_opts_find(qemu_find_opts("smp-opts"), NULL));
4202
4203 machine_class->max_cpus = machine_class->max_cpus ?: 1; /* Default to UP */
4204 if (max_cpus > machine_class->max_cpus) {
4205 error_report("Number of SMP CPUs requested (%d) exceeds max CPUs "
4206 "supported by