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