1 #include "../perf.h" 2 #include "util.h" 3 #include <sys/mman.h> 4 #ifdef HAVE_BACKTRACE_SUPPORT 5 #include <execinfo.h> 6 #endif 7 #include <stdio.h> 8 #include <stdlib.h> 9 10 /* 11 * XXX We need to find a better place for these things... 12 */ 13 unsigned int page_size; 14 15 bool test_attr__enabled; 16 17 bool perf_host = true; 18 bool perf_guest = false; 19 20 char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events"; 21 22 void event_attr_init(struct perf_event_attr *attr) 23 { 24 if (!perf_host) 25 attr->exclude_host = 1; 26 if (!perf_guest) 27 attr->exclude_guest = 1; 28 /* to capture ABI version */ 29 attr->size = sizeof(*attr); 30 } 31 32 int mkdir_p(char *path, mode_t mode) 33 { 34 struct stat st; 35 int err; 36 char *d = path; 37 38 if (*d != '/') 39 return -1; 40 41 if (stat(path, &st) == 0) 42 return 0; 43 44 while (*++d == '/'); 45 46 while ((d = strchr(d, '/'))) { 47 *d = '\0'; 48 err = stat(path, &st) && mkdir(path, mode); 49 *d++ = '/'; 50 if (err) 51 return -1; 52 while (*d == '/') 53 ++d; 54 } 55 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; 56 } 57 58 static int slow_copyfile(const char *from, const char *to, mode_t mode) 59 { 60 int err = -1; 61 char *line = NULL; 62 size_t n; 63 FILE *from_fp = fopen(from, "r"), *to_fp; 64 mode_t old_umask; 65 66 if (from_fp == NULL) 67 goto out; 68 69 old_umask = umask(mode ^ 0777); 70 to_fp = fopen(to, "w"); 71 umask(old_umask); 72 if (to_fp == NULL) 73 goto out_fclose_from; 74 75 while (getline(&line, &n, from_fp) > 0) 76 if (fputs(line, to_fp) == EOF) 77 goto out_fclose_to; 78 err = 0; 79 out_fclose_to: 80 fclose(to_fp); 81 free(line); 82 out_fclose_from: 83 fclose(from_fp); 84 out: 85 return err; 86 } 87 88 int copyfile_mode(const char *from, const char *to, mode_t mode) 89 { 90 int fromfd, tofd; 91 struct stat st; 92 void *addr; 93 int err = -1; 94 95 if (stat(from, &st)) 96 goto out; 97 98 if (st.st_size == 0) /* /proc? do it slowly... */ 99 return slow_copyfile(from, to, mode); 100 101 fromfd = open(from, O_RDONLY); 102 if (fromfd < 0) 103 goto out; 104 105 tofd = creat(to, mode); 106 if (tofd < 0) 107 goto out_close_from; 108 109 addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fromfd, 0); 110 if (addr == MAP_FAILED) 111 goto out_close_to; 112 113 if (write(tofd, addr, st.st_size) == st.st_size) 114 err = 0; 115 116 munmap(addr, st.st_size); 117 out_close_to: 118 close(tofd); 119 if (err) 120 unlink(to); 121 out_close_from: 122 close(fromfd); 123 out: 124 return err; 125 } 126 127 int copyfile(const char *from, const char *to) 128 { 129 return copyfile_mode(from, to, 0755); 130 } 131 132 unsigned long convert_unit(unsigned long value, char *unit) 133 { 134 *unit = ' '; 135 136 if (value > 1000) { 137 value /= 1000; 138 *unit = 'K'; 139 } 140 141 if (value > 1000) { 142 value /= 1000; 143 *unit = 'M'; 144 } 145 146 if (value > 1000) { 147 value /= 1000; 148 *unit = 'G'; 149 } 150 151 return value; 152 } 153 154 int readn(int fd, void *buf, size_t n) 155 { 156 void *buf_start = buf; 157 158 while (n) { 159 int ret = read(fd, buf, n); 160 161 if (ret <= 0) 162 return ret; 163 164 n -= ret; 165 buf += ret; 166 } 167 168 return buf - buf_start; 169 } 170 171 size_t hex_width(u64 v) 172 { 173 size_t n = 1; 174 175 while ((v >>= 4)) 176 ++n; 177 178 return n; 179 } 180 181 static int hex(char ch) 182 { 183 if ((ch >= '0') && (ch <= '9')) 184 return ch - '0'; 185 if ((ch >= 'a') && (ch <= 'f')) 186 return ch - 'a' + 10; 187 if ((ch >= 'A') && (ch <= 'F')) 188 return ch - 'A' + 10; 189 return -1; 190 } 191 192 /* 193 * While we find nice hex chars, build a long_val. 194 * Return number of chars processed. 195 */ 196 int hex2u64(const char *ptr, u64 *long_val) 197 { 198 const char *p = ptr; 199 *long_val = 0; 200 201 while (*p) { 202 const int hex_val = hex(*p); 203 204 if (hex_val < 0) 205 break; 206 207 *long_val = (*long_val << 4) | hex_val; 208 p++; 209 } 210 211 return p - ptr; 212 } 213 214 /* Obtain a backtrace and print it to stdout. */ 215 #ifdef HAVE_BACKTRACE_SUPPORT 216 void dump_stack(void) 217 { 218 void *array[16]; 219 size_t size = backtrace(array, ARRAY_SIZE(array)); 220 char **strings = backtrace_symbols(array, size); 221 size_t i; 222 223 printf("Obtained %zd stack frames.\n", size); 224 225 for (i = 0; i < size; i++) 226 printf("%s\n", strings[i]); 227 228 free(strings); 229 } 230 #else 231 void dump_stack(void) {} 232 #endif 233 234 void get_term_dimensions(struct winsize *ws) 235 { 236 char *s = getenv("LINES"); 237 238 if (s != NULL) { 239 ws->ws_row = atoi(s); 240 s = getenv("COLUMNS"); 241 if (s != NULL) { 242 ws->ws_col = atoi(s); 243 if (ws->ws_row && ws->ws_col) 244 return; 245 } 246 } 247 #ifdef TIOCGWINSZ 248 if (ioctl(1, TIOCGWINSZ, ws) == 0 && 249 ws->ws_row && ws->ws_col) 250 return; 251 #endif 252 ws->ws_row = 25; 253 ws->ws_col = 80; 254 } 255 256 static void set_tracing_events_path(const char *mountpoint) 257 { 258 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", 259 mountpoint, "tracing/events"); 260 } 261 262 const char *perf_debugfs_mount(const char *mountpoint) 263 { 264 const char *mnt; 265 266 mnt = debugfs_mount(mountpoint); 267 if (!mnt) 268 return NULL; 269 270 set_tracing_events_path(mnt); 271 272 return mnt; 273 } 274 275 void perf_debugfs_set_path(const char *mntpt) 276 { 277 snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt); 278 set_tracing_events_path(mntpt); 279 } 280 281 static const char *find_debugfs(void) 282 { 283 const char *path = perf_debugfs_mount(NULL); 284 285 if (!path) 286 fprintf(stderr, "Your kernel does not support the debugfs filesystem"); 287 288 return path; 289 } 290 291 /* 292 * Finds the path to the debugfs/tracing 293 * Allocates the string and stores it. 294 */ 295 const char *find_tracing_dir(void) 296 { 297 static char *tracing; 298 static int tracing_found; 299 const char *debugfs; 300 301 if (tracing_found) 302 return tracing; 303 304 debugfs = find_debugfs(); 305 if (!debugfs) 306 return NULL; 307 308 tracing = malloc(strlen(debugfs) + 9); 309 if (!tracing) 310 return NULL; 311 312 sprintf(tracing, "%s/tracing", debugfs); 313 314 tracing_found = 1; 315 return tracing; 316 } 317 318 char *get_tracing_file(const char *name) 319 { 320 const char *tracing; 321 char *file; 322 323 tracing = find_tracing_dir(); 324 if (!tracing) 325 return NULL; 326 327 file = malloc(strlen(tracing) + strlen(name) + 2); 328 if (!file) 329 return NULL; 330 331 sprintf(file, "%s/%s", tracing, name); 332 return file; 333 } 334 335 void put_tracing_file(char *file) 336 { 337 free(file); 338 } 339 340 int parse_nsec_time(const char *str, u64 *ptime) 341 { 342 u64 time_sec, time_nsec; 343 char *end; 344 345 time_sec = strtoul(str, &end, 10); 346 if (*end != '.' && *end != '\0') 347 return -1; 348 349 if (*end == '.') { 350 int i; 351 char nsec_buf[10]; 352 353 if (strlen(++end) > 9) 354 return -1; 355 356 strncpy(nsec_buf, end, 9); 357 nsec_buf[9] = '\0'; 358 359 /* make it nsec precision */ 360 for (i = strlen(nsec_buf); i < 9; i++) 361 nsec_buf[i] = '0'; 362 363 time_nsec = strtoul(nsec_buf, &end, 10); 364 if (*end != '\0') 365 return -1; 366 } else 367 time_nsec = 0; 368 369 *ptime = time_sec * NSEC_PER_SEC + time_nsec; 370 return 0; 371 } 372 373 unsigned long parse_tag_value(const char *str, struct parse_tag *tags) 374 { 375 struct parse_tag *i = tags; 376 377 while (i->tag) { 378 char *s; 379 380 s = strchr(str, i->tag); 381 if (s) { 382 unsigned long int value; 383 char *endptr; 384 385 value = strtoul(str, &endptr, 10); 386 if (s != endptr) 387 break; 388 389 if (value > ULONG_MAX / i->mult) 390 break; 391 value *= i->mult; 392 return value; 393 } 394 i++; 395 } 396 397 return (unsigned long) -1; 398 } 399 400 int filename__read_int(const char *filename, int *value) 401 { 402 char line[64]; 403 int fd = open(filename, O_RDONLY), err = -1; 404 405 if (fd < 0) 406 return -1; 407 408 if (read(fd, line, sizeof(line)) > 0) { 409 *value = atoi(line); 410 err = 0; 411 } 412 413 close(fd); 414 return err; 415 } 416