|
@@ -678,6 +678,63 @@ void hmp_info_qdm(Monitor *mon, const QDict *qdict)
|
|
|
qdev_print_devinfos(true);
|
|
|
}
|
|
|
|
|
|
+typedef struct QOMCompositionState {
|
|
|
+ Monitor *mon;
|
|
|
+ int indent;
|
|
|
+} QOMCompositionState;
|
|
|
+
|
|
|
+static void print_qom_composition(Monitor *mon, Object *obj, int indent);
|
|
|
+
|
|
|
+static int print_qom_composition_child(Object *obj, void *opaque)
|
|
|
+{
|
|
|
+ QOMCompositionState *s = opaque;
|
|
|
+
|
|
|
+ print_qom_composition(s->mon, obj, s->indent);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void print_qom_composition(Monitor *mon, Object *obj, int indent)
|
|
|
+{
|
|
|
+ QOMCompositionState s = {
|
|
|
+ .mon = mon,
|
|
|
+ .indent = indent + 2,
|
|
|
+ };
|
|
|
+ char *name;
|
|
|
+
|
|
|
+ if (obj == object_get_root()) {
|
|
|
+ name = g_strdup("");
|
|
|
+ } else {
|
|
|
+ name = object_get_canonical_path_component(obj);
|
|
|
+ }
|
|
|
+ monitor_printf(mon, "%*s/%s (%s)\n", indent, "", name,
|
|
|
+ object_get_typename(obj));
|
|
|
+ g_free(name);
|
|
|
+ object_child_foreach(obj, print_qom_composition_child, &s);
|
|
|
+}
|
|
|
+
|
|
|
+void hmp_info_qom_tree(Monitor *mon, const QDict *dict)
|
|
|
+{
|
|
|
+ const char *path = qdict_get_try_str(dict, "path");
|
|
|
+ Object *obj;
|
|
|
+ bool ambiguous = false;
|
|
|
+
|
|
|
+ if (path) {
|
|
|
+ obj = object_resolve_path(path, &ambiguous);
|
|
|
+ if (!obj) {
|
|
|
+ monitor_printf(mon, "Path '%s' could not be resolved.\n", path);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (ambiguous) {
|
|
|
+ monitor_printf(mon, "Warning: Path '%s' is ambiguous.\n", path);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ obj = qdev_get_machine();
|
|
|
+ }
|
|
|
+ print_qom_composition(mon, obj, 0);
|
|
|
+}
|
|
|
+
|
|
|
int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
|
|
{
|
|
|
Error *local_err = NULL;
|