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