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