diff options
author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2014-01-16 04:39:47 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2014-01-16 14:29:02 -0500 |
commit | e53b00d382f4d8f55bcae301f49863c469fdff65 (patch) | |
tree | 7dab9ad69098d2c33aba7f065fc6f540e4fa7b1c /tools | |
parent | 981d05adf2e2acc328abb929a6ed3536c0d41c5f (diff) |
perf probe: Release all dynamically allocated parameters
To fix a memory leak, release all dynamically allocated
options/parameters in params data structure. This also
introduces/exports some init/clear routines.
Reported-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: "David A. Long" <dave.long@linaro.org>
Cc: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: yrl.pp-manager.tt@hitachi.com
Link: http://lkml.kernel.org/r/20140116093947.24403.80118.stgit@kbuild-fedora.novalocal
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-probe.c | 48 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 22 | ||||
-rw-r--r-- | tools/perf/util/probe-event.h | 6 |
3 files changed, 71 insertions, 5 deletions
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 43ff33d0007b..78948882e3de 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -59,7 +59,7 @@ static struct { | |||
59 | struct perf_probe_event events[MAX_PROBES]; | 59 | struct perf_probe_event events[MAX_PROBES]; |
60 | struct strlist *dellist; | 60 | struct strlist *dellist; |
61 | struct line_range line_range; | 61 | struct line_range line_range; |
62 | const char *target; | 62 | char *target; |
63 | int max_probe_points; | 63 | int max_probe_points; |
64 | struct strfilter *filter; | 64 | struct strfilter *filter; |
65 | } params; | 65 | } params; |
@@ -98,7 +98,10 @@ static int set_target(const char *ptr) | |||
98 | * short module name. | 98 | * short module name. |
99 | */ | 99 | */ |
100 | if (!params.target && ptr && *ptr == '/') { | 100 | if (!params.target && ptr && *ptr == '/') { |
101 | params.target = ptr; | 101 | params.target = strdup(ptr); |
102 | if (!params.target) | ||
103 | return -ENOMEM; | ||
104 | |||
102 | found = 1; | 105 | found = 1; |
103 | buf = ptr + (strlen(ptr) - 3); | 106 | buf = ptr + (strlen(ptr) - 3); |
104 | 107 | ||
@@ -116,6 +119,9 @@ static int parse_probe_event_argv(int argc, const char **argv) | |||
116 | char *buf; | 119 | char *buf; |
117 | 120 | ||
118 | found_target = set_target(argv[0]); | 121 | found_target = set_target(argv[0]); |
122 | if (found_target < 0) | ||
123 | return found_target; | ||
124 | |||
119 | if (found_target && argc == 1) | 125 | if (found_target && argc == 1) |
120 | return 0; | 126 | return 0; |
121 | 127 | ||
@@ -217,7 +223,6 @@ static int opt_show_lines(const struct option *opt __maybe_unused, | |||
217 | 223 | ||
218 | params.show_lines = true; | 224 | params.show_lines = true; |
219 | ret = parse_line_range_desc(str, ¶ms.line_range); | 225 | ret = parse_line_range_desc(str, ¶ms.line_range); |
220 | INIT_LIST_HEAD(¶ms.line_range.line_list); | ||
221 | 226 | ||
222 | return ret; | 227 | return ret; |
223 | } | 228 | } |
@@ -263,7 +268,28 @@ static int opt_set_filter(const struct option *opt __maybe_unused, | |||
263 | return 0; | 268 | return 0; |
264 | } | 269 | } |
265 | 270 | ||
266 | int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | 271 | static void init_params(void) |
272 | { | ||
273 | line_range__init(¶ms.line_range); | ||
274 | } | ||
275 | |||
276 | static void cleanup_params(void) | ||
277 | { | ||
278 | int i; | ||
279 | |||
280 | for (i = 0; i < params.nevents; i++) | ||
281 | clear_perf_probe_event(params.events + i); | ||
282 | if (params.dellist) | ||
283 | strlist__delete(params.dellist); | ||
284 | line_range__clear(¶ms.line_range); | ||
285 | free(params.target); | ||
286 | if (params.filter) | ||
287 | strfilter__delete(params.filter); | ||
288 | memset(¶ms, 0, sizeof(params)); | ||
289 | } | ||
290 | |||
291 | static int | ||
292 | __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | ||
267 | { | 293 | { |
268 | const char * const probe_usage[] = { | 294 | const char * const probe_usage[] = { |
269 | "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", | 295 | "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", |
@@ -417,6 +443,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
417 | ret = show_available_funcs(params.target, params.filter, | 443 | ret = show_available_funcs(params.target, params.filter, |
418 | params.uprobes); | 444 | params.uprobes); |
419 | strfilter__delete(params.filter); | 445 | strfilter__delete(params.filter); |
446 | params.filter = NULL; | ||
420 | if (ret < 0) | 447 | if (ret < 0) |
421 | pr_err(" Error: Failed to show functions." | 448 | pr_err(" Error: Failed to show functions." |
422 | " (%d)\n", ret); | 449 | " (%d)\n", ret); |
@@ -456,6 +483,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
456 | params.filter, | 483 | params.filter, |
457 | params.show_ext_vars); | 484 | params.show_ext_vars); |
458 | strfilter__delete(params.filter); | 485 | strfilter__delete(params.filter); |
486 | params.filter = NULL; | ||
459 | if (ret < 0) | 487 | if (ret < 0) |
460 | pr_err(" Error: Failed to show vars. (%d)\n", ret); | 488 | pr_err(" Error: Failed to show vars. (%d)\n", ret); |
461 | return ret; | 489 | return ret; |
@@ -464,7 +492,6 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
464 | 492 | ||
465 | if (params.dellist) { | 493 | if (params.dellist) { |
466 | ret = del_perf_probe_events(params.dellist); | 494 | ret = del_perf_probe_events(params.dellist); |
467 | strlist__delete(params.dellist); | ||
468 | if (ret < 0) { | 495 | if (ret < 0) { |
469 | pr_err(" Error: Failed to delete events. (%d)\n", ret); | 496 | pr_err(" Error: Failed to delete events. (%d)\n", ret); |
470 | return ret; | 497 | return ret; |
@@ -483,3 +510,14 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
483 | } | 510 | } |
484 | return 0; | 511 | return 0; |
485 | } | 512 | } |
513 | |||
514 | int cmd_probe(int argc, const char **argv, const char *prefix) | ||
515 | { | ||
516 | int ret; | ||
517 | |||
518 | init_params(); | ||
519 | ret = __cmd_probe(argc, argv, prefix); | ||
520 | cleanup_params(); | ||
521 | |||
522 | return ret; | ||
523 | } | ||
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 579b655c0f93..c68711c50f47 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -794,6 +794,28 @@ int show_available_vars(struct perf_probe_event *pevs __maybe_unused, | |||
794 | } | 794 | } |
795 | #endif | 795 | #endif |
796 | 796 | ||
797 | void line_range__clear(struct line_range *lr) | ||
798 | { | ||
799 | struct line_node *ln; | ||
800 | |||
801 | free(lr->function); | ||
802 | free(lr->file); | ||
803 | free(lr->path); | ||
804 | free(lr->comp_dir); | ||
805 | while (!list_empty(&lr->line_list)) { | ||
806 | ln = list_first_entry(&lr->line_list, struct line_node, list); | ||
807 | list_del(&ln->list); | ||
808 | free(ln); | ||
809 | } | ||
810 | memset(lr, 0, sizeof(*lr)); | ||
811 | } | ||
812 | |||
813 | void line_range__init(struct line_range *lr) | ||
814 | { | ||
815 | memset(lr, 0, sizeof(*lr)); | ||
816 | INIT_LIST_HEAD(&lr->line_list); | ||
817 | } | ||
818 | |||
797 | static int parse_line_num(char **ptr, int *val, const char *what) | 819 | static int parse_line_num(char **ptr, int *val, const char *what) |
798 | { | 820 | { |
799 | const char *start = *ptr; | 821 | const char *start = *ptr; |
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index d481c46e0796..fcaf7273e85a 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h | |||
@@ -120,6 +120,12 @@ extern void clear_perf_probe_event(struct perf_probe_event *pev); | |||
120 | /* Command string to line-range */ | 120 | /* Command string to line-range */ |
121 | extern int parse_line_range_desc(const char *cmd, struct line_range *lr); | 121 | extern int parse_line_range_desc(const char *cmd, struct line_range *lr); |
122 | 122 | ||
123 | /* Release line range members */ | ||
124 | extern void line_range__clear(struct line_range *lr); | ||
125 | |||
126 | /* Initialize line range */ | ||
127 | extern void line_range__init(struct line_range *lr); | ||
128 | |||
123 | /* Internal use: Return kernel/module path */ | 129 | /* Internal use: Return kernel/module path */ |
124 | extern const char *kernel_get_module_path(const char *module); | 130 | extern const char *kernel_get_module_path(const char *module); |
125 | 131 | ||