diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-07-05 05:29:32 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-07-05 05:29:32 -0400 |
commit | 8b5b584daf3b92fc5cdc83919e64231817d2f5a7 (patch) | |
tree | 20519c481b8233a3efda947ea0c7202e4881b087 /tools/perf/util | |
parent | 432100ba2aacc2146a2b1f26e5b5ae5d6e29972a (diff) | |
parent | 8ac631cd502d6b31fd29f6d019305305b479fa3e (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf into perf/core
Pull perf/core improvements and fixes from Jiri Olsa:
* Handle the num array type in python properly (Sebastian Andrzej Siewior)
* Fix wrong condition for allocation failure (Jiri Olsa)
* Adjust callchain based on DWARF debug info on powerpc (Sukadev Bhattiprolu)
* Fix a risk for doing free on uninitialized pointer in traceevent lib (Rickard Strandqvist)
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/callchain.h | 13 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 18 | ||||
-rw-r--r-- | tools/perf/util/scripting-engines/trace-event-python.c | 57 |
3 files changed, 71 insertions, 17 deletions
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 8f84423a75da..da43619d6173 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
@@ -176,4 +176,17 @@ static inline void callchain_cursor_snapshot(struct callchain_cursor *dest, | |||
176 | dest->first = src->curr; | 176 | dest->first = src->curr; |
177 | dest->nr -= src->pos; | 177 | dest->nr -= src->pos; |
178 | } | 178 | } |
179 | |||
180 | #ifdef HAVE_SKIP_CALLCHAIN_IDX | ||
181 | extern int arch_skip_callchain_idx(struct machine *machine, | ||
182 | struct thread *thread, struct ip_callchain *chain); | ||
183 | #else | ||
184 | static inline int arch_skip_callchain_idx(struct machine *machine __maybe_unused, | ||
185 | struct thread *thread __maybe_unused, | ||
186 | struct ip_callchain *chain __maybe_unused) | ||
187 | { | ||
188 | return -1; | ||
189 | } | ||
190 | #endif | ||
191 | |||
179 | #endif /* __PERF_CALLCHAIN_H */ | 192 | #endif /* __PERF_CALLCHAIN_H */ |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index c73e1fc12e53..e9b943acaa5e 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -1281,7 +1281,9 @@ static int machine__resolve_callchain_sample(struct machine *machine, | |||
1281 | u8 cpumode = PERF_RECORD_MISC_USER; | 1281 | u8 cpumode = PERF_RECORD_MISC_USER; |
1282 | int chain_nr = min(max_stack, (int)chain->nr); | 1282 | int chain_nr = min(max_stack, (int)chain->nr); |
1283 | int i; | 1283 | int i; |
1284 | int j; | ||
1284 | int err; | 1285 | int err; |
1286 | int skip_idx __maybe_unused; | ||
1285 | 1287 | ||
1286 | callchain_cursor_reset(&callchain_cursor); | 1288 | callchain_cursor_reset(&callchain_cursor); |
1287 | 1289 | ||
@@ -1290,14 +1292,26 @@ static int machine__resolve_callchain_sample(struct machine *machine, | |||
1290 | return 0; | 1292 | return 0; |
1291 | } | 1293 | } |
1292 | 1294 | ||
1295 | /* | ||
1296 | * Based on DWARF debug information, some architectures skip | ||
1297 | * a callchain entry saved by the kernel. | ||
1298 | */ | ||
1299 | skip_idx = arch_skip_callchain_idx(machine, thread, chain); | ||
1300 | |||
1293 | for (i = 0; i < chain_nr; i++) { | 1301 | for (i = 0; i < chain_nr; i++) { |
1294 | u64 ip; | 1302 | u64 ip; |
1295 | struct addr_location al; | 1303 | struct addr_location al; |
1296 | 1304 | ||
1297 | if (callchain_param.order == ORDER_CALLEE) | 1305 | if (callchain_param.order == ORDER_CALLEE) |
1298 | ip = chain->ips[i]; | 1306 | j = i; |
1299 | else | 1307 | else |
1300 | ip = chain->ips[chain->nr - i - 1]; | 1308 | j = chain->nr - i - 1; |
1309 | |||
1310 | #ifdef HAVE_SKIP_CALLCHAIN_IDX | ||
1311 | if (j == skip_idx) | ||
1312 | continue; | ||
1313 | #endif | ||
1314 | ip = chain->ips[j]; | ||
1301 | 1315 | ||
1302 | if (ip >= PERF_CONTEXT_MAX) { | 1316 | if (ip >= PERF_CONTEXT_MAX) { |
1303 | switch (ip) { | 1317 | switch (ip) { |
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 1c419321f707..e55b65a65558 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -231,6 +231,47 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) | |||
231 | return event; | 231 | return event; |
232 | } | 232 | } |
233 | 233 | ||
234 | static PyObject *get_field_numeric_entry(struct event_format *event, | ||
235 | struct format_field *field, void *data) | ||
236 | { | ||
237 | bool is_array = field->flags & FIELD_IS_ARRAY; | ||
238 | PyObject *obj, *list = NULL; | ||
239 | unsigned long long val; | ||
240 | unsigned int item_size, n_items, i; | ||
241 | |||
242 | if (is_array) { | ||
243 | list = PyList_New(field->arraylen); | ||
244 | item_size = field->size / field->arraylen; | ||
245 | n_items = field->arraylen; | ||
246 | } else { | ||
247 | item_size = field->size; | ||
248 | n_items = 1; | ||
249 | } | ||
250 | |||
251 | for (i = 0; i < n_items; i++) { | ||
252 | |||
253 | val = read_size(event, data + field->offset + i * item_size, | ||
254 | item_size); | ||
255 | if (field->flags & FIELD_IS_SIGNED) { | ||
256 | if ((long long)val >= LONG_MIN && | ||
257 | (long long)val <= LONG_MAX) | ||
258 | obj = PyInt_FromLong(val); | ||
259 | else | ||
260 | obj = PyLong_FromLongLong(val); | ||
261 | } else { | ||
262 | if (val <= LONG_MAX) | ||
263 | obj = PyInt_FromLong(val); | ||
264 | else | ||
265 | obj = PyLong_FromUnsignedLongLong(val); | ||
266 | } | ||
267 | if (is_array) | ||
268 | PyList_SET_ITEM(list, i, obj); | ||
269 | } | ||
270 | if (is_array) | ||
271 | obj = list; | ||
272 | return obj; | ||
273 | } | ||
274 | |||
234 | static void python_process_tracepoint(struct perf_sample *sample, | 275 | static void python_process_tracepoint(struct perf_sample *sample, |
235 | struct perf_evsel *evsel, | 276 | struct perf_evsel *evsel, |
236 | struct thread *thread, | 277 | struct thread *thread, |
@@ -239,7 +280,6 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
239 | PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; | 280 | PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; |
240 | static char handler_name[256]; | 281 | static char handler_name[256]; |
241 | struct format_field *field; | 282 | struct format_field *field; |
242 | unsigned long long val; | ||
243 | unsigned long s, ns; | 283 | unsigned long s, ns; |
244 | struct event_format *event; | 284 | struct event_format *event; |
245 | unsigned n = 0; | 285 | unsigned n = 0; |
@@ -303,20 +343,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
303 | offset = field->offset; | 343 | offset = field->offset; |
304 | obj = PyString_FromString((char *)data + offset); | 344 | obj = PyString_FromString((char *)data + offset); |
305 | } else { /* FIELD_IS_NUMERIC */ | 345 | } else { /* FIELD_IS_NUMERIC */ |
306 | val = read_size(event, data + field->offset, | 346 | obj = get_field_numeric_entry(event, field, data); |
307 | field->size); | ||
308 | if (field->flags & FIELD_IS_SIGNED) { | ||
309 | if ((long long)val >= LONG_MIN && | ||
310 | (long long)val <= LONG_MAX) | ||
311 | obj = PyInt_FromLong(val); | ||
312 | else | ||
313 | obj = PyLong_FromLongLong(val); | ||
314 | } else { | ||
315 | if (val <= LONG_MAX) | ||
316 | obj = PyInt_FromLong(val); | ||
317 | else | ||
318 | obj = PyLong_FromUnsignedLongLong(val); | ||
319 | } | ||
320 | } | 347 | } |
321 | if (handler) | 348 | if (handler) |
322 | PyTuple_SetItem(t, n++, obj); | 349 | PyTuple_SetItem(t, n++, obj); |