Commit a01ff75f authored by Andreas Färber's avatar Andreas Färber
Browse files

qom: Implement info qom-tree HMP command



To complement qdev's bus-oriented info qtree, info qom-tree
prints a hierarchical view of the QOM composition tree.

By default, the machine composition tree is shown. This can be overriden
by supplying a path argument, such as "info qom-tree /".

Tested-by: default avatarAlistair Francis <alistair.francis@xilinx.com>
Signed-off-by: default avatarAndreas Färber <afaerber@suse.de>
parent c0e6ee9e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1782,6 +1782,8 @@ show balloon information
show device tree
@item info qdm
show qdev device model list
@item info qom-tree
show object composition tree
@item info roms
show roms
@item info tpm
+1 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@

void hmp_info_qtree(Monitor *mon, const QDict *qdict);
void hmp_info_qdm(Monitor *mon, const QDict *qdict);
void hmp_info_qom_tree(Monitor *mon, const QDict *dict);
int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
int qdev_device_help(QemuOpts *opts);
DeviceState *qdev_device_add(QemuOpts *opts);
+7 −0
Original line number Diff line number Diff line
@@ -2889,6 +2889,13 @@ static mon_cmd_t info_cmds[] = {
        .help       = "show qdev device model list",
        .mhandler.cmd = hmp_info_qdm,
    },
    {
        .name       = "qom-tree",
        .args_type  = "path:s?",
        .params     = "[path]",
        .help       = "show QOM composition tree",
        .mhandler.cmd = hmp_info_qom_tree,
    },
    {
        .name       = "roms",
        .args_type  = "",
+57 −0
Original line number Diff line number Diff line
@@ -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;