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) 170 return ret; 171 172 left -= ret; 173 buf += ret; 174 } 175 176 BUG_ON((size_t)(buf - buf_start) != n); 177 return n; 178 } 179 180 /* 181 * Read exactly 'n' bytes or return an error. 182 */ 183 ssize_t readn(int fd, void *buf, size_t n) 184 { 185 return ion(true, fd, buf, n); 186 } 187 188 /* 189 * Write exactly 'n' bytes or return an error. 190 */ 191 ssize_t writen(int fd, void *buf, size_t n) 192 { 193 return ion(false, fd, buf, n); 194 } 195 196 size_t hex_width(u64 v) 197 { 198 size_t n = 1; 199 200 while ((v >>= 4)) 201 ++n; 202 203 return n; 204 } 205 206 static int hex(char ch) 207 { 208 if ((ch >= '0') && (ch <= '9')) 209 return ch - '0'; 210 if ((ch >= 'a') && (ch <= 'f')) 211 return ch - 'a' + 10; 212 if ((ch >= 'A') && (ch <= 'F')) 213 return ch - 'A' + 10; 214 return -1; 215 } 216 217 /* 218 * While we find nice hex chars, build a long_val. 219 * Return number of chars processed. 220 */ 221 int hex2u64(const char *ptr, u64 *long_val) 222 { 223 const char *p = ptr; 224 *long_val = 0; 225 226 while (*p) { 227 const int hex_val = hex(*p); 228 229 if (hex_val < 0) 230 break; 231 232 *long_val = (*long_val << 4) | hex_val; 233 p++; 234 } 235 236 return p - ptr; 237 } 238 239 /* Obtain a backtrace and print it to stdout. */ 240 #ifdef HAVE_BACKTRACE_SUPPORT 241 void dump_stack(void) 242 { 243 void *array[16]; 244 size_t size = backtrace(array, ARRAY_SIZE(array)); 245 char **strings = backtrace_symbols(array, size); 246 size_t i; 247 248 printf("Obtained %zd stack frames.\n", size); 249 250 for (i = 0; i < size; i++) 251 printf("%s\n", strings[i]); 252 253 free(strings); 254 } 255 #else 256 void dump_stack(void) {} 257 #endif 258 259 void get_term_dimensions(struct winsize *ws) 260 { 261 char *s = getenv("LINES"); 262 263 if (s != NULL) { 264 ws->ws_row = atoi(s); 265 s = getenv("COLUMNS"); 266 if (s != NULL) { 267 ws->ws_col = atoi(s); 268 if (ws->ws_row && ws->ws_col) 269 return; 270 } 271 } 272 #ifdef TIOCGWINSZ 273 if (ioctl(1, TIOCGWINSZ, ws) == 0 && 274 ws->ws_row && ws->ws_col) 275 return; 276 #endif 277 ws->ws_row = 25; 278 ws->ws_col = 80; 279 } 280 281 static void set_tracing_events_path(const char *mountpoint) 282 { 283 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", 284 mountpoint, "tracing/events"); 285 } 286 287 const char *perf_debugfs_mount(const char *mountpoint) 288 { 289 const char *mnt; 290 291 mnt = debugfs_mount(mountpoint); 292 if (!mnt) 293 return NULL; 294 295 set_tracing_events_path(mnt); 296 297 return mnt; 298 } 299 300 void perf_debugfs_set_path(const char *mntpt) 301 { 302 snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt); 303 set_tracing_events_path(mntpt); 304 } 305 306 static const char *find_debugfs(void) 307 { 308 const char *path = perf_debugfs_mount(NULL); 309 310 if (!path) 311 fprintf(stderr, "Your kernel does not support the debugfs filesystem"); 312 313 return path; 314 } 315 316 /* 317 * Finds the path to the debugfs/tracing 318 * Allocates the string and stores it. 319 */ 320 const char *find_tracing_dir(void) 321 { 322 static char *tracing; 323 static int tracing_found; 324 const char *debugfs; 325 326 if (tracing_found) 327 return tracing; 328 329 debugfs = find_debugfs(); 330 if (!debugfs) 331 return NULL; 332 333 tracing = malloc(strlen(debugfs) + 9); 334 if (!tracing) 335 return NULL; 336 337 sprintf(tracing, "%s/tracing", debugfs); 338 339 tracing_found = 1; 340 return tracing; 341 } 342 343 char *get_tracing_file(const char *name) 344 { 345 const char *tracing; 346 char *file; 347 348 tracing = find_tracing_dir(); 349 if (!tracing) 350 return NULL; 351 352 file = malloc(strlen(tracing) + strlen(name) + 2); 353 if (!file) 354 return NULL; 355 356 sprintf(file, "%s/%s", tracing, name); 357 return file; 358 } 359 360 void put_tracing_file(char *file) 361 { 362 free(file); 363 } 364 365 int parse_nsec_time(const char *str, u64 *ptime) 366 { 367 u64 time_sec, time_nsec; 368 char *end; 369 370 time_sec = strtoul(str, &end, 10); 371 if (*end != '.' && *end != '\0') 372 return -1; 373 374 if (*end == '.') { 375 int i; 376 char nsec_buf[10]; 377 378 if (strlen(++end) > 9) 379 return -1; 380 381 strncpy(nsec_buf, end, 9); 382 nsec_buf[9] = '\0'; 383 384 /* make it nsec precision */ 385 for (i = strlen(nsec_buf); i < 9; i++) 386 nsec_buf[i] = '0'; 387 388 time_nsec = strtoul(nsec_buf, &end, 10); 389 if (*end != '\0') 390 return -1; 391 } else 392 time_nsec = 0; 393 394 *ptime = time_sec * NSEC_PER_SEC + time_nsec; 395 return 0; 396 } 397 398 unsigned long parse_tag_value(const char *str, struct parse_tag *tags) 399 { 400 struct parse_tag *i = tags; 401 402 while (i->tag) { 403 char *s; 404 405 s = strchr(str, i->tag); 406 if (s) { 407 unsigned long int value; 408 char *endptr; 409 410 value = strtoul(str, &endptr, 10); 411 if (s != endptr) 412 break; 413 414 if (value > ULONG_MAX / i->mult) 415 break; 416 value *= i->mult; 417 return value; 418 } 419 i++; 420 } 421 422 return (unsigned long) -1; 423 } 424 425 int filename__read_int(const char *filename, int *value) 426 { 427 char line[64]; 428 int fd = open(filename, O_RDONLY), err = -1; 429 430 if (fd < 0) 431 return -1; 432 433 if (read(fd, line, sizeof(line)) > 0) { 434 *value = atoi(line); 435 err = 0; 436 } 437 438 close(fd); 439 return err; 440 } 441 442 int filename__read_str(const char *filename, char **buf, size_t *sizep) 443 { 444 size_t size = 0, alloc_size = 0; 445 void *bf = NULL, *nbf; 446 int fd, n, err = 0; 447 448 fd = open(filename, O_RDONLY); 449 if (fd < 0) 450 return -errno; 451 452 do { 453 if (size == alloc_size) { 454 alloc_size += BUFSIZ; 455 nbf = realloc(bf, alloc_size); 456 if (!nbf) { 457 err = -ENOMEM; 458 break; 459 } 460 461 bf = nbf; 462 } 463 464 n = read(fd, bf + size, alloc_size - size); 465 if (n < 0) { 466 if (size) { 467 pr_warning("read failed %d: %s\n", 468 errno, strerror(errno)); 469 err = 0; 470 } else 471 err = -errno; 472 473 break; 474 } 475 476 size += n; 477 } while (n > 0); 478 479 if (!err) { 480 *sizep = size; 481 *buf = bf; 482 } else 483 free(bf); 484 485 close(fd); 486 return err; 487 } 488 489 const char *get_filename_for_perf_kvm(void) 490 { 491 const char *filename; 492 493 if (perf_host && !perf_guest) 494 filename = strdup("perf.data.host"); 495 else if (!perf_host && perf_guest) 496 filename = strdup("perf.data.guest"); 497 else 498 filename = strdup("perf.data.kvm"); 499 500 return filename; 501 } 502 503 int perf_event_paranoid(void) 504 { 505 char path[PATH_MAX]; 506 const char *procfs = procfs__mountpoint(); 507 int value; 508 509 if (!procfs) 510 return INT_MAX; 511 512 scnprintf(path, PATH_MAX, "%s/sys/kernel/perf_event_paranoid", procfs); 513 514 if (filename__read_int(path, &value)) 515 return INT_MAX; 516 517 return value; 518 } 519 520 void mem_bswap_32(void *src, int byte_size) 521 { 522 u32 *m = src; 523 while (byte_size > 0) { 524 *m = bswap_32(*m); 525 byte_size -= sizeof(u32); 526 ++m; 527 } 528 } 529 530 void mem_bswap_64(void *src, int byte_size) 531 { 532 u64 *m = src; 533 534 while (byte_size > 0) { 535 *m = bswap_64(*m); 536 byte_size -= sizeof(u64); 537 ++m; 538 } 539 } 540