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.c111
1 files changed, 63 insertions, 48 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index a4ee6b4a840f..a8a9b6cd93a8 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -72,6 +72,7 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)
72static char *synthesize_perf_probe_point(struct perf_probe_point *pp); 72static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
73static int convert_name_to_addr(struct perf_probe_event *pev, 73static int convert_name_to_addr(struct perf_probe_event *pev,
74 const char *exec); 74 const char *exec);
75static void clear_probe_trace_event(struct probe_trace_event *tev);
75static struct machine machine; 76static struct machine machine;
76 77
77/* Initialize symbol maps and path of vmlinux/modules */ 78/* Initialize symbol maps and path of vmlinux/modules */
@@ -172,54 +173,6 @@ const char *kernel_get_module_path(const char *module)
172 return (dso) ? dso->long_name : NULL; 173 return (dso) ? dso->long_name : NULL;
173} 174}
174 175
175#ifdef HAVE_DWARF_SUPPORT
176/* Copied from unwind.c */
177static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
178 GElf_Shdr *shp, const char *name)
179{
180 Elf_Scn *sec = NULL;
181
182 while ((sec = elf_nextscn(elf, sec)) != NULL) {
183 char *str;
184
185 gelf_getshdr(sec, shp);
186 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
187 if (!strcmp(name, str))
188 break;
189 }
190
191 return sec;
192}
193
194static int get_text_start_address(const char *exec, unsigned long *address)
195{
196 Elf *elf;
197 GElf_Ehdr ehdr;
198 GElf_Shdr shdr;
199 int fd, ret = -ENOENT;
200
201 fd = open(exec, O_RDONLY);
202 if (fd < 0)
203 return -errno;
204
205 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
206 if (elf == NULL)
207 return -EINVAL;
208
209 if (gelf_getehdr(elf, &ehdr) == NULL)
210 goto out;
211
212 if (!elf_section_by_name(elf, &ehdr, &shdr, ".text"))
213 goto out;
214
215 *address = shdr.sh_addr - shdr.sh_offset;
216 ret = 0;
217out:
218 elf_end(elf);
219 return ret;
220}
221#endif
222
223static int init_user_exec(void) 176static int init_user_exec(void)
224{ 177{
225 int ret = 0; 178 int ret = 0;
@@ -340,6 +293,34 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
340 return 0; 293 return 0;
341} 294}
342 295
296static int get_text_start_address(const char *exec, unsigned long *address)
297{
298 Elf *elf;
299 GElf_Ehdr ehdr;
300 GElf_Shdr shdr;
301 int fd, ret = -ENOENT;
302
303 fd = open(exec, O_RDONLY);
304 if (fd < 0)
305 return -errno;
306
307 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
308 if (elf == NULL)
309 return -EINVAL;
310
311 if (gelf_getehdr(elf, &ehdr) == NULL)
312 goto out;
313
314 if (!elf_section_by_name(elf, &ehdr, &shdr, ".text", NULL))
315 goto out;
316
317 *address = shdr.sh_addr - shdr.sh_offset;
318 ret = 0;
319out:
320 elf_end(elf);
321 return ret;
322}
323
343static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, 324static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
344 int ntevs, const char *exec) 325 int ntevs, const char *exec)
345{ 326{
@@ -407,6 +388,14 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
407 return ret; 388 return ret;
408} 389}
409 390
391static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
392{
393 int i;
394
395 for (i = 0; i < ntevs; i++)
396 clear_probe_trace_event(tevs + i);
397}
398
410/* Try to find perf_probe_event with debuginfo */ 399/* Try to find perf_probe_event with debuginfo */
411static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 400static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
412 struct probe_trace_event **tevs, 401 struct probe_trace_event **tevs,
@@ -442,6 +431,10 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
442 ret = add_module_to_probe_trace_events(*tevs, 431 ret = add_module_to_probe_trace_events(*tevs,
443 ntevs, target); 432 ntevs, target);
444 } 433 }
434 if (ret < 0) {
435 clear_probe_trace_events(*tevs, ntevs);
436 zfree(tevs);
437 }
445 return ret < 0 ? ret : ntevs; 438 return ret < 0 ? ret : ntevs;
446 } 439 }
447 440
@@ -781,6 +774,28 @@ int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
781} 774}
782#endif 775#endif
783 776
777void line_range__clear(struct line_range *lr)
778{
779 struct line_node *ln;
780
781 free(lr->function);
782 free(lr->file);
783 free(lr->path);
784 free(lr->comp_dir);
785 while (!list_empty(&lr->line_list)) {
786 ln = list_first_entry(&lr->line_list, struct line_node, list);
787 list_del(&ln->list);
788 free(ln);
789 }
790 memset(lr, 0, sizeof(*lr));
791}
792
793void line_range__init(struct line_range *lr)
794{
795 memset(lr, 0, sizeof(*lr));
796 INIT_LIST_HEAD(&lr->line_list);
797}
798
784static int parse_line_num(char **ptr, int *val, const char *what) 799static int parse_line_num(char **ptr, int *val, const char *what)
785{ 800{
786 const char *start = *ptr; 801 const char *start = *ptr;