We can not retrieve target list when do call to module_call_init(MODULE_INIT_QOM) But in future, we need iterate target list inside type_init referenced functions for generate all QOM variants depends on target list(without select the target). So we have to prepare the QOM target list before module_call_init(MODULE_INIT_QOM)
Signed-off-by: Yonggang Luo <[email protected]> --- include/qemu/target-info-qom.h | 4 ++++ system/vl.c | 2 +- target-info-qom.c | 26 +++++++++++++++++++++++++- tests/qtest/fuzz/fuzz.c | 2 +- tests/unit/test-multi-target.c | 20 +++++++++++++------- 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/include/qemu/target-info-qom.h b/include/qemu/target-info-qom.h index ba2e4370afb..031d9ce32a5 100644 --- a/include/qemu/target-info-qom.h +++ b/include/qemu/target-info-qom.h @@ -25,6 +25,10 @@ typedef struct TargetInfoQomClass { OBJECT_DECLARE_TYPE(TargetInfoQom, TargetInfoQomClass, TARGET_INFO) +/* Initialize before MODULE_INIT_QOM; cache is owned by this module. */ +void target_info_qom_init(void); +GSList *target_info_qom_get_targets(void); + void target_info_qom_set_target(void); void target_info_qom_set_target_info(const TargetInfo *ti); diff --git a/system/vl.c b/system/vl.c index fbe580746d3..a7684abdd3a 100644 --- a/system/vl.c +++ b/system/vl.c @@ -2914,7 +2914,7 @@ void qemu_init(int argc, char **argv) os_setup_limits(); - module_call_init(MODULE_INIT_TARGET_INFO); + target_info_qom_init(); target_info_qom_set_target(); module_init_info(qemu_modinfo); diff --git a/target-info-qom.c b/target-info-qom.c index aeeedb7e818..8d3f2b7280b 100644 --- a/target-info-qom.c +++ b/target-info-qom.c @@ -8,6 +8,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" +#include "qemu/module.h" #include "qom/object.h" #include "qemu/target-info-def.h" #include "qemu/target-info-init.h" @@ -34,6 +35,29 @@ static const TypeInfo target_info_parent_type = { DEFINE_TARGET_INFO_TYPE(target_info_parent_type) static const TargetInfo *target_info_ptr; +static GSList *target_info_classes; +static bool target_info_initialized; + +void target_info_qom_init(void) +{ + if (target_info_initialized) { + return; + } + + module_call_init(MODULE_INIT_TARGET_INFO); + /* + * Avoid enumerating target-info classes during QOM registration, + * which can leave unrelated types incomplete. + */ + target_info_classes = object_class_get_list(TYPE_TARGET_INFO, false); + target_info_initialized = true; +} + +GSList *target_info_qom_get_targets(void) +{ + assert(target_info_initialized); + return target_info_classes; +} const TargetInfo *target_info(void) { @@ -42,7 +66,7 @@ const TargetInfo *target_info(void) void target_info_qom_set_target(void) { - g_autoptr(GSList) targets = object_class_get_list(TYPE_TARGET_INFO, false); + GSList *targets = target_info_qom_get_targets(); size_t num_found = g_slist_length(targets); if (num_found != 1) { diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c index a3a131c80f8..570fc0b45b2 100644 --- a/tests/qtest/fuzz/fuzz.c +++ b/tests/qtest/fuzz/fuzz.c @@ -173,7 +173,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) /* Initialize qgraph and modules */ qos_graph_init(); - module_call_init(MODULE_INIT_TARGET_INFO); + target_info_qom_init(); target_info_qom_set_target(); module_call_init(MODULE_INIT_FUZZ_TARGET); module_call_init(MODULE_INIT_QOM); diff --git a/tests/unit/test-multi-target.c b/tests/unit/test-multi-target.c index 89b55bb1632..a91fe8e6d07 100644 --- a/tests/unit/test-multi-target.c +++ b/tests/unit/test-multi-target.c @@ -30,23 +30,29 @@ /* stub for system/main.c */ int (*qemu_main)(void); +static GSList *targets; + static void test_qom_types_are_unique(void) { - module_call_init(MODULE_INIT_TARGET_INFO); - g_autoptr(GSList) targets = object_class_get_list(TYPE_TARGET_INFO, false); g_assert(targets); - const TargetInfo *first_ti = TARGET_INFO_CLASS(targets->data)->target_info; - target_info_qom_set_target_info(first_ti); - - /* register all types */ - module_call_init(MODULE_INIT_QOM); /* trigger type_initialize for all types */ object_class_get_list("", false); + + g_assert_true(targets == target_info_qom_get_targets()); } int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); + target_info_qom_init(); + targets = target_info_qom_get_targets(); + + const TargetInfo *first_ti = TARGET_INFO_CLASS(targets->data)->target_info; + target_info_qom_set_target_info(first_ti); + + /* register all types */ + module_call_init(MODULE_INIT_QOM); + g_test_add_func("/multi-targets/qom-types-are-unique", test_qom_types_are_unique); return g_test_run(); -- 2.55.0.windows.3
