diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-01-19 16:09:01 +0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-01-19 16:09:01 +0400 |
commit | 45e6af06367e7b2eb8dc49671092462d8f8a5f47 (patch) | |
tree | 68187bf0c9d8a1eb653d230dbd0d38ffd0046a27 /tools/perf/util/probe-event.c | |
parent | 3e7e09dbd1080de5dcf10092830e39bc2e2932ec (diff) | |
parent | 2a29190c040c0b11e39197c67abf6f87e0a61f9a (diff) | |
download | linux-45e6af06367e7b2eb8dc49671092462d8f8a5f47.tar.xz |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf improvements and fixes from Arnaldo Carvalho de Melo:
Infrastructure changes:
* Improve callchain processing by removing unnecessary work. (Frederic Weisbecker)
* Fix comm override error handling (Frederic Weisbecker)
* Improve 'perf probe' exit path, release resources (Masami Hiramatsu)
* Improve libtraceevent plugins exit path, allowing the registering of
an unregister handler to be called at exit time (Namhyung Kim)
* Add an alias to the build test makefile (make -C tools/perf build-test)
(Namhyung Kim)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
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, ...) static char *synthesize_perf_probe_point(struct perf_probe_point *pp); static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec); +static void clear_probe_trace_event(struct probe_trace_event *tev); static struct machine machine; /* Initialize symbol maps and path of vmlinux/modules */ @@ -172,54 +173,6 @@ const char *kernel_get_module_path(const char *module) return (dso) ? dso->long_name : NULL; } -#ifdef HAVE_DWARF_SUPPORT -/* Copied from unwind.c */ -static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, - GElf_Shdr *shp, const char *name) -{ - Elf_Scn *sec = NULL; - - while ((sec = elf_nextscn(elf, sec)) != NULL) { - char *str; - - gelf_getshdr(sec, shp); - str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); - if (!strcmp(name, str)) - break; - } - - return sec; -} - -static int get_text_start_address(const char *exec, unsigned long *address) -{ - Elf *elf; - GElf_Ehdr ehdr; - GElf_Shdr shdr; - int fd, ret = -ENOENT; - - fd = open(exec, O_RDONLY); - if (fd < 0) - return -errno; - - elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); - if (elf == NULL) - return -EINVAL; - - if (gelf_getehdr(elf, &ehdr) == NULL) - goto out; - - if (!elf_section_by_name(elf, &ehdr, &shdr, ".text")) - goto out; - - *address = shdr.sh_addr - shdr.sh_offset; - ret = 0; -out: - elf_end(elf); - return ret; -} -#endif - static int init_user_exec(void) { int ret = 0; @@ -340,6 +293,34 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, return 0; } +static int get_text_start_address(const char *exec, unsigned long *address) +{ + Elf *elf; + GElf_Ehdr ehdr; + GElf_Shdr shdr; + int fd, ret = -ENOENT; + + fd = open(exec, O_RDONLY); + if (fd < 0) + return -errno; + + elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); + if (elf == NULL) + return -EINVAL; + + if (gelf_getehdr(elf, &ehdr) == NULL) + goto out; + + if (!elf_section_by_name(elf, &ehdr, &shdr, ".text", NULL)) + goto out; + + *address = shdr.sh_addr - shdr.sh_offset; + ret = 0; +out: + elf_end(elf); + return ret; +} + static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, int ntevs, const char *exec) { @@ -407,6 +388,14 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, return ret; } +static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs) +{ + int i; + + for (i = 0; i < ntevs; i++) + clear_probe_trace_event(tevs + i); +} + /* Try to find perf_probe_event with debuginfo */ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, struct probe_trace_event **tevs, @@ -442,6 +431,10 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, ret = add_module_to_probe_trace_events(*tevs, ntevs, target); } + if (ret < 0) { + clear_probe_trace_events(*tevs, ntevs); + zfree(tevs); + } return ret < 0 ? ret : ntevs; } @@ -781,6 +774,28 @@ int show_available_vars(struct perf_probe_event *pevs __maybe_unused, } #endif +void line_range__clear(struct line_range *lr) +{ + struct line_node *ln; + + free(lr->function); + free(lr->file); + free(lr->path); + free(lr->comp_dir); + while (!list_empty(&lr->line_list)) { + ln = list_first_entry(&lr->line_list, struct line_node, list); + list_del(&ln->list); + free(ln); + } + memset(lr, 0, sizeof(*lr)); +} + +void line_range__init(struct line_range *lr) +{ + memset(lr, 0, sizeof(*lr)); + INIT_LIST_HEAD(&lr->line_list); +} + static int parse_line_num(char **ptr, int *val, const char *what) { const char *start = *ptr; |