Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf script python: Fix string vs byte array resolving

Jirka reported that python code returns all arrays as strings. This
makes impossible to get all items for byte array tracepoint field
containing 0x00 value item.

Fixing this by scanning full length of the array and returning it as
PyByteArray object in case non printable byte is found.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Reported-and-Tested-by: Jiri Pirko <jiri@mellanox.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/1468685480-18951-2-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Jiri Olsa and committed by
Arnaldo Carvalho de Melo
249de6e0 e7049342

+33 -6
+33 -6
tools/perf/util/scripting-engines/trace-event-python.c
··· 386 386 return pylist; 387 387 } 388 388 389 + static int is_printable_array(char *p, unsigned int len) 390 + { 391 + unsigned int i; 392 + 393 + if (!p || !len || p[len - 1] != 0) 394 + return 0; 395 + 396 + len--; 397 + 398 + for (i = 0; i < len; i++) { 399 + if (!isprint(p[i]) && !isspace(p[i])) 400 + return 0; 401 + } 402 + return 1; 403 + } 389 404 390 405 static void python_process_tracepoint(struct perf_sample *sample, 391 406 struct perf_evsel *evsel, ··· 472 457 pydict_set_item_string_decref(dict, "common_callchain", callchain); 473 458 } 474 459 for (field = event->format.fields; field; field = field->next) { 475 - if (field->flags & FIELD_IS_STRING) { 476 - int offset; 460 + unsigned int offset, len; 461 + unsigned long long val; 462 + 463 + if (field->flags & FIELD_IS_ARRAY) { 464 + offset = field->offset; 465 + len = field->size; 477 466 if (field->flags & FIELD_IS_DYNAMIC) { 478 - offset = *(int *)(data + field->offset); 467 + val = pevent_read_number(scripting_context->pevent, 468 + data + offset, len); 469 + offset = val; 470 + len = offset >> 16; 479 471 offset &= 0xffff; 480 - } else 481 - offset = field->offset; 482 - obj = PyString_FromString((char *)data + offset); 472 + } 473 + if (field->flags & FIELD_IS_STRING && 474 + is_printable_array(data + offset, len)) { 475 + obj = PyString_FromString((char *) data + offset); 476 + } else { 477 + obj = PyByteArray_FromStringAndSize((const char *) data + offset, len); 478 + field->flags &= ~FIELD_IS_STRING; 479 + } 483 480 } else { /* FIELD_IS_NUMERIC */ 484 481 obj = get_field_numeric_entry(event, field, data); 485 482 }