Commit 73988d52 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/stefanha/tags/tracing-pull-request' into staging



# gpg: Signature made Mon 12 Mar 2018 15:59:54 GMT
# gpg:                using RSA key 9CA4ABB381AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"
# Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35  775A 9CA4 ABB3 81AB 73C8

* remotes/stefanha/tags/tracing-pull-request:
  trace: only permit standard C types and fixed size integer types
  trace: remove use of QEMU specific types from trace probes
  trace: include filename when printing parser error messages
  simpletrace: fix timestamp argument type
  log-for-trace.h: Split out parts of log.h used by trace.h

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 1396156f 73ff0610
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
/* log-for-trace.h: logging basics required by the trace.h generated
 * by the log trace backend.
 *
 * This should not be included directly by any .c file: if you
 * need to use the logging functions include "qemu/log.h".
 *
 * The purpose of splitting these parts out into their own header
 * is to catch the easy mistake where a .c file includes trace.h
 * but forgets to include qemu/log.h. Without this split, that
 * would result in the .c file compiling fine when the default
 * trace backend is in use but failing to compile with any other
 * backend.
 *
 * This code is licensed under the GNU General Public License,
 * version 2 or (at your option) any later version.
 */

#ifndef QEMU_LOG_FOR_TRACE_H
#define QEMU_LOG_FOR_TRACE_H

/* Private global variable, don't use */
extern int qemu_loglevel;

#define LOG_TRACE          (1 << 15)

/* Returns true if a bit is set in the current loglevel mask */
static inline bool qemu_loglevel_mask(int mask)
{
    return (qemu_loglevel & mask) != 0;
}

/* main logging function */
int GCC_FMT_ATTR(1, 2) qemu_log(const char *fmt, ...);

#endif
+4 −14
Original line number Diff line number Diff line
#ifndef QEMU_LOG_H
#define QEMU_LOG_H

/* A small part of this API is split into its own header */
#include "qemu/log-for-trace.h"

/* Private global variables, don't use */
/* Private global variable, don't use */
extern FILE *qemu_logfile;
extern int qemu_loglevel;

/* 
 * The new API:
@@ -41,16 +42,9 @@ static inline bool qemu_log_separate(void)
#define CPU_LOG_MMU        (1 << 12)
#define CPU_LOG_TB_NOCHAIN (1 << 13)
#define CPU_LOG_PAGE       (1 << 14)
#define LOG_TRACE          (1 << 15)
/* LOG_TRACE (1 << 15) is defined in log-for-trace.h */
#define CPU_LOG_TB_OP_IND  (1 << 16)

/* Returns true if a bit is set in the current loglevel mask
 */
static inline bool qemu_loglevel_mask(int mask)
{
    return (qemu_loglevel & mask) != 0;
}

/* Lock output for a series of related logs.  Since this is not needed
 * for a single qemu_log / qemu_log_mask / qemu_log_mask_and_addr, we
 * assume that qemu_loglevel_mask has already been tested, and that
@@ -69,10 +63,6 @@ static inline void qemu_log_unlock(void)

/* Logging functions: */

/* main logging function
 */
int GCC_FMT_ATTR(1, 2) qemu_log(const char *fmt, ...);

/* vfprintf-like logging function
 */
static inline void GCC_FMT_ATTR(1, 0)
+3 −3
Original line number Diff line number Diff line
@@ -168,7 +168,7 @@ class Analyzer(object):
def process(events, log, analyzer, read_header=True):
    """Invoke an analyzer on each event in a log."""
    if isinstance(events, str):
        events = read_events(open(events, 'r'))
        events = read_events(open(events, 'r'), events)
    if isinstance(log, str):
        log = open(log, 'rb')

@@ -199,7 +199,7 @@ def process(events, log, analyzer, read_header=True):
        fn_argcount = len(inspect.getargspec(fn)[0]) - 1
        if fn_argcount == event_argcount + 1:
            # Include timestamp as first argument
            return lambda _, rec: fn(*((rec[1:2],) + rec[3:3 + event_argcount]))
            return lambda _, rec: fn(*(rec[1:2] + rec[3:3 + event_argcount]))
        elif fn_argcount == event_argcount + 2:
            # Include timestamp and pid
            return lambda _, rec: fn(*rec[1:3 + event_argcount])
@@ -233,7 +233,7 @@ def run(analyzer):
                         '<trace-file>\n' % sys.argv[0])
        sys.exit(1)

    events = read_events(open(sys.argv[1], 'r'))
    events = read_events(open(sys.argv[1], 'r'), sys.argv[1])
    process(events, sys.argv[2], analyzer, read_header=read_header)

if __name__ == '__main__':
+1 −1
Original line number Diff line number Diff line
@@ -142,7 +142,7 @@ def main(args):
    events = []
    for arg in args:
        with open(arg, "r") as fh:
            events.extend(tracetool.read_events(fh))
            events.extend(tracetool.read_events(fh, arg))

    try:
        tracetool.generate(events, arg_group, arg_format, arg_backends,
+50 −2
Original line number Diff line number Diff line
@@ -41,6 +41,51 @@ def out(*lines, **kwargs):
    lines = [ l % kwargs for l in lines ]
    sys.stdout.writelines("\n".join(lines) + "\n")

# We only want to allow standard C types or fixed sized
# integer types. We don't want QEMU specific types
# as we can't assume trace backends can resolve all the
# typedefs
ALLOWED_TYPES = [
    "int",
    "long",
    "short",
    "char",
    "bool",
    "unsigned",
    "signed",
    "float",
    "double",
    "int8_t",
    "uint8_t",
    "int16_t",
    "uint16_t",
    "int32_t",
    "uint32_t",
    "int64_t",
    "uint64_t",
    "void",
    "size_t",
    "ssize_t",
    "uintptr_t",
    "ptrdiff_t",
    # Magic substitution is done by tracetool
    "TCGv",
]

def validate_type(name):
    bits = name.split(" ")
    for bit in bits:
        bit = re.sub("\*", "", bit)
        if bit == "":
            continue
        if bit == "const":
            continue
        if bit not in ALLOWED_TYPES:
            raise ValueError("Argument type '%s' is not in whitelist. "
                             "Only standard C types and fixed size integer "
                             "types should be used. struct, union, and "
                             "other complex pointer types should be "
                             "declared as 'void *'" % name)

class Arguments:
    """Event arguments description."""
@@ -87,6 +132,7 @@ class Arguments:
            else:
                arg_type, identifier = arg.rsplit(None, 1)

            validate_type(arg_type)
            res.append((arg_type, identifier))
        return Arguments(res)

@@ -291,13 +337,15 @@ class Event(object):
                     self)


def read_events(fobj):
def read_events(fobj, fname):
    """Generate the output for the given (format, backends) pair.

    Parameters
    ----------
    fobj : file
        Event description file.
    fname : str
        Name of event file

    Returns a list of Event objects
    """
@@ -312,7 +360,7 @@ def read_events(fobj):
        try:
            event = Event.build(line)
        except ValueError as e:
            arg0 = 'Error on line %d: %s' % (lineno, e.args[0])
            arg0 = 'Error at %s:%d: %s' % (fname, lineno, e.args[0])
            e.args = (arg0,) + e.args[1:]
            raise

Loading