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