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