perf python: Add support to access tracepoint fields
Jiri Olsa
reviewerv2 cover perf python: Add support to access tracepoint fields
hi,
adding support to access tracepoint fields in python scripts.
v2 changes:
- most of the patches is already pulled in,
this is just leftover
- fixed is_printable_array [Steven]
- making is_printable_array global
- attached unrelated fix 3/3
With this patchset it's possible to access tracepoint fields in event python object like:
print "time %u prev_comm=%s prev_pid=%d prev_prio=%d prev_state=0x%x ==> next_comm=%s next_pid=%d next_prio=%d" % (
event.sample_time,
event.prev_comm,
event.prev_pid,
event.prev_prio,
event.prev_state,
event.next_comm,
event.next_pid,
event.next_prio)
Also available in:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/fixes
thanks,
jirka
---
Jiri Olsa (3):
perf script python: Fix string vs byte array resolving perf tools: Make is_printable_array global tools lib api fs: Use base 0 in filename__read_ull
tools/lib/api/fs/fs.c | 7 ++++++- tools/perf/util/python.c | 12 ------------ tools/perf/util/scripting-engines/trace-event-python.c | 25 ++++++++++++++++++------- tools/perf/util/util.c | 14 ++++++++++++++ tools/perf/util/util.h | 1 + 5 files changed, 39 insertions(+), 20 deletions(-)
Jiri Olsa
reviewerPATCH v2 1/3 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.
--- .../util/scripting-engines/trace-event-python.c | 37 ++++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-)
tools/perf/util/scripting-engines/trace-event-python.c +31 -6
@@ -386,6 +386,19 @@ exit:return pylist; } +static int is_printable_array (char *p,unsigned int len) +{ +unsigned int i; + +if (p[len -1 ] ==0 ) + len--; + +for (i =0 ; i < len -1 ; i++) +if (!isprint (p[i]) && !isspace (p[i])) +return 0 ; + +return 1 ; +} static void python_process_tracepoint(struct perf_sample *sample, struct perf_evsel *evsel,
@@ -457,14 +470,26 @@ static void python_process_tracepoint(struct perf_sample *sample,pydict_set_item_string_decref (dict,"common_callchain" , callchain); }for (field = event->format.fields; field; field = field->next) { -if (field->flags &FIELD_IS_STRING ) { -int offset; +unsigned int offset, len; +unsigned long long val; + +if (field->flags &FIELD_IS_ARRAY ) { + offset = field->offset; + len = field->size;if (field->flags &FIELD_IS_DYNAMIC ) { - offset = *(int *)(data + field->offset); + val =pevent_read_number (scripting_context->pevent, + data + offset, len); + offset = val; + len = offset >>16 ; offset &=0xffff ; - }else - offset = field->offset; - obj =PyString_FromString ((char *)data + offset); + } +if (field->flags &FIELD_IS_STRING && +is_printable_array (data + offset, len)) { + obj =PyString_FromString ((char *) data + offset); + }else { + obj =PyByteArray_FromStringAndSize ((const char *) data + offset, len); + field->flags &= ~FIELD_IS_STRING ; + } }else {/* FIELD_IS_NUMERIC */ obj =get_field_numeric_entry (event, field, data); }
Signature · 1 line
2.4.11
Re: [PATCH 1/3] perf script python: Fix string vs byte array resolving
Quoted 9 lines · Jiri Olsa
Jirka reported that python code returns all arrays as strings. This makes impossible to get all items for byte array tracepoint field containing
0x00value item.Fixing this by scanning full length of the array and returning it as PyByteArray object in case non printable byte is found.
Cc Steven Rostedt (Red Hat) <[email protected]>Cc Jiri Pirko <[email protected]>
forgot:
Jirka,
could I please also have your tested-by on this version?
thanks,
jirka
Re: [PATCH 1/3] perf script python: Fix string vs byte array resolving
In reply to Jiri OlsaQuoted 4 lines · On Fri, 15 Jul 2016 09:29:55 +0200 Jiri Olsa <[email protected]> wrote:
Jirka reported that python code returns all arrays as strings. This makes impossible to get all items for byte array tracepoint field containing
0x00value item.
Quoted 8 lines
Fixing this by scanning full length of the array and returning it as PyByteArray object in case non printable byte is found.
Cc Steven Rostedt (Red Hat) <[email protected]>Cc Jiri Pirko <[email protected]>Signed-off-by Jiri Olsa <[email protected]>---
-- Steve
Re: [PATCH 1/3] perf script python: Fix string vs byte array resolving
In reply to Jiri OlsaQuoted 23 lines · Fri, Jul 15, 2016 at 09:29:55AM CEST, [email protected] wrote:
Jirka reported that python code returns all arrays as strings. This makes impossible to get all items for byte array tracepoint field containing
0x00value item.Fixing this by scanning full length of the array and returning it as PyByteArray object in case non printable byte is found.
Cc Steven Rostedt (Red Hat) <[email protected]>Cc Jiri Pirko <[email protected]>Signed-off-by Jiri Olsa <[email protected]>---
.../util/scripting-engines/trace-event-python.c| 37 ++++++++++++++++++----1 file changed, 31 insertions(+), 6 deletions(-)tools/perf/util/scripting-engines/trace-event-python.c +0
-0@@ -386,6 +386,19 @@ exit:return pylist; }
tools/perf/util/scripting-engines/trace-event-python.c exit: · line 398
Quoted 10 lines
tools/perf/util/scripting-engines/trace-event-python.c +10
-0+static int is_printable_array (char *p,unsigned int len) +{ +unsigned int i; + +if (p[len -1 ] ==0 ) + len--; + +for (i =0 ; i < len -1 ; i++) +if (!isprint (p[i]) && !isspace (p[i])) +return 0 ;
for "AA\1\0" this returns "1" although that should return "0".
orig len 4
decremented len 3
for:
0 1
index 2 would not be inspected. Or am I missing something?
I think that the for check should be "i < len"
Thanks.
Quoted 42 lines
tools/perf/util/scripting-engines/trace-event-python.c +21
-6+ +return 1 ; +} static void python_process_tracepoint(struct perf_sample *sample, struct perf_evsel *evsel,@@ -457,14 +470,26 @@ static void python_process_tracepoint(struct perf_sample *sample,pydict_set_item_string_decref (dict,"common_callchain" , callchain); }for (field = event->format.fields; field; field = field->next) { -if (field->flags &FIELD_IS_STRING ) { -int offset; +unsigned int offset, len; +unsigned long long val; + +if (field->flags &FIELD_IS_ARRAY ) { + offset = field->offset; + len = field->size;if (field->flags &FIELD_IS_DYNAMIC ) { - offset = *(int *)(data + field->offset); + val =pevent_read_number (scripting_context->pevent, + data + offset, len); + offset = val; + len = offset >>16 ; offset &=0xffff ; - }else - offset = field->offset; - obj =PyString_FromString ((char *)data + offset); + } +if (field->flags &FIELD_IS_STRING && +is_printable_array (data + offset, len)) { + obj =PyString_FromString ((char *) data + offset); + }else { + obj =PyByteArray_FromStringAndSize ((const char *) data + offset, len); + field->flags &= ~FIELD_IS_STRING ; + } }else {/* FIELD_IS_NUMERIC */ obj =get_field_numeric_entry (event, field, data); }Signature · 1 line
2.4.11
Re: [PATCH 1/3] perf script python: Fix string vs byte array resolving
Quoted 38 lines · On Fri, 15 Jul 2016 17:51:10 +0200 Jiri Pirko <[email protected]> wrote:
Quoted 23 lines · Fri, Jul 15, 2016 at 09:29:55AM CEST, [email protected] wrote:
Jirka reported that python code returns all arrays as strings. This makes impossible to get all items for byte array tracepoint field containing
0x00value item.Fixing this by scanning full length of the array and returning it as PyByteArray object in case non printable byte is found.
Cc Steven Rostedt (Red Hat) <[email protected]>Cc Jiri Pirko <[email protected]>Signed-off-by Jiri Olsa <[email protected]>---
.../util/scripting-engines/trace-event-python.c| 37 ++++++++++++++++++----1 file changed, 31 insertions(+), 6 deletions(-)tools/perf/util/scripting-engines/trace-event-python.c +0
-0@@ -386,6 +386,19 @@ exit:return pylist; }tools/perf/util/scripting-engines/trace-event-python.c exit: · line 398
Quoted 10 lines
tools/perf/util/scripting-engines/trace-event-python.c +10
-0+static int is_printable_array (char *p,unsigned int len) +{ +unsigned int i; + +if (p[len -1 ] ==0 ) + len--; + +for (i =0 ; i < len -1 ; i++) +if (!isprint (p[i]) && !isspace (p[i])) +return 0 ;for "AA\1\0" this returns "1" although that should return "0".
Quoted 8 lines
orig len 4
decremented len 3
for:
0 1index 2 would not be inspected. Or am I missing something?
I think that the for check should be "i < len"
Yes it should be. I think we got the two solutions mixed up.
With the above len--, it should be i < len, but when we did the check for zero at the end, we needed the i < len - 1
-- Steve
Re: [PATCH 1/3] perf script python: Fix string vs byte array resolving
On Fri, Jul 15, 2016 at 12:02:31PM -0400, Steven Rostedt wrote:
SNIP
Quoted 7 lines
Quoted 7 lines
for "AA\1\0" this returns "1" although that should return "0".
orig len 4
decremented len 3
for:
0 1
Quoted 8 lines
Quoted 3 lines
index 2 would not be inspected. Or am I missing something?
I think that the for check should be "i < len"
Yes it should be. I think we got the two solutions mixed up.
With the above len--, it should be i < len, but when we did the check for zero at the end, we needed the i < len - 1
ugh right.. should be 'i < len' check in the for loop,
there's also the patch 2/3 that needs to be changed
Arnaldo,
please let me know if you need me to resend this.
thanks,
jirka
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 1/3] perf script python: Fix string vs byte array resolving
Em Fri, Jul 15, 2016 at 06:13:10PM +0200, Jiri Olsa escreveu:
Quoted 20 lines · Steven Rostedt
SNIP
Quoted 7 lines
Quoted 7 lines
for "AA\1\0" this returns "1" although that should return "0".
orig len 4
decremented len 3
for:
0 1Quoted 8 lines
Quoted 3 lines
index 2 would not be inspected. Or am I missing something?
I think that the for check should be "i < len"
Yes it should be. I think we got the two solutions mixed up.
With the above len--, it should be i < len, but when we did the check for zero at the end, we needed the i < len - 1
Quoted 6 lines
ugh right.. should be 'i < len' check in the for loop,
there's also the patch 2/3 that needs to be changed
Arnaldo,
please let me know if you need me to resend this.
So I need to drop those, even with Rostedt's acked-by? Ok, please resend, hopefully this time with a Tested-by from the reporter?
- Arnaldo
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 1/3] perf script python: Fix string vs byte array resolving
Em Fri, Jul 15, 2016 at 01:37:31PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 23 lines
Em Fri, Jul 15, 2016 at 06:13:10PM +0200, Jiri Olsa escreveu:
Quoted 22 lines · Steven Rostedt
SNIP
Quoted 7 lines
Quoted 7 lines
for "AA\1\0" this returns "1" although that should return "0".
orig len 4
decremented len 3
for:
0 1Quoted 8 lines
Quoted 3 lines
index 2 would not be inspected. Or am I missing something?
I think that the for check should be "i < len"
Yes it should be. I think we got the two solutions mixed up.
With the above len--, it should be i < len, but when we did the check for zero at the end, we needed the i < len - 1
ugh right.. should be 'i < len' check in the for loop,
Quoted 7 lines
Quoted 4 lines
there's also the patch 2/3 that needs to be changed
Arnaldo,
please let me know if you need me to resend this.So I need to drop those, even with Rostedt's acked-by? Ok, please resend, hopefully this time with a Tested-by from the reporter?
I removed the first two, as the second needs context from the first, kept the third one, so please resend just the first two.
- Arnaldo
Re: [PATCH 1/3] perf script python: Fix string vs byte array resolving
In reply to Jiri OlsaQuoted 15 lines · On Fri, 15 Jul 2016 18:13:10 +0200 Jiri Olsa <[email protected]> wrote:
On Fri, Jul 15, 2016 at 12:02:31PM -0400, Steven Rostedt wrote:
SNIP
Quoted 11 lines
Quoted 10 lines
for "AA\1\0" this returns "1" although that should return "0".
orig len 4
decremented len 3
for:
0 1index 2 would not be inspected. Or am I missing something?
I think that the for check should be "i < len"
Quoted 9 lines
Quoted 4 lines
Yes it should be. I think we got the two solutions mixed up.
With the above len--, it should be i < len, but when we did the check for zero at the end, we needed the i < len - 1
ugh right.. should be 'i < len' check in the for loop,
there's also the patch 2/3 that needs to be changed
I'm wondering if we should also add at the beginning:
if (!len) return 0;
Otherwise we will be accessing out of bounds with the len-1.
-- Steve
Re: [PATCH 1/3] perf script python: Fix string vs byte array resolving
In reply to Jiri Olsatools/perf/util/scripting-engines/trace-event-python.c static void python_process_tracepoint(struct perf_sample *sample, · line 488
Quoted 3 lines · On Fri, 15 Jul 2016 09:29:55 +0200 Jiri Olsa <[email protected]> wrote:
tools/perf/util/scripting-engines/trace-event-python.c +3
-0+if (field->flags &FIELD_IS_STRING && +is_printable_array (data + offset, len)) { + obj =PyString_FromString ((char *) data + offset);
Hmm. As I stated, It is possible that strings can be non nul terminated. But I'm looking here and thinking we need to make sure that it is nul terminated.
Can PyString_FromString() handle a non nul terminated string?
-- Steve
Quoted 7 lines
tools/perf/util/scripting-engines/trace-event-python.c +4
-0+ }else { + obj =PyByteArray_FromStringAndSize ((const char *) data + offset, len); + field->flags &= ~FIELD_IS_STRING ; + } }else {/* FIELD_IS_NUMERIC */ obj =get_field_numeric_entry (event, field, data); }
Re: [PATCH 1/3] perf script python: Fix string vs byte array resolving
Quoted 11 lines · Steven Rostedt
tools/perf/util/scripting-engines/trace-event-python.c static void python_process_tracepoint(struct perf_sample *sample, · line 488
Quoted 3 lines · On Fri, 15 Jul 2016 09:29:55 +0200 Jiri Olsa <[email protected]> wrote:
tools/perf/util/scripting-engines/trace-event-python.c +3
-0+if (field->flags &FIELD_IS_STRING && +is_printable_array (data + offset, len)) { + obj =PyString_FromString ((char *) data + offset);Hmm. As I stated, It is possible that strings can be non nul terminated. But I'm looking here and thinking we need to make sure that it is nul terminated.
Quoted 1 line
Can
PyString_FromString()handle a non nul terminated string?
couldn't find in the doc.. but I think it's necessary, there's no other way it could tell the end ;-)
I'll make the is_printable_array in case the final 0 is missing
thanks,
jirka
Jiri Olsa
reviewerPATCH v2 2/3 perf tools: Make is_printable_array global
In reply to Jiri OlsaIt's used from 2 objects in perf, so it's better
to keep just one copy.
--- tools/perf/util/python.c | 12 ------------ tools/perf/util/scripting-engines/trace-event-python.c | 14 -------------- tools/perf/util/util.c | 14 ++++++++++++++ tools/perf/util/util.h | 1 + 4 files changed, 15 insertions(+), 26 deletions(-)
tools/perf/util/python.c +0 -12
@@ -295,18 +295,6 @@ static bool is_tracepoint(struct pyrf_event *pevent)return pevent->evsel->attr.type ==PERF_TYPE_TRACEPOINT ; } -static int is_printable_array (char *p,unsigned int len) -{ -unsigned int i; - -for (i =0 ; i < len; i++) { -if (!isprint (p[i]) && !isspace (p[i])) -return 0 ; - } - -return 1 ; -} -static PyObject *tracepoint_field (struct pyrf_event *pe,struct format_field *field) {
tools/perf/util/scripting-engines/trace-event-python.c +0 -14
@@ -386,20 +386,6 @@ exit:return pylist; } -static int is_printable_array (char *p,unsigned int len) -{ -unsigned int i; - -if (p[len -1 ] ==0 ) - len--; - -for (i =0 ; i < len -1 ; i++) -if (!isprint (p[i]) && !isspace (p[i])) -return 0 ; - -return 1 ; -} -static void python_process_tracepoint (struct perf_sample *sample,struct perf_evsel *evsel,struct addr_location *al)
tools/perf/util/util.c +14 -0
@@ -746,3 +746,17 @@ void print_binary(unsigned char *data, size_t len, }printer (BINARY_PRINT_DATA_END ,-1 , extra); } + +int is_printable_array (char *p,unsigned int len) +{ +unsigned int i; + +if (p[len -1 ] ==0 ) + len--; + +for (i =0 ; i < len -1 ; i++) +if (!isprint (p[i]) && !isspace (p[i])) +return 0 ; + +return 1 ; +}
tools/perf/util/util.h +1 -0
@@ -364,4 +364,5 @@ void print_binary(unsigned char *data, size_t len,extern int sched_getcpu (void );#endif +int is_printable_array (char *p,unsigned int len);#endif /* GIT_COMPAT_UTIL_H */
Signature · 1 line
2.4.11
Re: [PATCH 2/3] perf tools: Make is_printable_array global
Quoted 6 lines · On Fri, 15 Jul 2016 09:29:56 +0200 Jiri Olsa <[email protected]> wrote:
It's used from 2 objects in perf, so it's better
to keep just one copy.Cc Steven Rostedt (Red Hat) <[email protected]>Signed-off-by Jiri Olsa <[email protected]>
-- Steve
Jiri Olsa
reviewerPATCH v2 3/3 tools lib api fs: Use base 0 in filename__read_ull
In reply to Jiri OlsaBy using 0 for base, the strtoull detects the base automatically (see man strtoull).
ATM we have just one user of this function, the cpu__get_max_freq function reading cpuinfo_max_freq sysfs. It should not get affected by this change.
--- tools/lib/api/fs/fs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
tools/lib/api/fs/fs.c +6 -1
@@ -283,6 +283,11 @@ int filename__read_int(const char *filename, int *value)return err; } +/* +* Parses @value out of @filename with strtoull. +* By using 0 for base, the strtoull detects the +* base automatically (see man strtoull). +*/ int filename__read_ull (const char *filename,unsigned long long *value) {char line[64 ];
@@ -292,7 +297,7 @@ int filename__read_ull(const char *filename, unsigned long long *value)return -1 ;if (read (fd, line,sizeof (line)) >0 ) { - *value =strtoull (line,NULL ,10 ); + *value =strtoull (line,NULL ,0 );if (*value !=ULLONG_MAX ) err =0 ; }
Signature · 1 line
2.4.11
tip-bot for Jiri Olsa
merge bot[tip:perf/core] tools lib api fs: Use base 0 in filename__read_ull
tools lib api fs: Use base 0 in filename__read_ull
Commit-ID: db49120a32b347fb93aea3319305932657dd118c Gitweb: http://git.kernel.org/tip/db49120a32b347fb93aea3319305932657dd118c Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 15 Jul 2016 09:29:57 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 15 Jul 2016 13:38:05 -0300
tools lib api fs: Use base 0 in filename__read_ull
By using 0 for base, the strtoull() detects the base automatically (see 'man strtoull').
ATM we have just one user of this function, the cpu__get_max_freq function reading the "cpuinfo_max_freq" sysfs file. It should not get affected by this change.
Committer note:
This change seems motivated by this discussion:
"[PATCH] [RFC V1]s390/perf: fix 'start' address of module's map"
http://lkml.kernel.org/r/20160711120155.GA29929@krava
I.e. this patches paves the way for filename__read_ull() to be used in a S/390 related fix.
--- tools/lib/api/fs/fs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
tools/lib/api/fs/fs.c +6 -1
@@ -283,6 +283,11 @@ int filename__read_int(const char *filename, int *value)return err; } +/* +* Parses @value out of @filename with strtoull. +* By using 0 for base, the strtoull detects the +* base automatically (see man strtoull). +*/ int filename__read_ull (const char *filename,unsigned long long *value) {char line[64 ];
@@ -292,7 +297,7 @@ int filename__read_ull(const char *filename, unsigned long long *value)return -1 ;if (read (fd, line,sizeof (line)) >0 ) { - *value =strtoull (line,NULL ,10 ); + *value =strtoull (line,NULL ,0 );if (*value !=ULLONG_MAX ) err =0 ; }