diff options
Diffstat (limited to 'tools/perf/util/probe-event.c')
-rw-r--r-- | tools/perf/util/probe-event.c | 111 |
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, ...) | |||
72 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp); | 72 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp); |
73 | static int convert_name_to_addr(struct perf_probe_event *pev, | 73 | static int convert_name_to_addr(struct perf_probe_event *pev, |
74 | const char *exec); | 74 | const char *exec); |
75 | static void clear_probe_trace_event(struct probe_trace_event *tev); | ||
75 | static struct machine machine; | 76 | static 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 */ | ||
177 | static 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 | |||
194 | static 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; | ||
217 | out: | ||
218 | elf_end(elf); | ||
219 | return ret; | ||
220 | } | ||
221 | #endif | ||
222 | |||
223 | static int init_user_exec(void) | 176 | static 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 | ||
296 | static 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; | ||
319 | out: | ||
320 | elf_end(elf); | ||
321 | return ret; | ||
322 | } | ||
323 | |||
343 | static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, | 324 | static 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 | ||
391 | static 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 */ |
411 | static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | 400 | static 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 | ||
777 | void 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 | |||
793 | void line_range__init(struct line_range *lr) | ||
794 | { | ||
795 | memset(lr, 0, sizeof(*lr)); | ||
796 | INIT_LIST_HEAD(&lr->line_list); | ||
797 | } | ||
798 | |||
784 | static int parse_line_num(char **ptr, int *val, const char *what) | 799 | static int parse_line_num(char **ptr, int *val, const char *what) |
785 | { | 800 | { |
786 | const char *start = *ptr; | 801 | const char *start = *ptr; |