at v4.2-rc2 696 lines 12 kB view raw
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}