linux/tools/perf/util/util.c
<<
>>
Prefs
   1#include "../perf.h"
   2#include "util.h"
   3#include "debug.h"
   4#include <api/fs/fs.h>
   5#include <sys/mman.h>
   6#include <sys/utsname.h>
   7#ifdef HAVE_BACKTRACE_SUPPORT
   8#include <execinfo.h>
   9#endif
  10#include <stdio.h>
  11#include <stdlib.h>
  12#include <string.h>
  13#include <errno.h>
  14#include <limits.h>
  15#include <byteswap.h>
  16#include <linux/kernel.h>
  17#include <linux/log2.h>
  18#include <unistd.h>
  19#include "callchain.h"
  20#include "strlist.h"
  21
  22struct callchain_param  callchain_param = {
  23        .mode   = CHAIN_GRAPH_ABS,
  24        .min_percent = 0.5,
  25        .order  = ORDER_CALLEE,
  26        .key    = CCKEY_FUNCTION,
  27        .value  = CCVAL_PERCENT,
  28};
  29
  30/*
  31 * XXX We need to find a better place for these things...
  32 */
  33unsigned int page_size;
  34int cacheline_size;
  35
  36int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH;
  37int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK;
  38
  39bool test_attr__enabled;
  40
  41bool perf_host  = true;
  42bool perf_guest = false;
  43
  44void event_attr_init(struct perf_event_attr *attr)
  45{
  46        if (!perf_host)
  47                attr->exclude_host  = 1;
  48        if (!perf_guest)
  49                attr->exclude_guest = 1;
  50        /* to capture ABI version */
  51        attr->size = sizeof(*attr);
  52}
  53
  54int mkdir_p(char *path, mode_t mode)
  55{
  56        struct stat st;
  57        int err;
  58        char *d = path;
  59
  60        if (*d != '/')
  61                return -1;
  62
  63        if (stat(path, &st) == 0)
  64                return 0;
  65
  66        while (*++d == '/');
  67
  68        while ((d = strchr(d, '/'))) {
  69                *d = '\0';
  70                err = stat(path, &st) && mkdir(path, mode);
  71                *d++ = '/';
  72                if (err)
  73                        return -1;
  74                while (*d == '/')
  75                        ++d;
  76        }
  77        return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
  78}
  79
  80int rm_rf(char *path)
  81{
  82        DIR *dir;
  83        int ret = 0;
  84        struct dirent *d;
  85        char namebuf[PATH_MAX];
  86
  87        dir = opendir(path);
  88        if (dir == NULL)
  89                return 0;
  90
  91        while ((d = readdir(dir)) != NULL && !ret) {
  92                struct stat statbuf;
  93
  94                if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
  95                        continue;
  96
  97                scnprintf(namebuf, sizeof(namebuf), "%s/%s",
  98                          path, d->d_name);
  99
 100                ret = stat(namebuf, &statbuf);
 101                if (ret < 0) {
 102                        pr_debug("stat failed: %s\n", namebuf);
 103                        break;
 104                }
 105
 106                if (S_ISREG(statbuf.st_mode))
 107                        ret = unlink(namebuf);
 108                else if (S_ISDIR(statbuf.st_mode))
 109                        ret = rm_rf(namebuf);
 110                else {
 111                        pr_debug("unknown file: %s\n", namebuf);
 112                        ret = -1;
 113                }
 114        }
 115        closedir(dir);
 116
 117        if (ret < 0)
 118                return ret;
 119
 120        return rmdir(path);
 121}
 122
 123/* A filter which removes dot files */
 124bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d)
 125{
 126        return d->d_name[0] != '.';
 127}
 128
 129/* lsdir reads a directory and store it in strlist */
 130struct strlist *lsdir(const char *name,
 131                      bool (*filter)(const char *, struct dirent *))
 132{
 133        struct strlist *list = NULL;
 134        DIR *dir;
 135        struct dirent *d;
 136
 137        dir = opendir(name);
 138        if (!dir)
 139                return NULL;
 140
 141        list = strlist__new(NULL, NULL);
 142        if (!list) {
 143                errno = ENOMEM;
 144                goto out;
 145        }
 146
 147        while ((d = readdir(dir)) != NULL) {
 148                if (!filter || filter(name, d))
 149                        strlist__add(list, d->d_name);
 150        }
 151
 152out:
 153        closedir(dir);
 154        return list;
 155}
 156
 157static int slow_copyfile(const char *from, const char *to)
 158{
 159        int err = -1;
 160        char *line = NULL;
 161        size_t n;
 162        FILE *from_fp = fopen(from, "r"), *to_fp;
 163
 164        if (from_fp == NULL)
 165                goto out;
 166
 167        to_fp = fopen(to, "w");
 168        if (to_fp == NULL)
 169                goto out_fclose_from;
 170
 171        while (getline(&line, &n, from_fp) > 0)
 172                if (fputs(line, to_fp) == EOF)
 173                        goto out_fclose_to;
 174        err = 0;
 175out_fclose_to:
 176        fclose(to_fp);
 177        free(line);
 178out_fclose_from:
 179        fclose(from_fp);
 180out:
 181        return err;
 182}
 183
 184int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
 185{
 186        void *ptr;
 187        loff_t pgoff;
 188
 189        pgoff = off_in & ~(page_size - 1);
 190        off_in -= pgoff;
 191
 192        ptr = mmap(NULL, off_in + size, PROT_READ, MAP_PRIVATE, ifd, pgoff);
 193        if (ptr == MAP_FAILED)
 194                return -1;
 195
 196        while (size) {
 197                ssize_t ret = pwrite(ofd, ptr + off_in, size, off_out);
 198                if (ret < 0 && errno == EINTR)
 199                        continue;
 200                if (ret <= 0)
 201                        break;
 202
 203                size -= ret;
 204                off_in += ret;
 205                off_out -= ret;
 206        }
 207        munmap(ptr, off_in + size);
 208
 209        return size ? -1 : 0;
 210}
 211
 212int copyfile_mode(const char *from, const char *to, mode_t mode)
 213{
 214        int fromfd, tofd;
 215        struct stat st;
 216        int err = -1;
 217        char *tmp = NULL, *ptr = NULL;
 218
 219        if (stat(from, &st))
 220                goto out;
 221
 222        /* extra 'x' at the end is to reserve space for '.' */
 223        if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) {
 224                tmp = NULL;
 225                goto out;
 226        }
 227        ptr = strrchr(tmp, '/');
 228        if (!ptr)
 229                goto out;
 230        ptr = memmove(ptr + 1, ptr, strlen(ptr) - 1);
 231        *ptr = '.';
 232
 233        tofd = mkstemp(tmp);
 234        if (tofd < 0)
 235                goto out;
 236
 237        if (fchmod(tofd, mode))
 238                goto out_close_to;
 239
 240        if (st.st_size == 0) { /* /proc? do it slowly... */
 241                err = slow_copyfile(from, tmp);
 242                goto out_close_to;
 243        }
 244
 245        fromfd = open(from, O_RDONLY);
 246        if (fromfd < 0)
 247                goto out_close_to;
 248
 249        err = copyfile_offset(fromfd, 0, tofd, 0, st.st_size);
 250
 251        close(fromfd);
 252out_close_to:
 253        close(tofd);
 254        if (!err)
 255                err = link(tmp, to);
 256        unlink(tmp);
 257out:
 258        free(tmp);
 259        return err;
 260}
 261
 262int copyfile(const char *from, const char *to)
 263{
 264        return copyfile_mode(from, to, 0755);
 265}
 266
 267unsigned long convert_unit(unsigned long value, char *unit)
 268{
 269        *unit = ' ';
 270
 271        if (value > 1000) {
 272                value /= 1000;
 273                *unit = 'K';
 274        }
 275
 276        if (value > 1000) {
 277                value /= 1000;
 278                *unit = 'M';
 279        }
 280
 281        if (value > 1000) {
 282                value /= 1000;
 283                *unit = 'G';
 284        }
 285
 286        return value;
 287}
 288
 289static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
 290{
 291        void *buf_start = buf;
 292        size_t left = n;
 293
 294        while (left) {
 295                ssize_t ret = is_read ? read(fd, buf, left) :
 296                                        write(fd, buf, left);
 297
 298                if (ret < 0 && errno == EINTR)
 299                        continue;
 300                if (ret <= 0)
 301                        return ret;
 302
 303                left -= ret;
 304                buf  += ret;
 305        }
 306
 307        BUG_ON((size_t)(buf - buf_start) != n);
 308        return n;
 309}
 310
 311/*
 312 * Read exactly 'n' bytes or return an error.
 313 */
 314ssize_t readn(int fd, void *buf, size_t n)
 315{
 316        return ion(true, fd, buf, n);
 317}
 318
 319/*
 320 * Write exactly 'n' bytes or return an error.
 321 */
 322ssize_t writen(int fd, void *buf, size_t n)
 323{
 324        return ion(false, fd, buf, n);
 325}
 326
 327size_t hex_width(u64 v)
 328{
 329        size_t n = 1;
 330
 331        while ((v >>= 4))
 332                ++n;
 333
 334        return n;
 335}
 336
 337static int hex(char ch)
 338{
 339        if ((ch >= '0') && (ch <= '9'))
 340                return ch - '0';
 341        if ((ch >= 'a') && (ch <= 'f'))
 342                return ch - 'a' + 10;
 343        if ((ch >= 'A') && (ch <= 'F'))
 344                return ch - 'A' + 10;
 345        return -1;
 346}
 347
 348/*
 349 * While we find nice hex chars, build a long_val.
 350 * Return number of chars processed.
 351 */
 352int hex2u64(const char *ptr, u64 *long_val)
 353{
 354        const char *p = ptr;
 355        *long_val = 0;
 356
 357        while (*p) {
 358                const int hex_val = hex(*p);
 359
 360                if (hex_val < 0)
 361                        break;
 362
 363                *long_val = (*long_val << 4) | hex_val;
 364                p++;
 365        }
 366
 367        return p - ptr;
 368}
 369
 370/* Obtain a backtrace and print it to stdout. */
 371#ifdef HAVE_BACKTRACE_SUPPORT
 372void dump_stack(void)
 373{
 374        void *array[16];
 375        size_t size = backtrace(array, ARRAY_SIZE(array));
 376        char **strings = backtrace_symbols(array, size);
 377        size_t i;
 378
 379        printf("Obtained %zd stack frames.\n", size);
 380
 381        for (i = 0; i < size; i++)
 382                printf("%s\n", strings[i]);
 383
 384        free(strings);
 385}
 386#else
 387void dump_stack(void) {}
 388#endif
 389
 390void sighandler_dump_stack(int sig)
 391{
 392        psignal(sig, "perf");
 393        dump_stack();
 394        signal(sig, SIG_DFL);
 395        raise(sig);
 396}
 397
 398int parse_nsec_time(const char *str, u64 *ptime)
 399{
 400        u64 time_sec, time_nsec;
 401        char *end;
 402
 403        time_sec = strtoul(str, &end, 10);
 404        if (*end != '.' && *end != '\0')
 405                return -1;
 406
 407        if (*end == '.') {
 408                int i;
 409                char nsec_buf[10];
 410
 411                if (strlen(++end) > 9)
 412                        return -1;
 413
 414                strncpy(nsec_buf, end, 9);
 415                nsec_buf[9] = '\0';
 416
 417                /* make it nsec precision */
 418                for (i = strlen(nsec_buf); i < 9; i++)
 419                        nsec_buf[i] = '0';
 420
 421                time_nsec = strtoul(nsec_buf, &end, 10);
 422                if (*end != '\0')
 423                        return -1;
 424        } else
 425                time_nsec = 0;
 426
 427        *ptime = time_sec * NSEC_PER_SEC + time_nsec;
 428        return 0;
 429}
 430
 431unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
 432{
 433        struct parse_tag *i = tags;
 434
 435        while (i->tag) {
 436                char *s;
 437
 438                s = strchr(str, i->tag);
 439                if (s) {
 440                        unsigned long int value;
 441                        char *endptr;
 442
 443                        value = strtoul(str, &endptr, 10);
 444                        if (s != endptr)
 445                                break;
 446
 447                        if (value > ULONG_MAX / i->mult)
 448                                break;
 449                        value *= i->mult;
 450                        return value;
 451                }
 452                i++;
 453        }
 454
 455        return (unsigned long) -1;
 456}
 457
 458int get_stack_size(const char *str, unsigned long *_size)
 459{
 460        char *endptr;
 461        unsigned long size;
 462        unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
 463
 464        size = strtoul(str, &endptr, 0);
 465
 466        do {
 467                if (*endptr)
 468                        break;
 469
 470                size = round_up(size, sizeof(u64));
 471                if (!size || size > max_size)
 472                        break;
 473
 474                *_size = size;
 475                return 0;
 476
 477        } while (0);
 478
 479        pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
 480               max_size, str);
 481        return -1;
 482}
 483
 484int parse_callchain_record(const char *arg, struct callchain_param *param)
 485{
 486        char *tok, *name, *saveptr = NULL;
 487        char *buf;
 488        int ret = -1;
 489
 490        /* We need buffer that we know we can write to. */
 491        buf = malloc(strlen(arg) + 1);
 492        if (!buf)
 493                return -ENOMEM;
 494
 495        strcpy(buf, arg);
 496
 497        tok = strtok_r((char *)buf, ",", &saveptr);
 498        name = tok ? : (char *)buf;
 499
 500        do {
 501                /* Framepointer style */
 502                if (!strncmp(name, "fp", sizeof("fp"))) {
 503                        if (!strtok_r(NULL, ",", &saveptr)) {
 504                                param->record_mode = CALLCHAIN_FP;
 505                                ret = 0;
 506                        } else
 507                                pr_err("callchain: No more arguments "
 508                                       "needed for --call-graph fp\n");
 509                        break;
 510
 511                /* Dwarf style */
 512                } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
 513                        const unsigned long default_stack_dump_size = 8192;
 514
 515                        ret = 0;
 516                        param->record_mode = CALLCHAIN_DWARF;
 517                        param->dump_size = default_stack_dump_size;
 518
 519                        tok = strtok_r(NULL, ",", &saveptr);
 520                        if (tok) {
 521                                unsigned long size = 0;
 522
 523                                ret = get_stack_size(tok, &size);
 524                                param->dump_size = size;
 525                        }
 526                } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
 527                        if (!strtok_r(NULL, ",", &saveptr)) {
 528                                param->record_mode = CALLCHAIN_LBR;
 529                                ret = 0;
 530                        } else
 531                                pr_err("callchain: No more arguments "
 532                                        "needed for --call-graph lbr\n");
 533                        break;
 534                } else {
 535                        pr_err("callchain: Unknown --call-graph option "
 536                               "value: %s\n", arg);
 537                        break;
 538                }
 539
 540        } while (0);
 541
 542        free(buf);
 543        return ret;
 544}
 545
 546const char *get_filename_for_perf_kvm(void)
 547{
 548        const char *filename;
 549
 550        if (perf_host && !perf_guest)
 551                filename = strdup("perf.data.host");
 552        else if (!perf_host && perf_guest)
 553                filename = strdup("perf.data.guest");
 554        else
 555                filename = strdup("perf.data.kvm");
 556
 557        return filename;
 558}
 559
 560int perf_event_paranoid(void)
 561{
 562        int value;
 563
 564        if (sysctl__read_int("kernel/perf_event_paranoid", &value))
 565                return INT_MAX;
 566
 567        return value;
 568}
 569
 570void mem_bswap_32(void *src, int byte_size)
 571{
 572        u32 *m = src;
 573        while (byte_size > 0) {
 574                *m = bswap_32(*m);
 575                byte_size -= sizeof(u32);
 576                ++m;
 577        }
 578}
 579
 580void mem_bswap_64(void *src, int byte_size)
 581{
 582        u64 *m = src;
 583
 584        while (byte_size > 0) {
 585                *m = bswap_64(*m);
 586                byte_size -= sizeof(u64);
 587                ++m;
 588        }
 589}
 590
 591bool find_process(const char *name)
 592{
 593        size_t len = strlen(name);
 594        DIR *dir;
 595        struct dirent *d;
 596        int ret = -1;
 597
 598        dir = opendir(procfs__mountpoint());
 599        if (!dir)
 600                return false;
 601
 602        /* Walk through the directory. */
 603        while (ret && (d = readdir(dir)) != NULL) {
 604                char path[PATH_MAX];
 605                char *data;
 606                size_t size;
 607
 608                if ((d->d_type != DT_DIR) ||
 609                     !strcmp(".", d->d_name) ||
 610                     !strcmp("..", d->d_name))
 611                        continue;
 612
 613                scnprintf(path, sizeof(path), "%s/%s/comm",
 614                          procfs__mountpoint(), d->d_name);
 615
 616                if (filename__read_str(path, &data, &size))
 617                        continue;
 618
 619                ret = strncmp(name, data, len);
 620                free(data);
 621        }
 622
 623        closedir(dir);
 624        return ret ? false : true;
 625}
 626
 627int
 628fetch_kernel_version(unsigned int *puint, char *str,
 629                     size_t str_size)
 630{
 631        struct utsname utsname;
 632        int version, patchlevel, sublevel, err;
 633
 634        if (uname(&utsname))
 635                return -1;
 636
 637        if (str && str_size) {
 638                strncpy(str, utsname.release, str_size);
 639                str[str_size - 1] = '\0';
 640        }
 641
 642        err = sscanf(utsname.release, "%d.%d.%d",
 643                     &version, &patchlevel, &sublevel);
 644
 645        if (err != 3) {
 646                pr_debug("Unablt to get kernel version from uname '%s'\n",
 647                         utsname.release);
 648                return -1;
 649        }
 650
 651        if (puint)
 652                *puint = (version << 16) + (patchlevel << 8) + sublevel;
 653        return 0;
 654}
 655
 656const char *perf_tip(const char *dirpath)
 657{
 658        struct strlist *tips;
 659        struct str_node *node;
 660        char *tip = NULL;
 661        struct strlist_config conf = {
 662                .dirname = dirpath,
 663                .file_only = true,
 664        };
 665
 666        tips = strlist__new("tips.txt", &conf);
 667        if (tips == NULL)
 668                return errno == ENOENT ? NULL : "Tip: get more memory! ;-p";
 669
 670        if (strlist__nr_entries(tips) == 0)
 671                goto out;
 672
 673        node = strlist__entry(tips, random() % strlist__nr_entries(tips));
 674        if (asprintf(&tip, "Tip: %s", node->s) < 0)
 675                tip = (char *)"Tip: get more memory! ;-)";
 676
 677out:
 678        strlist__delete(tips);
 679
 680        return tip;
 681}
 682
 683bool is_regular_file(const char *file)
 684{
 685        struct stat st;
 686
 687        if (stat(file, &st))
 688                return false;
 689
 690        return S_ISREG(st.st_mode);
 691}
 692
 693int fetch_current_timestamp(char *buf, size_t sz)
 694{
 695        struct timeval tv;
 696        struct tm tm;
 697        char dt[32];
 698
 699        if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm))
 700                return -1;
 701
 702        if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm))
 703                return -1;
 704
 705        scnprintf(buf, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000);
 706
 707        return 0;
 708}
 709
 710void print_binary(unsigned char *data, size_t len,
 711                  size_t bytes_per_line, print_binary_t printer,
 712                  void *extra)
 713{
 714        size_t i, j, mask;
 715
 716        if (!printer)
 717                return;
 718
 719        bytes_per_line = roundup_pow_of_two(bytes_per_line);
 720        mask = bytes_per_line - 1;
 721
 722        printer(BINARY_PRINT_DATA_BEGIN, 0, extra);
 723        for (i = 0; i < len; i++) {
 724                if ((i & mask) == 0) {
 725                        printer(BINARY_PRINT_LINE_BEGIN, -1, extra);
 726                        printer(BINARY_PRINT_ADDR, i, extra);
 727                }
 728
 729                printer(BINARY_PRINT_NUM_DATA, data[i], extra);
 730
 731                if (((i & mask) == mask) || i == len - 1) {
 732                        for (j = 0; j < mask-(i & mask); j++)
 733                                printer(BINARY_PRINT_NUM_PAD, -1, extra);
 734
 735                        printer(BINARY_PRINT_SEP, i, extra);
 736                        for (j = i & ~mask; j <= i; j++)
 737                                printer(BINARY_PRINT_CHAR_DATA, data[j], extra);
 738                        for (j = 0; j < mask-(i & mask); j++)
 739                                printer(BINARY_PRINT_CHAR_PAD, i, extra);
 740                        printer(BINARY_PRINT_LINE_END, -1, extra);
 741                }
 742        }
 743        printer(BINARY_PRINT_DATA_END, -1, extra);
 744}
 745