aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/tests/code-reading.c
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2013-08-07 07:38:53 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-08-07 16:35:34 -0400
commit7a77bc2c0d2726a7fc9e6b91b36f984c3e377008 (patch)
tree7cd77b4e8acec51e14985881430aceeea03cd6b2 /tools/perf/tests/code-reading.c
parent82e75d00adc5bde3cf98f11e937eed6127163969 (diff)
perf tests: Add kcore to the object code reading test
Make the "object code reading" test attempt to read from kcore. The test uses objdump which struggles with kcore. i.e. doesn't always work, sometimes takes a long time. The test has been made to work around those issues. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/r/1375875537-4509-10-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/tests/code-reading.c')
-rw-r--r--tools/perf/tests/code-reading.c100
1 files changed, 82 insertions, 18 deletions
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 0c7b052cead2..8e0943b966d7 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -20,6 +20,11 @@
20#define BUFSZ 1024 20#define BUFSZ 1024
21#define READLEN 128 21#define READLEN 128
22 22
23struct state {
24 u64 done[1024];
25 size_t done_cnt;
26};
27
23static unsigned int hex(char c) 28static unsigned int hex(char c)
24{ 29{
25 if (c >= '0' && c <= '9') 30 if (c >= '0' && c <= '9')
@@ -107,6 +112,9 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
107 112
108 pr_debug("Objdump command is: %s\n", cmd); 113 pr_debug("Objdump command is: %s\n", cmd);
109 114
115 /* Ignore objdump errors */
116 strcat(cmd, " 2>/dev/null");
117
110 f = popen(cmd, "r"); 118 f = popen(cmd, "r");
111 if (!f) { 119 if (!f) {
112 pr_debug("popen failed\n"); 120 pr_debug("popen failed\n");
@@ -126,7 +134,8 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
126} 134}
127 135
128static int read_object_code(u64 addr, size_t len, u8 cpumode, 136static int read_object_code(u64 addr, size_t len, u8 cpumode,
129 struct thread *thread, struct machine *machine) 137 struct thread *thread, struct machine *machine,
138 struct state *state)
130{ 139{
131 struct addr_location al; 140 struct addr_location al;
132 unsigned char buf1[BUFSZ]; 141 unsigned char buf1[BUFSZ];
@@ -146,7 +155,8 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
146 155
147 pr_debug("File is: %s\n", al.map->dso->long_name); 156 pr_debug("File is: %s\n", al.map->dso->long_name);
148 157
149 if (al.map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) { 158 if (al.map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
159 !dso__is_kcore(al.map->dso)) {
150 pr_debug("Unexpected kernel address - skipping\n"); 160 pr_debug("Unexpected kernel address - skipping\n");
151 return 0; 161 return 0;
152 } 162 }
@@ -175,6 +185,24 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
175 if (map__load(al.map, NULL)) 185 if (map__load(al.map, NULL))
176 return -1; 186 return -1;
177 187
188 /* objdump struggles with kcore - try each map only once */
189 if (dso__is_kcore(al.map->dso)) {
190 size_t d;
191
192 for (d = 0; d < state->done_cnt; d++) {
193 if (state->done[d] == al.map->start) {
194 pr_debug("kcore map tested already");
195 pr_debug(" - skipping\n");
196 return 0;
197 }
198 }
199 if (state->done_cnt >= ARRAY_SIZE(state->done)) {
200 pr_debug("Too many kcore maps - skipping\n");
201 return 0;
202 }
203 state->done[state->done_cnt++] = al.map->start;
204 }
205
178 /* Read the object code using objdump */ 206 /* Read the object code using objdump */
179 objdump_addr = map__rip_2objdump(al.map, al.addr); 207 objdump_addr = map__rip_2objdump(al.map, al.addr);
180 ret = read_via_objdump(al.map->dso->long_name, objdump_addr, buf2, len); 208 ret = read_via_objdump(al.map->dso->long_name, objdump_addr, buf2, len);
@@ -186,10 +214,19 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
186 if (cpumode == PERF_RECORD_MISC_KERNEL || 214 if (cpumode == PERF_RECORD_MISC_KERNEL ||
187 cpumode == PERF_RECORD_MISC_GUEST_KERNEL) { 215 cpumode == PERF_RECORD_MISC_GUEST_KERNEL) {
188 len -= ret; 216 len -= ret;
189 if (len) 217 if (len) {
190 pr_debug("Reducing len to %zu\n", len); 218 pr_debug("Reducing len to %zu\n", len);
191 else 219 } else if (dso__is_kcore(al.map->dso)) {
220 /*
221 * objdump cannot handle very large segments
222 * that may be found in kcore.
223 */
224 pr_debug("objdump failed for kcore");
225 pr_debug(" - skipping\n");
226 return 0;
227 } else {
192 return -1; 228 return -1;
229 }
193 } 230 }
194 } 231 }
195 if (ret < 0) { 232 if (ret < 0) {
@@ -209,7 +246,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
209 246
210static int process_sample_event(struct machine *machine, 247static int process_sample_event(struct machine *machine,
211 struct perf_evlist *evlist, 248 struct perf_evlist *evlist,
212 union perf_event *event) 249 union perf_event *event, struct state *state)
213{ 250{
214 struct perf_sample sample; 251 struct perf_sample sample;
215 struct thread *thread; 252 struct thread *thread;
@@ -228,14 +265,15 @@ static int process_sample_event(struct machine *machine,
228 265
229 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 266 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
230 267
231 return read_object_code(sample.ip, READLEN, cpumode, thread, machine); 268 return read_object_code(sample.ip, READLEN, cpumode, thread, machine,
269 state);
232} 270}
233 271
234static int process_event(struct machine *machine, struct perf_evlist *evlist, 272static int process_event(struct machine *machine, struct perf_evlist *evlist,
235 union perf_event *event) 273 union perf_event *event, struct state *state)
236{ 274{
237 if (event->header.type == PERF_RECORD_SAMPLE) 275 if (event->header.type == PERF_RECORD_SAMPLE)
238 return process_sample_event(machine, evlist, event); 276 return process_sample_event(machine, evlist, event, state);
239 277
240 if (event->header.type < PERF_RECORD_MAX) 278 if (event->header.type < PERF_RECORD_MAX)
241 return machine__process_event(machine, event); 279 return machine__process_event(machine, event);
@@ -243,14 +281,15 @@ static int process_event(struct machine *machine, struct perf_evlist *evlist,
243 return 0; 281 return 0;
244} 282}
245 283
246static int process_events(struct machine *machine, struct perf_evlist *evlist) 284static int process_events(struct machine *machine, struct perf_evlist *evlist,
285 struct state *state)
247{ 286{
248 union perf_event *event; 287 union perf_event *event;
249 int i, ret; 288 int i, ret;
250 289
251 for (i = 0; i < evlist->nr_mmaps; i++) { 290 for (i = 0; i < evlist->nr_mmaps; i++) {
252 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 291 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
253 ret = process_event(machine, evlist, event); 292 ret = process_event(machine, evlist, event, state);
254 if (ret < 0) 293 if (ret < 0)
255 return ret; 294 return ret;
256 } 295 }
@@ -331,10 +370,12 @@ static void do_something(void)
331enum { 370enum {
332 TEST_CODE_READING_OK, 371 TEST_CODE_READING_OK,
333 TEST_CODE_READING_NO_VMLINUX, 372 TEST_CODE_READING_NO_VMLINUX,
373 TEST_CODE_READING_NO_KCORE,
334 TEST_CODE_READING_NO_ACCESS, 374 TEST_CODE_READING_NO_ACCESS,
375 TEST_CODE_READING_NO_KERNEL_OBJ,
335}; 376};
336 377
337static int do_test_code_reading(void) 378static int do_test_code_reading(bool try_kcore)
338{ 379{
339 struct machines machines; 380 struct machines machines;
340 struct machine *machine; 381 struct machine *machine;
@@ -348,6 +389,9 @@ static int do_test_code_reading(void)
348 .uses_mmap = true, 389 .uses_mmap = true,
349 }, 390 },
350 }; 391 };
392 struct state state = {
393 .done_cnt = 0,
394 };
351 struct thread_map *threads = NULL; 395 struct thread_map *threads = NULL;
352 struct cpu_map *cpus = NULL; 396 struct cpu_map *cpus = NULL;
353 struct perf_evlist *evlist = NULL; 397 struct perf_evlist *evlist = NULL;
@@ -355,7 +399,7 @@ static int do_test_code_reading(void)
355 int err = -1, ret; 399 int err = -1, ret;
356 pid_t pid; 400 pid_t pid;
357 struct map *map; 401 struct map *map;
358 bool have_vmlinux, excl_kernel = false; 402 bool have_vmlinux, have_kcore, excl_kernel = false;
359 403
360 pid = getpid(); 404 pid = getpid();
361 405
@@ -368,6 +412,10 @@ static int do_test_code_reading(void)
368 goto out_err; 412 goto out_err;
369 } 413 }
370 414
415 /* Force the use of kallsyms instead of vmlinux to try kcore */
416 if (try_kcore)
417 symbol_conf.kallsyms_name = "/proc/kallsyms";
418
371 /* Load kernel map */ 419 /* Load kernel map */
372 map = machine->vmlinux_maps[MAP__FUNCTION]; 420 map = machine->vmlinux_maps[MAP__FUNCTION];
373 ret = map__load(map, NULL); 421 ret = map__load(map, NULL);
@@ -375,9 +423,15 @@ static int do_test_code_reading(void)
375 pr_debug("map__load failed\n"); 423 pr_debug("map__load failed\n");
376 goto out_err; 424 goto out_err;
377 } 425 }
378 have_vmlinux = map->dso->symtab_type == DSO_BINARY_TYPE__VMLINUX; 426 have_vmlinux = dso__is_vmlinux(map->dso);
379 /* No point getting kernel events if there is no vmlinux */ 427 have_kcore = dso__is_kcore(map->dso);
380 if (!have_vmlinux) 428
429 /* 2nd time through we just try kcore */
430 if (try_kcore && !have_kcore)
431 return TEST_CODE_READING_NO_KCORE;
432
433 /* No point getting kernel events if there is no kernel object */
434 if (!have_vmlinux && !have_kcore)
381 excl_kernel = true; 435 excl_kernel = true;
382 436
383 threads = thread_map__new_by_tid(pid); 437 threads = thread_map__new_by_tid(pid);
@@ -461,11 +515,13 @@ static int do_test_code_reading(void)
461 515
462 perf_evlist__disable(evlist); 516 perf_evlist__disable(evlist);
463 517
464 ret = process_events(machine, evlist); 518 ret = process_events(machine, evlist, &state);
465 if (ret < 0) 519 if (ret < 0)
466 goto out_err; 520 goto out_err;
467 521
468 if (!have_vmlinux) 522 if (!have_vmlinux && !have_kcore && !try_kcore)
523 err = TEST_CODE_READING_NO_KERNEL_OBJ;
524 else if (!have_vmlinux && !try_kcore)
469 err = TEST_CODE_READING_NO_VMLINUX; 525 err = TEST_CODE_READING_NO_VMLINUX;
470 else if (excl_kernel) 526 else if (excl_kernel)
471 err = TEST_CODE_READING_NO_ACCESS; 527 err = TEST_CODE_READING_NO_ACCESS;
@@ -492,7 +548,9 @@ int test__code_reading(void)
492{ 548{
493 int ret; 549 int ret;
494 550
495 ret = do_test_code_reading(); 551 ret = do_test_code_reading(false);
552 if (!ret)
553 ret = do_test_code_reading(true);
496 554
497 switch (ret) { 555 switch (ret) {
498 case TEST_CODE_READING_OK: 556 case TEST_CODE_READING_OK:
@@ -500,9 +558,15 @@ int test__code_reading(void)
500 case TEST_CODE_READING_NO_VMLINUX: 558 case TEST_CODE_READING_NO_VMLINUX:
501 fprintf(stderr, " (no vmlinux)"); 559 fprintf(stderr, " (no vmlinux)");
502 return 0; 560 return 0;
561 case TEST_CODE_READING_NO_KCORE:
562 fprintf(stderr, " (no kcore)");
563 return 0;
503 case TEST_CODE_READING_NO_ACCESS: 564 case TEST_CODE_READING_NO_ACCESS:
504 fprintf(stderr, " (no access)"); 565 fprintf(stderr, " (no access)");
505 return 0; 566 return 0;
567 case TEST_CODE_READING_NO_KERNEL_OBJ:
568 fprintf(stderr, " (no kernel obj)");
569 return 0;
506 default: 570 default:
507 return -1; 571 return -1;
508 }; 572 };