aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-event.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/probe-event.c')
-rw-r--r--tools/perf/util/probe-event.c173
1 files changed, 131 insertions, 42 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index f0223166e76..eb25900e221 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -117,6 +117,10 @@ static struct map *kernel_get_module_map(const char *module)
117 struct rb_node *nd; 117 struct rb_node *nd;
118 struct map_groups *grp = &machine.kmaps; 118 struct map_groups *grp = &machine.kmaps;
119 119
120 /* A file path -- this is an offline module */
121 if (module && strchr(module, '/'))
122 return machine__new_module(&machine, 0, module);
123
120 if (!module) 124 if (!module)
121 module = "kernel"; 125 module = "kernel";
122 126
@@ -170,16 +174,24 @@ const char *kernel_get_module_path(const char *module)
170} 174}
171 175
172#ifdef DWARF_SUPPORT 176#ifdef DWARF_SUPPORT
173static int open_vmlinux(const char *module) 177/* Open new debuginfo of given module */
178static struct debuginfo *open_debuginfo(const char *module)
174{ 179{
175 const char *path = kernel_get_module_path(module); 180 const char *path;
176 if (!path) { 181
177 pr_err("Failed to find path of %s module.\n", 182 /* A file path -- this is an offline module */
178 module ?: "kernel"); 183 if (module && strchr(module, '/'))
179 return -ENOENT; 184 path = module;
185 else {
186 path = kernel_get_module_path(module);
187
188 if (!path) {
189 pr_err("Failed to find path of %s module.\n",
190 module ?: "kernel");
191 return NULL;
192 }
180 } 193 }
181 pr_debug("Try to open %s\n", path); 194 return debuginfo__new(path);
182 return open(path, O_RDONLY);
183} 195}
184 196
185/* 197/*
@@ -193,13 +205,24 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
193 struct map *map; 205 struct map *map;
194 u64 addr; 206 u64 addr;
195 int ret = -ENOENT; 207 int ret = -ENOENT;
208 struct debuginfo *dinfo;
196 209
197 sym = __find_kernel_function_by_name(tp->symbol, &map); 210 sym = __find_kernel_function_by_name(tp->symbol, &map);
198 if (sym) { 211 if (sym) {
199 addr = map->unmap_ip(map, sym->start + tp->offset); 212 addr = map->unmap_ip(map, sym->start + tp->offset);
200 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol, 213 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
201 tp->offset, addr); 214 tp->offset, addr);
202 ret = find_perf_probe_point((unsigned long)addr, pp); 215
216 dinfo = debuginfo__new_online_kernel(addr);
217 if (dinfo) {
218 ret = debuginfo__find_probe_point(dinfo,
219 (unsigned long)addr, pp);
220 debuginfo__delete(dinfo);
221 } else {
222 pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n",
223 addr);
224 ret = -ENOENT;
225 }
203 } 226 }
204 if (ret <= 0) { 227 if (ret <= 0) {
205 pr_debug("Failed to find corresponding probes from " 228 pr_debug("Failed to find corresponding probes from "
@@ -214,30 +237,70 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
214 return 0; 237 return 0;
215} 238}
216 239
240static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
241 int ntevs, const char *module)
242{
243 int i, ret = 0;
244 char *tmp;
245
246 if (!module)
247 return 0;
248
249 tmp = strrchr(module, '/');
250 if (tmp) {
251 /* This is a module path -- get the module name */
252 module = strdup(tmp + 1);
253 if (!module)
254 return -ENOMEM;
255 tmp = strchr(module, '.');
256 if (tmp)
257 *tmp = '\0';
258 tmp = (char *)module; /* For free() */
259 }
260
261 for (i = 0; i < ntevs; i++) {
262 tevs[i].point.module = strdup(module);
263 if (!tevs[i].point.module) {
264 ret = -ENOMEM;
265 break;
266 }
267 }
268
269 if (tmp)
270 free(tmp);
271
272 return ret;
273}
274
217/* Try to find perf_probe_event with debuginfo */ 275/* Try to find perf_probe_event with debuginfo */
218static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 276static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
219 struct probe_trace_event **tevs, 277 struct probe_trace_event **tevs,
220 int max_tevs, const char *module) 278 int max_tevs, const char *module)
221{ 279{
222 bool need_dwarf = perf_probe_event_need_dwarf(pev); 280 bool need_dwarf = perf_probe_event_need_dwarf(pev);
223 int fd, ntevs; 281 struct debuginfo *dinfo = open_debuginfo(module);
282 int ntevs, ret = 0;
224 283
225 fd = open_vmlinux(module); 284 if (!dinfo) {
226 if (fd < 0) {
227 if (need_dwarf) { 285 if (need_dwarf) {
228 pr_warning("Failed to open debuginfo file.\n"); 286 pr_warning("Failed to open debuginfo file.\n");
229 return fd; 287 return -ENOENT;
230 } 288 }
231 pr_debug("Could not open vmlinux. Try to use symbols.\n"); 289 pr_debug("Could not open debuginfo. Try to use symbols.\n");
232 return 0; 290 return 0;
233 } 291 }
234 292
235 /* Searching trace events corresponding to probe event */ 293 /* Searching trace events corresponding to a probe event */
236 ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); 294 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
295
296 debuginfo__delete(dinfo);
237 297
238 if (ntevs > 0) { /* Succeeded to find trace events */ 298 if (ntevs > 0) { /* Succeeded to find trace events */
239 pr_debug("find %d probe_trace_events.\n", ntevs); 299 pr_debug("find %d probe_trace_events.\n", ntevs);
240 return ntevs; 300 if (module)
301 ret = add_module_to_probe_trace_events(*tevs, ntevs,
302 module);
303 return ret < 0 ? ret : ntevs;
241 } 304 }
242 305
243 if (ntevs == 0) { /* No error but failed to find probe point. */ 306 if (ntevs == 0) { /* No error but failed to find probe point. */
@@ -371,8 +434,9 @@ int show_line_range(struct line_range *lr, const char *module)
371{ 434{
372 int l = 1; 435 int l = 1;
373 struct line_node *ln; 436 struct line_node *ln;
437 struct debuginfo *dinfo;
374 FILE *fp; 438 FILE *fp;
375 int fd, ret; 439 int ret;
376 char *tmp; 440 char *tmp;
377 441
378 /* Search a line range */ 442 /* Search a line range */
@@ -380,13 +444,14 @@ int show_line_range(struct line_range *lr, const char *module)
380 if (ret < 0) 444 if (ret < 0)
381 return ret; 445 return ret;
382 446
383 fd = open_vmlinux(module); 447 dinfo = open_debuginfo(module);
384 if (fd < 0) { 448 if (!dinfo) {
385 pr_warning("Failed to open debuginfo file.\n"); 449 pr_warning("Failed to open debuginfo file.\n");
386 return fd; 450 return -ENOENT;
387 } 451 }
388 452
389 ret = find_line_range(fd, lr); 453 ret = debuginfo__find_line_range(dinfo, lr);
454 debuginfo__delete(dinfo);
390 if (ret == 0) { 455 if (ret == 0) {
391 pr_warning("Specified source line is not found.\n"); 456 pr_warning("Specified source line is not found.\n");
392 return -ENOENT; 457 return -ENOENT;
@@ -448,7 +513,8 @@ end:
448 return ret; 513 return ret;
449} 514}
450 515
451static int show_available_vars_at(int fd, struct perf_probe_event *pev, 516static int show_available_vars_at(struct debuginfo *dinfo,
517 struct perf_probe_event *pev,
452 int max_vls, struct strfilter *_filter, 518 int max_vls, struct strfilter *_filter,
453 bool externs) 519 bool externs)
454{ 520{
@@ -463,7 +529,8 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,
463 return -EINVAL; 529 return -EINVAL;
464 pr_debug("Searching variables at %s\n", buf); 530 pr_debug("Searching variables at %s\n", buf);
465 531
466 ret = find_available_vars_at(fd, pev, &vls, max_vls, externs); 532 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
533 max_vls, externs);
467 if (ret <= 0) { 534 if (ret <= 0) {
468 pr_err("Failed to find variables at %s (%d)\n", buf, ret); 535 pr_err("Failed to find variables at %s (%d)\n", buf, ret);
469 goto end; 536 goto end;
@@ -504,24 +571,26 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
504 int max_vls, const char *module, 571 int max_vls, const char *module,
505 struct strfilter *_filter, bool externs) 572 struct strfilter *_filter, bool externs)
506{ 573{
507 int i, fd, ret = 0; 574 int i, ret = 0;
575 struct debuginfo *dinfo;
508 576
509 ret = init_vmlinux(); 577 ret = init_vmlinux();
510 if (ret < 0) 578 if (ret < 0)
511 return ret; 579 return ret;
512 580
581 dinfo = open_debuginfo(module);
582 if (!dinfo) {
583 pr_warning("Failed to open debuginfo file.\n");
584 return -ENOENT;
585 }
586
513 setup_pager(); 587 setup_pager();
514 588
515 for (i = 0; i < npevs && ret >= 0; i++) { 589 for (i = 0; i < npevs && ret >= 0; i++)
516 fd = open_vmlinux(module); 590 ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
517 if (fd < 0) {
518 pr_warning("Failed to open debug information file.\n");
519 ret = fd;
520 break;
521 }
522 ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter,
523 externs); 591 externs);
524 } 592
593 debuginfo__delete(dinfo);
525 return ret; 594 return ret;
526} 595}
527 596
@@ -990,7 +1059,7 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
990 1059
991/* Parse probe_events event into struct probe_point */ 1060/* Parse probe_events event into struct probe_point */
992static int parse_probe_trace_command(const char *cmd, 1061static int parse_probe_trace_command(const char *cmd,
993 struct probe_trace_event *tev) 1062 struct probe_trace_event *tev)
994{ 1063{
995 struct probe_trace_point *tp = &tev->point; 1064 struct probe_trace_point *tp = &tev->point;
996 char pr; 1065 char pr;
@@ -1023,8 +1092,14 @@ static int parse_probe_trace_command(const char *cmd,
1023 1092
1024 tp->retprobe = (pr == 'r'); 1093 tp->retprobe = (pr == 'r');
1025 1094
1026 /* Scan function name and offset */ 1095 /* Scan module name(if there), function name and offset */
1027 ret = sscanf(argv[1], "%a[^+]+%lu", (float *)(void *)&tp->symbol, 1096 p = strchr(argv[1], ':');
1097 if (p) {
1098 tp->module = strndup(argv[1], p - argv[1]);
1099 p++;
1100 } else
1101 p = argv[1];
1102 ret = sscanf(p, "%a[^+]+%lu", (float *)(void *)&tp->symbol,
1028 &tp->offset); 1103 &tp->offset);
1029 if (ret == 1) 1104 if (ret == 1)
1030 tp->offset = 0; 1105 tp->offset = 0;
@@ -1269,9 +1344,10 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
1269 if (buf == NULL) 1344 if (buf == NULL)
1270 return NULL; 1345 return NULL;
1271 1346
1272 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu", 1347 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu",
1273 tp->retprobe ? 'r' : 'p', 1348 tp->retprobe ? 'r' : 'p',
1274 tev->group, tev->event, 1349 tev->group, tev->event,
1350 tp->module ?: "", tp->module ? ":" : "",
1275 tp->symbol, tp->offset); 1351 tp->symbol, tp->offset);
1276 if (len <= 0) 1352 if (len <= 0)
1277 goto error; 1353 goto error;
@@ -1378,6 +1454,8 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
1378 free(tev->group); 1454 free(tev->group);
1379 if (tev->point.symbol) 1455 if (tev->point.symbol)
1380 free(tev->point.symbol); 1456 free(tev->point.symbol);
1457 if (tev->point.module)
1458 free(tev->point.module);
1381 for (i = 0; i < tev->nargs; i++) { 1459 for (i = 0; i < tev->nargs; i++) {
1382 if (tev->args[i].name) 1460 if (tev->args[i].name)
1383 free(tev->args[i].name); 1461 free(tev->args[i].name);
@@ -1729,7 +1807,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1729 /* Convert perf_probe_event with debuginfo */ 1807 /* Convert perf_probe_event with debuginfo */
1730 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module); 1808 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module);
1731 if (ret != 0) 1809 if (ret != 0)
1732 return ret; 1810 return ret; /* Found in debuginfo or got an error */
1733 1811
1734 /* Allocate trace event buffer */ 1812 /* Allocate trace event buffer */
1735 tev = *tevs = zalloc(sizeof(struct probe_trace_event)); 1813 tev = *tevs = zalloc(sizeof(struct probe_trace_event));
@@ -1742,6 +1820,15 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1742 ret = -ENOMEM; 1820 ret = -ENOMEM;
1743 goto error; 1821 goto error;
1744 } 1822 }
1823
1824 if (module) {
1825 tev->point.module = strdup(module);
1826 if (tev->point.module == NULL) {
1827 ret = -ENOMEM;
1828 goto error;
1829 }
1830 }
1831
1745 tev->point.offset = pev->point.offset; 1832 tev->point.offset = pev->point.offset;
1746 tev->point.retprobe = pev->point.retprobe; 1833 tev->point.retprobe = pev->point.retprobe;
1747 tev->nargs = pev->nargs; 1834 tev->nargs = pev->nargs;
@@ -1869,8 +1956,10 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
1869 1956
1870 pr_debug("Writing event: %s\n", buf); 1957 pr_debug("Writing event: %s\n", buf);
1871 ret = write(fd, buf, strlen(buf)); 1958 ret = write(fd, buf, strlen(buf));
1872 if (ret < 0) 1959 if (ret < 0) {
1960 ret = -errno;
1873 goto error; 1961 goto error;
1962 }
1874 1963
1875 printf("Remove event: %s\n", ent->s); 1964 printf("Remove event: %s\n", ent->s);
1876 return 0; 1965 return 0;