diff options
author | Vaibhav Nagarnaik <vnagarnaik@google.com> | 2012-04-05 18:48:00 -0400 |
---|---|---|
committer | Frederic Weisbecker <fweisbec@gmail.com> | 2012-04-25 07:35:28 -0400 |
commit | d69afed55be1016c2bcfcb3e00cd5365d2f557f6 (patch) | |
tree | 1c5dcb6fd48531ea1ee278fbc2a54ec613637472 /tools | |
parent | 54a3625829c9de60f4acbd0efe3ec4201b174fd6 (diff) |
parse-events: Handle invalid opcode parsing gracefully
If an invalid opcode is encountered, trace-cmd exits with an error.
Instead it can be treated as a soft error where the event's print format
is not parsed and its binary data is dumped out.
This patch adds a return value to arg_num_eval() function to indicate if
the parsing was successful. If not, then the error is considered soft
and the parsing of the offending event fails.
Cc: Michael Rubin <mrubin@google.com>
Cc: David Sharp <dhsharp@google.com>
Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
Link: http://lkml.kernel.org/r/1310785241-3799-2-git-send-email-vnagarnaik@google.com
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Arun Sharma <asharma@fb.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/lib/traceevent/event-parse.c | 125 |
1 files changed, 83 insertions, 42 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 16da20c552bc..ef2c65f91677 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c | |||
@@ -1915,90 +1915,120 @@ eval_type(unsigned long long val, struct print_arg *arg, int pointer) | |||
1915 | return eval_type_str(val, arg->typecast.type, pointer); | 1915 | return eval_type_str(val, arg->typecast.type, pointer); |
1916 | } | 1916 | } |
1917 | 1917 | ||
1918 | static long long arg_num_eval(struct print_arg *arg) | 1918 | static int arg_num_eval(struct print_arg *arg, long long *val) |
1919 | { | 1919 | { |
1920 | long long left, right; | 1920 | long long left, right; |
1921 | long long val = 0; | 1921 | int ret = 1; |
1922 | 1922 | ||
1923 | switch (arg->type) { | 1923 | switch (arg->type) { |
1924 | case PRINT_ATOM: | 1924 | case PRINT_ATOM: |
1925 | val = strtoll(arg->atom.atom, NULL, 0); | 1925 | *val = strtoll(arg->atom.atom, NULL, 0); |
1926 | break; | 1926 | break; |
1927 | case PRINT_TYPE: | 1927 | case PRINT_TYPE: |
1928 | val = arg_num_eval(arg->typecast.item); | 1928 | ret = arg_num_eval(arg->typecast.item, val); |
1929 | val = eval_type(val, arg, 0); | 1929 | if (!ret) |
1930 | break; | ||
1931 | *val = eval_type(*val, arg, 0); | ||
1930 | break; | 1932 | break; |
1931 | case PRINT_OP: | 1933 | case PRINT_OP: |
1932 | switch (arg->op.op[0]) { | 1934 | switch (arg->op.op[0]) { |
1933 | case '|': | 1935 | case '|': |
1934 | left = arg_num_eval(arg->op.left); | 1936 | ret = arg_num_eval(arg->op.left, &left); |
1935 | right = arg_num_eval(arg->op.right); | 1937 | if (!ret) |
1938 | break; | ||
1939 | ret = arg_num_eval(arg->op.right, &right); | ||
1940 | if (!ret) | ||
1941 | break; | ||
1936 | if (arg->op.op[1]) | 1942 | if (arg->op.op[1]) |
1937 | val = left || right; | 1943 | *val = left || right; |
1938 | else | 1944 | else |
1939 | val = left | right; | 1945 | *val = left | right; |
1940 | break; | 1946 | break; |
1941 | case '&': | 1947 | case '&': |
1942 | left = arg_num_eval(arg->op.left); | 1948 | ret = arg_num_eval(arg->op.left, &left); |
1943 | right = arg_num_eval(arg->op.right); | 1949 | if (!ret) |
1950 | break; | ||
1951 | ret = arg_num_eval(arg->op.right, &right); | ||
1952 | if (!ret) | ||
1953 | break; | ||
1944 | if (arg->op.op[1]) | 1954 | if (arg->op.op[1]) |
1945 | val = left && right; | 1955 | *val = left && right; |
1946 | else | 1956 | else |
1947 | val = left & right; | 1957 | *val = left & right; |
1948 | break; | 1958 | break; |
1949 | case '<': | 1959 | case '<': |
1950 | left = arg_num_eval(arg->op.left); | 1960 | ret = arg_num_eval(arg->op.left, &left); |
1951 | right = arg_num_eval(arg->op.right); | 1961 | if (!ret) |
1962 | break; | ||
1963 | ret = arg_num_eval(arg->op.right, &right); | ||
1964 | if (!ret) | ||
1965 | break; | ||
1952 | switch (arg->op.op[1]) { | 1966 | switch (arg->op.op[1]) { |
1953 | case 0: | 1967 | case 0: |
1954 | val = left < right; | 1968 | *val = left < right; |
1955 | break; | 1969 | break; |
1956 | case '<': | 1970 | case '<': |
1957 | val = left << right; | 1971 | *val = left << right; |
1958 | break; | 1972 | break; |
1959 | case '=': | 1973 | case '=': |
1960 | val = left <= right; | 1974 | *val = left <= right; |
1961 | break; | 1975 | break; |
1962 | default: | 1976 | default: |
1963 | die("unknown op '%s'", arg->op.op); | 1977 | do_warning("unknown op '%s'", arg->op.op); |
1978 | ret = 0; | ||
1964 | } | 1979 | } |
1965 | break; | 1980 | break; |
1966 | case '>': | 1981 | case '>': |
1967 | left = arg_num_eval(arg->op.left); | 1982 | ret = arg_num_eval(arg->op.left, &left); |
1968 | right = arg_num_eval(arg->op.right); | 1983 | if (!ret) |
1984 | break; | ||
1985 | ret = arg_num_eval(arg->op.right, &right); | ||
1986 | if (!ret) | ||
1987 | break; | ||
1969 | switch (arg->op.op[1]) { | 1988 | switch (arg->op.op[1]) { |
1970 | case 0: | 1989 | case 0: |
1971 | val = left > right; | 1990 | *val = left > right; |
1972 | break; | 1991 | break; |
1973 | case '>': | 1992 | case '>': |
1974 | val = left >> right; | 1993 | *val = left >> right; |
1975 | break; | 1994 | break; |
1976 | case '=': | 1995 | case '=': |
1977 | val = left >= right; | 1996 | *val = left >= right; |
1978 | break; | 1997 | break; |
1979 | default: | 1998 | default: |
1980 | die("unknown op '%s'", arg->op.op); | 1999 | do_warning("unknown op '%s'", arg->op.op); |
2000 | ret = 0; | ||
1981 | } | 2001 | } |
1982 | break; | 2002 | break; |
1983 | case '=': | 2003 | case '=': |
1984 | left = arg_num_eval(arg->op.left); | 2004 | ret = arg_num_eval(arg->op.left, &left); |
1985 | right = arg_num_eval(arg->op.right); | 2005 | if (!ret) |
1986 | 2006 | break; | |
1987 | if (arg->op.op[1] != '=') | 2007 | ret = arg_num_eval(arg->op.right, &right); |
1988 | die("unknown op '%s'", arg->op.op); | 2008 | if (!ret) |
2009 | break; | ||
1989 | 2010 | ||
1990 | val = left == right; | 2011 | if (arg->op.op[1] != '=') { |
2012 | do_warning("unknown op '%s'", arg->op.op); | ||
2013 | ret = 0; | ||
2014 | } else | ||
2015 | *val = left == right; | ||
1991 | break; | 2016 | break; |
1992 | case '!': | 2017 | case '!': |
1993 | left = arg_num_eval(arg->op.left); | 2018 | ret = arg_num_eval(arg->op.left, &left); |
1994 | right = arg_num_eval(arg->op.right); | 2019 | if (!ret) |
2020 | break; | ||
2021 | ret = arg_num_eval(arg->op.right, &right); | ||
2022 | if (!ret) | ||
2023 | break; | ||
1995 | 2024 | ||
1996 | switch (arg->op.op[1]) { | 2025 | switch (arg->op.op[1]) { |
1997 | case '=': | 2026 | case '=': |
1998 | val = left != right; | 2027 | *val = left != right; |
1999 | break; | 2028 | break; |
2000 | default: | 2029 | default: |
2001 | die("unknown op '%s'", arg->op.op); | 2030 | do_warning("unknown op '%s'", arg->op.op); |
2031 | ret = 0; | ||
2002 | } | 2032 | } |
2003 | break; | 2033 | break; |
2004 | case '-': | 2034 | case '-': |
@@ -2006,12 +2036,17 @@ static long long arg_num_eval(struct print_arg *arg) | |||
2006 | if (arg->op.left->type == PRINT_NULL) | 2036 | if (arg->op.left->type == PRINT_NULL) |
2007 | left = 0; | 2037 | left = 0; |
2008 | else | 2038 | else |
2009 | left = arg_num_eval(arg->op.left); | 2039 | ret = arg_num_eval(arg->op.left, &left); |
2010 | right = arg_num_eval(arg->op.right); | 2040 | if (!ret) |
2011 | val = left - right; | 2041 | break; |
2042 | ret = arg_num_eval(arg->op.right, &right); | ||
2043 | if (!ret) | ||
2044 | break; | ||
2045 | *val = left - right; | ||
2012 | break; | 2046 | break; |
2013 | default: | 2047 | default: |
2014 | die("unknown op '%s'", arg->op.op); | 2048 | do_warning("unknown op '%s'", arg->op.op); |
2049 | ret = 0; | ||
2015 | } | 2050 | } |
2016 | break; | 2051 | break; |
2017 | 2052 | ||
@@ -2020,10 +2055,11 @@ static long long arg_num_eval(struct print_arg *arg) | |||
2020 | case PRINT_STRING: | 2055 | case PRINT_STRING: |
2021 | case PRINT_BSTRING: | 2056 | case PRINT_BSTRING: |
2022 | default: | 2057 | default: |
2023 | die("invalid eval type %d", arg->type); | 2058 | do_warning("invalid eval type %d", arg->type); |
2059 | ret = 0; | ||
2024 | 2060 | ||
2025 | } | 2061 | } |
2026 | return val; | 2062 | return ret; |
2027 | } | 2063 | } |
2028 | 2064 | ||
2029 | static char *arg_eval (struct print_arg *arg) | 2065 | static char *arg_eval (struct print_arg *arg) |
@@ -2037,7 +2073,8 @@ static char *arg_eval (struct print_arg *arg) | |||
2037 | case PRINT_TYPE: | 2073 | case PRINT_TYPE: |
2038 | return arg_eval(arg->typecast.item); | 2074 | return arg_eval(arg->typecast.item); |
2039 | case PRINT_OP: | 2075 | case PRINT_OP: |
2040 | val = arg_num_eval(arg); | 2076 | if (!arg_num_eval(arg, &val)) |
2077 | break; | ||
2041 | sprintf(buf, "%lld", val); | 2078 | sprintf(buf, "%lld", val); |
2042 | return buf; | 2079 | return buf; |
2043 | 2080 | ||
@@ -2079,6 +2116,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char ** | |||
2079 | memset(field, 0, sizeof(*field)); | 2116 | memset(field, 0, sizeof(*field)); |
2080 | 2117 | ||
2081 | value = arg_eval(arg); | 2118 | value = arg_eval(arg); |
2119 | if (value == NULL) | ||
2120 | goto out_free; | ||
2082 | field->value = strdup(value); | 2121 | field->value = strdup(value); |
2083 | 2122 | ||
2084 | free_arg(arg); | 2123 | free_arg(arg); |
@@ -2090,6 +2129,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char ** | |||
2090 | goto out_free; | 2129 | goto out_free; |
2091 | 2130 | ||
2092 | value = arg_eval(arg); | 2131 | value = arg_eval(arg); |
2132 | if (value == NULL) | ||
2133 | goto out_free; | ||
2093 | field->str = strdup(value); | 2134 | field->str = strdup(value); |
2094 | free_arg(arg); | 2135 | free_arg(arg); |
2095 | arg = NULL; | 2136 | arg = NULL; |