blob: bae8756a4eb1ed7221518879bb1e841c7f9c8e0c [file] [log] [blame]
Joerg Roedel1aed2672012-01-04 17:54:20 +01001#include "../perf.h"
Arnaldo Carvalho de Melo4cf40132009-12-27 21:37:06 -02002#include "util.h"
Frederic Weisbecker69e3f522010-01-16 14:21:15 +01003#include <sys/mman.h>
Ingo Molnar89fe8082013-09-30 12:07:11 +02004#ifdef HAVE_BACKTRACE_SUPPORT
Arnaldo Carvalho de Melodc4552b2012-08-07 23:32:05 -03005#include <execinfo.h>
Irina Tirdeac9f08be2012-09-08 03:43:23 +03006#endif
Arnaldo Carvalho de Melodc4552b2012-08-07 23:32:05 -03007#include <stdio.h>
8#include <stdlib.h>
Jiri Olsacef82c92013-12-03 14:09:22 +01009#include <string.h>
10#include <errno.h>
Jiri Olsa838d1452013-11-28 11:30:15 +010011#include <linux/kernel.h>
Arnaldo Carvalho de Melo4cf40132009-12-27 21:37:06 -020012
Joerg Roedel1aed2672012-01-04 17:54:20 +010013/*
14 * XXX We need to find a better place for these things...
15 */
Arnaldo Carvalho de Melo0c1fe6b2012-10-06 14:57:10 -030016unsigned int page_size;
17
Arnaldo Carvalho de Melo0c6332e2012-12-13 16:43:04 -030018bool test_attr__enabled;
19
Joerg Roedel1aed2672012-01-04 17:54:20 +010020bool perf_host = true;
Joerg Roedelc4a7dca2012-02-10 18:05:05 +010021bool perf_guest = false;
Joerg Roedel1aed2672012-01-04 17:54:20 +010022
Borislav Petkov13559152013-02-20 16:32:31 +010023char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
24
Joerg Roedel1aed2672012-01-04 17:54:20 +010025void event_attr_init(struct perf_event_attr *attr)
26{
27 if (!perf_host)
28 attr->exclude_host = 1;
29 if (!perf_guest)
30 attr->exclude_guest = 1;
Stephane Eranian7e1ccd32012-02-09 16:12:38 +010031 /* to capture ABI version */
32 attr->size = sizeof(*attr);
Joerg Roedel1aed2672012-01-04 17:54:20 +010033}
34
Arnaldo Carvalho de Melo4cf40132009-12-27 21:37:06 -020035int mkdir_p(char *path, mode_t mode)
36{
37 struct stat st;
38 int err;
39 char *d = path;
40
41 if (*d != '/')
42 return -1;
43
44 if (stat(path, &st) == 0)
45 return 0;
46
47 while (*++d == '/');
48
49 while ((d = strchr(d, '/'))) {
50 *d = '\0';
51 err = stat(path, &st) && mkdir(path, mode);
52 *d++ = '/';
53 if (err)
54 return -1;
55 while (*d == '/')
56 ++d;
57 }
58 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
59}
60
Adrian Hunter9a17d722013-10-14 13:43:41 +030061static int slow_copyfile(const char *from, const char *to, mode_t mode)
Arnaldo Carvalho de Melo9e201442010-01-14 18:30:06 -020062{
Adrian Hunter9a17d722013-10-14 13:43:41 +030063 int err = -1;
Arnaldo Carvalho de Melo9e201442010-01-14 18:30:06 -020064 char *line = NULL;
65 size_t n;
66 FILE *from_fp = fopen(from, "r"), *to_fp;
Adrian Hunter9a17d722013-10-14 13:43:41 +030067 mode_t old_umask;
Arnaldo Carvalho de Melo9e201442010-01-14 18:30:06 -020068
69 if (from_fp == NULL)
70 goto out;
71
Adrian Hunter9a17d722013-10-14 13:43:41 +030072 old_umask = umask(mode ^ 0777);
Arnaldo Carvalho de Melo9e201442010-01-14 18:30:06 -020073 to_fp = fopen(to, "w");
Adrian Hunter9a17d722013-10-14 13:43:41 +030074 umask(old_umask);
Arnaldo Carvalho de Melo9e201442010-01-14 18:30:06 -020075 if (to_fp == NULL)
76 goto out_fclose_from;
77
78 while (getline(&line, &n, from_fp) > 0)
79 if (fputs(line, to_fp) == EOF)
80 goto out_fclose_to;
81 err = 0;
82out_fclose_to:
83 fclose(to_fp);
84 free(line);
85out_fclose_from:
86 fclose(from_fp);
87out:
88 return err;
89}
90
Adrian Hunter9a17d722013-10-14 13:43:41 +030091int copyfile_mode(const char *from, const char *to, mode_t mode)
Arnaldo Carvalho de Melo4cf40132009-12-27 21:37:06 -020092{
93 int fromfd, tofd;
94 struct stat st;
95 void *addr;
96 int err = -1;
97
98 if (stat(from, &st))
99 goto out;
100
Arnaldo Carvalho de Melo9e201442010-01-14 18:30:06 -0200101 if (st.st_size == 0) /* /proc? do it slowly... */
Adrian Hunter9a17d722013-10-14 13:43:41 +0300102 return slow_copyfile(from, to, mode);
Arnaldo Carvalho de Melo9e201442010-01-14 18:30:06 -0200103
Arnaldo Carvalho de Melo4cf40132009-12-27 21:37:06 -0200104 fromfd = open(from, O_RDONLY);
105 if (fromfd < 0)
106 goto out;
107
Adrian Hunter9a17d722013-10-14 13:43:41 +0300108 tofd = creat(to, mode);
Arnaldo Carvalho de Melo4cf40132009-12-27 21:37:06 -0200109 if (tofd < 0)
110 goto out_close_from;
111
112 addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fromfd, 0);
113 if (addr == MAP_FAILED)
114 goto out_close_to;
115
116 if (write(tofd, addr, st.st_size) == st.st_size)
117 err = 0;
118
119 munmap(addr, st.st_size);
120out_close_to:
121 close(tofd);
122 if (err)
123 unlink(to);
124out_close_from:
125 close(fromfd);
126out:
127 return err;
128}
Arnaldo Carvalho de Meloc82ee822010-05-14 14:19:35 -0300129
Adrian Hunter9a17d722013-10-14 13:43:41 +0300130int copyfile(const char *from, const char *to)
131{
132 return copyfile_mode(from, to, 0755);
133}
134
Arnaldo Carvalho de Meloc82ee822010-05-14 14:19:35 -0300135unsigned long convert_unit(unsigned long value, char *unit)
136{
137 *unit = ' ';
138
139 if (value > 1000) {
140 value /= 1000;
141 *unit = 'K';
142 }
143
144 if (value > 1000) {
145 value /= 1000;
146 *unit = 'M';
147 }
148
149 if (value > 1000) {
150 value /= 1000;
151 *unit = 'G';
152 }
153
154 return value;
155}
Arnaldo Carvalho de Melo1e7972c2011-01-03 16:50:55 -0200156
Jiri Olsabc3a5022013-11-28 11:30:16 +0100157static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
Arnaldo Carvalho de Melo1e7972c2011-01-03 16:50:55 -0200158{
159 void *buf_start = buf;
Jiri Olsa838d1452013-11-28 11:30:15 +0100160 size_t left = n;
Arnaldo Carvalho de Melo1e7972c2011-01-03 16:50:55 -0200161
Jiri Olsa838d1452013-11-28 11:30:15 +0100162 while (left) {
Jiri Olsabc3a5022013-11-28 11:30:16 +0100163 ssize_t ret = is_read ? read(fd, buf, left) :
164 write(fd, buf, left);
Arnaldo Carvalho de Melo1e7972c2011-01-03 16:50:55 -0200165
166 if (ret <= 0)
167 return ret;
168
Jiri Olsa838d1452013-11-28 11:30:15 +0100169 left -= ret;
170 buf += ret;
Arnaldo Carvalho de Melo1e7972c2011-01-03 16:50:55 -0200171 }
172
Jiri Olsa838d1452013-11-28 11:30:15 +0100173 BUG_ON((size_t)(buf - buf_start) != n);
174 return n;
Arnaldo Carvalho de Melo1e7972c2011-01-03 16:50:55 -0200175}
Arnaldo Carvalho de Melo61e04b32012-04-19 13:15:24 -0300176
Jiri Olsabc3a5022013-11-28 11:30:16 +0100177/*
178 * Read exactly 'n' bytes or return an error.
179 */
180ssize_t readn(int fd, void *buf, size_t n)
181{
182 return ion(true, fd, buf, n);
183}
184
185/*
186 * Write exactly 'n' bytes or return an error.
187 */
188ssize_t writen(int fd, void *buf, size_t n)
189{
190 return ion(false, fd, buf, n);
191}
192
Arnaldo Carvalho de Melo61e04b32012-04-19 13:15:24 -0300193size_t hex_width(u64 v)
194{
195 size_t n = 1;
196
197 while ((v >>= 4))
198 ++n;
199
200 return n;
201}
Arnaldo Carvalho de Melodc4552b2012-08-07 23:32:05 -0300202
Jiri Olsab2aff5f2012-10-27 23:18:30 +0200203static int hex(char ch)
204{
205 if ((ch >= '0') && (ch <= '9'))
206 return ch - '0';
207 if ((ch >= 'a') && (ch <= 'f'))
208 return ch - 'a' + 10;
209 if ((ch >= 'A') && (ch <= 'F'))
210 return ch - 'A' + 10;
211 return -1;
212}
213
214/*
215 * While we find nice hex chars, build a long_val.
216 * Return number of chars processed.
217 */
218int hex2u64(const char *ptr, u64 *long_val)
219{
220 const char *p = ptr;
221 *long_val = 0;
222
223 while (*p) {
224 const int hex_val = hex(*p);
225
226 if (hex_val < 0)
227 break;
228
229 *long_val = (*long_val << 4) | hex_val;
230 p++;
231 }
232
233 return p - ptr;
234}
235
Arnaldo Carvalho de Melodc4552b2012-08-07 23:32:05 -0300236/* Obtain a backtrace and print it to stdout. */
Ingo Molnar89fe8082013-09-30 12:07:11 +0200237#ifdef HAVE_BACKTRACE_SUPPORT
Arnaldo Carvalho de Melodc4552b2012-08-07 23:32:05 -0300238void dump_stack(void)
239{
240 void *array[16];
241 size_t size = backtrace(array, ARRAY_SIZE(array));
242 char **strings = backtrace_symbols(array, size);
243 size_t i;
244
245 printf("Obtained %zd stack frames.\n", size);
246
247 for (i = 0; i < size; i++)
248 printf("%s\n", strings[i]);
249
250 free(strings);
251}
Irina Tirdeac9f08be2012-09-08 03:43:23 +0300252#else
253void dump_stack(void) {}
254#endif
David Ahern2c803e52013-01-14 10:48:01 -0700255
256void get_term_dimensions(struct winsize *ws)
257{
258 char *s = getenv("LINES");
259
260 if (s != NULL) {
261 ws->ws_row = atoi(s);
262 s = getenv("COLUMNS");
263 if (s != NULL) {
264 ws->ws_col = atoi(s);
265 if (ws->ws_row && ws->ws_col)
266 return;
267 }
268 }
269#ifdef TIOCGWINSZ
270 if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
271 ws->ws_row && ws->ws_col)
272 return;
273#endif
274 ws->ws_row = 25;
275 ws->ws_col = 80;
276}
Borislav Petkov13559152013-02-20 16:32:31 +0100277
278static void set_tracing_events_path(const char *mountpoint)
279{
280 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
281 mountpoint, "tracing/events");
282}
283
284const char *perf_debugfs_mount(const char *mountpoint)
285{
286 const char *mnt;
287
288 mnt = debugfs_mount(mountpoint);
289 if (!mnt)
290 return NULL;
291
292 set_tracing_events_path(mnt);
293
294 return mnt;
295}
296
297void perf_debugfs_set_path(const char *mntpt)
298{
299 snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt);
300 set_tracing_events_path(mntpt);
301}
Namhyung Kim167aedc2013-06-26 16:14:04 +0900302
303static const char *find_debugfs(void)
304{
305 const char *path = perf_debugfs_mount(NULL);
306
307 if (!path)
308 fprintf(stderr, "Your kernel does not support the debugfs filesystem");
309
310 return path;
311}
312
313/*
314 * Finds the path to the debugfs/tracing
315 * Allocates the string and stores it.
316 */
317const char *find_tracing_dir(void)
318{
319 static char *tracing;
320 static int tracing_found;
321 const char *debugfs;
322
323 if (tracing_found)
324 return tracing;
325
326 debugfs = find_debugfs();
327 if (!debugfs)
328 return NULL;
329
330 tracing = malloc(strlen(debugfs) + 9);
331 if (!tracing)
332 return NULL;
333
334 sprintf(tracing, "%s/tracing", debugfs);
335
336 tracing_found = 1;
337 return tracing;
338}
339
340char *get_tracing_file(const char *name)
341{
342 const char *tracing;
343 char *file;
344
345 tracing = find_tracing_dir();
346 if (!tracing)
347 return NULL;
348
349 file = malloc(strlen(tracing) + strlen(name) + 2);
350 if (!file)
351 return NULL;
352
353 sprintf(file, "%s/%s", tracing, name);
354 return file;
355}
356
357void put_tracing_file(char *file)
358{
359 free(file);
360}
Namhyung Kim3b47abe2013-06-04 10:50:29 +0900361
362int parse_nsec_time(const char *str, u64 *ptime)
363{
364 u64 time_sec, time_nsec;
365 char *end;
366
367 time_sec = strtoul(str, &end, 10);
368 if (*end != '.' && *end != '\0')
369 return -1;
370
371 if (*end == '.') {
372 int i;
373 char nsec_buf[10];
374
375 if (strlen(++end) > 9)
376 return -1;
377
378 strncpy(nsec_buf, end, 9);
379 nsec_buf[9] = '\0';
380
381 /* make it nsec precision */
382 for (i = strlen(nsec_buf); i < 9; i++)
383 nsec_buf[i] = '0';
384
385 time_nsec = strtoul(nsec_buf, &end, 10);
386 if (*end != '\0')
387 return -1;
388 } else
389 time_nsec = 0;
390
391 *ptime = time_sec * NSEC_PER_SEC + time_nsec;
392 return 0;
393}
Jiri Olsa27050f52013-09-01 12:36:13 +0200394
395unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
396{
397 struct parse_tag *i = tags;
398
399 while (i->tag) {
400 char *s;
401
402 s = strchr(str, i->tag);
403 if (s) {
404 unsigned long int value;
405 char *endptr;
406
407 value = strtoul(str, &endptr, 10);
408 if (s != endptr)
409 break;
410
Adrian Hunter56921be2013-10-22 10:34:17 +0300411 if (value > ULONG_MAX / i->mult)
412 break;
Jiri Olsa27050f52013-09-01 12:36:13 +0200413 value *= i->mult;
414 return value;
415 }
416 i++;
417 }
418
419 return (unsigned long) -1;
420}
Arnaldo Carvalho de Melo97a07f12013-10-17 16:33:43 -0300421
422int filename__read_int(const char *filename, int *value)
423{
424 char line[64];
425 int fd = open(filename, O_RDONLY), err = -1;
426
427 if (fd < 0)
428 return -1;
429
430 if (read(fd, line, sizeof(line)) > 0) {
431 *value = atoi(line);
432 err = 0;
433 }
434
435 close(fd);
436 return err;
437}
Jiri Olsacef82c92013-12-03 14:09:22 +0100438
439int filename__read_str(const char *filename, char **buf, size_t *sizep)
440{
441 size_t size = 0, alloc_size = 0;
442 void *bf = NULL, *nbf;
443 int fd, n, err = 0;
444
445 fd = open(filename, O_RDONLY);
446 if (fd < 0)
447 return -errno;
448
449 do {
450 if (size == alloc_size) {
451 alloc_size += BUFSIZ;
452 nbf = realloc(bf, alloc_size);
453 if (!nbf) {
454 err = -ENOMEM;
455 break;
456 }
457
458 bf = nbf;
459 }
460
461 n = read(fd, bf + size, alloc_size - size);
462 if (n < 0) {
463 if (size) {
464 pr_warning("read failed %d: %s\n",
465 errno, strerror(errno));
466 err = 0;
467 } else
468 err = -errno;
469
470 break;
471 }
472
473 size += n;
474 } while (n > 0);
475
476 if (!err) {
477 *sizep = size;
478 *buf = bf;
479 } else
480 free(bf);
481
482 close(fd);
483 return err;
484}