After playing with v3.2-rc4, I found that the perf command failed to parse record contain data from (relatively new) btrfs tracepoints. This patch set will improve parser code of perf command and allow it to handle these data from btrfs tracepoints well. Thanks, H.Seto Hidetoshi Seto (3): perf: parse greater/less than or equal perf: allow processing single op args perf: allow typecast for signed value tools/perf/util/trace-event-parse.c | 25 +++++++++++++++++++++++-- 1 files changed, 23 insertions(+), 2 deletions(-)
Some btrfs tracepoints have complex format like following, but perf command failed to parse it: print fmt: "%s", ((REC->id >= min) || (REC->id <= max )) ? __print_symbolic(REC->id, { 1ULL, "ROOT_TREE" }, ... ) : "-" $ perf script Warning: unknown op ''>='' Warning: Error: expected type 5 but read 1 Warning: failed to read event print fmt for btrfs_transaction_commit This patch allow perf command to parse operation tokens, ''>='' and ''<=''. Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> --- tools/perf/util/trace-event-parse.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 0a7ed5b..c2adc76 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -1229,6 +1229,8 @@ process_op(struct event *event, struct print_arg *arg, char **tok) strcmp(token, "/") == 0 || strcmp(token, "<") == 0 || strcmp(token, ">") == 0 || + strcmp(token, "<=") == 0 || + strcmp(token, ">=") == 0 || strcmp(token, "==") == 0 || strcmp(token, "!=") == 0) { -- 1.7.7.3
I got following error from record with btrfs tracepoints: $ perf script Fatal: unknown op ''-'' It seems that perf failed to handle ''-'' in the following format: print fmt: "%s", ((REC->id >= -9) || (REC->id <= 7)) ? "x" : "y" ~ process_arg() have code to parse ''-9'' as a "single op" arg, which is PRINT_OP as type, ''-'' as op and have ''9'' as right arg but no left arg. However arg_num_eval() have no code to handle this "single op" arg even it is parsed successfully. This patch allow perf to process such "single op" args. Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> --- tools/perf/util/trace-event-parse.c | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-) diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index c2adc76..b709f78 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -1355,6 +1355,24 @@ static long long arg_num_eval(struct print_arg *arg) val = arg_num_eval(arg->typecast.item); break; case PRINT_OP: + if (!arg->op.left || arg->op.left->type == PRINT_NULL) { + /* handle single op */ + right = arg_num_eval(arg->op.right); + switch (arg->op.op[0]) { + case ''!'': + val = !right; + break; + case ''+'': + val = right; + break; + case ''-'': + val = -right; + break; + default: + die("unknown single op %s", arg->op.op); + } + break; + } switch (arg->op.op[0]) { case ''|'': left = arg_num_eval(arg->op.left); -- 1.7.7.3
Still I got following warning with btrfs tracepoints: $ perf script Warning: Error: expected type 5 but read 4 Warning: Error: expected type 5 but read 0 I found that the complained format is: print fmt: "%s", (REC->val >= (u64)-4) ? "-" : __print_symbolic(...) ~ In perf''s parser, the typecast, which is processed in process_paren(), only expects that (unsigned) token or another parenthesis will follow to the typecast. It should expect signed tokens can be there too. Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> --- tools/perf/util/trace-event-parse.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index b709f78..032f3de 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -1645,10 +1645,11 @@ process_paren(struct event *event, struct print_arg *arg, char **tok) type = read_token_item(&token); /* - * If the next token is an item or another open paren, then - * this was a typecast. + * If the next token is an item (might be signed, with single op "-") + * or another open paren, then this was a typecast. */ if (event_item_type(type) || + (type == EVENT_OP && strcmp(token, "-") == 0) || (type == EVENT_DELIM && strcmp(token, "(") == 0)) { /* make this a typecast and contine */ -- 1.7.7.3