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

error.c (6742B)


      1/*
      2 * QEMU Error Objects
      3 *
      4 * Copyright IBM, Corp. 2011
      5 * Copyright (C) 2011-2015 Red Hat, Inc.
      6 *
      7 * Authors:
      8 *  Anthony Liguori   <aliguori@us.ibm.com>
      9 *  Markus Armbruster <armbru@redhat.com>,
     10 *
     11 * This work is licensed under the terms of the GNU LGPL, version 2.  See
     12 * the COPYING.LIB file in the top-level directory.
     13 */
     14
     15#include "qemu/osdep.h"
     16#include "qapi/error.h"
     17#include "qemu/error-report.h"
     18
     19struct Error
     20{
     21    char *msg;
     22    ErrorClass err_class;
     23    const char *src, *func;
     24    int line;
     25    GString *hint;
     26};
     27
     28Error *error_abort;
     29Error *error_fatal;
     30
     31static void error_handle_fatal(Error **errp, Error *err)
     32{
     33    if (errp == &error_abort) {
     34        fprintf(stderr, "Unexpected error in %s() at %s:%d:\n",
     35                err->func, err->src, err->line);
     36        error_report("%s", error_get_pretty(err));
     37        if (err->hint) {
     38            error_printf("%s", err->hint->str);
     39        }
     40        abort();
     41    }
     42    if (errp == &error_fatal) {
     43        error_report_err(err);
     44        exit(1);
     45    }
     46}
     47
     48static void error_setv(Error **errp,
     49                       const char *src, int line, const char *func,
     50                       ErrorClass err_class, const char *fmt, va_list ap,
     51                       const char *suffix)
     52{
     53    Error *err;
     54    int saved_errno = errno;
     55
     56    if (errp == NULL) {
     57        return;
     58    }
     59    assert(*errp == NULL);
     60
     61    err = g_malloc0(sizeof(*err));
     62    err->msg = g_strdup_vprintf(fmt, ap);
     63    if (suffix) {
     64        char *msg = err->msg;
     65        err->msg = g_strdup_printf("%s: %s", msg, suffix);
     66        g_free(msg);
     67    }
     68    err->err_class = err_class;
     69    err->src = src;
     70    err->line = line;
     71    err->func = func;
     72
     73    error_handle_fatal(errp, err);
     74    *errp = err;
     75
     76    errno = saved_errno;
     77}
     78
     79void error_set_internal(Error **errp,
     80                        const char *src, int line, const char *func,
     81                        ErrorClass err_class, const char *fmt, ...)
     82{
     83    va_list ap;
     84
     85    va_start(ap, fmt);
     86    error_setv(errp, src, line, func, err_class, fmt, ap, NULL);
     87    va_end(ap);
     88}
     89
     90void error_setg_internal(Error **errp,
     91                         const char *src, int line, const char *func,
     92                         const char *fmt, ...)
     93{
     94    va_list ap;
     95
     96    va_start(ap, fmt);
     97    error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap, NULL);
     98    va_end(ap);
     99}
    100
    101void error_setg_errno_internal(Error **errp,
    102                               const char *src, int line, const char *func,
    103                               int os_errno, const char *fmt, ...)
    104{
    105    va_list ap;
    106    int saved_errno = errno;
    107
    108    va_start(ap, fmt);
    109    error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap,
    110               os_errno != 0 ? strerror(os_errno) : NULL);
    111    va_end(ap);
    112
    113    errno = saved_errno;
    114}
    115
    116void error_setg_file_open_internal(Error **errp,
    117                                   const char *src, int line, const char *func,
    118                                   int os_errno, const char *filename)
    119{
    120    error_setg_errno_internal(errp, src, line, func, os_errno,
    121                              "Could not open '%s'", filename);
    122}
    123
    124void error_vprepend(Error *const *errp, const char *fmt, va_list ap)
    125{
    126    GString *newmsg;
    127
    128    if (!errp) {
    129        return;
    130    }
    131
    132    newmsg = g_string_new(NULL);
    133    g_string_vprintf(newmsg, fmt, ap);
    134    g_string_append(newmsg, (*errp)->msg);
    135    g_free((*errp)->msg);
    136    (*errp)->msg = g_string_free(newmsg, 0);
    137}
    138
    139void error_prepend(Error *const *errp, const char *fmt, ...)
    140{
    141    va_list ap;
    142
    143    va_start(ap, fmt);
    144    error_vprepend(errp, fmt, ap);
    145    va_end(ap);
    146}
    147
    148void error_append_hint(Error *const *errp, const char *fmt, ...)
    149{
    150    va_list ap;
    151    int saved_errno = errno;
    152    Error *err;
    153
    154    if (!errp) {
    155        return;
    156    }
    157    err = *errp;
    158    assert(err && errp != &error_abort && errp != &error_fatal);
    159
    160    if (!err->hint) {
    161        err->hint = g_string_new(NULL);
    162    }
    163    va_start(ap, fmt);
    164    g_string_append_vprintf(err->hint, fmt, ap);
    165    va_end(ap);
    166
    167    errno = saved_errno;
    168}
    169
    170#ifdef _WIN32
    171
    172void error_setg_win32_internal(Error **errp,
    173                               const char *src, int line, const char *func,
    174                               int win32_err, const char *fmt, ...)
    175{
    176    va_list ap;
    177    char *suffix = NULL;
    178
    179    if (errp == NULL) {
    180        return;
    181    }
    182
    183    if (win32_err != 0) {
    184        suffix = g_win32_error_message(win32_err);
    185    }
    186
    187    va_start(ap, fmt);
    188    error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR,
    189               fmt, ap, suffix);
    190    va_end(ap);
    191
    192    g_free(suffix);
    193}
    194
    195#endif
    196
    197Error *error_copy(const Error *err)
    198{
    199    Error *err_new;
    200
    201    err_new = g_malloc0(sizeof(*err));
    202    err_new->msg = g_strdup(err->msg);
    203    err_new->err_class = err->err_class;
    204    err_new->src = err->src;
    205    err_new->line = err->line;
    206    err_new->func = err->func;
    207    if (err->hint) {
    208        err_new->hint = g_string_new(err->hint->str);
    209    }
    210
    211    return err_new;
    212}
    213
    214ErrorClass error_get_class(const Error *err)
    215{
    216    return err->err_class;
    217}
    218
    219const char *error_get_pretty(const Error *err)
    220{
    221    return err->msg;
    222}
    223
    224void error_report_err(Error *err)
    225{
    226    error_report("%s", error_get_pretty(err));
    227    if (err->hint) {
    228        error_printf("%s", err->hint->str);
    229    }
    230    error_free(err);
    231}
    232
    233void warn_report_err(Error *err)
    234{
    235    warn_report("%s", error_get_pretty(err));
    236    if (err->hint) {
    237        error_printf("%s", err->hint->str);
    238    }
    239    error_free(err);
    240}
    241
    242void error_reportf_err(Error *err, const char *fmt, ...)
    243{
    244    va_list ap;
    245
    246    va_start(ap, fmt);
    247    error_vprepend(&err, fmt, ap);
    248    va_end(ap);
    249    error_report_err(err);
    250}
    251
    252
    253void warn_reportf_err(Error *err, const char *fmt, ...)
    254{
    255    va_list ap;
    256
    257    va_start(ap, fmt);
    258    error_vprepend(&err, fmt, ap);
    259    va_end(ap);
    260    warn_report_err(err);
    261}
    262
    263void error_free(Error *err)
    264{
    265    if (err) {
    266        g_free(err->msg);
    267        if (err->hint) {
    268            g_string_free(err->hint, true);
    269        }
    270        g_free(err);
    271    }
    272}
    273
    274void error_free_or_abort(Error **errp)
    275{
    276    assert(errp && *errp);
    277    error_free(*errp);
    278    *errp = NULL;
    279}
    280
    281void error_propagate(Error **dst_errp, Error *local_err)
    282{
    283    if (!local_err) {
    284        return;
    285    }
    286    error_handle_fatal(dst_errp, local_err);
    287    if (dst_errp && !*dst_errp) {
    288        *dst_errp = local_err;
    289    } else {
    290        error_free(local_err);
    291    }
    292}
    293
    294void error_propagate_prepend(Error **dst_errp, Error *err,
    295                             const char *fmt, ...)
    296{
    297    va_list ap;
    298
    299    if (dst_errp && !*dst_errp) {
    300        va_start(ap, fmt);
    301        error_vprepend(&err, fmt, ap);
    302        va_end(ap);
    303    } /* else error is being ignored, don't bother with prepending */
    304    error_propagate(dst_errp, err);
    305}