linux/tools/perf/util/debug.c
<<
>>
Prefs
   1/* For general debugging purposes */
   2
   3#include "../perf.h"
   4
   5#include <string.h>
   6#include <stdarg.h>
   7#include <stdio.h>
   8#include <api/debug.h>
   9#include <linux/time64.h>
  10
  11#include "cache.h"
  12#include "color.h"
  13#include "event.h"
  14#include "debug.h"
  15#include "util.h"
  16#include "target.h"
  17
  18int verbose;
  19bool dump_trace = false, quiet = false;
  20int debug_ordered_events;
  21static int redirect_to_stderr;
  22int debug_data_convert;
  23
  24int veprintf(int level, int var, const char *fmt, va_list args)
  25{
  26        int ret = 0;
  27
  28        if (var >= level) {
  29                if (use_browser >= 1 && !redirect_to_stderr)
  30                        ui_helpline__vshow(fmt, args);
  31                else
  32                        ret = vfprintf(stderr, fmt, args);
  33        }
  34
  35        return ret;
  36}
  37
  38int eprintf(int level, int var, const char *fmt, ...)
  39{
  40        va_list args;
  41        int ret;
  42
  43        va_start(args, fmt);
  44        ret = veprintf(level, var, fmt, args);
  45        va_end(args);
  46
  47        return ret;
  48}
  49
  50static int veprintf_time(u64 t, const char *fmt, va_list args)
  51{
  52        int ret = 0;
  53        u64 secs, usecs, nsecs = t;
  54
  55        secs   = nsecs / NSEC_PER_SEC;
  56        nsecs -= secs  * NSEC_PER_SEC;
  57        usecs  = nsecs / NSEC_PER_USEC;
  58
  59        ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ",
  60                      secs, usecs);
  61        ret += vfprintf(stderr, fmt, args);
  62        return ret;
  63}
  64
  65int eprintf_time(int level, int var, u64 t, const char *fmt, ...)
  66{
  67        int ret = 0;
  68        va_list args;
  69
  70        if (var >= level) {
  71                va_start(args, fmt);
  72                ret = veprintf_time(t, fmt, args);
  73                va_end(args);
  74        }
  75
  76        return ret;
  77}
  78
  79/*
  80 * Overloading libtraceevent standard info print
  81 * function, display with -v in perf.
  82 */
  83void pr_stat(const char *fmt, ...)
  84{
  85        va_list args;
  86
  87        va_start(args, fmt);
  88        veprintf(1, verbose, fmt, args);
  89        va_end(args);
  90        eprintf(1, verbose, "\n");
  91}
  92
  93int dump_printf(const char *fmt, ...)
  94{
  95        va_list args;
  96        int ret = 0;
  97
  98        if (dump_trace) {
  99                va_start(args, fmt);
 100                ret = vprintf(fmt, args);
 101                va_end(args);
 102        }
 103
 104        return ret;
 105}
 106
 107static void trace_event_printer(enum binary_printer_ops op,
 108                                unsigned int val, void *extra)
 109{
 110        const char *color = PERF_COLOR_BLUE;
 111        union perf_event *event = (union perf_event *)extra;
 112        unsigned char ch = (unsigned char)val;
 113
 114        switch (op) {
 115        case BINARY_PRINT_DATA_BEGIN:
 116                printf(".");
 117                color_fprintf(stdout, color, "\n. ... raw event: size %d bytes\n",
 118                                event->header.size);
 119                break;
 120        case BINARY_PRINT_LINE_BEGIN:
 121                printf(".");
 122                break;
 123        case BINARY_PRINT_ADDR:
 124                color_fprintf(stdout, color, "  %04x: ", val);
 125                break;
 126        case BINARY_PRINT_NUM_DATA:
 127                color_fprintf(stdout, color, " %02x", val);
 128                break;
 129        case BINARY_PRINT_NUM_PAD:
 130                color_fprintf(stdout, color, "   ");
 131                break;
 132        case BINARY_PRINT_SEP:
 133                color_fprintf(stdout, color, "  ");
 134                break;
 135        case BINARY_PRINT_CHAR_DATA:
 136                color_fprintf(stdout, color, "%c",
 137                              isprint(ch) ? ch : '.');
 138                break;
 139        case BINARY_PRINT_CHAR_PAD:
 140                color_fprintf(stdout, color, " ");
 141                break;
 142        case BINARY_PRINT_LINE_END:
 143                color_fprintf(stdout, color, "\n");
 144                break;
 145        case BINARY_PRINT_DATA_END:
 146                printf("\n");
 147                break;
 148        default:
 149                break;
 150        }
 151}
 152
 153void trace_event(union perf_event *event)
 154{
 155        unsigned char *raw_event = (void *)event;
 156
 157        if (!dump_trace)
 158                return;
 159
 160        print_binary(raw_event, event->header.size, 16,
 161                     trace_event_printer, event);
 162}
 163
 164static struct debug_variable {
 165        const char *name;
 166        int *ptr;
 167} debug_variables[] = {
 168        { .name = "verbose",            .ptr = &verbose },
 169        { .name = "ordered-events",     .ptr = &debug_ordered_events},
 170        { .name = "stderr",             .ptr = &redirect_to_stderr},
 171        { .name = "data-convert",       .ptr = &debug_data_convert },
 172        { .name = NULL, }
 173};
 174
 175int perf_debug_option(const char *str)
 176{
 177        struct debug_variable *var = &debug_variables[0];
 178        char *vstr, *s = strdup(str);
 179        int v = 1;
 180
 181        vstr = strchr(s, '=');
 182        if (vstr)
 183                *vstr++ = 0;
 184
 185        while (var->name) {
 186                if (!strcmp(s, var->name))
 187                        break;
 188                var++;
 189        }
 190
 191        if (!var->name) {
 192                pr_err("Unknown debug variable name '%s'\n", s);
 193                free(s);
 194                return -1;
 195        }
 196
 197        if (vstr) {
 198                v = atoi(vstr);
 199                /*
 200                 * Allow only values in range (0, 10),
 201                 * otherwise set 0.
 202                 */
 203                v = (v < 0) || (v > 10) ? 0 : v;
 204        }
 205
 206        *var->ptr = v;
 207        free(s);
 208        return 0;
 209}
 210
 211#define DEBUG_WRAPPER(__n, __l)                         \
 212static int pr_ ## __n ## _wrapper(const char *fmt, ...) \
 213{                                                       \
 214        va_list args;                                   \
 215        int ret;                                        \
 216                                                        \
 217        va_start(args, fmt);                            \
 218        ret = veprintf(__l, verbose, fmt, args);        \
 219        va_end(args);                                   \
 220        return ret;                                     \
 221}
 222
 223DEBUG_WRAPPER(warning, 0);
 224DEBUG_WRAPPER(debug, 1);
 225
 226void perf_debug_setup(void)
 227{
 228        libapi_set_print(pr_warning_wrapper, pr_warning_wrapper, pr_debug_wrapper);
 229}
 230