aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2010-03-16 18:06:12 -0400
committerIngo Molnar <mingo@elte.hu>2010-03-17 06:32:31 -0400
commit4235b0454ebeefc2295ad8417e18a8761425b19e (patch)
treee6b0a3c66618dede18117a71fd16d2e65f93cba1 /tools/perf
parentf4d7da499e4fc1fdff8f26fdeb1a058d475a7a6c (diff)
perf probe: Introduce kprobe_trace_event and perf_probe_event
Introduce kprobe_trace_event and perf_probe_event and replace old probe_point structure with it. probe_point structure is not enough flexible nor extensible. New data structures will help implementing further features. Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Cc: systemtap <systemtap@sources.redhat.com> Cc: DLE <dle-develop@lists.sourceforge.net> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <20100316220612.32050.33806.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-probe.c30
-rw-r--r--tools/perf/util/probe-event.c626
-rw-r--r--tools/perf/util/probe-event.h111
-rw-r--r--tools/perf/util/probe-finder.c140
-rw-r--r--tools/perf/util/probe-finder.h58
5 files changed, 589 insertions, 376 deletions
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index a1a2891ca66f..e0dafd9dfeb5 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -48,12 +48,11 @@
48 48
49/* Session management structure */ 49/* Session management structure */
50static struct { 50static struct {
51 bool need_dwarf;
52 bool list_events; 51 bool list_events;
53 bool force_add; 52 bool force_add;
54 bool show_lines; 53 bool show_lines;
55 int nr_probe; 54 int nevents;
56 struct probe_point probes[MAX_PROBES]; 55 struct perf_probe_event events[MAX_PROBES];
57 struct strlist *dellist; 56 struct strlist *dellist;
58 struct line_range line_range; 57 struct line_range line_range;
59} params; 58} params;
@@ -62,16 +61,16 @@ static struct {
62/* Parse an event definition. Note that any error must die. */ 61/* Parse an event definition. Note that any error must die. */
63static void parse_probe_event(const char *str) 62static void parse_probe_event(const char *str)
64{ 63{
65 struct probe_point *pp = &params.probes[params.nr_probe]; 64 struct perf_probe_event *pev = &params.events[params.nevents];
66 65
67 pr_debug("probe-definition(%d): %s\n", params.nr_probe, str); 66 pr_debug("probe-definition(%d): %s\n", params.nevents, str);
68 if (++params.nr_probe == MAX_PROBES) 67 if (++params.nevents == MAX_PROBES)
69 die("Too many probes (> %d) are specified.", MAX_PROBES); 68 die("Too many probes (> %d) are specified.", MAX_PROBES);
70 69
71 /* Parse perf-probe event into probe_point */ 70 /* Parse a perf-probe command into event */
72 parse_perf_probe_event(str, pp, &params.need_dwarf); 71 parse_perf_probe_command(str, pev);
73 72
74 pr_debug("%d arguments\n", pp->nr_args); 73 pr_debug("%d arguments\n", pev->nargs);
75} 74}
76 75
77static void parse_probe_event_argv(int argc, const char **argv) 76static void parse_probe_event_argv(int argc, const char **argv)
@@ -191,7 +190,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
191 parse_probe_event_argv(argc, argv); 190 parse_probe_event_argv(argc, argv);
192 } 191 }
193 192
194 if ((!params.nr_probe && !params.dellist && !params.list_events && 193 if ((!params.nevents && !params.dellist && !params.list_events &&
195 !params.show_lines)) 194 !params.show_lines))
196 usage_with_options(probe_usage, options); 195 usage_with_options(probe_usage, options);
197 196
@@ -199,7 +198,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
199 die("Failed to find debugfs path."); 198 die("Failed to find debugfs path.");
200 199
201 if (params.list_events) { 200 if (params.list_events) {
202 if (params.nr_probe != 0 || params.dellist) { 201 if (params.nevents != 0 || params.dellist) {
203 pr_warning(" Error: Don't use --list with" 202 pr_warning(" Error: Don't use --list with"
204 " --add/--del.\n"); 203 " --add/--del.\n");
205 usage_with_options(probe_usage, options); 204 usage_with_options(probe_usage, options);
@@ -214,7 +213,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
214 213
215#ifndef NO_DWARF_SUPPORT 214#ifndef NO_DWARF_SUPPORT
216 if (params.show_lines) { 215 if (params.show_lines) {
217 if (params.nr_probe != 0 || params.dellist) { 216 if (params.nevents != 0 || params.dellist) {
218 pr_warning(" Error: Don't use --line with" 217 pr_warning(" Error: Don't use --line with"
219 " --add/--del.\n"); 218 " --add/--del.\n");
220 usage_with_options(probe_usage, options); 219 usage_with_options(probe_usage, options);
@@ -226,14 +225,13 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
226#endif 225#endif
227 226
228 if (params.dellist) { 227 if (params.dellist) {
229 del_trace_kprobe_events(params.dellist); 228 del_perf_probe_events(params.dellist);
230 strlist__delete(params.dellist); 229 strlist__delete(params.dellist);
231 if (params.nr_probe == 0) 230 if (params.nevents == 0)
232 return 0; 231 return 0;
233 } 232 }
234 233
235 add_trace_kprobe_events(params.probes, params.nr_probe, 234 add_perf_probe_events(params.events, params.nevents, params.force_add);
236 params.force_add, params.need_dwarf);
237 return 0; 235 return 0;
238} 236}
239 237
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index ac41578a3552..b44ddfb030d7 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -44,6 +44,7 @@
44#include "thread.h" 44#include "thread.h"
45#include "parse-events.h" /* For debugfs_path */ 45#include "parse-events.h" /* For debugfs_path */
46#include "probe-event.h" 46#include "probe-event.h"
47#include "probe-finder.h"
47 48
48#define MAX_CMDLEN 256 49#define MAX_CMDLEN 256
49#define MAX_PROBE_ARGS 128 50#define MAX_PROBE_ARGS 128
@@ -150,8 +151,9 @@ static bool check_event_name(const char *name)
150} 151}
151 152
152/* Parse probepoint definition. */ 153/* Parse probepoint definition. */
153static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) 154static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
154{ 155{
156 struct perf_probe_point *pp = &pev->point;
155 char *ptr, *tmp; 157 char *ptr, *tmp;
156 char c, nc = 0; 158 char c, nc = 0;
157 /* 159 /*
@@ -172,7 +174,8 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
172 if (!check_event_name(arg)) 174 if (!check_event_name(arg))
173 semantic_error("%s is bad for event name -it must " 175 semantic_error("%s is bad for event name -it must "
174 "follow C symbol-naming rule.", arg); 176 "follow C symbol-naming rule.", arg);
175 pp->event = xstrdup(arg); 177 pev->event = xstrdup(arg);
178 pev->group = NULL;
176 arg = tmp; 179 arg = tmp;
177 } 180 }
178 181
@@ -255,57 +258,65 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
255 semantic_error("Offset/Line/Lazy pattern can't be used with " 258 semantic_error("Offset/Line/Lazy pattern can't be used with "
256 "return probe."); 259 "return probe.");
257 260
258 pr_debug("symbol:%s file:%s line:%d offset:%d return:%d lazy:%s\n", 261 pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n",
259 pp->function, pp->file, pp->line, pp->offset, pp->retprobe, 262 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
260 pp->lazy_line); 263 pp->lazy_line);
261} 264}
262 265
263/* Parse perf-probe event definition */ 266/* Parse perf-probe event command */
264void parse_perf_probe_event(const char *str, struct probe_point *pp, 267void parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev)
265 bool *need_dwarf)
266{ 268{
267 char **argv; 269 char **argv;
268 int argc, i; 270 int argc, i;
269 271
270 *need_dwarf = false; 272 argv = argv_split(cmd, &argc);
271
272 argv = argv_split(str, &argc);
273 if (!argv) 273 if (!argv)
274 die("argv_split failed."); 274 die("argv_split failed.");
275 if (argc > MAX_PROBE_ARGS + 1) 275 if (argc > MAX_PROBE_ARGS + 1)
276 semantic_error("Too many arguments"); 276 semantic_error("Too many arguments");
277 277
278 /* Parse probe point */ 278 /* Parse probe point */
279 parse_perf_probe_probepoint(argv[0], pp); 279 parse_perf_probe_point(argv[0], pev);
280 if (pp->file || pp->line || pp->lazy_line)
281 *need_dwarf = true;
282 280
283 /* Copy arguments and ensure return probe has no C argument */ 281 /* Copy arguments and ensure return probe has no C argument */
284 pp->nr_args = argc - 1; 282 pev->nargs = argc - 1;
285 pp->args = xzalloc(sizeof(char *) * pp->nr_args); 283 pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs);
286 for (i = 0; i < pp->nr_args; i++) { 284 for (i = 0; i < pev->nargs; i++) {
287 pp->args[i] = xstrdup(argv[i + 1]); 285 pev->args[i].name = xstrdup(argv[i + 1]);
288 if (is_c_varname(pp->args[i])) { 286 if (is_c_varname(pev->args[i].name) && pev->point.retprobe)
289 if (pp->retprobe) 287 semantic_error("You can't specify local variable for"
290 semantic_error("You can't specify local" 288 " kretprobe");
291 " variable for kretprobe");
292 *need_dwarf = true;
293 }
294 } 289 }
295 290
296 argv_free(argv); 291 argv_free(argv);
297} 292}
298 293
294/* Return true if this perf_probe_event requires debuginfo */
295bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
296{
297 int i;
298
299 if (pev->point.file || pev->point.line || pev->point.lazy_line)
300 return true;
301
302 for (i = 0; i < pev->nargs; i++)
303 if (is_c_varname(pev->args[i].name))
304 return true;
305
306 return false;
307}
308
299/* Parse kprobe_events event into struct probe_point */ 309/* Parse kprobe_events event into struct probe_point */
300void parse_trace_kprobe_event(const char *str, struct probe_point *pp) 310void parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev)
301{ 311{
312 struct kprobe_trace_point *tp = &tev->point;
302 char pr; 313 char pr;
303 char *p; 314 char *p;
304 int ret, i, argc; 315 int ret, i, argc;
305 char **argv; 316 char **argv;
306 317
307 pr_debug("Parsing kprobe_events: %s\n", str); 318 pr_debug("Parsing kprobe_events: %s\n", cmd);
308 argv = argv_split(str, &argc); 319 argv = argv_split(cmd, &argc);
309 if (!argv) 320 if (!argv)
310 die("argv_split failed."); 321 die("argv_split failed.");
311 if (argc < 2) 322 if (argc < 2)
@@ -313,47 +324,46 @@ void parse_trace_kprobe_event(const char *str, struct probe_point *pp)
313 324
314 /* Scan event and group name. */ 325 /* Scan event and group name. */
315 ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]", 326 ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
316 &pr, (float *)(void *)&pp->group, 327 &pr, (float *)(void *)&tev->group,
317 (float *)(void *)&pp->event); 328 (float *)(void *)&tev->event);
318 if (ret != 3) 329 if (ret != 3)
319 semantic_error("Failed to parse event name: %s", argv[0]); 330 semantic_error("Failed to parse event name: %s", argv[0]);
320 pr_debug("Group:%s Event:%s probe:%c\n", pp->group, pp->event, pr); 331 pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr);
321 332
322 pp->retprobe = (pr == 'r'); 333 tp->retprobe = (pr == 'r');
323 334
324 /* Scan function name and offset */ 335 /* Scan function name and offset */
325 ret = sscanf(argv[1], "%a[^+]+%d", (float *)(void *)&pp->function, 336 ret = sscanf(argv[1], "%a[^+]+%lu", (float *)(void *)&tp->symbol,
326 &pp->offset); 337 &tp->offset);
327 if (ret == 1) 338 if (ret == 1)
328 pp->offset = 0; 339 tp->offset = 0;
329
330 /* kprobe_events doesn't have this information */
331 pp->line = 0;
332 pp->file = NULL;
333 340
334 pp->nr_args = argc - 2; 341 tev->nargs = argc - 2;
335 pp->args = xzalloc(sizeof(char *) * pp->nr_args); 342 tev->args = xzalloc(sizeof(struct kprobe_trace_arg) * tev->nargs);
336 for (i = 0; i < pp->nr_args; i++) { 343 for (i = 0; i < tev->nargs; i++) {
337 p = strchr(argv[i + 2], '='); 344 p = strchr(argv[i + 2], '=');
338 if (p) /* We don't need which register is assigned. */ 345 if (p) /* We don't need which register is assigned. */
339 *p = '\0'; 346 *p++ = '\0';
340 pp->args[i] = xstrdup(argv[i + 2]); 347 else
348 p = argv[i + 2];
349 tev->args[i].name = xstrdup(argv[i + 2]);
350 /* TODO: parse regs and offset */
351 tev->args[i].value = xstrdup(p);
341 } 352 }
342 353
343 argv_free(argv); 354 argv_free(argv);
344} 355}
345 356
346/* Synthesize only probe point (not argument) */ 357/* Compose only probe point (not argument) */
347int synthesize_perf_probe_point(struct probe_point *pp) 358static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
348{ 359{
349 char *buf; 360 char *buf;
350 char offs[64] = "", line[64] = ""; 361 char offs[64] = "", line[64] = "";
351 int ret; 362 int ret;
352 363
353 pp->probes[0] = buf = xzalloc(MAX_CMDLEN); 364 buf = xzalloc(MAX_CMDLEN);
354 pp->found = 1;
355 if (pp->offset) { 365 if (pp->offset) {
356 ret = e_snprintf(offs, 64, "+%d", pp->offset); 366 ret = e_snprintf(offs, 64, "+%lu", pp->offset);
357 if (ret <= 0) 367 if (ret <= 0)
358 goto error; 368 goto error;
359 } 369 }
@@ -368,68 +378,209 @@ int synthesize_perf_probe_point(struct probe_point *pp)
368 offs, pp->retprobe ? "%return" : "", line); 378 offs, pp->retprobe ? "%return" : "", line);
369 else 379 else
370 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", pp->file, line); 380 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", pp->file, line);
371 if (ret <= 0) { 381 if (ret <= 0)
382 goto error;
383
384 return buf;
372error: 385error:
373 free(pp->probes[0]); 386 die("Failed to synthesize perf probe point: %s", strerror(-ret));
374 pp->probes[0] = NULL;
375 pp->found = 0;
376 }
377 return ret;
378} 387}
379 388
380int synthesize_perf_probe_event(struct probe_point *pp) 389#if 0
390char *synthesize_perf_probe_command(struct perf_probe_event *pev)
381{ 391{
382 char *buf; 392 char *buf;
383 int i, len, ret; 393 int i, len, ret;
384 394
385 len = synthesize_perf_probe_point(pp); 395 buf = synthesize_perf_probe_point(&pev->point);
386 if (len < 0) 396 if (!buf)
387 return 0; 397 return NULL;
388 398
389 buf = pp->probes[0]; 399 len = strlen(buf);
390 for (i = 0; i < pp->nr_args; i++) { 400 for (i = 0; i < pev->nargs; i++) {
391 ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", 401 ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
392 pp->args[i]); 402 pev->args[i].name);
393 if (ret <= 0) 403 if (ret <= 0) {
394 goto error; 404 free(buf);
405 return NULL;
406 }
395 len += ret; 407 len += ret;
396 } 408 }
397 pp->found = 1;
398 409
399 return pp->found; 410 return buf;
400error: 411}
401 free(pp->probes[0]); 412#endif
402 pp->probes[0] = NULL; 413
414static int __synthesize_kprobe_trace_arg_ref(struct kprobe_trace_arg_ref *ref,
415 char **buf, size_t *buflen,
416 int depth)
417{
418 int ret;
419 if (ref->next) {
420 depth = __synthesize_kprobe_trace_arg_ref(ref->next, buf,
421 buflen, depth + 1);
422 if (depth < 0)
423 goto out;
424 }
425
426 ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset);
427 if (ret < 0)
428 depth = ret;
429 else {
430 *buf += ret;
431 *buflen -= ret;
432 }
433out:
434 return depth;
403 435
404 return ret;
405} 436}
406 437
407int synthesize_trace_kprobe_event(struct probe_point *pp) 438static int synthesize_kprobe_trace_arg(struct kprobe_trace_arg *arg,
439 char *buf, size_t buflen)
408{ 440{
441 int ret, depth = 0;
442 char *tmp = buf;
443
444 /* Argument name or separator */
445 if (arg->name)
446 ret = e_snprintf(buf, buflen, " %s=", arg->name);
447 else
448 ret = e_snprintf(buf, buflen, " ");
449 if (ret < 0)
450 return ret;
451 buf += ret;
452 buflen -= ret;
453
454 /* Dereferencing arguments */
455 if (arg->ref) {
456 depth = __synthesize_kprobe_trace_arg_ref(arg->ref, &buf,
457 &buflen, 1);
458 if (depth < 0)
459 return depth;
460 }
461
462 /* Print argument value */
463 ret = e_snprintf(buf, buflen, "%s", arg->value);
464 if (ret < 0)
465 return ret;
466 buf += ret;
467 buflen -= ret;
468
469 /* Closing */
470 while (depth--) {
471 ret = e_snprintf(buf, buflen, ")");
472 if (ret < 0)
473 return ret;
474 buf += ret;
475 buflen -= ret;
476 }
477
478 return buf - tmp;
479}
480
481char *synthesize_kprobe_trace_command(struct kprobe_trace_event *tev)
482{
483 struct kprobe_trace_point *tp = &tev->point;
409 char *buf; 484 char *buf;
410 int i, len, ret; 485 int i, len, ret;
411 486
412 pp->probes[0] = buf = xzalloc(MAX_CMDLEN); 487 buf = xzalloc(MAX_CMDLEN);
413 ret = e_snprintf(buf, MAX_CMDLEN, "%s+%d", pp->function, pp->offset); 488 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu",
414 if (ret <= 0) 489 tp->retprobe ? 'r' : 'p',
490 tev->group, tev->event,
491 tp->symbol, tp->offset);
492 if (len <= 0)
415 goto error; 493 goto error;
416 len = ret;
417 494
418 for (i = 0; i < pp->nr_args; i++) { 495 for (i = 0; i < tev->nargs; i++) {
419 ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", 496 ret = synthesize_kprobe_trace_arg(&tev->args[i], buf + len,
420 pp->args[i]); 497 MAX_CMDLEN - len);
421 if (ret <= 0) 498 if (ret <= 0)
422 goto error; 499 goto error;
423 len += ret; 500 len += ret;
424 } 501 }
425 pp->found = 1;
426 502
427 return pp->found; 503 return buf;
428error: 504error:
429 free(pp->probes[0]); 505 free(buf);
430 pp->probes[0] = NULL; 506 return NULL;
507}
431 508
432 return ret; 509void convert_to_perf_probe_event(struct kprobe_trace_event *tev,
510 struct perf_probe_event *pev)
511{
512 char buf[64];
513 int i;
514
515 pev->event = xstrdup(tev->event);
516 pev->group = xstrdup(tev->group);
517
518 /* Convert trace_point to probe_point */
519 pev->point.function = xstrdup(tev->point.symbol);
520 pev->point.offset = tev->point.offset;
521 pev->point.retprobe = tev->point.retprobe;
522
523 /* Convert trace_arg to probe_arg */
524 pev->nargs = tev->nargs;
525 pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs);
526 for (i = 0; i < tev->nargs; i++)
527 if (tev->args[i].name)
528 pev->args[i].name = xstrdup(tev->args[i].name);
529 else {
530 synthesize_kprobe_trace_arg(&tev->args[i], buf, 64);
531 pev->args[i].name = xstrdup(buf);
532 }
533}
534
535void clear_perf_probe_event(struct perf_probe_event *pev)
536{
537 struct perf_probe_point *pp = &pev->point;
538 int i;
539
540 if (pev->event)
541 free(pev->event);
542 if (pev->group)
543 free(pev->group);
544 if (pp->file)
545 free(pp->file);
546 if (pp->function)
547 free(pp->function);
548 if (pp->lazy_line)
549 free(pp->lazy_line);
550 for (i = 0; i < pev->nargs; i++)
551 if (pev->args[i].name)
552 free(pev->args[i].name);
553 if (pev->args)
554 free(pev->args);
555 memset(pev, 0, sizeof(*pev));
556}
557
558void clear_kprobe_trace_event(struct kprobe_trace_event *tev)
559{
560 struct kprobe_trace_arg_ref *ref, *next;
561 int i;
562
563 if (tev->event)
564 free(tev->event);
565 if (tev->group)
566 free(tev->group);
567 if (tev->point.symbol)
568 free(tev->point.symbol);
569 for (i = 0; i < tev->nargs; i++) {
570 if (tev->args[i].name)
571 free(tev->args[i].name);
572 if (tev->args[i].value)
573 free(tev->args[i].value);
574 ref = tev->args[i].ref;
575 while (ref) {
576 next = ref->next;
577 free(ref);
578 ref = next;
579 }
580 }
581 if (tev->args)
582 free(tev->args);
583 memset(tev, 0, sizeof(*tev));
433} 584}
434 585
435static int open_kprobe_events(bool readwrite) 586static int open_kprobe_events(bool readwrite)
@@ -458,7 +609,7 @@ static int open_kprobe_events(bool readwrite)
458} 609}
459 610
460/* Get raw string list of current kprobe_events */ 611/* Get raw string list of current kprobe_events */
461static struct strlist *get_trace_kprobe_event_rawlist(int fd) 612static struct strlist *get_kprobe_trace_command_rawlist(int fd)
462{ 613{
463 int ret, idx; 614 int ret, idx;
464 FILE *fp; 615 FILE *fp;
@@ -486,99 +637,82 @@ static struct strlist *get_trace_kprobe_event_rawlist(int fd)
486 return sl; 637 return sl;
487} 638}
488 639
489/* Free and zero clear probe_point */
490static void clear_probe_point(struct probe_point *pp)
491{
492 int i;
493
494 if (pp->event)
495 free(pp->event);
496 if (pp->group)
497 free(pp->group);
498 if (pp->function)
499 free(pp->function);
500 if (pp->file)
501 free(pp->file);
502 if (pp->lazy_line)
503 free(pp->lazy_line);
504 for (i = 0; i < pp->nr_args; i++)
505 free(pp->args[i]);
506 if (pp->args)
507 free(pp->args);
508 for (i = 0; i < pp->found; i++)
509 free(pp->probes[i]);
510 memset(pp, 0, sizeof(*pp));
511}
512
513/* Show an event */ 640/* Show an event */
514static void show_perf_probe_event(const char *event, const char *place, 641static void show_perf_probe_event(struct perf_probe_event *pev)
515 struct probe_point *pp)
516{ 642{
517 int i, ret; 643 int i, ret;
518 char buf[128]; 644 char buf[128];
645 char *place;
519 646
520 ret = e_snprintf(buf, 128, "%s:%s", pp->group, event); 647 /* Synthesize only event probe point */
648 place = synthesize_perf_probe_point(&pev->point);
649
650 ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event);
521 if (ret < 0) 651 if (ret < 0)
522 die("Failed to copy event: %s", strerror(-ret)); 652 die("Failed to copy event: %s", strerror(-ret));
523 printf(" %-40s (on %s", buf, place); 653 printf(" %-40s (on %s", buf, place);
524 654
525 if (pp->nr_args > 0) { 655 if (pev->nargs > 0) {
526 printf(" with"); 656 printf(" with");
527 for (i = 0; i < pp->nr_args; i++) 657 for (i = 0; i < pev->nargs; i++)
528 printf(" %s", pp->args[i]); 658 printf(" %s", pev->args[i].name);
529 } 659 }
530 printf(")\n"); 660 printf(")\n");
661 free(place);
531} 662}
532 663
533/* List up current perf-probe events */ 664/* List up current perf-probe events */
534void show_perf_probe_events(void) 665void show_perf_probe_events(void)
535{ 666{
536 int fd; 667 int fd;
537 struct probe_point pp; 668 struct kprobe_trace_event tev;
669 struct perf_probe_event pev;
538 struct strlist *rawlist; 670 struct strlist *rawlist;
539 struct str_node *ent; 671 struct str_node *ent;
540 672
541 setup_pager(); 673 setup_pager();
542 memset(&pp, 0, sizeof(pp)); 674
675 memset(&tev, 0, sizeof(tev));
676 memset(&pev, 0, sizeof(pev));
543 677
544 fd = open_kprobe_events(false); 678 fd = open_kprobe_events(false);
545 rawlist = get_trace_kprobe_event_rawlist(fd); 679 rawlist = get_kprobe_trace_command_rawlist(fd);
546 close(fd); 680 close(fd);
547 681
548 strlist__for_each(ent, rawlist) { 682 strlist__for_each(ent, rawlist) {
549 parse_trace_kprobe_event(ent->s, &pp); 683 parse_kprobe_trace_command(ent->s, &tev);
550 /* Synthesize only event probe point */ 684 convert_to_perf_probe_event(&tev, &pev);
551 synthesize_perf_probe_point(&pp);
552 /* Show an event */ 685 /* Show an event */
553 show_perf_probe_event(pp.event, pp.probes[0], &pp); 686 show_perf_probe_event(&pev);
554 clear_probe_point(&pp); 687 clear_perf_probe_event(&pev);
688 clear_kprobe_trace_event(&tev);
555 } 689 }
556 690
557 strlist__delete(rawlist); 691 strlist__delete(rawlist);
558} 692}
559 693
560/* Get current perf-probe event names */ 694/* Get current perf-probe event names */
561static struct strlist *get_perf_event_names(int fd, bool include_group) 695static struct strlist *get_kprobe_trace_event_names(int fd, bool include_group)
562{ 696{
563 char buf[128]; 697 char buf[128];
564 struct strlist *sl, *rawlist; 698 struct strlist *sl, *rawlist;
565 struct str_node *ent; 699 struct str_node *ent;
566 struct probe_point pp; 700 struct kprobe_trace_event tev;
567 701
568 memset(&pp, 0, sizeof(pp)); 702 memset(&tev, 0, sizeof(tev));
569 rawlist = get_trace_kprobe_event_rawlist(fd);
570 703
704 rawlist = get_kprobe_trace_command_rawlist(fd);
571 sl = strlist__new(true, NULL); 705 sl = strlist__new(true, NULL);
572 strlist__for_each(ent, rawlist) { 706 strlist__for_each(ent, rawlist) {
573 parse_trace_kprobe_event(ent->s, &pp); 707 parse_kprobe_trace_command(ent->s, &tev);
574 if (include_group) { 708 if (include_group) {
575 if (e_snprintf(buf, 128, "%s:%s", pp.group, 709 if (e_snprintf(buf, 128, "%s:%s", tev.group,
576 pp.event) < 0) 710 tev.event) < 0)
577 die("Failed to copy group:event name."); 711 die("Failed to copy group:event name.");
578 strlist__add(sl, buf); 712 strlist__add(sl, buf);
579 } else 713 } else
580 strlist__add(sl, pp.event); 714 strlist__add(sl, tev.event);
581 clear_probe_point(&pp); 715 clear_kprobe_trace_event(&tev);
582 } 716 }
583 717
584 strlist__delete(rawlist); 718 strlist__delete(rawlist);
@@ -586,9 +720,10 @@ static struct strlist *get_perf_event_names(int fd, bool include_group)
586 return sl; 720 return sl;
587} 721}
588 722
589static void write_trace_kprobe_event(int fd, const char *buf) 723static void write_kprobe_trace_event(int fd, struct kprobe_trace_event *tev)
590{ 724{
591 int ret; 725 int ret;
726 char *buf = synthesize_kprobe_trace_command(tev);
592 727
593 pr_debug("Writing event: %s\n", buf); 728 pr_debug("Writing event: %s\n", buf);
594 if (!probe_event_dry_run) { 729 if (!probe_event_dry_run) {
@@ -596,6 +731,7 @@ static void write_trace_kprobe_event(int fd, const char *buf)
596 if (ret <= 0) 731 if (ret <= 0)
597 die("Failed to write event: %s", strerror(errno)); 732 die("Failed to write event: %s", strerror(errno));
598 } 733 }
734 free(buf);
599} 735}
600 736
601static void get_new_event_name(char *buf, size_t len, const char *base, 737static void get_new_event_name(char *buf, size_t len, const char *base,
@@ -628,81 +764,83 @@ static void get_new_event_name(char *buf, size_t len, const char *base,
628 die("Too many events are on the same function."); 764 die("Too many events are on the same function.");
629} 765}
630 766
631static void __add_trace_kprobe_events(struct probe_point *probes, 767static void __add_kprobe_trace_events(struct perf_probe_event *pev,
632 int nr_probes, bool force_add) 768 struct kprobe_trace_event *tevs,
769 int ntevs, bool allow_suffix)
633{ 770{
634 int i, j, fd; 771 int i, fd;
635 struct probe_point *pp; 772 struct kprobe_trace_event *tev;
636 char buf[MAX_CMDLEN]; 773 char buf[64];
637 char event[64]; 774 const char *event, *group;
638 struct strlist *namelist; 775 struct strlist *namelist;
639 bool allow_suffix;
640 776
641 fd = open_kprobe_events(true); 777 fd = open_kprobe_events(true);
642 /* Get current event names */ 778 /* Get current event names */
643 namelist = get_perf_event_names(fd, false); 779 namelist = get_kprobe_trace_event_names(fd, false);
644 780
645 for (j = 0; j < nr_probes; j++) { 781 printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":");
646 pp = probes + j; 782 for (i = 0; i < ntevs; i++) {
647 if (!pp->event) 783 tev = &tevs[i];
648 pp->event = xstrdup(pp->function); 784 if (pev->event)
649 if (!pp->group) 785 event = pev->event;
650 pp->group = xstrdup(PERFPROBE_GROUP); 786 else
651 /* If force_add is true, suffix search is allowed */ 787 if (pev->point.function)
652 allow_suffix = force_add; 788 event = pev->point.function;
653 for (i = 0; i < pp->found; i++) { 789 else
654 /* Get an unused new event name */ 790 event = tev->point.symbol;
655 get_new_event_name(event, 64, pp->event, namelist, 791 if (pev->group)
656 allow_suffix); 792 group = pev->group;
657 snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s\n", 793 else
658 pp->retprobe ? 'r' : 'p', 794 group = PERFPROBE_GROUP;
659 pp->group, event, 795
660 pp->probes[i]); 796 /* Get an unused new event name */
661 write_trace_kprobe_event(fd, buf); 797 get_new_event_name(buf, 64, event, namelist, allow_suffix);
662 printf("Added new event:\n"); 798 event = buf;
663 /* Get the first parameter (probe-point) */ 799
664 sscanf(pp->probes[i], "%s", buf); 800 tev->event = xstrdup(event);
665 show_perf_probe_event(event, buf, pp); 801 tev->group = xstrdup(group);
666 /* Add added event name to namelist */ 802 write_kprobe_trace_event(fd, tev);
667 strlist__add(namelist, event); 803 /* Add added event name to namelist */
668 /* 804 strlist__add(namelist, event);
669 * Probes after the first probe which comes from same 805
670 * user input are always allowed to add suffix, because 806 /* Trick here - save current event/group */
671 * there might be several addresses corresponding to 807 event = pev->event;
672 * one code line. 808 group = pev->group;
673 */ 809 pev->event = tev->event;
674 allow_suffix = true; 810 pev->group = tev->group;
675 } 811 show_perf_probe_event(pev);
812 /* Trick here - restore current event/group */
813 pev->event = (char *)event;
814 pev->group = (char *)group;
815
816 /*
817 * Probes after the first probe which comes from same
818 * user input are always allowed to add suffix, because
819 * there might be several addresses corresponding to
820 * one code line.
821 */
822 allow_suffix = true;
676 } 823 }
677 /* Show how to use the event. */ 824 /* Show how to use the event. */
678 printf("\nYou can now use it on all perf tools, such as:\n\n"); 825 printf("\nYou can now use it on all perf tools, such as:\n\n");
679 printf("\tperf record -e %s:%s -a sleep 1\n\n", PERFPROBE_GROUP, event); 826 printf("\tperf record -e %s:%s -a sleep 1\n\n", tev->group, tev->event);
680 827
681 strlist__delete(namelist); 828 strlist__delete(namelist);
682 close(fd); 829 close(fd);
683} 830}
684 831
685/* Currently just checking function name from symbol map */ 832static int convert_to_kprobe_trace_events(struct perf_probe_event *pev,
686static void evaluate_probe_point(struct probe_point *pp) 833 struct kprobe_trace_event **tevs)
687{ 834{
688 struct symbol *sym; 835 struct symbol *sym;
689 sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], 836 bool need_dwarf;
690 pp->function, NULL);
691 if (!sym)
692 die("Kernel symbol \'%s\' not found - probe not added.",
693 pp->function);
694}
695
696void add_trace_kprobe_events(struct probe_point *probes, int nr_probes,
697 bool force_add, bool need_dwarf)
698{
699 int i, ret;
700 struct probe_point *pp;
701#ifndef NO_DWARF_SUPPORT 837#ifndef NO_DWARF_SUPPORT
702 int fd; 838 int fd;
703#endif 839#endif
704 /* Add probes */ 840 int ntevs = 0, i;
705 init_vmlinux(); 841 struct kprobe_trace_event *tev;
842
843 need_dwarf = perf_probe_event_need_dwarf(pev);
706 844
707 if (need_dwarf) 845 if (need_dwarf)
708#ifdef NO_DWARF_SUPPORT 846#ifdef NO_DWARF_SUPPORT
@@ -721,57 +859,90 @@ void add_trace_kprobe_events(struct probe_point *probes, int nr_probes,
721 } 859 }
722 860
723 /* Searching probe points */ 861 /* Searching probe points */
724 for (i = 0; i < nr_probes; i++) { 862 ntevs = find_kprobe_trace_events(fd, pev, tevs);
725 pp = &probes[i]; 863
726 if (pp->found) 864 if (ntevs > 0) /* Found */
727 continue; 865 goto found;
728 866
729 lseek(fd, SEEK_SET, 0); 867 if (ntevs == 0) /* No error but failed to find probe point. */
730 ret = find_probe_point(fd, pp); 868 die("Probe point '%s' not found. - probe not added.",
731 if (ret > 0) 869 synthesize_perf_probe_point(&pev->point));
732 continue; 870
733 if (ret == 0) { /* No error but failed to find probe point. */ 871 /* Error path */
734 synthesize_perf_probe_point(pp); 872 if (need_dwarf) {
735 die("Probe point '%s' not found. - probe not added.", 873 if (ntevs == -ENOENT)
736 pp->probes[0]); 874 pr_warning("No dwarf info found in the vmlinux - please rebuild with CONFIG_DEBUG_INFO=y.\n");
737 } 875 die("Could not analyze debuginfo.");
738 /* Error path */
739 if (need_dwarf) {
740 if (ret == -ENOENT)
741 pr_warning("No dwarf info found in the vmlinux - please rebuild with CONFIG_DEBUG_INFO=y.\n");
742 die("Could not analyze debuginfo.");
743 }
744 pr_debug("An error occurred in debuginfo analysis."
745 " Try to use symbols.\n");
746 break;
747 } 876 }
748 close(fd); 877 pr_debug("An error occurred in debuginfo analysis."
878 " Try to use symbols.\n");
749 879
750end_dwarf: 880end_dwarf:
751#endif /* !NO_DWARF_SUPPORT */ 881#endif /* !NO_DWARF_SUPPORT */
752 882
753 /* Synthesize probes without dwarf */ 883 /* Allocate trace event buffer */
754 for (i = 0; i < nr_probes; i++) { 884 ntevs = 1;
755 pp = &probes[i]; 885 tev = *tevs = xzalloc(sizeof(struct kprobe_trace_event));
756 if (pp->found) /* This probe is already found. */ 886
757 continue; 887 /* Copy parameters */
888 tev->point.symbol = xstrdup(pev->point.function);
889 tev->point.offset = pev->point.offset;
890 tev->nargs = pev->nargs;
891 if (tev->nargs) {
892 tev->args = xzalloc(sizeof(struct kprobe_trace_arg)
893 * tev->nargs);
894 for (i = 0; i < tev->nargs; i++)
895 tev->args[i].value = xstrdup(pev->args[i].name);
896 }
897
898 /* Currently just checking function name from symbol map */
899 sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION],
900 tev->point.symbol, NULL);
901 if (!sym)
902 die("Kernel symbol \'%s\' not found - probe not added.",
903 tev->point.symbol);
904found:
905 close(fd);
906 return ntevs;
907}
908
909struct __event_package {
910 struct perf_probe_event *pev;
911 struct kprobe_trace_event *tevs;
912 int ntevs;
913};
758 914
759 evaluate_probe_point(pp); 915void add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
760 ret = synthesize_trace_kprobe_event(pp); 916 bool force_add)
761 if (ret == -E2BIG) 917{
762 die("probe point definition becomes too long."); 918 int i;
763 else if (ret < 0) 919 struct __event_package *pkgs;
764 die("Failed to synthesize a probe point."); 920
921 pkgs = xzalloc(sizeof(struct __event_package) * npevs);
922
923 /* Init vmlinux path */
924 init_vmlinux();
925
926 /* Loop 1: convert all events */
927 for (i = 0; i < npevs; i++) {
928 pkgs[i].pev = &pevs[i];
929 /* Convert with or without debuginfo */
930 pkgs[i].ntevs = convert_to_kprobe_trace_events(pkgs[i].pev,
931 &pkgs[i].tevs);
765 } 932 }
766 933
767 /* Settng up probe points */ 934 /* Loop 2: add all events */
768 __add_trace_kprobe_events(probes, nr_probes, force_add); 935 for (i = 0; i < npevs; i++)
936 __add_kprobe_trace_events(pkgs[i].pev, pkgs[i].tevs,
937 pkgs[i].ntevs, force_add);
938 /* TODO: cleanup all trace events? */
769} 939}
770 940
771static void __del_trace_kprobe_event(int fd, struct str_node *ent) 941static void __del_trace_kprobe_event(int fd, struct str_node *ent)
772{ 942{
773 char *p; 943 char *p;
774 char buf[128]; 944 char buf[128];
945 int ret;
775 946
776 /* Convert from perf-probe event to trace-kprobe event */ 947 /* Convert from perf-probe event to trace-kprobe event */
777 if (e_snprintf(buf, 128, "-:%s", ent->s) < 0) 948 if (e_snprintf(buf, 128, "-:%s", ent->s) < 0)
@@ -781,7 +952,10 @@ static void __del_trace_kprobe_event(int fd, struct str_node *ent)
781 die("Internal error: %s should have ':' but not.", ent->s); 952 die("Internal error: %s should have ':' but not.", ent->s);
782 *p = '/'; 953 *p = '/';
783 954
784 write_trace_kprobe_event(fd, buf); 955 pr_debug("Writing event: %s\n", buf);
956 ret = write(fd, buf, strlen(buf));
957 if (ret <= 0)
958 die("Failed to write event: %s", strerror(errno));
785 printf("Remove event: %s\n", ent->s); 959 printf("Remove event: %s\n", ent->s);
786} 960}
787 961
@@ -814,7 +988,7 @@ static void del_trace_kprobe_event(int fd, const char *group,
814 pr_info("Info: event \"%s\" does not exist, could not remove it.\n", buf); 988 pr_info("Info: event \"%s\" does not exist, could not remove it.\n", buf);
815} 989}
816 990
817void del_trace_kprobe_events(struct strlist *dellist) 991void del_perf_probe_events(struct strlist *dellist)
818{ 992{
819 int fd; 993 int fd;
820 const char *group, *event; 994 const char *group, *event;
@@ -824,7 +998,7 @@ void del_trace_kprobe_events(struct strlist *dellist)
824 998
825 fd = open_kprobe_events(true); 999 fd = open_kprobe_events(true);
826 /* Get current event names */ 1000 /* Get current event names */
827 namelist = get_perf_event_names(fd, true); 1001 namelist = get_kprobe_trace_event_names(fd, true);
828 1002
829 strlist__for_each(ent, dellist) { 1003 strlist__for_each(ent, dellist) {
830 str = xstrdup(ent->s); 1004 str = xstrdup(ent->s);
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 703b8876dfb1..2a2f0a26dc67 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -2,24 +2,113 @@
2#define _PROBE_EVENT_H 2#define _PROBE_EVENT_H
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include "probe-finder.h"
6#include "strlist.h" 5#include "strlist.h"
7 6
8extern bool probe_event_dry_run; 7extern bool probe_event_dry_run;
9 8
10extern void parse_line_range_desc(const char *arg, struct line_range *lr); 9/* kprobe-tracer tracing point */
11extern void parse_perf_probe_event(const char *str, struct probe_point *pp, 10struct kprobe_trace_point {
12 bool *need_dwarf); 11 char *symbol; /* Base symbol */
13extern int synthesize_perf_probe_point(struct probe_point *pp); 12 unsigned long offset; /* Offset from symbol */
14extern int synthesize_perf_probe_event(struct probe_point *pp); 13 bool retprobe; /* Return probe flag */
15extern void parse_trace_kprobe_event(const char *str, struct probe_point *pp); 14};
16extern int synthesize_trace_kprobe_event(struct probe_point *pp); 15
17extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes, 16/* kprobe-tracer tracing argument referencing offset */
18 bool force_add, bool need_dwarf); 17struct kprobe_trace_arg_ref {
19extern void del_trace_kprobe_events(struct strlist *dellist); 18 struct kprobe_trace_arg_ref *next; /* Next reference */
19 long offset; /* Offset value */
20};
21
22/* kprobe-tracer tracing argument */
23struct kprobe_trace_arg {
24 char *name; /* Argument name */
25 char *value; /* Base value */
26 struct kprobe_trace_arg_ref *ref; /* Referencing offset */
27};
28
29/* kprobe-tracer tracing event (point + arg) */
30struct kprobe_trace_event {
31 char *event; /* Event name */
32 char *group; /* Group name */
33 struct kprobe_trace_point point; /* Trace point */
34 int nargs; /* Number of args */
35 struct kprobe_trace_arg *args; /* Arguments */
36};
37
38/* Perf probe probing point */
39struct perf_probe_point {
40 char *file; /* File path */
41 char *function; /* Function name */
42 int line; /* Line number */
43 char *lazy_line; /* Lazy matching pattern */
44 unsigned long offset; /* Offset from function entry */
45 bool retprobe; /* Return probe flag */
46};
47
48/* Perf probe probing argument */
49struct perf_probe_arg {
50 char *name; /* Argument name */
51};
52
53/* Perf probe probing event (point + arg) */
54struct perf_probe_event {
55 char *event; /* Event name */
56 char *group; /* Group name */
57 struct perf_probe_point point; /* Probe point */
58 int nargs; /* Number of arguments */
59 struct perf_probe_arg *args; /* Arguments */
60};
61
62
63/* Line number container */
64struct line_node {
65 struct list_head list;
66 unsigned int line;
67};
68
69/* Line range */
70struct line_range {
71 char *file; /* File name */
72 char *function; /* Function name */
73 unsigned int start; /* Start line number */
74 unsigned int end; /* End line number */
75 int offset; /* Start line offset */
76 char *path; /* Real path name */
77 struct list_head line_list; /* Visible lines */
78};
79
80/* Command string to events */
81extern void parse_perf_probe_command(const char *cmd,
82 struct perf_probe_event *pev);
83extern void parse_kprobe_trace_command(const char *cmd,
84 struct kprobe_trace_event *tev);
85
86/* Events to command string */
87extern char *synthesize_perf_probe_command(struct perf_probe_event *pev);
88extern char *synthesize_kprobe_trace_command(struct kprobe_trace_event *tev);
89
90/* Check the perf_probe_event needs debuginfo */
91extern bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
92
93/* Convert from kprobe_trace_event to perf_probe_event */
94extern void convert_to_perf_probe_event(struct kprobe_trace_event *tev,
95 struct perf_probe_event *pev);
96
97/* Release event contents */
98extern void clear_perf_probe_event(struct perf_probe_event *pev);
99extern void clear_kprobe_trace_event(struct kprobe_trace_event *tev);
100
101/* Command string to line-range */
102extern void parse_line_range_desc(const char *cmd, struct line_range *lr);
103
104
105extern void add_perf_probe_events(struct perf_probe_event *pevs, int ntevs,
106 bool force_add);
107extern void del_perf_probe_events(struct strlist *dellist);
20extern void show_perf_probe_events(void); 108extern void show_perf_probe_events(void);
21extern void show_line_range(struct line_range *lr); 109extern void show_line_range(struct line_range *lr);
22 110
111
23/* Maximum index number of event-name postfix */ 112/* Maximum index number of event-name postfix */
24#define MAX_EVENT_INDEX 1024 113#define MAX_EVENT_INDEX 1024
25 114
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 3942e14e95cf..251b4c49653e 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -319,19 +319,20 @@ static Dwarf_Die *die_find_variable(Dwarf_Die *sp_die, const char *name,
319 */ 319 */
320 320
321/* Show a location */ 321/* Show a location */
322static void show_location(Dwarf_Op *op, struct probe_finder *pf) 322static void convert_location(Dwarf_Op *op, struct probe_finder *pf)
323{ 323{
324 unsigned int regn; 324 unsigned int regn;
325 Dwarf_Word offs = 0; 325 Dwarf_Word offs = 0;
326 int deref = 0, ret; 326 bool ref = false;
327 const char *regs; 327 const char *regs;
328 struct kprobe_trace_arg *tvar = pf->tvar;
328 329
329 /* TODO: support CFA */ 330 /* TODO: support CFA */
330 /* If this is based on frame buffer, set the offset */ 331 /* If this is based on frame buffer, set the offset */
331 if (op->atom == DW_OP_fbreg) { 332 if (op->atom == DW_OP_fbreg) {
332 if (pf->fb_ops == NULL) 333 if (pf->fb_ops == NULL)
333 die("The attribute of frame base is not supported.\n"); 334 die("The attribute of frame base is not supported.\n");
334 deref = 1; 335 ref = true;
335 offs = op->number; 336 offs = op->number;
336 op = &pf->fb_ops[0]; 337 op = &pf->fb_ops[0];
337 } 338 }
@@ -339,13 +340,13 @@ static void show_location(Dwarf_Op *op, struct probe_finder *pf)
339 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) { 340 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
340 regn = op->atom - DW_OP_breg0; 341 regn = op->atom - DW_OP_breg0;
341 offs += op->number; 342 offs += op->number;
342 deref = 1; 343 ref = true;
343 } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) { 344 } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
344 regn = op->atom - DW_OP_reg0; 345 regn = op->atom - DW_OP_reg0;
345 } else if (op->atom == DW_OP_bregx) { 346 } else if (op->atom == DW_OP_bregx) {
346 regn = op->number; 347 regn = op->number;
347 offs += op->number2; 348 offs += op->number2;
348 deref = 1; 349 ref = true;
349 } else if (op->atom == DW_OP_regx) { 350 } else if (op->atom == DW_OP_regx) {
350 regn = op->number; 351 regn = op->number;
351 } else 352 } else
@@ -355,17 +356,15 @@ static void show_location(Dwarf_Op *op, struct probe_finder *pf)
355 if (!regs) 356 if (!regs)
356 die("%u exceeds max register number.", regn); 357 die("%u exceeds max register number.", regn);
357 358
358 if (deref) 359 tvar->value = xstrdup(regs);
359 ret = snprintf(pf->buf, pf->len, " %s=%+jd(%s)", 360 if (ref) {
360 pf->var, (intmax_t)offs, regs); 361 tvar->ref = xzalloc(sizeof(struct kprobe_trace_arg_ref));
361 else 362 tvar->ref->offset = (long)offs;
362 ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs); 363 }
363 DIE_IF(ret < 0);
364 DIE_IF(ret >= pf->len);
365} 364}
366 365
367/* Show a variables in kprobe event format */ 366/* Show a variables in kprobe event format */
368static void show_variable(Dwarf_Die *vr_die, struct probe_finder *pf) 367static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
369{ 368{
370 Dwarf_Attribute attr; 369 Dwarf_Attribute attr;
371 Dwarf_Op *expr; 370 Dwarf_Op *expr;
@@ -379,50 +378,51 @@ static void show_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
379 if (ret <= 0 || nexpr == 0) 378 if (ret <= 0 || nexpr == 0)
380 goto error; 379 goto error;
381 380
382 show_location(expr, pf); 381 convert_location(expr, pf);
383 /* *expr will be cached in libdw. Don't free it. */ 382 /* *expr will be cached in libdw. Don't free it. */
384 return ; 383 return ;
385error: 384error:
386 /* TODO: Support const_value */ 385 /* TODO: Support const_value */
387 die("Failed to find the location of %s at this address.\n" 386 die("Failed to find the location of %s at this address.\n"
388 " Perhaps, it has been optimized out.", pf->var); 387 " Perhaps, it has been optimized out.", pf->pvar->name);
389} 388}
390 389
391/* Find a variable in a subprogram die */ 390/* Find a variable in a subprogram die */
392static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) 391static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
393{ 392{
394 int ret;
395 Dwarf_Die vr_die; 393 Dwarf_Die vr_die;
396 394
397 /* TODO: Support struct members and arrays */ 395 /* TODO: Support struct members and arrays */
398 if (!is_c_varname(pf->var)) { 396 if (!is_c_varname(pf->pvar->name)) {
399 /* Output raw parameters */ 397 /* Copy raw parameters */
400 ret = snprintf(pf->buf, pf->len, " %s", pf->var); 398 pf->tvar->value = xstrdup(pf->pvar->name);
401 DIE_IF(ret < 0); 399 } else {
402 DIE_IF(ret >= pf->len); 400 pf->tvar->name = xstrdup(pf->pvar->name);
403 return ; 401 pr_debug("Searching '%s' variable in context.\n",
402 pf->pvar->name);
403 /* Search child die for local variables and parameters. */
404 if (!die_find_variable(sp_die, pf->pvar->name, &vr_die))
405 die("Failed to find '%s' in this function.",
406 pf->pvar->name);
407 convert_variable(&vr_die, pf);
404 } 408 }
405
406 pr_debug("Searching '%s' variable in context.\n", pf->var);
407 /* Search child die for local variables and parameters. */
408 if (!die_find_variable(sp_die, pf->var, &vr_die))
409 die("Failed to find '%s' in this function.", pf->var);
410
411 show_variable(&vr_die, pf);
412} 409}
413 410
414/* Show a probe point to output buffer */ 411/* Show a probe point to output buffer */
415static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) 412static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
416{ 413{
417 struct probe_point *pp = pf->pp; 414 struct kprobe_trace_event *tev;
418 Dwarf_Addr eaddr; 415 Dwarf_Addr eaddr;
419 Dwarf_Die die_mem; 416 Dwarf_Die die_mem;
420 const char *name; 417 const char *name;
421 char tmp[MAX_PROBE_BUFFER]; 418 int ret, i;
422 int ret, i, len;
423 Dwarf_Attribute fb_attr; 419 Dwarf_Attribute fb_attr;
424 size_t nops; 420 size_t nops;
425 421
422 if (pf->ntevs == MAX_PROBES)
423 die("Too many( > %d) probe point found.\n", MAX_PROBES);
424 tev = &pf->tevs[pf->ntevs++];
425
426 /* If no real subprogram, find a real one */ 426 /* If no real subprogram, find a real one */
427 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) { 427 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
428 sp_die = die_find_real_subprogram(&pf->cu_die, 428 sp_die = die_find_real_subprogram(&pf->cu_die,
@@ -431,31 +431,18 @@ static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
431 die("Probe point is not found in subprograms."); 431 die("Probe point is not found in subprograms.");
432 } 432 }
433 433
434 /* Output name of probe point */ 434 /* Copy the name of probe point */
435 name = dwarf_diename(sp_die); 435 name = dwarf_diename(sp_die);
436 if (name) { 436 if (name) {
437 dwarf_entrypc(sp_die, &eaddr); 437 dwarf_entrypc(sp_die, &eaddr);
438 ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%lu", name, 438 tev->point.symbol = xstrdup(name);
439 (unsigned long)(pf->addr - eaddr)); 439 tev->point.offset = (unsigned long)(pf->addr - eaddr);
440 /* Copy the function name if possible */ 440 } else
441 if (!pp->function) {
442 pp->function = xstrdup(name);
443 pp->offset = (size_t)(pf->addr - eaddr);
444 }
445 } else {
446 /* This function has no name. */ 441 /* This function has no name. */
447 ret = snprintf(tmp, MAX_PROBE_BUFFER, "0x%jx", 442 tev->point.offset = (unsigned long)pf->addr;
448 (uintmax_t)pf->addr); 443
449 if (!pp->function) { 444 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
450 /* TODO: Use _stext */ 445 tev->point.offset);
451 pp->function = xstrdup("");
452 pp->offset = (size_t)pf->addr;
453 }
454 }
455 DIE_IF(ret < 0);
456 DIE_IF(ret >= MAX_PROBE_BUFFER);
457 len = ret;
458 pr_debug("Probe point found: %s\n", tmp);
459 446
460 /* Get the frame base attribute/ops */ 447 /* Get the frame base attribute/ops */
461 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr); 448 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
@@ -465,22 +452,16 @@ static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
465 452
466 /* Find each argument */ 453 /* Find each argument */
467 /* TODO: use dwarf_cfi_addrframe */ 454 /* TODO: use dwarf_cfi_addrframe */
468 for (i = 0; i < pp->nr_args; i++) { 455 tev->nargs = pf->pev->nargs;
469 pf->var = pp->args[i]; 456 tev->args = xzalloc(sizeof(struct kprobe_trace_arg) * tev->nargs);
470 pf->buf = &tmp[len]; 457 for (i = 0; i < pf->pev->nargs; i++) {
471 pf->len = MAX_PROBE_BUFFER - len; 458 pf->pvar = &pf->pev->args[i];
459 pf->tvar = &tev->args[i];
472 find_variable(sp_die, pf); 460 find_variable(sp_die, pf);
473 len += strlen(pf->buf);
474 } 461 }
475 462
476 /* *pf->fb_ops will be cached in libdw. Don't free it. */ 463 /* *pf->fb_ops will be cached in libdw. Don't free it. */
477 pf->fb_ops = NULL; 464 pf->fb_ops = NULL;
478
479 if (pp->found == MAX_PROBES)
480 die("Too many( > %d) probe point found.\n", MAX_PROBES);
481
482 pp->probes[pp->found] = xstrdup(tmp);
483 pp->found++;
484} 465}
485 466
486/* Find probe point from its line number */ 467/* Find probe point from its line number */
@@ -512,7 +493,7 @@ static void find_probe_point_by_line(struct probe_finder *pf)
512 (int)i, lineno, (uintmax_t)addr); 493 (int)i, lineno, (uintmax_t)addr);
513 pf->addr = addr; 494 pf->addr = addr;
514 495
515 show_probe_point(NULL, pf); 496 convert_probe_point(NULL, pf);
516 /* Continuing, because target line might be inlined. */ 497 /* Continuing, because target line might be inlined. */
517 } 498 }
518} 499}
@@ -563,7 +544,7 @@ static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
563 if (list_empty(&pf->lcache)) { 544 if (list_empty(&pf->lcache)) {
564 /* Matching lazy line pattern */ 545 /* Matching lazy line pattern */
565 ret = find_lazy_match_lines(&pf->lcache, pf->fname, 546 ret = find_lazy_match_lines(&pf->lcache, pf->fname,
566 pf->pp->lazy_line); 547 pf->pev->point.lazy_line);
567 if (ret <= 0) 548 if (ret <= 0)
568 die("No matched lines found in %s.", pf->fname); 549 die("No matched lines found in %s.", pf->fname);
569 } 550 }
@@ -596,7 +577,7 @@ static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
596 (int)i, lineno, (unsigned long long)addr); 577 (int)i, lineno, (unsigned long long)addr);
597 pf->addr = addr; 578 pf->addr = addr;
598 579
599 show_probe_point(sp_die, pf); 580 convert_probe_point(sp_die, pf);
600 /* Continuing, because target line might be inlined. */ 581 /* Continuing, because target line might be inlined. */
601 } 582 }
602 /* TODO: deallocate lines, but how? */ 583 /* TODO: deallocate lines, but how? */
@@ -605,7 +586,7 @@ static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
605static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) 586static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
606{ 587{
607 struct probe_finder *pf = (struct probe_finder *)data; 588 struct probe_finder *pf = (struct probe_finder *)data;
608 struct probe_point *pp = pf->pp; 589 struct perf_probe_point *pp = &pf->pev->point;
609 590
610 if (pp->lazy_line) 591 if (pp->lazy_line)
611 find_probe_point_lazy(in_die, pf); 592 find_probe_point_lazy(in_die, pf);
@@ -616,7 +597,7 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
616 pr_debug("found inline addr: 0x%jx\n", 597 pr_debug("found inline addr: 0x%jx\n",
617 (uintmax_t)pf->addr); 598 (uintmax_t)pf->addr);
618 599
619 show_probe_point(in_die, pf); 600 convert_probe_point(in_die, pf);
620 } 601 }
621 602
622 return DWARF_CB_OK; 603 return DWARF_CB_OK;
@@ -626,7 +607,7 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
626static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) 607static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
627{ 608{
628 struct probe_finder *pf = (struct probe_finder *)data; 609 struct probe_finder *pf = (struct probe_finder *)data;
629 struct probe_point *pp = pf->pp; 610 struct perf_probe_point *pp = &pf->pev->point;
630 611
631 /* Check tag and diename */ 612 /* Check tag and diename */
632 if (dwarf_tag(sp_die) != DW_TAG_subprogram || 613 if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
@@ -646,7 +627,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
646 pf->addr = die_get_entrypc(sp_die); 627 pf->addr = die_get_entrypc(sp_die);
647 pf->addr += pp->offset; 628 pf->addr += pp->offset;
648 /* TODO: Check the address in this function */ 629 /* TODO: Check the address in this function */
649 show_probe_point(sp_die, pf); 630 convert_probe_point(sp_die, pf);
650 } 631 }
651 } else 632 } else
652 /* Inlined function: search instances */ 633 /* Inlined function: search instances */
@@ -660,20 +641,25 @@ static void find_probe_point_by_func(struct probe_finder *pf)
660 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, pf, 0); 641 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, pf, 0);
661} 642}
662 643
663/* Find a probe point */ 644/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
664int find_probe_point(int fd, struct probe_point *pp) 645int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
646 struct kprobe_trace_event **tevs)
665{ 647{
666 struct probe_finder pf = {.pp = pp}; 648 struct probe_finder pf = {.pev = pev};
649 struct perf_probe_point *pp = &pev->point;
667 Dwarf_Off off, noff; 650 Dwarf_Off off, noff;
668 size_t cuhl; 651 size_t cuhl;
669 Dwarf_Die *diep; 652 Dwarf_Die *diep;
670 Dwarf *dbg; 653 Dwarf *dbg;
671 654
655 pf.tevs = xzalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES);
656 *tevs = pf.tevs;
657 pf.ntevs = 0;
658
672 dbg = dwarf_begin(fd, DWARF_C_READ); 659 dbg = dwarf_begin(fd, DWARF_C_READ);
673 if (!dbg) 660 if (!dbg)
674 return -ENOENT; 661 return -ENOENT;
675 662
676 pp->found = 0;
677 off = 0; 663 off = 0;
678 line_list__init(&pf.lcache); 664 line_list__init(&pf.lcache);
679 /* Loop on CUs (Compilation Unit) */ 665 /* Loop on CUs (Compilation Unit) */
@@ -704,7 +690,7 @@ int find_probe_point(int fd, struct probe_point *pp)
704 line_list__free(&pf.lcache); 690 line_list__free(&pf.lcache);
705 dwarf_end(dbg); 691 dwarf_end(dbg);
706 692
707 return pp->found; 693 return pf.ntevs;
708} 694}
709 695
710/* Find line range from its line number */ 696/* Find line range from its line number */
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 21f7354397b4..494952619b9c 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -3,6 +3,7 @@
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include "util.h" 5#include "util.h"
6#include "probe-event.h"
6 7
7#define MAX_PATH_LEN 256 8#define MAX_PATH_LEN 256
8#define MAX_PROBE_BUFFER 1024 9#define MAX_PROBE_BUFFER 1024
@@ -14,67 +15,32 @@ static inline int is_c_varname(const char *name)
14 return isalpha(name[0]) || name[0] == '_'; 15 return isalpha(name[0]) || name[0] == '_';
15} 16}
16 17
17struct probe_point {
18 char *event; /* Event name */
19 char *group; /* Event group */
20
21 /* Inputs */
22 char *file; /* File name */
23 int line; /* Line number */
24 char *lazy_line; /* Lazy line pattern */
25
26 char *function; /* Function name */
27 int offset; /* Offset bytes */
28
29 int nr_args; /* Number of arguments */
30 char **args; /* Arguments */
31
32 int retprobe; /* Return probe */
33
34 /* Output */
35 int found; /* Number of found probe points */
36 char *probes[MAX_PROBES]; /* Output buffers (will be allocated)*/
37};
38
39/* Line number container */
40struct line_node {
41 struct list_head list;
42 unsigned int line;
43};
44
45/* Line range */
46struct line_range {
47 char *file; /* File name */
48 char *function; /* Function name */
49 unsigned int start; /* Start line number */
50 unsigned int end; /* End line number */
51 int offset; /* Start line offset */
52 char *path; /* Real path name */
53 struct list_head line_list; /* Visible lines */
54};
55
56#ifndef NO_DWARF_SUPPORT 18#ifndef NO_DWARF_SUPPORT
57extern int find_probe_point(int fd, struct probe_point *pp); 19/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
20extern int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
21 struct kprobe_trace_event **tevs);
22
58extern int find_line_range(int fd, struct line_range *lr); 23extern int find_line_range(int fd, struct line_range *lr);
59 24
60#include <dwarf.h> 25#include <dwarf.h>
61#include <libdw.h> 26#include <libdw.h>
62 27
63struct probe_finder { 28struct probe_finder {
64 struct probe_point *pp; /* Target probe point */ 29 struct perf_probe_event *pev; /* Target probe event */
30 int ntevs; /* number of trace events */
31 struct kprobe_trace_event *tevs; /* Result trace events */
65 32
66 /* For function searching */ 33 /* For function searching */
67 Dwarf_Addr addr; /* Address */ 34 Dwarf_Addr addr; /* Address */
68 const char *fname; /* File name */ 35 const char *fname; /* Real file name */
69 int lno; /* Line number */ 36 int lno; /* Line number */
70 Dwarf_Die cu_die; /* Current CU */ 37 Dwarf_Die cu_die; /* Current CU */
38 struct list_head lcache; /* Line cache for lazy match */
71 39
72 /* For variable searching */ 40 /* For variable searching */
73 Dwarf_Op *fb_ops; /* Frame base attribute */ 41 Dwarf_Op *fb_ops; /* Frame base attribute */
74 const char *var; /* Current variable name */ 42 struct perf_probe_arg *pvar; /* Current target variable */
75 char *buf; /* Current output buffer */ 43 struct kprobe_trace_arg *tvar; /* Current result variable */
76 int len; /* Length of output buffer */
77 struct list_head lcache; /* Line cache for lazy match */
78}; 44};
79 45
80struct line_finder { 46struct line_finder {