cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

qobject-output-visitor.c (8506B)


      1/*
      2 * Core Definitions for QAPI/QMP Command Registry
      3 *
      4 * Copyright (C) 2012-2016 Red Hat, Inc.
      5 * Copyright IBM, Corp. 2011
      6 *
      7 * Authors:
      8 *  Anthony Liguori   <aliguori@us.ibm.com>
      9 *
     10 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
     11 * See the COPYING.LIB file in the top-level directory.
     12 *
     13 */
     14
     15#include "qemu/osdep.h"
     16#include "qapi/compat-policy.h"
     17#include "qapi/qobject-output-visitor.h"
     18#include "qapi/visitor-impl.h"
     19#include "qemu/queue.h"
     20#include "qapi/qmp/qbool.h"
     21#include "qapi/qmp/qdict.h"
     22#include "qapi/qmp/qlist.h"
     23#include "qapi/qmp/qnull.h"
     24#include "qapi/qmp/qnum.h"
     25#include "qapi/qmp/qstring.h"
     26
     27typedef struct QStackEntry {
     28    QObject *value;
     29    void *qapi; /* sanity check that caller uses same pointer */
     30    QSLIST_ENTRY(QStackEntry) node;
     31} QStackEntry;
     32
     33struct QObjectOutputVisitor {
     34    Visitor visitor;
     35    CompatPolicyOutput deprecated_policy;
     36
     37    QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */
     38    QObject *root; /* Root of the output visit */
     39    QObject **result; /* User's storage location for result */
     40};
     41
     42#define qobject_output_add(qov, name, value) \
     43    qobject_output_add_obj(qov, name, QOBJECT(value))
     44#define qobject_output_push(qov, value, qapi) \
     45    qobject_output_push_obj(qov, QOBJECT(value), qapi)
     46
     47static QObjectOutputVisitor *to_qov(Visitor *v)
     48{
     49    return container_of(v, QObjectOutputVisitor, visitor);
     50}
     51
     52/* Push @value onto the stack of current QObjects being built */
     53static void qobject_output_push_obj(QObjectOutputVisitor *qov, QObject *value,
     54                                    void *qapi)
     55{
     56    QStackEntry *e = g_malloc0(sizeof(*e));
     57
     58    assert(qov->root);
     59    assert(value);
     60    e->value = value;
     61    e->qapi = qapi;
     62    QSLIST_INSERT_HEAD(&qov->stack, e, node);
     63}
     64
     65/* Pop a value off the stack of QObjects being built, and return it. */
     66static QObject *qobject_output_pop(QObjectOutputVisitor *qov, void *qapi)
     67{
     68    QStackEntry *e = QSLIST_FIRST(&qov->stack);
     69    QObject *value;
     70
     71    assert(e);
     72    assert(e->qapi == qapi);
     73    QSLIST_REMOVE_HEAD(&qov->stack, node);
     74    value = e->value;
     75    assert(value);
     76    g_free(e);
     77    return value;
     78}
     79
     80/* Add @value to the current QObject being built.
     81 * If the stack is visiting a dictionary or list, @value is now owned
     82 * by that container. Otherwise, @value is now the root.  */
     83static void qobject_output_add_obj(QObjectOutputVisitor *qov, const char *name,
     84                                   QObject *value)
     85{
     86    QStackEntry *e = QSLIST_FIRST(&qov->stack);
     87    QObject *cur = e ? e->value : NULL;
     88
     89    if (!cur) {
     90        /* Don't allow reuse of visitor on more than one root */
     91        assert(!qov->root);
     92        qov->root = value;
     93    } else {
     94        switch (qobject_type(cur)) {
     95        case QTYPE_QDICT:
     96            assert(name);
     97            qdict_put_obj(qobject_to(QDict, cur), name, value);
     98            break;
     99        case QTYPE_QLIST:
    100            assert(!name);
    101            qlist_append_obj(qobject_to(QList, cur), value);
    102            break;
    103        default:
    104            g_assert_not_reached();
    105        }
    106    }
    107}
    108
    109static bool qobject_output_start_struct(Visitor *v, const char *name,
    110                                        void **obj, size_t unused, Error **errp)
    111{
    112    QObjectOutputVisitor *qov = to_qov(v);
    113    QDict *dict = qdict_new();
    114
    115    qobject_output_add(qov, name, dict);
    116    qobject_output_push(qov, dict, obj);
    117    return true;
    118}
    119
    120static void qobject_output_end_struct(Visitor *v, void **obj)
    121{
    122    QObjectOutputVisitor *qov = to_qov(v);
    123    QObject *value = qobject_output_pop(qov, obj);
    124    assert(qobject_type(value) == QTYPE_QDICT);
    125}
    126
    127static bool qobject_output_start_list(Visitor *v, const char *name,
    128                                      GenericList **listp, size_t size,
    129                                      Error **errp)
    130{
    131    QObjectOutputVisitor *qov = to_qov(v);
    132    QList *list = qlist_new();
    133
    134    qobject_output_add(qov, name, list);
    135    qobject_output_push(qov, list, listp);
    136    return true;
    137}
    138
    139static GenericList *qobject_output_next_list(Visitor *v, GenericList *tail,
    140                                             size_t size)
    141{
    142    return tail->next;
    143}
    144
    145static void qobject_output_end_list(Visitor *v, void **obj)
    146{
    147    QObjectOutputVisitor *qov = to_qov(v);
    148    QObject *value = qobject_output_pop(qov, obj);
    149    assert(qobject_type(value) == QTYPE_QLIST);
    150}
    151
    152static bool qobject_output_type_int64(Visitor *v, const char *name,
    153                                      int64_t *obj, Error **errp)
    154{
    155    QObjectOutputVisitor *qov = to_qov(v);
    156    qobject_output_add(qov, name, qnum_from_int(*obj));
    157    return true;
    158}
    159
    160static bool qobject_output_type_uint64(Visitor *v, const char *name,
    161                                       uint64_t *obj, Error **errp)
    162{
    163    QObjectOutputVisitor *qov = to_qov(v);
    164    qobject_output_add(qov, name, qnum_from_uint(*obj));
    165    return true;
    166}
    167
    168static bool qobject_output_type_bool(Visitor *v, const char *name, bool *obj,
    169                                     Error **errp)
    170{
    171    QObjectOutputVisitor *qov = to_qov(v);
    172    qobject_output_add(qov, name, qbool_from_bool(*obj));
    173    return true;
    174}
    175
    176static bool qobject_output_type_str(Visitor *v, const char *name, char **obj,
    177                                    Error **errp)
    178{
    179    QObjectOutputVisitor *qov = to_qov(v);
    180    if (*obj) {
    181        qobject_output_add(qov, name, qstring_from_str(*obj));
    182    } else {
    183        qobject_output_add(qov, name, qstring_from_str(""));
    184    }
    185    return true;
    186}
    187
    188static bool qobject_output_type_number(Visitor *v, const char *name,
    189                                       double *obj, Error **errp)
    190{
    191    QObjectOutputVisitor *qov = to_qov(v);
    192    qobject_output_add(qov, name, qnum_from_double(*obj));
    193    return true;
    194}
    195
    196static bool qobject_output_type_any(Visitor *v, const char *name,
    197                                    QObject **obj, Error **errp)
    198{
    199    QObjectOutputVisitor *qov = to_qov(v);
    200
    201    qobject_output_add_obj(qov, name, qobject_ref(*obj));
    202    return true;
    203}
    204
    205static bool qobject_output_type_null(Visitor *v, const char *name,
    206                                     QNull **obj, Error **errp)
    207{
    208    QObjectOutputVisitor *qov = to_qov(v);
    209    qobject_output_add(qov, name, qnull());
    210    return true;
    211}
    212
    213static bool qobject_output_deprecated(Visitor *v, const char *name)
    214{
    215    QObjectOutputVisitor *qov = to_qov(v);
    216
    217    return qov->deprecated_policy != COMPAT_POLICY_OUTPUT_HIDE;
    218}
    219
    220/* Finish building, and return the root object.
    221 * The root object is never null. The caller becomes the object's
    222 * owner, and should use qobject_unref() when done with it.  */
    223static void qobject_output_complete(Visitor *v, void *opaque)
    224{
    225    QObjectOutputVisitor *qov = to_qov(v);
    226
    227    /* A visit must have occurred, with each start paired with end.  */
    228    assert(qov->root && QSLIST_EMPTY(&qov->stack));
    229    assert(opaque == qov->result);
    230
    231    *qov->result = qobject_ref(qov->root);
    232    qov->result = NULL;
    233}
    234
    235static void qobject_output_free(Visitor *v)
    236{
    237    QObjectOutputVisitor *qov = to_qov(v);
    238    QStackEntry *e;
    239
    240    while (!QSLIST_EMPTY(&qov->stack)) {
    241        e = QSLIST_FIRST(&qov->stack);
    242        QSLIST_REMOVE_HEAD(&qov->stack, node);
    243        g_free(e);
    244    }
    245
    246    qobject_unref(qov->root);
    247    g_free(qov);
    248}
    249
    250Visitor *qobject_output_visitor_new(QObject **result)
    251{
    252    QObjectOutputVisitor *v;
    253
    254    v = g_malloc0(sizeof(*v));
    255
    256    v->visitor.type = VISITOR_OUTPUT;
    257    v->visitor.start_struct = qobject_output_start_struct;
    258    v->visitor.end_struct = qobject_output_end_struct;
    259    v->visitor.start_list = qobject_output_start_list;
    260    v->visitor.next_list = qobject_output_next_list;
    261    v->visitor.end_list = qobject_output_end_list;
    262    v->visitor.type_int64 = qobject_output_type_int64;
    263    v->visitor.type_uint64 = qobject_output_type_uint64;
    264    v->visitor.type_bool = qobject_output_type_bool;
    265    v->visitor.type_str = qobject_output_type_str;
    266    v->visitor.type_number = qobject_output_type_number;
    267    v->visitor.type_any = qobject_output_type_any;
    268    v->visitor.type_null = qobject_output_type_null;
    269    v->visitor.deprecated = qobject_output_deprecated;
    270    v->visitor.complete = qobject_output_complete;
    271    v->visitor.free = qobject_output_free;
    272
    273    *result = NULL;
    274    v->result = result;
    275
    276    return &v->visitor;
    277}
    278
    279void qobject_output_visitor_set_policy(Visitor *v,
    280                                       CompatPolicyOutput deprecated)
    281{
    282    QObjectOutputVisitor *qov = to_qov(v);
    283
    284    qov->deprecated_policy = deprecated;
    285}