#include "../perf.h" #include "util.h" #include <sys/mman.h> #ifdef BACKTRACE_SUPPORT #include <execinfo.h> #endif #include <stdio.h> #include <stdlib.h> /* * XXX We need to find a better place for these things... */ unsigned int page_size; bool test_attr__enabled; bool perf_host = true; bool perf_guest = false; char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events"; void event_attr_init(struct perf_event_attr *attr) { if (!perf_host) attr->exclude_host = 1; if (!perf_guest) attr->exclude_guest = 1; /* to capture ABI version */ attr->size = sizeof(*attr); } int mkdir_p(char *path, mode_t mode) { struct stat st; int err; char *d = path; if (*d != '/') return -1; if (stat(path, &st) == 0) return 0; while (*++d == '/'); while ((d = strchr(d, '/'))) { *d = '\0'; err = stat(path, &st) && mkdir(path, mode); *d++ = '/'; if (err) return -1; while (*d == '/') ++d; } return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; } static int slow_copyfile(const char *from, const char *to) { int err = 0; char *line = NULL; size_t n; FILE *from_fp = fopen(from, "r"), *to_fp; if (from_fp == NULL) goto out; to_fp = fopen(to, "w"); if (to_fp == NULL) goto out_fclose_from; while (getline(&line, &n, from_fp) > 0) if (fputs(line, to_fp) == EOF) goto out_fclose_to; err = 0; out_fclose_to: fclose(to_fp); free(line); out_fclose_from: fclose(from_fp); out: return err; } int copyfile(const char *from, const char *to) { int fromfd, tofd; struct stat st; void *addr; int err = -1; if (stat(from, &st)) goto out; if (st.st_size == 0) /* /proc? do it slowly... */ return slow_copyfile(from, to); fromfd = open(from, O_RDONLY); if (fromfd < 0) goto out; tofd = creat(to, 0755); if (tofd < 0) goto out_close_from; addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fromfd, 0); if (addr == MAP_FAILED) goto out_close_to; if (write(tofd, addr, st.st_size) == st.st_size) err = 0; munmap(addr, st.st_size); out_close_to: close(tofd); if (err) unlink(to); out_close_from: close(fromfd); out: return err; } unsigned long convert_unit(unsigned long value, char *unit) { *unit = ' '; if (value > 1000) { value /= 1000; *unit = 'K'; } if (value > 1000) { value /= 1000; *unit = 'M'; } if (value > 1000) { value /= 1000; *unit = 'G'; } return value; } int readn(int fd, void *buf, size_t n) { void *buf_start = buf; while (n) { int ret = read(fd, buf, n); if (ret <= 0) return ret; n -= ret; buf += ret; } return buf - buf_start; } size_t hex_width(u64 v) { size_t n = 1; while ((v >>= 4)) ++n; return n; } static int hex(char ch) { if ((ch >= '0') && (ch <= '9')) return ch - '0'; if ((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10; if ((ch >= 'A') && (ch <= 'F')) return ch - 'A' + 10; return -1; } /* * While we find nice hex chars, build a long_val. * Return number of chars processed. */ int hex2u64(const char *ptr, u64 *long_val) { const char *p = ptr; *long_val = 0; while (*p) { const int hex_val = hex(*p); if (hex_val < 0) break; *long_val = (*long_val << 4) | hex_val; p++; } return p - ptr; } /* Obtain a backtrace and print it to stdout. */ #ifdef BACKTRACE_SUPPORT void dump_stack(void) { void *array[16]; size_t size = backtrace(array, ARRAY_SIZE(array)); char **strings = backtrace_symbols(array, size); size_t i; printf("Obtained %zd stack frames.\n", size); for (i = 0; i < size; i++) printf("%s\n", strings[i]); free(strings); } #else void dump_stack(void) {} #endif void get_term_dimensions(struct winsize *ws) { char *s = getenv("LINES"); if (s != NULL) { ws->ws_row = atoi(s); s = getenv("COLUMNS"); if (s != NULL) { ws->ws_col = atoi(s); if (ws->ws_row && ws->ws_col) return; } } #ifdef TIOCGWINSZ if (ioctl(1, TIOCGWINSZ, ws) == 0 && ws->ws_row && ws->ws_col) return; #endif ws->ws_row = 25; ws->ws_col = 80; } static void set_tracing_events_path(const char *mountpoint) { snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", mountpoint, "tracing/events"); } const char *perf_debugfs_mount(const char *mountpoint) { const char *mnt; mnt = debugfs_mount(mountpoint); if (!mnt) return NULL; set_tracing_events_path(mnt); return mnt; } void perf_debugfs_set_path(const char *mntpt) { snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt); set_tracing_events_path(mntpt); }