From a2a99e8e12798706ec1026e5d8fc36f7c86122ce Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 5 Oct 2009 14:26:18 -0300 Subject: perf tools: /proc/modules names don't always match its name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit $ cut -d' ' -f1 /proc/modules|grep _|wc -l 29 $ cut -d' ' -f1 /proc/modules|grep _|sed 's/$/.ko'/g|while read n;do find /lib/modules/`uname -r` -name $n;done|wc -l 12 For instance: $ grep ^aes_x86 /proc/modules aes_x86_64 9056 2 - Live 0xffffffffa0091000 $ l /lib/modules/2.6.31-tip/kernel/arch/x86/crypto/aes-x86_64.ko -rw-r--r-- 1 root root 136438 2009-09-22 19:05 /lib/modules/2.6.31-tip/kernel/arch/x86/crypto/aes-x86_64.ko Handle that by introducing a strxfrchar routine that replaces dashes with underscores when matching file names to loaded modules. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Peter Zijlstra Cc: Mike Galbraith LKML-Reference: Signed-off-by: Ingo Molnar --- tools/perf/util/string.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'tools/perf/util/string.c') diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index c93eca9a7be..04743d3e903 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -1,3 +1,4 @@ +#include #include "string.h" static int hex(char ch) @@ -32,3 +33,13 @@ int hex2u64(const char *ptr, u64 *long_val) return p - ptr; } + +char *strxfrchar(char *s, char from, char to) +{ + char *p = s; + + while ((p = strchr(p, from)) != NULL) + *p++ = to; + + return s; +} -- cgit v1.2.3-70-g09d2 From d2fb8b4151a92223da6a84006f8f248ebeb6677d Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Sun, 15 Nov 2009 20:36:53 +0900 Subject: perf tools: Add new perf_atoll() function to parse string representing size in bytes This patch modifies util/string.[ch] to add new function: perf_atoll() to parse string representing size in bytes. This function parses (\d+)(b|B|kb|KB|mb|MB|gb|GB) (e.g. "256MB") and returns its numeric value. (e.g. 268435456) Signed-off-by: Hitoshi Mitake Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Frederic Weisbecker LKML-Reference: <1258285013-4759-1-git-send-email-mitake@dcl.info.waseda.ac.jp> Signed-off-by: Ingo Molnar --- tools/perf/util/string.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/string.h | 1 + 2 files changed, 85 insertions(+) (limited to 'tools/perf/util/string.c') diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index 04743d3e903..227043577e0 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -1,5 +1,7 @@ #include +#include #include "string.h" +#include "util.h" static int hex(char ch) { @@ -43,3 +45,85 @@ char *strxfrchar(char *s, char from, char to) return s; } + +#define K 1024LL +/* + * perf_atoll() + * Parse (\d+)(b|B|kb|KB|mb|MB|gb|GB|tb|TB) (e.g. "256MB") + * and return its numeric value + */ +s64 perf_atoll(const char *str) +{ + unsigned int i; + s64 length = -1, unit = 1; + + if (!isdigit(str[0])) + goto out_err; + + for (i = 1; i < strlen(str); i++) { + switch (str[i]) { + case 'B': + case 'b': + break; + case 'K': + if (str[i + 1] != 'B') + goto out_err; + else + goto kilo; + case 'k': + if (str[i + 1] != 'b') + goto out_err; +kilo: + unit = K; + break; + case 'M': + if (str[i + 1] != 'B') + goto out_err; + else + goto mega; + case 'm': + if (str[i + 1] != 'b') + goto out_err; +mega: + unit = K * K; + break; + case 'G': + if (str[i + 1] != 'B') + goto out_err; + else + goto giga; + case 'g': + if (str[i + 1] != 'b') + goto out_err; +giga: + unit = K * K * K; + break; + case 'T': + if (str[i + 1] != 'B') + goto out_err; + else + goto tera; + case 't': + if (str[i + 1] != 'b') + goto out_err; +tera: + unit = K * K * K * K; + break; + case '\0': /* only specified figures */ + unit = 1; + break; + default: + if (!isdigit(str[i])) + goto out_err; + break; + } + } + + length = atoll(str) * unit; + goto out; + +out_err: + length = -1; +out: + return length; +} diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h index 2c84bf65ba0..e50b07f8082 100644 --- a/tools/perf/util/string.h +++ b/tools/perf/util/string.h @@ -5,6 +5,7 @@ int hex2u64(const char *ptr, u64 *val); char *strxfrchar(char *s, char from, char to); +s64 perf_atoll(const char *str); #define _STR(x) #x #define STR(x) _STR(x) -- cgit v1.2.3-70-g09d2 From e1c01d61a98703fcc80d15b8068ec36d5a215f7e Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 30 Nov 2009 19:20:05 -0500 Subject: perf probe: Add argv_split() from lib/argv_split.c Add argv_split() ported from lib/argv_split.c to string.c and use it in util/probe-event.c. Signed-off-by: Masami Hiramatsu Cc: systemtap Cc: DLE Cc: Steven Rostedt Cc: Jim Keniston Cc: Ananth N Mavinakayanahalli Cc: Christoph Hellwig Cc: Frank Ch. Eigler Cc: Frederic Weisbecker Cc: Jason Baron Cc: K.Prasad Cc: Peter Zijlstra Cc: Srikar Dronamraju Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker LKML-Reference: <20091201002005.10235.55602.stgit@harusame> Signed-off-by: Ingo Molnar --- tools/perf/util/probe-event.c | 55 +++++++---------------- tools/perf/util/string.c | 101 ++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/string.h | 2 + 3 files changed, 118 insertions(+), 40 deletions(-) (limited to 'tools/perf/util/string.c') diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 7335a3b5e49..e3a683ab976 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -32,6 +32,7 @@ #undef _GNU_SOURCE #include "event.h" +#include "string.h" #include "debug.h" #include "parse-events.h" /* For debugfs_path */ #include "probe-event.h" @@ -132,62 +133,36 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) /* Parse perf-probe event definition */ int parse_perf_probe_event(const char *str, struct probe_point *pp) { - char *argv[MAX_PROBE_ARGS + 1]; /* probe + args */ + char **argv; int argc, i, need_dwarf = 0; - /* Separate arguments, similar to argv_split */ - argc = 0; - do { - /* Skip separators */ - while (isspace(*str)) - str++; - - /* Add an argument */ - if (*str != '\0') { - const char *s = str; - /* Check the limit number of arguments */ - if (argc == MAX_PROBE_ARGS + 1) - semantic_error("Too many arguments"); - - /* Skip the argument */ - while (!isspace(*str) && *str != '\0') - str++; - - /* Duplicate the argument */ - argv[argc] = strndup(s, str - s); - if (argv[argc] == NULL) - die("strndup"); - pr_debug("argv[%d]=%s\n", argc, argv[argc]); - argc++; - } - } while (*str != '\0'); - if (!argc) - semantic_error("An empty argument."); + argv = argv_split(str, &argc); + if (!argv) + die("argv_split failed."); + if (argc > MAX_PROBE_ARGS + 1) + semantic_error("Too many arguments"); /* Parse probe point */ parse_perf_probe_probepoint(argv[0], pp); - free(argv[0]); if (pp->file || pp->line) need_dwarf = 1; - /* Copy arguments */ + /* Copy arguments and ensure return probe has no C argument */ pp->nr_args = argc - 1; - if (pp->nr_args > 0) { - pp->args = (char **)malloc(sizeof(char *) * pp->nr_args); - if (!pp->args) - die("malloc"); - memcpy(pp->args, &argv[1], sizeof(char *) * pp->nr_args); - } - - /* Ensure return probe has no C argument */ - for (i = 0; i < pp->nr_args; i++) + pp->args = zalloc(sizeof(char *) * pp->nr_args); + for (i = 0; i < pp->nr_args; i++) { + pp->args[i] = strdup(argv[i + 1]); + if (!pp->args[i]) + die("Failed to copy argument."); if (is_c_varname(pp->args[i])) { if (pp->retprobe) semantic_error("You can't specify local" " variable for kretprobe"); need_dwarf = 1; } + } + argv_free(argv); return need_dwarf; } diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index 227043577e0..0977cf43178 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -127,3 +127,104 @@ out_err: out: return length; } + +/* + * Helper function for splitting a string into an argv-like array. + * originaly copied from lib/argv_split.c + */ +static const char *skip_sep(const char *cp) +{ + while (*cp && isspace(*cp)) + cp++; + + return cp; +} + +static const char *skip_arg(const char *cp) +{ + while (*cp && !isspace(*cp)) + cp++; + + return cp; +} + +static int count_argc(const char *str) +{ + int count = 0; + + while (*str) { + str = skip_sep(str); + if (*str) { + count++; + str = skip_arg(str); + } + } + + return count; +} + +/** + * argv_free - free an argv + * @argv - the argument vector to be freed + * + * Frees an argv and the strings it points to. + */ +void argv_free(char **argv) +{ + char **p; + for (p = argv; *p; p++) + free(*p); + + free(argv); +} + +/** + * argv_split - split a string at whitespace, returning an argv + * @str: the string to be split + * @argcp: returned argument count + * + * Returns an array of pointers to strings which are split out from + * @str. This is performed by strictly splitting on white-space; no + * quote processing is performed. Multiple whitespace characters are + * considered to be a single argument separator. The returned array + * is always NULL-terminated. Returns NULL on memory allocation + * failure. + */ +char **argv_split(const char *str, int *argcp) +{ + int argc = count_argc(str); + char **argv = zalloc(sizeof(*argv) * (argc+1)); + char **argvp; + + if (argv == NULL) + goto out; + + if (argcp) + *argcp = argc; + + argvp = argv; + + while (*str) { + str = skip_sep(str); + + if (*str) { + const char *p = str; + char *t; + + str = skip_arg(str); + + t = strndup(p, str-p); + if (t == NULL) + goto fail; + *argvp++ = t; + } + } + *argvp = NULL; + +out: + return argv; + +fail: + argv_free(argv); + return NULL; +} diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h index e50b07f8082..bfecec265a1 100644 --- a/tools/perf/util/string.h +++ b/tools/perf/util/string.h @@ -6,6 +6,8 @@ int hex2u64(const char *ptr, u64 *val); char *strxfrchar(char *s, char from, char to); s64 perf_atoll(const char *str); +char **argv_split(const char *str, int *argcp); +void argv_free(char **argv); #define _STR(x) #x #define STR(x) _STR(x) -- cgit v1.2.3-70-g09d2 From c19e33aa840e9202ef8d4c93056b59f3edc2208d Mon Sep 17 00:00:00 2001 From: Liming Wang Date: Wed, 2 Dec 2009 14:11:46 +0800 Subject: perf tools: Fix _GNU_SOURCE macro related strndup() build error strndup is a GNU extension. So dont include string.h without defining _GNU_SOURCE (it results in a compile error otherwise). Remove these includes as util.h does it already. Signed-off-by: Liming Wang Acked-by: Frederic Weisbecker Acked-by: Xiao Guangrong Cc: peterz@infradead.org Cc: mhiramat@redhat.com LKML-Reference: <1259734306-26323-1-git-send-email-liming.wang@windriver.com> Signed-off-by: Ingo Molnar --- tools/perf/util/string.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'tools/perf/util/string.c') diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index 0977cf43178..f24a8cc933d 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -1,5 +1,3 @@ -#include -#include #include "string.h" #include "util.h" -- cgit v1.2.3-70-g09d2