aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-11-18 17:20:52 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-19 02:28:12 -0500
commitf1617b40596cb341ee6602a9d969c5e4cebe9260 (patch)
tree70a6a16d3fc07ed916c9679afec64d568a6fd71f
parente30a3d12ddf04add3268bfceb0e57ffe47f254c6 (diff)
perf symbols: Record the build_ids of kernel modules too
[root@doppio linux-2.6-tip]# perf record -a sleep 2s;perf buildid-list|tail [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.162 MB perf.data (~7078 samples) ] 881588fa57b3c1696bc91e5e804a11304f093535 [cfg80211] 4d47ce1da9d16bad00c962c072451b7c681e82df [snd_page_alloc] 5146377e89a7caac617f9782f1a02e46263d3a31 [rfkill] 2153b937bff0d345fea83b63a2e1d3138569f83d [i915] 4e6fb1bb97362e3ee4d306988b9ad6912d5fb9ae [drm_kms_helper] f56ef2bf853e3a798f0d8d51f797622e5dc4420e [drm] b0d157a3b5c4e017329ffc07c64623cd6ad65e95 [i2c_algo_bit] 8125374b905ef9fa8b65d98e166b008ad952f198 [i2c_core] fc875c6e5a90e7b915e9d445d0efc859e1b2678c [video] 4b43c5006589f977e9762fdfc7ac1a92b72fca52 [output] [root@doppio linux-2.6-tip]# elfutils libdwfl/linux-kernel-modules.c was used as reference, as suggested by Roland McGrath. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Roland McGrath <roland@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1258582853-8579-3-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--tools/perf/util/header.c5
-rw-r--r--tools/perf/util/symbol.c53
-rw-r--r--tools/perf/util/symbol.h2
3 files changed, 59 insertions, 1 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 31731f1606b2..d3d656f9a621 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -241,6 +241,11 @@ perf_header__adds_write(struct perf_header *self, int fd)
241 241
242 buildid_sec = &feat_sec[idx++]; 242 buildid_sec = &feat_sec[idx++];
243 243
244 /*
245 * Read the list of loaded modules with its build_ids
246 */
247 dsos__load_modules();
248
244 /* Write build-ids */ 249 /* Write build-ids */
245 buildid_sec->offset = lseek(fd, 0, SEEK_CUR); 250 buildid_sec->offset = lseek(fd, 0, SEEK_CUR);
246 if (dsos__write_buildid_table(fd) < 0) 251 if (dsos__write_buildid_table(fd) < 0)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 946ec319568b..7b4cedeb3020 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -9,6 +9,7 @@
9#include <libelf.h> 9#include <libelf.h>
10#include <gelf.h> 10#include <gelf.h>
11#include <elf.h> 11#include <elf.h>
12#include <limits.h>
12#include <sys/utsname.h> 13#include <sys/utsname.h>
13 14
14enum dso_origin { 15enum dso_origin {
@@ -943,6 +944,50 @@ out:
943 return err; 944 return err;
944} 945}
945 946
947int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
948{
949 int fd, err = -1;
950
951 if (size < BUILD_ID_SIZE)
952 goto out;
953
954 fd = open(filename, O_RDONLY);
955 if (fd < 0)
956 goto out;
957
958 while (1) {
959 char bf[BUFSIZ];
960 GElf_Nhdr nhdr;
961 int namesz, descsz;
962
963 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
964 break;
965
966 namesz = (nhdr.n_namesz + 3) & -4U;
967 descsz = (nhdr.n_descsz + 3) & -4U;
968 if (nhdr.n_type == NT_GNU_BUILD_ID &&
969 nhdr.n_namesz == sizeof("GNU")) {
970 if (read(fd, bf, namesz) != namesz)
971 break;
972 if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
973 if (read(fd, build_id,
974 BUILD_ID_SIZE) == BUILD_ID_SIZE) {
975 err = 0;
976 break;
977 }
978 } else if (read(fd, bf, descsz) != descsz)
979 break;
980 } else {
981 int n = namesz + descsz;
982 if (read(fd, bf, n) != n)
983 break;
984 }
985 }
986 close(fd);
987out:
988 return err;
989}
990
946char dso__symtab_origin(const struct dso *self) 991char dso__symtab_origin(const struct dso *self)
947{ 992{
948 static const char origin[] = { 993 static const char origin[] = {
@@ -1218,7 +1263,7 @@ static struct map *map__new2(u64 start, struct dso *dso)
1218 return self; 1263 return self;
1219} 1264}
1220 1265
1221static int dsos__load_modules(void) 1266int dsos__load_modules(void)
1222{ 1267{
1223 char *line = NULL; 1268 char *line = NULL;
1224 size_t n; 1269 size_t n;
@@ -1268,6 +1313,12 @@ static int dsos__load_modules(void)
1268 goto out_delete_line; 1313 goto out_delete_line;
1269 } 1314 }
1270 1315
1316 snprintf(name, sizeof(name),
1317 "/sys/module/%s/notes/.note.gnu.build-id", line);
1318 if (sysfs__read_build_id(name, dso->build_id,
1319 sizeof(dso->build_id)) == 0)
1320 dso->has_build_id = true;
1321
1271 dso->origin = DSO__ORIG_KMODULE; 1322 dso->origin = DSO__ORIG_KMODULE;
1272 kernel_maps__insert(map); 1323 kernel_maps__insert(map);
1273 dsos__add(dso); 1324 dsos__add(dso);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 546eb766d81e..da7ec1af255a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -78,6 +78,7 @@ void dso__delete(struct dso *self);
78struct symbol *dso__find_symbol(struct dso *self, u64 ip); 78struct symbol *dso__find_symbol(struct dso *self, u64 ip);
79 79
80int dsos__load_kernel(const char *vmlinux, symbol_filter_t filter, int modules); 80int dsos__load_kernel(const char *vmlinux, symbol_filter_t filter, int modules);
81int dsos__load_modules(void);
81struct dso *dsos__findnew(const char *name); 82struct dso *dsos__findnew(const char *name);
82int dso__load(struct dso *self, struct map *map, symbol_filter_t filter); 83int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
83void dsos__fprintf(FILE *fp); 84void dsos__fprintf(FILE *fp);
@@ -89,6 +90,7 @@ char dso__symtab_origin(const struct dso *self);
89void dso__set_build_id(struct dso *self, void *build_id); 90void dso__set_build_id(struct dso *self, void *build_id);
90 91
91int filename__read_build_id(const char *filename, void *bf, size_t size); 92int filename__read_build_id(const char *filename, void *bf, size_t size);
93int sysfs__read_build_id(const char *filename, void *bf, size_t size);
92bool dsos__read_build_ids(void); 94bool dsos__read_build_ids(void);
93int build_id__sprintf(u8 *self, int len, char *bf); 95int build_id__sprintf(u8 *self, int len, char *bf);
94 96