diff options
Diffstat (limited to 'tools/perf/builtin-buildid-cache.c')
-rw-r--r-- | tools/perf/builtin-buildid-cache.c | 156 |
1 files changed, 153 insertions, 3 deletions
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c index c96c8fa38243..cfede86161d8 100644 --- a/tools/perf/builtin-buildid-cache.c +++ b/tools/perf/builtin-buildid-cache.c | |||
@@ -6,6 +6,11 @@ | |||
6 | * Copyright (C) 2010, Red Hat Inc. | 6 | * Copyright (C) 2010, Red Hat Inc. |
7 | * Copyright (C) 2010, Arnaldo Carvalho de Melo <acme@redhat.com> | 7 | * Copyright (C) 2010, Arnaldo Carvalho de Melo <acme@redhat.com> |
8 | */ | 8 | */ |
9 | #include <sys/types.h> | ||
10 | #include <sys/time.h> | ||
11 | #include <time.h> | ||
12 | #include <dirent.h> | ||
13 | #include <unistd.h> | ||
9 | #include "builtin.h" | 14 | #include "builtin.h" |
10 | #include "perf.h" | 15 | #include "perf.h" |
11 | #include "util/cache.h" | 16 | #include "util/cache.h" |
@@ -17,6 +22,140 @@ | |||
17 | #include "util/session.h" | 22 | #include "util/session.h" |
18 | #include "util/symbol.h" | 23 | #include "util/symbol.h" |
19 | 24 | ||
25 | static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid) | ||
26 | { | ||
27 | char root_dir[PATH_MAX]; | ||
28 | char notes[PATH_MAX]; | ||
29 | u8 build_id[BUILD_ID_SIZE]; | ||
30 | char *p; | ||
31 | |||
32 | strlcpy(root_dir, proc_dir, sizeof(root_dir)); | ||
33 | |||
34 | p = strrchr(root_dir, '/'); | ||
35 | if (!p) | ||
36 | return -1; | ||
37 | *p = '\0'; | ||
38 | |||
39 | scnprintf(notes, sizeof(notes), "%s/sys/kernel/notes", root_dir); | ||
40 | |||
41 | if (sysfs__read_build_id(notes, build_id, sizeof(build_id))) | ||
42 | return -1; | ||
43 | |||
44 | build_id__sprintf(build_id, sizeof(build_id), sbuildid); | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static int build_id_cache__kcore_dir(char *dir, size_t sz) | ||
50 | { | ||
51 | struct timeval tv; | ||
52 | struct tm tm; | ||
53 | char dt[32]; | ||
54 | |||
55 | if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm)) | ||
56 | return -1; | ||
57 | |||
58 | if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm)) | ||
59 | return -1; | ||
60 | |||
61 | scnprintf(dir, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000); | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir, | ||
67 | size_t to_dir_sz) | ||
68 | { | ||
69 | char from[PATH_MAX]; | ||
70 | char to[PATH_MAX]; | ||
71 | struct dirent *dent; | ||
72 | int ret = -1; | ||
73 | DIR *d; | ||
74 | |||
75 | d = opendir(to_dir); | ||
76 | if (!d) | ||
77 | return -1; | ||
78 | |||
79 | scnprintf(from, sizeof(from), "%s/modules", from_dir); | ||
80 | |||
81 | while (1) { | ||
82 | dent = readdir(d); | ||
83 | if (!dent) | ||
84 | break; | ||
85 | if (dent->d_type != DT_DIR) | ||
86 | continue; | ||
87 | scnprintf(to, sizeof(to), "%s/%s/modules", to_dir, | ||
88 | dent->d_name); | ||
89 | if (!compare_proc_modules(from, to)) { | ||
90 | scnprintf(to, sizeof(to), "%s/%s", to_dir, | ||
91 | dent->d_name); | ||
92 | strlcpy(to_dir, to, to_dir_sz); | ||
93 | ret = 0; | ||
94 | break; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | closedir(d); | ||
99 | |||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | static int build_id_cache__add_kcore(const char *filename, const char *debugdir) | ||
104 | { | ||
105 | char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1]; | ||
106 | char from_dir[PATH_MAX], to_dir[PATH_MAX]; | ||
107 | char *p; | ||
108 | |||
109 | strlcpy(from_dir, filename, sizeof(from_dir)); | ||
110 | |||
111 | p = strrchr(from_dir, '/'); | ||
112 | if (!p || strcmp(p + 1, "kcore")) | ||
113 | return -1; | ||
114 | *p = '\0'; | ||
115 | |||
116 | if (build_id_cache__kcore_buildid(from_dir, sbuildid)) | ||
117 | return -1; | ||
118 | |||
119 | scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s", | ||
120 | debugdir, sbuildid); | ||
121 | |||
122 | if (!build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) { | ||
123 | pr_debug("same kcore found in %s\n", to_dir); | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | if (build_id_cache__kcore_dir(dir, sizeof(dir))) | ||
128 | return -1; | ||
129 | |||
130 | scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s", | ||
131 | debugdir, sbuildid, dir); | ||
132 | |||
133 | if (mkdir_p(to_dir, 0755)) | ||
134 | return -1; | ||
135 | |||
136 | if (kcore_copy(from_dir, to_dir)) { | ||
137 | /* Remove YYYYmmddHHMMSShh directory */ | ||
138 | if (!rmdir(to_dir)) { | ||
139 | p = strrchr(to_dir, '/'); | ||
140 | if (p) | ||
141 | *p = '\0'; | ||
142 | /* Try to remove buildid directory */ | ||
143 | if (!rmdir(to_dir)) { | ||
144 | p = strrchr(to_dir, '/'); | ||
145 | if (p) | ||
146 | *p = '\0'; | ||
147 | /* Try to remove [kernel.kcore] directory */ | ||
148 | rmdir(to_dir); | ||
149 | } | ||
150 | } | ||
151 | return -1; | ||
152 | } | ||
153 | |||
154 | pr_debug("kcore added to build-id cache directory %s\n", to_dir); | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
20 | static int build_id_cache__add_file(const char *filename, const char *debugdir) | 159 | static int build_id_cache__add_file(const char *filename, const char *debugdir) |
21 | { | 160 | { |
22 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | 161 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; |
@@ -82,8 +221,12 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused) | |||
82 | 221 | ||
83 | static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp) | 222 | static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp) |
84 | { | 223 | { |
85 | struct perf_session *session = perf_session__new(filename, O_RDONLY, | 224 | struct perf_data_file file = { |
86 | force, false, NULL); | 225 | .path = filename, |
226 | .mode = PERF_DATA_MODE_READ, | ||
227 | .force = force, | ||
228 | }; | ||
229 | struct perf_session *session = perf_session__new(&file, false, NULL); | ||
87 | if (session == NULL) | 230 | if (session == NULL) |
88 | return -1; | 231 | return -1; |
89 | 232 | ||
@@ -130,11 +273,14 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
130 | char const *add_name_list_str = NULL, | 273 | char const *add_name_list_str = NULL, |
131 | *remove_name_list_str = NULL, | 274 | *remove_name_list_str = NULL, |
132 | *missing_filename = NULL, | 275 | *missing_filename = NULL, |
133 | *update_name_list_str = NULL; | 276 | *update_name_list_str = NULL, |
277 | *kcore_filename; | ||
134 | 278 | ||
135 | const struct option buildid_cache_options[] = { | 279 | const struct option buildid_cache_options[] = { |
136 | OPT_STRING('a', "add", &add_name_list_str, | 280 | OPT_STRING('a', "add", &add_name_list_str, |
137 | "file list", "file(s) to add"), | 281 | "file list", "file(s) to add"), |
282 | OPT_STRING('k', "kcore", &kcore_filename, | ||
283 | "file", "kcore file to add"), | ||
138 | OPT_STRING('r', "remove", &remove_name_list_str, "file list", | 284 | OPT_STRING('r', "remove", &remove_name_list_str, "file list", |
139 | "file(s) to remove"), | 285 | "file(s) to remove"), |
140 | OPT_STRING('M', "missing", &missing_filename, "file", | 286 | OPT_STRING('M', "missing", &missing_filename, "file", |
@@ -217,5 +363,9 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
217 | } | 363 | } |
218 | } | 364 | } |
219 | 365 | ||
366 | if (kcore_filename && | ||
367 | build_id_cache__add_kcore(kcore_filename, debugdir)) | ||
368 | pr_warning("Couldn't add %s\n", kcore_filename); | ||
369 | |||
220 | return ret; | 370 | return ret; |
221 | } | 371 | } |