aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-record.c49
-rw-r--r--tools/perf/util/data_map.c37
-rw-r--r--tools/perf/util/event.h7
-rw-r--r--tools/perf/util/header.c10
-rw-r--r--tools/perf/util/header.h4
-rw-r--r--tools/perf/util/map.c14
-rw-r--r--tools/perf/util/symbol.c78
-rw-r--r--tools/perf/util/symbol.h10
8 files changed, 179 insertions, 30 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4a73d89ce5d1..ab333812ace6 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -17,6 +17,7 @@
17#include "util/header.h" 17#include "util/header.h"
18#include "util/event.h" 18#include "util/event.h"
19#include "util/debug.h" 19#include "util/debug.h"
20#include "util/symbol.h"
20 21
21#include <unistd.h> 22#include <unistd.h>
22#include <sched.h> 23#include <sched.h>
@@ -109,9 +110,21 @@ static void write_output(void *buf, size_t size)
109 } 110 }
110} 111}
111 112
113static void write_event(event_t *buf, size_t size)
114{
115 /*
116 * Add it to the list of DSOs, so that when we finish this
117 * record session we can pick the available build-ids.
118 */
119 if (buf->header.type == PERF_RECORD_MMAP)
120 dsos__findnew(buf->mmap.filename);
121
122 write_output(buf, size);
123}
124
112static int process_synthesized_event(event_t *event) 125static int process_synthesized_event(event_t *event)
113{ 126{
114 write_output(event, event->header.size); 127 write_event(event, event->header.size);
115 return 0; 128 return 0;
116} 129}
117 130
@@ -163,14 +176,14 @@ static void mmap_read(struct mmap_data *md)
163 size = md->mask + 1 - (old & md->mask); 176 size = md->mask + 1 - (old & md->mask);
164 old += size; 177 old += size;
165 178
166 write_output(buf, size); 179 write_event(buf, size);
167 } 180 }
168 181
169 buf = &data[old & md->mask]; 182 buf = &data[old & md->mask];
170 size = head - old; 183 size = head - old;
171 old += size; 184 old += size;
172 185
173 write_output(buf, size); 186 write_event(buf, size);
174 187
175 md->prev = old; 188 md->prev = old;
176 mmap_write_tail(md, old); 189 mmap_write_tail(md, old);
@@ -365,10 +378,38 @@ static void open_counters(int cpu, pid_t pid)
365 nr_cpu++; 378 nr_cpu++;
366} 379}
367 380
381static bool write_buildid_table(void)
382{
383 struct dso *pos;
384 bool have_buildid = false;
385
386 list_for_each_entry(pos, &dsos, node) {
387 struct build_id_event b;
388 size_t len;
389
390 if (filename__read_build_id(pos->long_name,
391 &b.build_id,
392 sizeof(b.build_id)) < 0)
393 continue;
394 have_buildid = true;
395 memset(&b.header, 0, sizeof(b.header));
396 len = strlen(pos->long_name) + 1;
397 len = ALIGN(len, 64);
398 b.header.size = sizeof(b) + len;
399 write_output(&b, sizeof(b));
400 write_output(pos->long_name, len);
401 }
402
403 return have_buildid;
404}
405
368static void atexit_header(void) 406static void atexit_header(void)
369{ 407{
370 header->data_size += bytes_written; 408 header->data_size += bytes_written;
371 409
410 if (write_buildid_table())
411 perf_header__set_feat(header, HEADER_BUILD_ID);
412
372 perf_header__write(header, output); 413 perf_header__write(header, output);
373} 414}
374 415
@@ -572,6 +613,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
572{ 613{
573 int counter; 614 int counter;
574 615
616 symbol__init(0);
617
575 argc = parse_options(argc, argv, options, record_usage, 618 argc = parse_options(argc, argv, options, record_usage,
576 PARSE_OPT_STOP_AT_NON_OPTION); 619 PARSE_OPT_STOP_AT_NON_OPTION);
577 if (!argc && target_pid == -1 && !system_wide) 620 if (!argc && target_pid == -1 && !system_wide)
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
index c458db9ede6d..00a9c114c8d0 100644
--- a/tools/perf/util/data_map.c
+++ b/tools/perf/util/data_map.c
@@ -70,6 +70,39 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
70 } 70 }
71} 71}
72 72
73static int perf_header__read_build_ids(const struct perf_header *self,
74 int input, off_t file_size)
75{
76 off_t offset = self->data_offset + self->data_size;
77 struct build_id_event bev;
78 char filename[PATH_MAX];
79 int err = -1;
80
81 if (lseek(input, offset, SEEK_SET) < 0)
82 return -1;
83
84 while (offset < file_size) {
85 struct dso *dso;
86 ssize_t len;
87
88 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
89 goto out;
90
91 len = bev.header.size - sizeof(bev);
92 if (read(input, filename, len) != len)
93 goto out;
94
95 dso = dsos__findnew(filename);
96 if (dso != NULL)
97 dso__set_build_id(dso, &bev.build_id);
98
99 offset += bev.header.size;
100 }
101 err = 0;
102out:
103 return err;
104}
105
73int mmap_dispatch_perf_file(struct perf_header **pheader, 106int mmap_dispatch_perf_file(struct perf_header **pheader,
74 const char *input_name, 107 const char *input_name,
75 int force, 108 int force,
@@ -130,6 +163,10 @@ int mmap_dispatch_perf_file(struct perf_header **pheader,
130 if (curr_handler->sample_type_check(sample_type) < 0) 163 if (curr_handler->sample_type_check(sample_type) < 0)
131 exit(-1); 164 exit(-1);
132 165
166 if (perf_header__has_feat(header, HEADER_BUILD_ID) &&
167 perf_header__read_build_ids(header, input, input_stat.st_size))
168 pr_debug("failed to read buildids, continuing...\n");
169
133 if (load_kernel(NULL) < 0) { 170 if (load_kernel(NULL) < 0) {
134 perror("failed to load kernel symbols"); 171 perror("failed to load kernel symbols");
135 return EXIT_FAILURE; 172 return EXIT_FAILURE;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 0a443bea68db..34c6fcb82d92 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -61,6 +61,13 @@ struct sample_event{
61 u64 array[]; 61 u64 array[];
62}; 62};
63 63
64#define BUILD_ID_SIZE 20
65
66struct build_id_event {
67 struct perf_event_header header;
68 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))];
69 char filename[];
70};
64 71
65typedef union event_union { 72typedef union event_union {
66 struct perf_event_header header; 73 struct perf_event_header header;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 7d26659b806c..050f543fd965 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -149,6 +149,16 @@ void perf_header__feat_trace_info(struct perf_header *header)
149 set_bit(HEADER_TRACE_INFO, header->adds_features); 149 set_bit(HEADER_TRACE_INFO, header->adds_features);
150} 150}
151 151
152void perf_header__set_feat(struct perf_header *self, int feat)
153{
154 set_bit(feat, self->adds_features);
155}
156
157bool perf_header__has_feat(const struct perf_header *self, int feat)
158{
159 return test_bit(feat, self->adds_features);
160}
161
152static void do_write(int fd, void *buf, size_t size) 162static void do_write(int fd, void *buf, size_t size)
153{ 163{
154 while (size) { 164 while (size) {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 2ea9dfb1236a..2f233c5db7e9 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -3,6 +3,7 @@
3 3
4#include "../../../include/linux/perf_event.h" 4#include "../../../include/linux/perf_event.h"
5#include <sys/types.h> 5#include <sys/types.h>
6#include <stdbool.h>
6#include "types.h" 7#include "types.h"
7 8
8#include <linux/bitmap.h> 9#include <linux/bitmap.h>
@@ -15,6 +16,7 @@ struct perf_header_attr {
15}; 16};
16 17
17#define HEADER_TRACE_INFO 1 18#define HEADER_TRACE_INFO 1
19#define HEADER_BUILD_ID 2
18 20
19#define HEADER_FEAT_BITS 256 21#define HEADER_FEAT_BITS 256
20 22
@@ -48,6 +50,8 @@ u64 perf_header__sample_type(struct perf_header *header);
48struct perf_event_attr * 50struct perf_event_attr *
49perf_header__find_attr(u64 id, struct perf_header *header); 51perf_header__find_attr(u64 id, struct perf_header *header);
50void perf_header__feat_trace_info(struct perf_header *header); 52void perf_header__feat_trace_info(struct perf_header *header);
53void perf_header__set_feat(struct perf_header *self, int feat);
54bool perf_header__has_feat(const struct perf_header *self, int feat);
51 55
52struct perf_header *perf_header__new(void); 56struct perf_header *perf_header__new(void);
53 57
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 33f868420d73..94ca95073c40 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -84,8 +84,18 @@ map__find_symbol(struct map *self, u64 ip, symbol_filter_t filter)
84 int nr = dso__load(self->dso, self, filter); 84 int nr = dso__load(self->dso, self, filter);
85 85
86 if (nr < 0) { 86 if (nr < 0) {
87 pr_warning("Failed to open %s, continuing without symbols\n", 87 if (self->dso->has_build_id) {
88 self->dso->long_name); 88 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
89
90 build_id__sprintf(self->dso->build_id,
91 sizeof(self->dso->build_id),
92 sbuild_id);
93 pr_warning("%s with build id %s not found",
94 self->dso->long_name, sbuild_id);
95 } else
96 pr_warning("Failed to open %s",
97 self->dso->long_name);
98 pr_warning(", continuing without symbols\n");
89 return NULL; 99 return NULL;
90 } else if (nr == 0) { 100 } else if (nr == 0) {
91 const char *name = self->dso->long_name; 101 const char *name = self->dso->long_name;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e7c7cdb851c2..a2e95ce1f223 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -121,7 +121,8 @@ struct dso *dso__new(const char *name)
121 self->find_symbol = dso__find_symbol; 121 self->find_symbol = dso__find_symbol;
122 self->slen_calculated = 0; 122 self->slen_calculated = 0;
123 self->origin = DSO__ORIG_NOT_FOUND; 123 self->origin = DSO__ORIG_NOT_FOUND;
124 self->loaded = false; 124 self->loaded = 0;
125 self->has_build_id = 0;
125 } 126 }
126 127
127 return self; 128 return self;
@@ -148,6 +149,12 @@ void dso__delete(struct dso *self)
148 free(self); 149 free(self);
149} 150}
150 151
152void dso__set_build_id(struct dso *self, void *build_id)
153{
154 memcpy(self->build_id, build_id, sizeof(self->build_id));
155 self->has_build_id = 1;
156}
157
151static void dso__insert_symbol(struct dso *self, struct symbol *sym) 158static void dso__insert_symbol(struct dso *self, struct symbol *sym)
152{ 159{
153 struct rb_node **p = &self->syms.rb_node; 160 struct rb_node **p = &self->syms.rb_node;
@@ -190,11 +197,30 @@ struct symbol *dso__find_symbol(struct dso *self, u64 ip)
190 return NULL; 197 return NULL;
191} 198}
192 199
193size_t dso__fprintf(struct dso *self, FILE *fp) 200int build_id__sprintf(u8 *self, int len, char *bf)
194{ 201{
195 size_t ret = fprintf(fp, "dso: %s\n", self->short_name); 202 char *bid = bf;
203 u8 *raw = self;
204 int i;
196 205
206 for (i = 0; i < len; ++i) {
207 sprintf(bid, "%02x", *raw);
208 ++raw;
209 bid += 2;
210 }
211
212 return raw - self;
213}
214
215size_t dso__fprintf(struct dso *self, FILE *fp)
216{
217 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
197 struct rb_node *nd; 218 struct rb_node *nd;
219 size_t ret;
220
221 build_id__sprintf(self->build_id, sizeof(self->build_id), sbuild_id);
222 ret = fprintf(fp, "dso: %s (%s)\n", self->short_name, sbuild_id);
223
198 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) { 224 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) {
199 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 225 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
200 ret += symbol__fprintf(pos, fp); 226 ret += symbol__fprintf(pos, fp);
@@ -825,8 +851,6 @@ out_close:
825 return err; 851 return err;
826} 852}
827 853
828#define BUILD_ID_SIZE 20
829
830int filename__read_build_id(const char *filename, void *bf, size_t size) 854int filename__read_build_id(const char *filename, void *bf, size_t size)
831{ 855{
832 int fd, err = -1; 856 int fd, err = -1;
@@ -845,7 +869,7 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
845 869
846 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 870 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
847 if (elf == NULL) { 871 if (elf == NULL) {
848 pr_err("%s: cannot read %s ELF file.\n", __func__, filename); 872 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
849 goto out_close; 873 goto out_close;
850 } 874 }
851 875
@@ -874,9 +898,9 @@ out:
874 898
875static char *dso__read_build_id(struct dso *self) 899static char *dso__read_build_id(struct dso *self)
876{ 900{
877 int i, len; 901 int len;
878 char *build_id = NULL, *bid; 902 char *build_id = NULL;
879 unsigned char rawbf[BUILD_ID_SIZE], *raw; 903 unsigned char rawbf[BUILD_ID_SIZE];
880 904
881 len = filename__read_build_id(self->long_name, rawbf, sizeof(rawbf)); 905 len = filename__read_build_id(self->long_name, rawbf, sizeof(rawbf));
882 if (len < 0) 906 if (len < 0)
@@ -885,15 +909,8 @@ static char *dso__read_build_id(struct dso *self)
885 build_id = malloc(len * 2 + 1); 909 build_id = malloc(len * 2 + 1);
886 if (build_id == NULL) 910 if (build_id == NULL)
887 goto out; 911 goto out;
888 bid = build_id;
889 912
890 raw = rawbf; 913 build_id__sprintf(rawbf, len, build_id);
891 for (i = 0; i < len; ++i) {
892 sprintf(bid, "%02x", *raw);
893 ++raw;
894 bid += 2;
895 }
896 pr_debug2("%s(%s): %s\n", __func__, self->long_name, build_id);
897out: 914out:
898 return build_id; 915 return build_id;
899} 916}
@@ -922,7 +939,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
922 int ret = -1; 939 int ret = -1;
923 int fd; 940 int fd;
924 941
925 self->loaded = true; 942 self->loaded = 1;
926 943
927 if (!name) 944 if (!name)
928 return -1; 945 return -1;
@@ -940,6 +957,8 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
940 957
941more: 958more:
942 do { 959 do {
960 int berr = 0;
961
943 self->origin++; 962 self->origin++;
944 switch (self->origin) { 963 switch (self->origin) {
945 case DSO__ORIG_FEDORA: 964 case DSO__ORIG_FEDORA:
@@ -956,8 +975,7 @@ more:
956 snprintf(name, size, 975 snprintf(name, size,
957 "/usr/lib/debug/.build-id/%.2s/%s.debug", 976 "/usr/lib/debug/.build-id/%.2s/%s.debug",
958 build_id, build_id + 2); 977 build_id, build_id + 2);
959 free(build_id); 978 goto compare_build_id;
960 break;
961 } 979 }
962 self->origin++; 980 self->origin++;
963 /* Fall thru */ 981 /* Fall thru */
@@ -969,6 +987,22 @@ more:
969 goto out; 987 goto out;
970 } 988 }
971 989
990 if (self->has_build_id) {
991 bool match;
992 build_id = malloc(BUILD_ID_SIZE);
993 if (build_id == NULL)
994 goto more;
995 berr = filename__read_build_id(name, build_id,
996 BUILD_ID_SIZE);
997compare_build_id:
998 match = berr > 0 && memcmp(build_id, self->build_id,
999 sizeof(self->build_id)) == 0;
1000 free(build_id);
1001 build_id = NULL;
1002 if (!match)
1003 goto more;
1004 }
1005
972 fd = open(name, O_RDONLY); 1006 fd = open(name, O_RDONLY);
973 } while (fd < 0); 1007 } while (fd < 0);
974 1008
@@ -1034,7 +1068,7 @@ static int dso__load_module_sym(struct dso *self, struct map *map,
1034{ 1068{
1035 int err = 0, fd = open(self->long_name, O_RDONLY); 1069 int err = 0, fd = open(self->long_name, O_RDONLY);
1036 1070
1037 self->loaded = true; 1071 self->loaded = 1;
1038 1072
1039 if (fd < 0) { 1073 if (fd < 0) {
1040 pr_err("%s: cannot open %s\n", __func__, self->long_name); 1074 pr_err("%s: cannot open %s\n", __func__, self->long_name);
@@ -1225,7 +1259,7 @@ static int dso__load_vmlinux(struct dso *self, struct map *map,
1225{ 1259{
1226 int err, fd = open(vmlinux, O_RDONLY); 1260 int err, fd = open(vmlinux, O_RDONLY);
1227 1261
1228 self->loaded = true; 1262 self->loaded = 1;
1229 1263
1230 if (fd < 0) 1264 if (fd < 0)
1231 return -1; 1265 return -1;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index e0d4a583f8dd..f8c1899af483 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -60,10 +60,12 @@ struct dso {
60 struct list_head node; 60 struct list_head node;
61 struct rb_root syms; 61 struct rb_root syms;
62 struct symbol *(*find_symbol)(struct dso *, u64 ip); 62 struct symbol *(*find_symbol)(struct dso *, u64 ip);
63 unsigned char adjust_symbols; 63 u8 adjust_symbols:1;
64 unsigned char slen_calculated; 64 u8 slen_calculated:1;
65 bool loaded; 65 u8 loaded:1;
66 u8 has_build_id:1;
66 unsigned char origin; 67 unsigned char origin;
68 u8 build_id[BUILD_ID_SIZE];
67 const char *short_name; 69 const char *short_name;
68 char *long_name; 70 char *long_name;
69 char name[0]; 71 char name[0];
@@ -81,8 +83,10 @@ void dsos__fprintf(FILE *fp);
81 83
82size_t dso__fprintf(struct dso *self, FILE *fp); 84size_t dso__fprintf(struct dso *self, FILE *fp);
83char dso__symtab_origin(const struct dso *self); 85char dso__symtab_origin(const struct dso *self);
86void dso__set_build_id(struct dso *self, void *build_id);
84 87
85int filename__read_build_id(const char *filename, void *bf, size_t size); 88int filename__read_build_id(const char *filename, void *bf, size_t size);
89int build_id__sprintf(u8 *self, int len, char *bf);
86 90
87int load_kernel(symbol_filter_t filter); 91int load_kernel(symbol_filter_t filter);
88 92