aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/util/probe-event.c55
-rw-r--r--tools/perf/util/string.c101
-rw-r--r--tools/perf/util/string.h2
3 files changed, 118 insertions, 40 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 7335a3b5e494..e3a683ab976f 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -32,6 +32,7 @@
32 32
33#undef _GNU_SOURCE 33#undef _GNU_SOURCE
34#include "event.h" 34#include "event.h"
35#include "string.h"
35#include "debug.h" 36#include "debug.h"
36#include "parse-events.h" /* For debugfs_path */ 37#include "parse-events.h" /* For debugfs_path */
37#include "probe-event.h" 38#include "probe-event.h"
@@ -132,62 +133,36 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
132/* Parse perf-probe event definition */ 133/* Parse perf-probe event definition */
133int parse_perf_probe_event(const char *str, struct probe_point *pp) 134int parse_perf_probe_event(const char *str, struct probe_point *pp)
134{ 135{
135 char *argv[MAX_PROBE_ARGS + 1]; /* probe + args */ 136 char **argv;
136 int argc, i, need_dwarf = 0; 137 int argc, i, need_dwarf = 0;
137 138
138 /* Separate arguments, similar to argv_split */ 139 argv = argv_split(str, &argc);
139 argc = 0; 140 if (!argv)
140 do { 141 die("argv_split failed.");
141 /* Skip separators */ 142 if (argc > MAX_PROBE_ARGS + 1)
142 while (isspace(*str)) 143 semantic_error("Too many arguments");
143 str++;
144
145 /* Add an argument */
146 if (*str != '\0') {
147 const char *s = str;
148 /* Check the limit number of arguments */
149 if (argc == MAX_PROBE_ARGS + 1)
150 semantic_error("Too many arguments");
151
152 /* Skip the argument */
153 while (!isspace(*str) && *str != '\0')
154 str++;
155
156 /* Duplicate the argument */
157 argv[argc] = strndup(s, str - s);
158 if (argv[argc] == NULL)
159 die("strndup");
160 pr_debug("argv[%d]=%s\n", argc, argv[argc]);
161 argc++;
162 }
163 } while (*str != '\0');
164 if (!argc)
165 semantic_error("An empty argument.");
166 144
167 /* Parse probe point */ 145 /* Parse probe point */
168 parse_perf_probe_probepoint(argv[0], pp); 146 parse_perf_probe_probepoint(argv[0], pp);
169 free(argv[0]);
170 if (pp->file || pp->line) 147 if (pp->file || pp->line)
171 need_dwarf = 1; 148 need_dwarf = 1;
172 149
173 /* Copy arguments */ 150 /* Copy arguments and ensure return probe has no C argument */
174 pp->nr_args = argc - 1; 151 pp->nr_args = argc - 1;
175 if (pp->nr_args > 0) { 152 pp->args = zalloc(sizeof(char *) * pp->nr_args);
176 pp->args = (char **)malloc(sizeof(char *) * pp->nr_args); 153 for (i = 0; i < pp->nr_args; i++) {
177 if (!pp->args) 154 pp->args[i] = strdup(argv[i + 1]);
178 die("malloc"); 155 if (!pp->args[i])
179 memcpy(pp->args, &argv[1], sizeof(char *) * pp->nr_args); 156 die("Failed to copy argument.");
180 }
181
182 /* Ensure return probe has no C argument */
183 for (i = 0; i < pp->nr_args; i++)
184 if (is_c_varname(pp->args[i])) { 157 if (is_c_varname(pp->args[i])) {
185 if (pp->retprobe) 158 if (pp->retprobe)
186 semantic_error("You can't specify local" 159 semantic_error("You can't specify local"
187 " variable for kretprobe"); 160 " variable for kretprobe");
188 need_dwarf = 1; 161 need_dwarf = 1;
189 } 162 }
163 }
190 164
165 argv_free(argv);
191 return need_dwarf; 166 return need_dwarf;
192} 167}
193 168
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index 227043577e06..0977cf431789 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -127,3 +127,104 @@ out_err:
127out: 127out:
128 return length; 128 return length;
129} 129}
130
131/*
132 * Helper function for splitting a string into an argv-like array.
133 * originaly copied from lib/argv_split.c
134 */
135static const char *skip_sep(const char *cp)
136{
137 while (*cp && isspace(*cp))
138 cp++;
139
140 return cp;
141}
142
143static const char *skip_arg(const char *cp)
144{
145 while (*cp && !isspace(*cp))
146 cp++;
147
148 return cp;
149}
150
151static int count_argc(const char *str)
152{
153 int count = 0;
154
155 while (*str) {
156 str = skip_sep(str);
157 if (*str) {
158 count++;
159 str = skip_arg(str);
160 }
161 }
162
163 return count;
164}
165
166/**
167 * argv_free - free an argv
168 * @argv - the argument vector to be freed
169 *
170 * Frees an argv and the strings it points to.
171 */
172void argv_free(char **argv)
173{
174 char **p;
175 for (p = argv; *p; p++)
176 free(*p);
177
178 free(argv);
179}
180
181/**
182 * argv_split - split a string at whitespace, returning an argv
183 * @str: the string to be split
184 * @argcp: returned argument count
185 *
186 * Returns an array of pointers to strings which are split out from
187 * @str. This is performed by strictly splitting on white-space; no
188 * quote processing is performed. Multiple whitespace characters are
189 * considered to be a single argument separator. The returned array
190 * is always NULL-terminated. Returns NULL on memory allocation
191 * failure.
192 */
193char **argv_split(const char *str, int *argcp)
194{
195 int argc = count_argc(str);
196 char **argv = zalloc(sizeof(*argv) * (argc+1));
197 char **argvp;
198
199 if (argv == NULL)
200 goto out;
201
202 if (argcp)
203 *argcp = argc;
204
205 argvp = argv;
206
207 while (*str) {
208 str = skip_sep(str);
209
210 if (*str) {
211 const char *p = str;
212 char *t;
213
214 str = skip_arg(str);
215
216 t = strndup(p, str-p);
217 if (t == NULL)
218 goto fail;
219 *argvp++ = t;
220 }
221 }
222 *argvp = NULL;
223
224out:
225 return argv;
226
227fail:
228 argv_free(argv);
229 return NULL;
230}
diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h
index e50b07f80827..bfecec265a1a 100644
--- a/tools/perf/util/string.h
+++ b/tools/perf/util/string.h
@@ -6,6 +6,8 @@
6int hex2u64(const char *ptr, u64 *val); 6int hex2u64(const char *ptr, u64 *val);
7char *strxfrchar(char *s, char from, char to); 7char *strxfrchar(char *s, char from, char to);
8s64 perf_atoll(const char *str); 8s64 perf_atoll(const char *str);
9char **argv_split(const char *str, int *argcp);
10void argv_free(char **argv);
9 11
10#define _STR(x) #x 12#define _STR(x) #x
11#define STR(x) _STR(x) 13#define STR(x) _STR(x)