xref: /linux/tools/perf/util/util.c (revision f884ab15afdc5514e88105c92a4e2e1e6539869a)
1 #include "../perf.h"
2 #include "util.h"
3 #include <sys/mman.h>
4 #ifdef 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)
59 {
60 	int err = 0;
61 	char *line = NULL;
62 	size_t n;
63 	FILE *from_fp = fopen(from, "r"), *to_fp;
64 
65 	if (from_fp == NULL)
66 		goto out;
67 
68 	to_fp = fopen(to, "w");
69 	if (to_fp == NULL)
70 		goto out_fclose_from;
71 
72 	while (getline(&line, &n, from_fp) > 0)
73 		if (fputs(line, to_fp) == EOF)
74 			goto out_fclose_to;
75 	err = 0;
76 out_fclose_to:
77 	fclose(to_fp);
78 	free(line);
79 out_fclose_from:
80 	fclose(from_fp);
81 out:
82 	return err;
83 }
84 
85 int copyfile(const char *from, const char *to)
86 {
87 	int fromfd, tofd;
88 	struct stat st;
89 	void *addr;
90 	int err = -1;
91 
92 	if (stat(from, &st))
93 		goto out;
94 
95 	if (st.st_size == 0) /* /proc? do it slowly... */
96 		return slow_copyfile(from, to);
97 
98 	fromfd = open(from, O_RDONLY);
99 	if (fromfd < 0)
100 		goto out;
101 
102 	tofd = creat(to, 0755);
103 	if (tofd < 0)
104 		goto out_close_from;
105 
106 	addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fromfd, 0);
107 	if (addr == MAP_FAILED)
108 		goto out_close_to;
109 
110 	if (write(tofd, addr, st.st_size) == st.st_size)
111 		err = 0;
112 
113 	munmap(addr, st.st_size);
114 out_close_to:
115 	close(tofd);
116 	if (err)
117 		unlink(to);
118 out_close_from:
119 	close(fromfd);
120 out:
121 	return err;
122 }
123 
124 unsigned long convert_unit(unsigned long value, char *unit)
125 {
126 	*unit = ' ';
127 
128 	if (value > 1000) {
129 		value /= 1000;
130 		*unit = 'K';
131 	}
132 
133 	if (value > 1000) {
134 		value /= 1000;
135 		*unit = 'M';
136 	}
137 
138 	if (value > 1000) {
139 		value /= 1000;
140 		*unit = 'G';
141 	}
142 
143 	return value;
144 }
145 
146 int readn(int fd, void *buf, size_t n)
147 {
148 	void *buf_start = buf;
149 
150 	while (n) {
151 		int ret = read(fd, buf, n);
152 
153 		if (ret <= 0)
154 			return ret;
155 
156 		n -= ret;
157 		buf += ret;
158 	}
159 
160 	return buf - buf_start;
161 }
162 
163 size_t hex_width(u64 v)
164 {
165 	size_t n = 1;
166 
167 	while ((v >>= 4))
168 		++n;
169 
170 	return n;
171 }
172 
173 static int hex(char ch)
174 {
175 	if ((ch >= '0') && (ch <= '9'))
176 		return ch - '0';
177 	if ((ch >= 'a') && (ch <= 'f'))
178 		return ch - 'a' + 10;
179 	if ((ch >= 'A') && (ch <= 'F'))
180 		return ch - 'A' + 10;
181 	return -1;
182 }
183 
184 /*
185  * While we find nice hex chars, build a long_val.
186  * Return number of chars processed.
187  */
188 int hex2u64(const char *ptr, u64 *long_val)
189 {
190 	const char *p = ptr;
191 	*long_val = 0;
192 
193 	while (*p) {
194 		const int hex_val = hex(*p);
195 
196 		if (hex_val < 0)
197 			break;
198 
199 		*long_val = (*long_val << 4) | hex_val;
200 		p++;
201 	}
202 
203 	return p - ptr;
204 }
205 
206 /* Obtain a backtrace and print it to stdout. */
207 #ifdef BACKTRACE_SUPPORT
208 void dump_stack(void)
209 {
210 	void *array[16];
211 	size_t size = backtrace(array, ARRAY_SIZE(array));
212 	char **strings = backtrace_symbols(array, size);
213 	size_t i;
214 
215 	printf("Obtained %zd stack frames.\n", size);
216 
217 	for (i = 0; i < size; i++)
218 		printf("%s\n", strings[i]);
219 
220 	free(strings);
221 }
222 #else
223 void dump_stack(void) {}
224 #endif
225 
226 void get_term_dimensions(struct winsize *ws)
227 {
228 	char *s = getenv("LINES");
229 
230 	if (s != NULL) {
231 		ws->ws_row = atoi(s);
232 		s = getenv("COLUMNS");
233 		if (s != NULL) {
234 			ws->ws_col = atoi(s);
235 			if (ws->ws_row && ws->ws_col)
236 				return;
237 		}
238 	}
239 #ifdef TIOCGWINSZ
240 	if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
241 	    ws->ws_row && ws->ws_col)
242 		return;
243 #endif
244 	ws->ws_row = 25;
245 	ws->ws_col = 80;
246 }
247 
248 static void set_tracing_events_path(const char *mountpoint)
249 {
250 	snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
251 		 mountpoint, "tracing/events");
252 }
253 
254 const char *perf_debugfs_mount(const char *mountpoint)
255 {
256 	const char *mnt;
257 
258 	mnt = debugfs_mount(mountpoint);
259 	if (!mnt)
260 		return NULL;
261 
262 	set_tracing_events_path(mnt);
263 
264 	return mnt;
265 }
266 
267 void perf_debugfs_set_path(const char *mntpt)
268 {
269 	snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt);
270 	set_tracing_events_path(mntpt);
271 }
272