aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-buildid-list.c36
-rw-r--r--tools/perf/util/header.c495
2 files changed, 264 insertions, 267 deletions
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index cb690a65bf02..4895668577b5 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -39,24 +39,6 @@ static const struct option options[] = {
39 OPT_END() 39 OPT_END()
40}; 40};
41 41
42static int perf_session__list_build_ids(void)
43{
44 struct perf_session *session;
45
46 session = perf_session__new(input_name, O_RDONLY, force, false,
47 &build_id__mark_dso_hit_ops);
48 if (session == NULL)
49 return -1;
50
51 if (with_hits)
52 perf_session__process_events(session, &build_id__mark_dso_hit_ops);
53
54 perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
55
56 perf_session__delete(session);
57 return 0;
58}
59
60static int sysfs__fprintf_build_id(FILE *fp) 42static int sysfs__fprintf_build_id(FILE *fp)
61{ 43{
62 u8 kallsyms_build_id[BUILD_ID_SIZE]; 44 u8 kallsyms_build_id[BUILD_ID_SIZE];
@@ -85,6 +67,24 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
85 return fprintf(fp, "%s\n", sbuild_id); 67 return fprintf(fp, "%s\n", sbuild_id);
86} 68}
87 69
70static int perf_session__list_build_ids(void)
71{
72 struct perf_session *session;
73
74 session = perf_session__new(input_name, O_RDONLY, force, false,
75 &build_id__mark_dso_hit_ops);
76 if (session == NULL)
77 return -1;
78
79 if (with_hits)
80 perf_session__process_events(session, &build_id__mark_dso_hit_ops);
81
82 perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
83
84 perf_session__delete(session);
85 return 0;
86}
87
88static int __cmd_buildid_list(void) 88static int __cmd_buildid_list(void)
89{ 89{
90 if (show_kernel) 90 if (show_kernel)
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 428a4a2ce350..609d79b5fb5e 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -28,9 +28,6 @@ static struct perf_trace_event_type *events;
28static u32 header_argc; 28static u32 header_argc;
29static const char **header_argv; 29static const char **header_argv;
30 30
31static int dsos__write_buildid_table(struct perf_header *header, int fd);
32static int perf_session__cache_build_ids(struct perf_session *session);
33
34int perf_header__push_event(u64 id, const char *name) 31int perf_header__push_event(u64 id, const char *name)
35{ 32{
36 if (strlen(name) > MAX_EVENT_NAME) 33 if (strlen(name) > MAX_EVENT_NAME)
@@ -187,6 +184,252 @@ perf_header__set_cmdline(int argc, const char **argv)
187 return 0; 184 return 0;
188} 185}
189 186
187#define dsos__for_each_with_build_id(pos, head) \
188 list_for_each_entry(pos, head, node) \
189 if (!pos->has_build_id) \
190 continue; \
191 else
192
193static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
194 u16 misc, int fd)
195{
196 struct dso *pos;
197
198 dsos__for_each_with_build_id(pos, head) {
199 int err;
200 struct build_id_event b;
201 size_t len;
202
203 if (!pos->hit)
204 continue;
205 len = pos->long_name_len + 1;
206 len = ALIGN(len, NAME_ALIGN);
207 memset(&b, 0, sizeof(b));
208 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
209 b.pid = pid;
210 b.header.misc = misc;
211 b.header.size = sizeof(b) + len;
212 err = do_write(fd, &b, sizeof(b));
213 if (err < 0)
214 return err;
215 err = write_padded(fd, pos->long_name,
216 pos->long_name_len + 1, len);
217 if (err < 0)
218 return err;
219 }
220
221 return 0;
222}
223
224static int machine__write_buildid_table(struct machine *machine, int fd)
225{
226 int err;
227 u16 kmisc = PERF_RECORD_MISC_KERNEL,
228 umisc = PERF_RECORD_MISC_USER;
229
230 if (!machine__is_host(machine)) {
231 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
232 umisc = PERF_RECORD_MISC_GUEST_USER;
233 }
234
235 err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid,
236 kmisc, fd);
237 if (err == 0)
238 err = __dsos__write_buildid_table(&machine->user_dsos,
239 machine->pid, umisc, fd);
240 return err;
241}
242
243static int dsos__write_buildid_table(struct perf_header *header, int fd)
244{
245 struct perf_session *session = container_of(header,
246 struct perf_session, header);
247 struct rb_node *nd;
248 int err = machine__write_buildid_table(&session->host_machine, fd);
249
250 if (err)
251 return err;
252
253 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
254 struct machine *pos = rb_entry(nd, struct machine, rb_node);
255 err = machine__write_buildid_table(pos, fd);
256 if (err)
257 break;
258 }
259 return err;
260}
261
262int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
263 const char *name, bool is_kallsyms)
264{
265 const size_t size = PATH_MAX;
266 char *realname, *filename = zalloc(size),
267 *linkname = zalloc(size), *targetname;
268 int len, err = -1;
269
270 if (is_kallsyms) {
271 if (symbol_conf.kptr_restrict) {
272 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
273 return 0;
274 }
275 realname = (char *)name;
276 } else
277 realname = realpath(name, NULL);
278
279 if (realname == NULL || filename == NULL || linkname == NULL)
280 goto out_free;
281
282 len = snprintf(filename, size, "%s%s%s",
283 debugdir, is_kallsyms ? "/" : "", realname);
284 if (mkdir_p(filename, 0755))
285 goto out_free;
286
287 snprintf(filename + len, sizeof(filename) - len, "/%s", sbuild_id);
288
289 if (access(filename, F_OK)) {
290 if (is_kallsyms) {
291 if (copyfile("/proc/kallsyms", filename))
292 goto out_free;
293 } else if (link(realname, filename) && copyfile(name, filename))
294 goto out_free;
295 }
296
297 len = snprintf(linkname, size, "%s/.build-id/%.2s",
298 debugdir, sbuild_id);
299
300 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
301 goto out_free;
302
303 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
304 targetname = filename + strlen(debugdir) - 5;
305 memcpy(targetname, "../..", 5);
306
307 if (symlink(targetname, linkname) == 0)
308 err = 0;
309out_free:
310 if (!is_kallsyms)
311 free(realname);
312 free(filename);
313 free(linkname);
314 return err;
315}
316
317static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
318 const char *name, const char *debugdir,
319 bool is_kallsyms)
320{
321 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
322
323 build_id__sprintf(build_id, build_id_size, sbuild_id);
324
325 return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms);
326}
327
328int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
329{
330 const size_t size = PATH_MAX;
331 char *filename = zalloc(size),
332 *linkname = zalloc(size);
333 int err = -1;
334
335 if (filename == NULL || linkname == NULL)
336 goto out_free;
337
338 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
339 debugdir, sbuild_id, sbuild_id + 2);
340
341 if (access(linkname, F_OK))
342 goto out_free;
343
344 if (readlink(linkname, filename, size - 1) < 0)
345 goto out_free;
346
347 if (unlink(linkname))
348 goto out_free;
349
350 /*
351 * Since the link is relative, we must make it absolute:
352 */
353 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
354 debugdir, sbuild_id, filename);
355
356 if (unlink(linkname))
357 goto out_free;
358
359 err = 0;
360out_free:
361 free(filename);
362 free(linkname);
363 return err;
364}
365
366static int dso__cache_build_id(struct dso *dso, const char *debugdir)
367{
368 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
369
370 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
371 dso->long_name, debugdir, is_kallsyms);
372}
373
374static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
375{
376 struct dso *pos;
377 int err = 0;
378
379 dsos__for_each_with_build_id(pos, head)
380 if (dso__cache_build_id(pos, debugdir))
381 err = -1;
382
383 return err;
384}
385
386static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
387{
388 int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir);
389 ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir);
390 return ret;
391}
392
393static int perf_session__cache_build_ids(struct perf_session *session)
394{
395 struct rb_node *nd;
396 int ret;
397 char debugdir[PATH_MAX];
398
399 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
400
401 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
402 return -1;
403
404 ret = machine__cache_build_ids(&session->host_machine, debugdir);
405
406 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
407 struct machine *pos = rb_entry(nd, struct machine, rb_node);
408 ret |= machine__cache_build_ids(pos, debugdir);
409 }
410 return ret ? -1 : 0;
411}
412
413static bool machine__read_build_ids(struct machine *machine, bool with_hits)
414{
415 bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits);
416 ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits);
417 return ret;
418}
419
420static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
421{
422 struct rb_node *nd;
423 bool ret = machine__read_build_ids(&session->host_machine, with_hits);
424
425 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
426 struct machine *pos = rb_entry(nd, struct machine, rb_node);
427 ret |= machine__read_build_ids(pos, with_hits);
428 }
429
430 return ret;
431}
432
190static int write_trace_info(int fd, struct perf_header *h __used, 433static int write_trace_info(int fd, struct perf_header *h __used,
191 struct perf_evlist *evlist) 434 struct perf_evlist *evlist)
192{ 435{
@@ -1136,252 +1379,6 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
1136 return 0; 1379 return 0;
1137} 1380}
1138 1381
1139#define dsos__for_each_with_build_id(pos, head) \
1140 list_for_each_entry(pos, head, node) \
1141 if (!pos->has_build_id) \
1142 continue; \
1143 else
1144
1145static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
1146 u16 misc, int fd)
1147{
1148 struct dso *pos;
1149
1150 dsos__for_each_with_build_id(pos, head) {
1151 int err;
1152 struct build_id_event b;
1153 size_t len;
1154
1155 if (!pos->hit)
1156 continue;
1157 len = pos->long_name_len + 1;
1158 len = ALIGN(len, NAME_ALIGN);
1159 memset(&b, 0, sizeof(b));
1160 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
1161 b.pid = pid;
1162 b.header.misc = misc;
1163 b.header.size = sizeof(b) + len;
1164 err = do_write(fd, &b, sizeof(b));
1165 if (err < 0)
1166 return err;
1167 err = write_padded(fd, pos->long_name,
1168 pos->long_name_len + 1, len);
1169 if (err < 0)
1170 return err;
1171 }
1172
1173 return 0;
1174}
1175
1176static int machine__write_buildid_table(struct machine *machine, int fd)
1177{
1178 int err;
1179 u16 kmisc = PERF_RECORD_MISC_KERNEL,
1180 umisc = PERF_RECORD_MISC_USER;
1181
1182 if (!machine__is_host(machine)) {
1183 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
1184 umisc = PERF_RECORD_MISC_GUEST_USER;
1185 }
1186
1187 err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid,
1188 kmisc, fd);
1189 if (err == 0)
1190 err = __dsos__write_buildid_table(&machine->user_dsos,
1191 machine->pid, umisc, fd);
1192 return err;
1193}
1194
1195static int dsos__write_buildid_table(struct perf_header *header, int fd)
1196{
1197 struct perf_session *session = container_of(header,
1198 struct perf_session, header);
1199 struct rb_node *nd;
1200 int err = machine__write_buildid_table(&session->host_machine, fd);
1201
1202 if (err)
1203 return err;
1204
1205 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
1206 struct machine *pos = rb_entry(nd, struct machine, rb_node);
1207 err = machine__write_buildid_table(pos, fd);
1208 if (err)
1209 break;
1210 }
1211 return err;
1212}
1213
1214int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
1215 const char *name, bool is_kallsyms)
1216{
1217 const size_t size = PATH_MAX;
1218 char *realname, *filename = zalloc(size),
1219 *linkname = zalloc(size), *targetname;
1220 int len, err = -1;
1221
1222 if (is_kallsyms) {
1223 if (symbol_conf.kptr_restrict) {
1224 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
1225 return 0;
1226 }
1227 realname = (char *)name;
1228 } else
1229 realname = realpath(name, NULL);
1230
1231 if (realname == NULL || filename == NULL || linkname == NULL)
1232 goto out_free;
1233
1234 len = snprintf(filename, size, "%s%s%s",
1235 debugdir, is_kallsyms ? "/" : "", realname);
1236 if (mkdir_p(filename, 0755))
1237 goto out_free;
1238
1239 snprintf(filename + len, sizeof(filename) - len, "/%s", sbuild_id);
1240
1241 if (access(filename, F_OK)) {
1242 if (is_kallsyms) {
1243 if (copyfile("/proc/kallsyms", filename))
1244 goto out_free;
1245 } else if (link(realname, filename) && copyfile(name, filename))
1246 goto out_free;
1247 }
1248
1249 len = snprintf(linkname, size, "%s/.build-id/%.2s",
1250 debugdir, sbuild_id);
1251
1252 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
1253 goto out_free;
1254
1255 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
1256 targetname = filename + strlen(debugdir) - 5;
1257 memcpy(targetname, "../..", 5);
1258
1259 if (symlink(targetname, linkname) == 0)
1260 err = 0;
1261out_free:
1262 if (!is_kallsyms)
1263 free(realname);
1264 free(filename);
1265 free(linkname);
1266 return err;
1267}
1268
1269static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
1270 const char *name, const char *debugdir,
1271 bool is_kallsyms)
1272{
1273 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1274
1275 build_id__sprintf(build_id, build_id_size, sbuild_id);
1276
1277 return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms);
1278}
1279
1280int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
1281{
1282 const size_t size = PATH_MAX;
1283 char *filename = zalloc(size),
1284 *linkname = zalloc(size);
1285 int err = -1;
1286
1287 if (filename == NULL || linkname == NULL)
1288 goto out_free;
1289
1290 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
1291 debugdir, sbuild_id, sbuild_id + 2);
1292
1293 if (access(linkname, F_OK))
1294 goto out_free;
1295
1296 if (readlink(linkname, filename, size - 1) < 0)
1297 goto out_free;
1298
1299 if (unlink(linkname))
1300 goto out_free;
1301
1302 /*
1303 * Since the link is relative, we must make it absolute:
1304 */
1305 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
1306 debugdir, sbuild_id, filename);
1307
1308 if (unlink(linkname))
1309 goto out_free;
1310
1311 err = 0;
1312out_free:
1313 free(filename);
1314 free(linkname);
1315 return err;
1316}
1317
1318static int dso__cache_build_id(struct dso *dso, const char *debugdir)
1319{
1320 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
1321
1322 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
1323 dso->long_name, debugdir, is_kallsyms);
1324}
1325
1326static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
1327{
1328 struct dso *pos;
1329 int err = 0;
1330
1331 dsos__for_each_with_build_id(pos, head)
1332 if (dso__cache_build_id(pos, debugdir))
1333 err = -1;
1334
1335 return err;
1336}
1337
1338static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
1339{
1340 int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir);
1341 ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir);
1342 return ret;
1343}
1344
1345static int perf_session__cache_build_ids(struct perf_session *session)
1346{
1347 struct rb_node *nd;
1348 int ret;
1349 char debugdir[PATH_MAX];
1350
1351 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
1352
1353 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
1354 return -1;
1355
1356 ret = machine__cache_build_ids(&session->host_machine, debugdir);
1357
1358 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
1359 struct machine *pos = rb_entry(nd, struct machine, rb_node);
1360 ret |= machine__cache_build_ids(pos, debugdir);
1361 }
1362 return ret ? -1 : 0;
1363}
1364
1365static bool machine__read_build_ids(struct machine *machine, bool with_hits)
1366{
1367 bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits);
1368 ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits);
1369 return ret;
1370}
1371
1372static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
1373{
1374 struct rb_node *nd;
1375 bool ret = machine__read_build_ids(&session->host_machine, with_hits);
1376
1377 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
1378 struct machine *pos = rb_entry(nd, struct machine, rb_node);
1379 ret |= machine__read_build_ids(pos, with_hits);
1380 }
1381
1382 return ret;
1383}
1384
1385static int do_write_feat(int fd, struct perf_header *h, int type, 1382static int do_write_feat(int fd, struct perf_header *h, int type,
1386 struct perf_file_section **p, 1383 struct perf_file_section **p,
1387 struct perf_evlist *evlist) 1384 struct perf_evlist *evlist)