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

qapi-clone-visitor.c (5559B)


      1/*
      2 * Copy one QAPI object to another
      3 *
      4 * Copyright (C) 2016 Red Hat, Inc.
      5 *
      6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
      7 * See the COPYING file in the top-level directory.
      8 *
      9 */
     10
     11#include "qemu/osdep.h"
     12#include "qapi/clone-visitor.h"
     13#include "qapi/visitor-impl.h"
     14#include "qapi/error.h"
     15#include "qapi/qmp/qnull.h"
     16
     17struct QapiCloneVisitor {
     18    Visitor visitor;
     19    size_t depth;
     20};
     21
     22static QapiCloneVisitor *to_qcv(Visitor *v)
     23{
     24    return container_of(v, QapiCloneVisitor, visitor);
     25}
     26
     27static bool qapi_clone_start_struct(Visitor *v, const char *name, void **obj,
     28                                    size_t size, Error **errp)
     29{
     30    QapiCloneVisitor *qcv = to_qcv(v);
     31
     32    if (!obj) {
     33        assert(qcv->depth);
     34        /* Only possible when visiting an alternate's object
     35         * branch. Nothing further to do here, since the earlier
     36         * visit_start_alternate() already copied memory. */
     37        return true;
     38    }
     39
     40    *obj = g_memdup(*obj, size);
     41    qcv->depth++;
     42    return true;
     43}
     44
     45static void qapi_clone_end(Visitor *v, void **obj)
     46{
     47    QapiCloneVisitor *qcv = to_qcv(v);
     48
     49    assert(qcv->depth);
     50    if (obj) {
     51        qcv->depth--;
     52    }
     53}
     54
     55static bool qapi_clone_start_list(Visitor *v, const char *name,
     56                                  GenericList **listp, size_t size,
     57                                  Error **errp)
     58{
     59    return qapi_clone_start_struct(v, name, (void **)listp, size, errp);
     60}
     61
     62static GenericList *qapi_clone_next_list(Visitor *v, GenericList *tail,
     63                                         size_t size)
     64{
     65    QapiCloneVisitor *qcv = to_qcv(v);
     66
     67    assert(qcv->depth);
     68    /* Unshare the tail of the list cloned by g_memdup() */
     69    tail->next = g_memdup(tail->next, size);
     70    return tail->next;
     71}
     72
     73static bool qapi_clone_start_alternate(Visitor *v, const char *name,
     74                                       GenericAlternate **obj, size_t size,
     75                                       Error **errp)
     76{
     77    return qapi_clone_start_struct(v, name, (void **)obj, size, errp);
     78}
     79
     80static bool qapi_clone_type_int64(Visitor *v, const char *name, int64_t *obj,
     81                                  Error **errp)
     82{
     83    QapiCloneVisitor *qcv = to_qcv(v);
     84
     85    assert(qcv->depth);
     86    /* Value was already cloned by g_memdup() */
     87    return true;
     88}
     89
     90static bool qapi_clone_type_uint64(Visitor *v, const char *name,
     91                                   uint64_t *obj, Error **errp)
     92{
     93    QapiCloneVisitor *qcv = to_qcv(v);
     94
     95    assert(qcv->depth);
     96    /* Value was already cloned by g_memdup() */
     97    return true;
     98}
     99
    100static bool qapi_clone_type_bool(Visitor *v, const char *name, bool *obj,
    101                                 Error **errp)
    102{
    103    QapiCloneVisitor *qcv = to_qcv(v);
    104
    105    assert(qcv->depth);
    106    /* Value was already cloned by g_memdup() */
    107    return true;
    108}
    109
    110static bool qapi_clone_type_str(Visitor *v, const char *name, char **obj,
    111                                Error **errp)
    112{
    113    QapiCloneVisitor *qcv = to_qcv(v);
    114
    115    assert(qcv->depth);
    116    /*
    117     * Pointer was already cloned by g_memdup; create fresh copy.
    118     * Note that as long as qobject-output-visitor accepts NULL instead of
    119     * "", then we must do likewise. However, we want to obey the
    120     * input visitor semantics of never producing NULL when the empty
    121     * string is intended.
    122     */
    123    *obj = g_strdup(*obj ?: "");
    124    return true;
    125}
    126
    127static bool qapi_clone_type_number(Visitor *v, const char *name, double *obj,
    128                                   Error **errp)
    129{
    130    QapiCloneVisitor *qcv = to_qcv(v);
    131
    132    assert(qcv->depth);
    133    /* Value was already cloned by g_memdup() */
    134    return true;
    135}
    136
    137static bool qapi_clone_type_null(Visitor *v, const char *name, QNull **obj,
    138                                 Error **errp)
    139{
    140    QapiCloneVisitor *qcv = to_qcv(v);
    141
    142    assert(qcv->depth);
    143    *obj = qnull();
    144    return true;
    145}
    146
    147static void qapi_clone_free(Visitor *v)
    148{
    149    g_free(v);
    150}
    151
    152static Visitor *qapi_clone_visitor_new(void)
    153{
    154    QapiCloneVisitor *v;
    155
    156    v = g_malloc0(sizeof(*v));
    157
    158    v->visitor.type = VISITOR_CLONE;
    159    v->visitor.start_struct = qapi_clone_start_struct;
    160    v->visitor.end_struct = qapi_clone_end;
    161    v->visitor.start_list = qapi_clone_start_list;
    162    v->visitor.next_list = qapi_clone_next_list;
    163    v->visitor.end_list = qapi_clone_end;
    164    v->visitor.start_alternate = qapi_clone_start_alternate;
    165    v->visitor.end_alternate = qapi_clone_end;
    166    v->visitor.type_int64 = qapi_clone_type_int64;
    167    v->visitor.type_uint64 = qapi_clone_type_uint64;
    168    v->visitor.type_bool = qapi_clone_type_bool;
    169    v->visitor.type_str = qapi_clone_type_str;
    170    v->visitor.type_number = qapi_clone_type_number;
    171    v->visitor.type_null = qapi_clone_type_null;
    172    v->visitor.free = qapi_clone_free;
    173
    174    return &v->visitor;
    175}
    176
    177void *qapi_clone(const void *src, bool (*visit_type)(Visitor *, const char *,
    178                                                     void **, Error **))
    179{
    180    Visitor *v;
    181    void *dst = (void *) src; /* Cast away const */
    182
    183    if (!src) {
    184        return NULL;
    185    }
    186
    187    v = qapi_clone_visitor_new();
    188    visit_type(v, NULL, &dst, &error_abort);
    189    visit_free(v);
    190    return dst;
    191}
    192
    193void qapi_clone_members(void *dst, const void *src, size_t sz,
    194                        bool (*visit_type_members)(Visitor *, void *,
    195                                                   Error **))
    196{
    197    Visitor *v;
    198
    199    v = qapi_clone_visitor_new();
    200    memcpy(dst, src, sz);
    201    to_qcv(v)->depth++;
    202    visit_type_members(v, dst, &error_abort);
    203    visit_free(v);
    204}