aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Makefile1
-rw-r--r--tools/perf/util/header.c82
-rw-r--r--tools/perf/util/symbol.c17
-rw-r--r--tools/perf/util/symbol.h2
-rw-r--r--tools/perf/util/util.c69
-rw-r--r--tools/perf/util/util.h3
6 files changed, 165 insertions, 9 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index fafea0b6f323..7c846424aebf 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -425,6 +425,7 @@ LIB_OBJS += util/svghelper.o
425LIB_OBJS += util/sort.o 425LIB_OBJS += util/sort.o
426LIB_OBJS += util/hist.o 426LIB_OBJS += util/hist.o
427LIB_OBJS += util/probe-event.o 427LIB_OBJS += util/probe-event.o
428LIB_OBJS += util/util.o
428 429
429BUILTIN_OBJS += builtin-annotate.o 430BUILTIN_OBJS += builtin-annotate.o
430 431
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 8a0bca55106f..df237c3a041b 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -169,20 +169,23 @@ static int do_write(int fd, const void *buf, size_t size)
169 return 0; 169 return 0;
170} 170}
171 171
172#define dsos__for_each_with_build_id(pos, head) \
173 list_for_each_entry(pos, head, node) \
174 if (!pos->has_build_id) \
175 continue; \
176 else
177
172static int __dsos__write_buildid_table(struct list_head *head, int fd) 178static int __dsos__write_buildid_table(struct list_head *head, int fd)
173{ 179{
174#define NAME_ALIGN 64 180#define NAME_ALIGN 64
175 struct dso *pos; 181 struct dso *pos;
176 static const char zero_buf[NAME_ALIGN]; 182 static const char zero_buf[NAME_ALIGN];
177 183
178 list_for_each_entry(pos, head, node) { 184 dsos__for_each_with_build_id(pos, head) {
179 int err; 185 int err;
180 struct build_id_event b; 186 struct build_id_event b;
181 size_t len; 187 size_t len = pos->long_name_len + 1;
182 188
183 if (!pos->has_build_id)
184 continue;
185 len = pos->long_name_len + 1;
186 len = ALIGN(len, NAME_ALIGN); 189 len = ALIGN(len, NAME_ALIGN);
187 memset(&b, 0, sizeof(b)); 190 memset(&b, 0, sizeof(b));
188 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); 191 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
@@ -209,6 +212,74 @@ static int dsos__write_buildid_table(int fd)
209 return err; 212 return err;
210} 213}
211 214
215static int dso__cache_build_id(struct dso *self, const char *debugdir)
216{
217 const size_t size = PATH_MAX;
218 char *filename = malloc(size),
219 *linkname = malloc(size), *targetname, *sbuild_id;
220 int len, err = -1;
221
222 if (filename == NULL || linkname == NULL)
223 goto out_free;
224
225 len = snprintf(filename, size, "%s%s", debugdir, self->long_name);
226 if (mkdir_p(filename, 0755))
227 goto out_free;
228
229 len += snprintf(filename + len, sizeof(filename) - len, "/");
230 sbuild_id = filename + len;
231 build_id__sprintf(self->build_id, sizeof(self->build_id), sbuild_id);
232
233 if (access(filename, F_OK) && link(self->long_name, filename) &&
234 copyfile(self->long_name, filename))
235 goto out_free;
236
237 len = snprintf(linkname, size, "%s/.build-id/%.2s",
238 debugdir, sbuild_id);
239
240 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
241 goto out_free;
242
243 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
244 targetname = filename + strlen(debugdir) - 5;
245 memcpy(targetname, "../..", 5);
246
247 if (symlink(targetname, linkname) == 0)
248 err = 0;
249out_free:
250 free(filename);
251 free(linkname);
252 return err;
253}
254
255static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
256{
257 struct dso *pos;
258 int err = 0;
259
260 dsos__for_each_with_build_id(pos, head)
261 if (dso__cache_build_id(pos, debugdir))
262 err = -1;
263
264 return err;
265}
266
267static int dsos__cache_build_ids(void)
268{
269 int err_kernel, err_user;
270 char debugdir[PATH_MAX];
271
272 snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"),
273 DEBUG_CACHE_DIR);
274
275 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
276 return -1;
277
278 err_kernel = __dsos__cache_build_ids(&dsos__kernel, debugdir);
279 err_user = __dsos__cache_build_ids(&dsos__user, debugdir);
280 return err_kernel || err_user ? -1 : 0;
281}
282
212static int perf_header__adds_write(struct perf_header *self, int fd) 283static int perf_header__adds_write(struct perf_header *self, int fd)
213{ 284{
214 int nr_sections; 285 int nr_sections;
@@ -258,6 +329,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
258 goto out_free; 329 goto out_free;
259 } 330 }
260 buildid_sec->size = lseek(fd, 0, SEEK_CUR) - buildid_sec->offset; 331 buildid_sec->size = lseek(fd, 0, SEEK_CUR) - buildid_sec->offset;
332 dsos__cache_build_ids();
261 } 333 }
262 334
263 lseek(fd, sec_start, SEEK_SET); 335 lseek(fd, sec_start, SEEK_SET);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index ab92763edb03..79ca6a099f96 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -22,6 +22,7 @@
22enum dso_origin { 22enum dso_origin {
23 DSO__ORIG_KERNEL = 0, 23 DSO__ORIG_KERNEL = 0,
24 DSO__ORIG_JAVA_JIT, 24 DSO__ORIG_JAVA_JIT,
25 DSO__ORIG_BUILD_ID_CACHE,
25 DSO__ORIG_FEDORA, 26 DSO__ORIG_FEDORA,
26 DSO__ORIG_UBUNTU, 27 DSO__ORIG_UBUNTU,
27 DSO__ORIG_BUILDID, 28 DSO__ORIG_BUILDID,
@@ -1191,6 +1192,7 @@ char dso__symtab_origin(const struct dso *self)
1191 static const char origin[] = { 1192 static const char origin[] = {
1192 [DSO__ORIG_KERNEL] = 'k', 1193 [DSO__ORIG_KERNEL] = 'k',
1193 [DSO__ORIG_JAVA_JIT] = 'j', 1194 [DSO__ORIG_JAVA_JIT] = 'j',
1195 [DSO__ORIG_BUILD_ID_CACHE] = 'B',
1194 [DSO__ORIG_FEDORA] = 'f', 1196 [DSO__ORIG_FEDORA] = 'f',
1195 [DSO__ORIG_UBUNTU] = 'u', 1197 [DSO__ORIG_UBUNTU] = 'u',
1196 [DSO__ORIG_BUILDID] = 'b', 1198 [DSO__ORIG_BUILDID] = 'b',
@@ -1209,6 +1211,7 @@ int dso__load(struct dso *self, struct map *map, struct perf_session *session,
1209 int size = PATH_MAX; 1211 int size = PATH_MAX;
1210 char *name; 1212 char *name;
1211 u8 build_id[BUILD_ID_SIZE]; 1213 u8 build_id[BUILD_ID_SIZE];
1214 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1212 int ret = -1; 1215 int ret = -1;
1213 int fd; 1216 int fd;
1214 1217
@@ -1230,8 +1233,16 @@ int dso__load(struct dso *self, struct map *map, struct perf_session *session,
1230 return ret; 1233 return ret;
1231 } 1234 }
1232 1235
1233 self->origin = DSO__ORIG_FEDORA - 1; 1236 self->origin = DSO__ORIG_BUILD_ID_CACHE;
1234 1237
1238 if (self->has_build_id) {
1239 build_id__sprintf(self->build_id, sizeof(self->build_id),
1240 build_id_hex);
1241 snprintf(name, size, "%s/%s/.build-id/%.2s/%s",
1242 getenv("HOME"), DEBUG_CACHE_DIR,
1243 build_id_hex, build_id_hex + 2);
1244 goto open_file;
1245 }
1235more: 1246more:
1236 do { 1247 do {
1237 self->origin++; 1248 self->origin++;
@@ -1247,8 +1258,6 @@ more:
1247 case DSO__ORIG_BUILDID: 1258 case DSO__ORIG_BUILDID:
1248 if (filename__read_build_id(self->long_name, build_id, 1259 if (filename__read_build_id(self->long_name, build_id,
1249 sizeof(build_id))) { 1260 sizeof(build_id))) {
1250 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1251
1252 build_id__sprintf(build_id, sizeof(build_id), 1261 build_id__sprintf(build_id, sizeof(build_id),
1253 build_id_hex); 1262 build_id_hex);
1254 snprintf(name, size, 1263 snprintf(name, size,
@@ -1276,7 +1285,7 @@ compare_build_id:
1276 if (!dso__build_id_equal(self, build_id)) 1285 if (!dso__build_id_equal(self, build_id))
1277 goto more; 1286 goto more;
1278 } 1287 }
1279 1288open_file:
1280 fd = open(name, O_RDONLY); 1289 fd = open(name, O_RDONLY);
1281 } while (fd < 0); 1290 } while (fd < 0);
1282 1291
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 9eabd60f819d..f27e158943e9 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -8,6 +8,8 @@
8#include <linux/rbtree.h> 8#include <linux/rbtree.h>
9#include "event.h" 9#include "event.h"
10 10
11#define DEBUG_CACHE_DIR ".debug"
12
11#ifdef HAVE_CPLUS_DEMANGLE 13#ifdef HAVE_CPLUS_DEMANGLE
12extern char *cplus_demangle(const char *, int); 14extern char *cplus_demangle(const char *, int);
13 15
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
new file mode 100644
index 000000000000..f3c0798a5e78
--- /dev/null
+++ b/tools/perf/util/util.c
@@ -0,0 +1,69 @@
1#include <sys/mman.h>
2#include <sys/stat.h>
3#include <sys/types.h>
4#include <fcntl.h>
5#include <string.h>
6#include <unistd.h>
7#include "util.h"
8
9int mkdir_p(char *path, mode_t mode)
10{
11 struct stat st;
12 int err;
13 char *d = path;
14
15 if (*d != '/')
16 return -1;
17
18 if (stat(path, &st) == 0)
19 return 0;
20
21 while (*++d == '/');
22
23 while ((d = strchr(d, '/'))) {
24 *d = '\0';
25 err = stat(path, &st) && mkdir(path, mode);
26 *d++ = '/';
27 if (err)
28 return -1;
29 while (*d == '/')
30 ++d;
31 }
32 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
33}
34
35int copyfile(const char *from, const char *to)
36{
37 int fromfd, tofd;
38 struct stat st;
39 void *addr;
40 int err = -1;
41
42 if (stat(from, &st))
43 goto out;
44
45 fromfd = open(from, O_RDONLY);
46 if (fromfd < 0)
47 goto out;
48
49 tofd = creat(to, 0755);
50 if (tofd < 0)
51 goto out_close_from;
52
53 addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fromfd, 0);
54 if (addr == MAP_FAILED)
55 goto out_close_to;
56
57 if (write(tofd, addr, st.st_size) == st.st_size)
58 err = 0;
59
60 munmap(addr, st.st_size);
61out_close_to:
62 close(tofd);
63 if (err)
64 unlink(to);
65out_close_from:
66 close(fromfd);
67out:
68 return err;
69}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index c673d8825883..0f5b2a6f1080 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -403,4 +403,7 @@ void git_qsort(void *base, size_t nmemb, size_t size,
403#endif 403#endif
404#endif 404#endif
405 405
406int mkdir_p(char *path, mode_t mode);
407int copyfile(const char *from, const char *to);
408
406#endif 409#endif