Good morning, We have developed a patch for the perf Python scripting interface to provide additional information about the pid, tid, and cpu of generic events as well as information about the call-stack and resolved symbol names. This provides scripts with a greater level of detail. The mentioned information is already available to the scripting engine and just has to be handed down. This is done by the attached patch. The patch is based on Linux-3.13.3.
Please let me know if you have any questions on this. Thanks Joseph -- Dipl. Inf. Joseph Schuchart Computer Scientist Technische Universität Dresden Center for Information Services and High Performance Computing (ZIH) 01062 Dresden, Germany Phone: +49 351 463-36494 Fax: +49 351 463-3773 E-Mail: joseph.schuch...@tu-dresden.de
Perf: Provide sample information and call-chain to Python script Provide additional sample information on generic events to Python scripts, including pid, tid, and cpu for which the event was recorded. Additionally, provide the call-stack recorded at each event with resolved symbols. At the moment, the pointer to the sample struct is passed to scripts, which seems to be of little use. The patch puts this information in dictionaries for easy access by Python scripts. Signed-off-by: Joseph Schuchart <joseph.schuch...@tu-dresden.de> Acked-by: Thomas Ilsche <thomas.ils...@tu-dresden.de> @@ -359,7 +359,7 @@ static void python_process_general_event struct thread *thread, struct addr_location *al) { - PyObject *handler, *retval, *t, *dict; + PyObject *handler, *retval, *t, *dict, *dict_sample; static char handler_name[64]; unsigned n = 0; @@ -375,6 +375,10 @@ static void python_process_general_event if (!dict) Py_FatalError("couldn't create Python dictionary"); + dict_sample = PyDict_New(); + if (!dict_sample) + Py_FatalError("couldn't create Python dictionary"); + snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); handler = PyDict_GetItemString(main_dict, handler_name); @@ -384,8 +388,76 @@ static void python_process_general_event pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( (const char *)&evsel->attr, sizeof(evsel->attr))); - pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize( - (const char *)sample, sizeof(*sample))); + + /* PID/TIDs are limited to 2^29, so we can safely use PyInt */ + pydict_set_item_string_decref(dict_sample, "pid", PyInt_FromLong(sample->pid)); + pydict_set_item_string_decref(dict_sample, "tid", PyInt_FromLong(sample->tid)); + pydict_set_item_string_decref(dict_sample, "cpu", PyInt_FromLong(sample->cpu)); + pydict_set_item_string_decref(dict_sample, "time", PyLong_FromUnsignedLongLong(sample->time)); + pydict_set_item_string_decref(dict, "sample", dict_sample); + + /* ip unwinding */ + + if (symbol_conf.use_callchain && sample->callchain) { + PyObject *pylist; + + if (machine__resolve_callchain(machine, evsel, al->thread, + sample, NULL, NULL, PERF_MAX_STACK_DEPTH) != 0) { + pr_err("Failed to resolve callchain. Skipping\n"); + goto exit; + } + callchain_cursor_commit(&callchain_cursor); + + pylist = PyList_New(0); + if (!pylist) + Py_FatalError("couldn't create Python list"); + + while (1) { + PyObject *pyelem; + struct callchain_cursor_node *node; + node = callchain_cursor_current(&callchain_cursor); + if (!node) + break; + + pyelem = PyDict_New(); + if (!pyelem) + Py_FatalError("couldn't create Python dictionary"); + + + pydict_set_item_string_decref(pyelem, "ip", PyInt_FromLong(node->ip)); + + if (node->sym) { + PyObject *pysym = PyDict_New(); + if (!pysym) + Py_FatalError("couldn't create Python dictionary"); + pydict_set_item_string_decref(pysym, "start", PyInt_FromLong(node->sym->start)); + pydict_set_item_string_decref(pysym, "end", PyInt_FromLong(node->sym->end)); + pydict_set_item_string_decref(pysym, "binding", PyInt_FromLong(node->sym->binding)); + pydict_set_item_string_decref(pysym, "name", PyString_FromStringAndSize(node->sym->name, node->sym->namelen)); + pydict_set_item_string_decref(pyelem, "sym", pysym); + Py_DECREF(pysym); + } + + if (node->map) { + struct map *map = node->map; + const char *dsoname = "[unknown]"; + if (map && map->dso && (map->dso->name || map->dso->long_name)) { + if (symbol_conf.show_kernel_path && map->dso->long_name) + dsoname = map->dso->long_name; + else if (map->dso->name) + dsoname = map->dso->name; + } + pydict_set_item_string_decref(pyelem, "dso", PyString_FromString(dsoname)); + } + + callchain_cursor_advance(&callchain_cursor); + PyList_Append(pylist, pyelem); + Py_DECREF(pyelem); + } + PyDict_SetItemString(dict, "callstack", pylist); + Py_DECREF(pylist); + } + pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( (const char *)sample->raw_data, sample->raw_size)); pydict_set_item_string_decref(dict, "comm", @@ -407,6 +479,7 @@ static void python_process_general_event if (retval == NULL) handler_call_die(handler_name); exit: + Py_DECREF(dict_sample); Py_DECREF(dict); Py_DECREF(t); }
smime.p7s
Description: S/MIME Cryptographic Signature