On 25/07/19 05:23, Oleinik, Alexander wrote: > Export normal qemu-system main so it can be called from tests/fuzz/fuzz.c > > Signed-off-by: Alexander Oleinik <alx...@bu.edu> > --- > include/sysemu/sysemu.h | 4 ++++ > vl.c | 21 ++++++++++++++++++++- > 2 files changed, 24 insertions(+), 1 deletion(-) > > diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h > index 984c439ac9..1bb8cf184c 100644 > --- a/include/sysemu/sysemu.h > +++ b/include/sysemu/sysemu.h > @@ -184,6 +184,10 @@ QemuOpts *qemu_get_machine_opts(void); > > bool defaults_enabled(void); > > +#ifdef CONFIG_FUZZ > +int real_main(int argc, char **argv, char **envp); > +#endif > + > extern QemuOptsList qemu_legacy_drive_opts; > extern QemuOptsList qemu_common_drive_opts; > extern QemuOptsList qemu_drive_opts; > diff --git a/vl.c b/vl.c > index b426b32134..b71b99b6f8 100644 > --- a/vl.c > +++ b/vl.c > @@ -130,6 +130,10 @@ int main(int argc, char **argv) > #include "sysemu/iothread.h" > #include "qemu/guest-random.h" > > +#ifdef CONFIG_FUZZ > +#include "tests/libqtest.h" > +#endif > + > #define MAX_VIRTIO_CONSOLES 1 > > static const char *data_dir[16]; > @@ -2853,8 +2857,11 @@ static void user_register_global_props(void) > qemu_opts_foreach(qemu_find_opts("global"), > global_init_func, NULL, NULL); > } > - > +#ifdef CONFIG_FUZZ > +int real_main(int argc, char **argv, char **envp) > +#else > int main(int argc, char **argv, char **envp) > +#endif > { > int i; > int snapshot, linux_boot; > @@ -2903,7 +2910,9 @@ int main(int argc, char **argv, char **envp) > atexit(qemu_run_exit_notifiers); > qemu_init_exec_dir(argv[0]); > > +#ifndef CONFIG_FUZZ // QOM is already set up by the fuzzer. > module_call_init(MODULE_INIT_QOM); > +#endif
You can modify module_call_init to record the modules that have been initialized, and skip the call (i.e. make it idempotent). > qemu_add_opts(&qemu_drive_opts); > qemu_add_drive_opts(&qemu_legacy_drive_opts); > @@ -4196,9 +4205,11 @@ int main(int argc, char **argv, char **envp) > */ > migration_object_init(); > > +#ifndef CONFIG_FUZZ // Already set up by the fuzzer > if (qtest_chrdev) { > qtest_init(qtest_chrdev, qtest_log, &error_fatal); > } > +#endif Here, I suspect the fuzzing target would have qtest_chrdev == NULL, therefore you can assert that qtest_init is only called once. For example, add an assert(!test_log_fp) in the function. > machine_opts = qemu_get_machine_opts(); > kernel_filename = qemu_opt_get(machine_opts, "kernel"); > @@ -4470,6 +4481,14 @@ int main(int argc, char **argv, char **envp) > accel_setup_post(current_machine); > os_setup_post(); > > +/* > + * Return to the fuzzer since it will run qtest programs and run the > + * main_loop > +*/ > +#ifdef CONFIG_FUZZ > + return 0; > +#endif Just place everything up to this point into a new function qemu_init(); for CONFIG_FUZZ that's what you call from LLVMFuzzerInitialize, while for !CONFIG_FUZZ you can call it from main(). All the functions below have no arguments, so the patch is trivial. Paolo > main_loop(); > > gdbserver_cleanup(); >