diff options
author | Vaibhav Nagarnaik <vnagarnaik@google.com> | 2011-07-15 23:00:39 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2011-07-29 12:43:19 -0400 |
commit | b33c8d01da95d1abdfb966eb7f91f2f0a58d8329 (patch) | |
tree | 38ca53105a867ef8ef280f535958ace77c0631d0 | |
parent | ba911ea7fc1fdd13e3bce1b2001f5b432df8edae (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>
-rw-r--r-- | parse-events.c | 125 |
1 files changed, 83 insertions, 42 deletions
diff --git a/parse-events.c b/parse-events.c index d8f322a..58ffe51 100644 --- a/parse-events.c +++ b/parse-events.c | |||
@@ -1901,90 +1901,120 @@ eval_type(unsigned long long val, struct print_arg *arg, int pointer) | |||
1901 | return eval_type_str(val, arg->typecast.type, pointer); | 1901 | return eval_type_str(val, arg->typecast.type, pointer); |
1902 | } | 1902 | } |
1903 | 1903 | ||
1904 | static long long arg_num_eval(struct print_arg *arg) | 1904 | static int arg_num_eval(struct print_arg *arg, long long *val) |
1905 | { | 1905 | { |
1906 | long long left, right; | 1906 | long long left, right; |
1907 | long long val = 0; | 1907 | int ret = 1; |
1908 | 1908 | ||
1909 | switch (arg->type) { | 1909 | switch (arg->type) { |
1910 | case PRINT_ATOM: | 1910 | case PRINT_ATOM: |
1911 | val = strtoll(arg->atom.atom, NULL, 0); | 1911 | *val = strtoll(arg->atom.atom, NULL, 0); |
1912 | break; | 1912 | break; |
1913 | case PRINT_TYPE: | 1913 | case PRINT_TYPE: |
1914 | val = arg_num_eval(arg->typecast.item); | 1914 | ret = arg_num_eval(arg->typecast.item, val); |
1915 | val = eval_type(val, arg, 0); | 1915 | if (!ret) |
1916 | break; | ||
1917 | *val = eval_type(*val, arg, 0); | ||
1916 | break; | 1918 | break; |
1917 | case PRINT_OP: | 1919 | case PRINT_OP: |
1918 | switch (arg->op.op[0]) { | 1920 | switch (arg->op.op[0]) { |
1919 | case '|': | 1921 | case '|': |
1920 | left = arg_num_eval(arg->op.left); | 1922 | ret = arg_num_eval(arg->op.left, &left); |
1921 | right = arg_num_eval(arg->op.right); | 1923 | if (!ret) |
1924 | break; | ||
1925 | ret = arg_num_eval(arg->op.right, &right); | ||
1926 | if (!ret) | ||
1927 | break; | ||
1922 | if (arg->op.op[1]) | 1928 | if (arg->op.op[1]) |
1923 | val = left || right; | 1929 | *val = left || right; |
1924 | else | 1930 | else |
1925 | val = left | right; | 1931 | *val = left | right; |
1926 | break; | 1932 | break; |
1927 | case '&': | 1933 | case '&': |
1928 | left = arg_num_eval(arg->op.left); | 1934 | ret = arg_num_eval(arg->op.left, &left); |
1929 | right = arg_num_eval(arg->op.right); | 1935 | if (!ret) |
1936 | break; | ||
1937 | ret = arg_num_eval(arg->op.right, &right); | ||
1938 | if (!ret) | ||
1939 | break; | ||
1930 | if (arg->op.op[1]) | 1940 | if (arg->op.op[1]) |
1931 | val = left && right; | 1941 | *val = left && right; |
1932 | else | 1942 | else |
1933 | val = left & right; | 1943 | *val = left & right; |
1934 | break; | 1944 | break; |
1935 | case '<': | 1945 | case '<': |
1936 | left = arg_num_eval(arg->op.left); | 1946 | ret = arg_num_eval(arg->op.left, &left); |
1937 | right = arg_num_eval(arg->op.right); | 1947 | if (!ret) |
1948 | break; | ||
1949 | ret = arg_num_eval(arg->op.right, &right); | ||
1950 | if (!ret) | ||
1951 | break; | ||
1938 | switch (arg->op.op[1]) { | 1952 | switch (arg->op.op[1]) { |
1939 | case 0: | 1953 | case 0: |
1940 | val = left < right; | 1954 | *val = left < right; |
1941 | break; | 1955 | break; |
1942 | case '<': | 1956 | case '<': |
1943 | val = left << right; | 1957 | *val = left << right; |
1944 | break; | 1958 | break; |
1945 | case '=': | 1959 | case '=': |
1946 | val = left <= right; | 1960 | *val = left <= right; |
1947 | break; | 1961 | break; |
1948 | default: | 1962 | default: |
1949 | die("unknown op '%s'", arg->op.op); | 1963 | do_warning("unknown op '%s'", arg->op.op); |
1964 | ret = 0; | ||
1950 | } | 1965 | } |
1951 | break; | 1966 | break; |
1952 | case '>': | 1967 | case '>': |
1953 | left = arg_num_eval(arg->op.left); | 1968 | ret = arg_num_eval(arg->op.left, &left); |
1954 | right = arg_num_eval(arg->op.right); | 1969 | if (!ret) |
1970 | break; | ||
1971 | ret = arg_num_eval(arg->op.right, &right); | ||
1972 | if (!ret) | ||
1973 | break; | ||
1955 | switch (arg->op.op[1]) { | 1974 | switch (arg->op.op[1]) { |
1956 | case 0: | 1975 | case 0: |
1957 | val = left > right; | 1976 | *val = left > right; |
1958 | break; | 1977 | break; |
1959 | case '>': | 1978 | case '>': |
1960 | val = left >> right; | 1979 | *val = left >> right; |
1961 | break; | 1980 | break; |
1962 | case '=': | 1981 | case '=': |
1963 | val = left >= right; | 1982 | *val = left >= right; |
1964 | break; | 1983 | break; |
1965 | default: | 1984 | default: |
1966 | die("unknown op '%s'", arg->op.op); | 1985 | do_warning("unknown op '%s'", arg->op.op); |
1986 | ret = 0; | ||
1967 | } | 1987 | } |
1968 | break; | 1988 | break; |
1969 | case '=': | 1989 | case '=': |
1970 | left = arg_num_eval(arg->op.left); | 1990 | ret = arg_num_eval(arg->op.left, &left); |
1971 | right = arg_num_eval(arg->op.right); | 1991 | if (!ret) |
1972 | 1992 | break; | |
1973 | if (arg->op.op[1] != '=') | 1993 | ret = arg_num_eval(arg->op.right, &right); |
1974 | die("unknown op '%s'", arg->op.op); | 1994 | if (!ret) |
1995 | break; | ||
1975 | 1996 | ||
1976 | val = left == right; | 1997 | if (arg->op.op[1] != '=') { |
1998 | do_warning("unknown op '%s'", arg->op.op); | ||
1999 | ret = 0; | ||
2000 | } else | ||
2001 | *val = left == right; | ||
1977 | break; | 2002 | break; |
1978 | case '!': | 2003 | case '!': |
1979 | left = arg_num_eval(arg->op.left); | 2004 | ret = arg_num_eval(arg->op.left, &left); |
1980 | right = arg_num_eval(arg->op.right); | 2005 | if (!ret) |
2006 | break; | ||
2007 | ret = arg_num_eval(arg->op.right, &right); | ||
2008 | if (!ret) | ||
2009 | break; | ||
1981 | 2010 | ||
1982 | switch (arg->op.op[1]) { | 2011 | switch (arg->op.op[1]) { |
1983 | case '=': | 2012 | case '=': |
1984 | val = left != right; | 2013 | *val = left != right; |
1985 | break; | 2014 | break; |
1986 | default: | 2015 | default: |
1987 | die("unknown op '%s'", arg->op.op); | 2016 | do_warning("unknown op '%s'", arg->op.op); |
2017 | ret = 0; | ||
1988 | } | 2018 | } |
1989 | break; | 2019 | break; |
1990 | case '-': | 2020 | case '-': |
@@ -1992,12 +2022,17 @@ static long long arg_num_eval(struct print_arg *arg) | |||
1992 | if (arg->op.left->type == PRINT_NULL) | 2022 | if (arg->op.left->type == PRINT_NULL) |
1993 | left = 0; | 2023 | left = 0; |
1994 | else | 2024 | else |
1995 | left = arg_num_eval(arg->op.left); | 2025 | ret = arg_num_eval(arg->op.left, &left); |
1996 | right = arg_num_eval(arg->op.right); | 2026 | if (!ret) |
1997 | val = left - right; | 2027 | break; |
2028 | ret = arg_num_eval(arg->op.right, &right); | ||
2029 | if (!ret) | ||
2030 | break; | ||
2031 | *val = left - right; | ||
1998 | break; | 2032 | break; |
1999 | default: | 2033 | default: |
2000 | die("unknown op '%s'", arg->op.op); | 2034 | do_warning("unknown op '%s'", arg->op.op); |
2035 | ret = 0; | ||
2001 | } | 2036 | } |
2002 | break; | 2037 | break; |
2003 | 2038 | ||
@@ -2006,10 +2041,11 @@ static long long arg_num_eval(struct print_arg *arg) | |||
2006 | case PRINT_STRING: | 2041 | case PRINT_STRING: |
2007 | case PRINT_BSTRING: | 2042 | case PRINT_BSTRING: |
2008 | default: | 2043 | default: |
2009 | die("invalid eval type %d", arg->type); | 2044 | do_warning("invalid eval type %d", arg->type); |
2045 | ret = 0; | ||
2010 | 2046 | ||
2011 | } | 2047 | } |
2012 | return val; | 2048 | return ret; |
2013 | } | 2049 | } |
2014 | 2050 | ||
2015 | static char *arg_eval (struct print_arg *arg) | 2051 | static char *arg_eval (struct print_arg *arg) |
@@ -2023,7 +2059,8 @@ static char *arg_eval (struct print_arg *arg) | |||
2023 | case PRINT_TYPE: | 2059 | case PRINT_TYPE: |
2024 | return arg_eval(arg->typecast.item); | 2060 | return arg_eval(arg->typecast.item); |
2025 | case PRINT_OP: | 2061 | case PRINT_OP: |
2026 | val = arg_num_eval(arg); | 2062 | if (!arg_num_eval(arg, &val)) |
2063 | break; | ||
2027 | sprintf(buf, "%lld", val); | 2064 | sprintf(buf, "%lld", val); |
2028 | return buf; | 2065 | return buf; |
2029 | 2066 | ||
@@ -2065,6 +2102,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char ** | |||
2065 | memset(field, 0, sizeof(field)); | 2102 | memset(field, 0, sizeof(field)); |
2066 | 2103 | ||
2067 | value = arg_eval(arg); | 2104 | value = arg_eval(arg); |
2105 | if (value == NULL) | ||
2106 | goto out_free; | ||
2068 | field->value = strdup(value); | 2107 | field->value = strdup(value); |
2069 | 2108 | ||
2070 | free_arg(arg); | 2109 | free_arg(arg); |
@@ -2076,6 +2115,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char ** | |||
2076 | goto out_free; | 2115 | goto out_free; |
2077 | 2116 | ||
2078 | value = arg_eval(arg); | 2117 | value = arg_eval(arg); |
2118 | if (value == NULL) | ||
2119 | goto out_free; | ||
2079 | field->str = strdup(value); | 2120 | field->str = strdup(value); |
2080 | free_arg(arg); | 2121 | free_arg(arg); |
2081 | arg = NULL; | 2122 | arg = NULL; |