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