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