4341 lines · 114.8 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0#define PY_SSIZE_T_CLEAN#include <Python.h> #include <inttypes.h>#include <string.h> #include <linux/err.h>#include <poll.h>#include <unistd.h> #include <internal/lib.h>#include <perf/cpumap.h>#include <perf/mmap.h>#include <structmember.h> #include "addr_location.h"#include "build-id.h"#include "callchain.h"#include "comm.h"#include "config.h"#include "counts.h"#include "data.h"#include "debug.h"#include "dso.h"#include "dwarf-regs.h"#include "event.h"#include "branch.h"#include "evlist.h"#include "evsel.h"#include "expr.h"#include "map.h"#include "metricgroup.h"#include "mmap.h"#include "pmus.h"#include "print_binary.h"#include "record.h"#include "sample.h"#include "session.h"#include "srccode.h"#include "srcline.h"#include "strbuf.h"#include "symbol.h"#include "stat.h"#include "header.h"#include "trace/beauty/syscalltbl.h"#include "thread.h"#include "thread_map.h"#include "tool.h"#include "tp_pmu.h"#include "trace-event.h" #ifdef HAVE_LIBTRACEEVENT#include <event-parse.h>#endif PyMODINIT_FUNC PyInit_perf(void); static PyObject *pyrf_evsel__from_evsel(struct evsel *evsel); #define member_def(type, member, ptype, help) \	{ #member, ptype, \	  offsetof(struct pyrf_event, event) + offsetof(struct type, member), \	  0, help } #define sample_member_def(name, member, ptype, help) \	{ #name, ptype, \	  offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \	  0, help } #define CHECK_INITIALIZED(ptr, msg) \	do { \		if (!(ptr)) { \			PyErr_SetString(PyExc_ValueError, msg " not initialized"); \			return NULL; \		} \	} while (0) #define CHECK_INITIALIZED_INT(ptr, msg) \	do { \		if (!(ptr)) { \			PyErr_SetString(PyExc_ValueError, msg " not initialized"); \			return -1; \		} \	} while (0) struct pyrf_event {	PyObject_HEAD	/** @sample: The parsed sample from the event. */	struct perf_sample sample;	/** @al: The address location from machine__resolve, lazily computed. */	struct addr_location al;	/** @al_resolved: True when machine__resolve been called. */	bool al_resolved;	/** @callchain: Resolved callchain, eagerly computed if requested. */	PyObject *callchain;	/** @brstack: Resolved branch stack, eagerly computed if requested. */	PyObject *brstack;	/** @event: The underlying perf_event that may be in a file or ring buffer. */	union perf_event event;}; #define sample_members \	sample_member_def(sample_pid, pid, T_INT, "event pid"),			 \	sample_member_def(sample_tid, tid, T_INT, "event tid"),			 \	sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"),		 \	sample_member_def(sample_id, id, T_ULONGLONG, "event id"),			 \	sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \	sample_member_def(sample_period, period, T_ULONGLONG, "event period"),		 \	sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"), static PyObject *pyrf_event__get_evsel(PyObject *self, void *closure __maybe_unused){	struct pyrf_event *pevent = (void *)self; 	if (!pevent->sample.evsel)		Py_RETURN_NONE; 	return pyrf_evsel__from_evsel(pevent->sample.evsel);} static PyGetSetDef pyrf_event__getset[] = {	{		.name = "evsel",		.get = pyrf_event__get_evsel,		.set = NULL,		.doc = "tracking event.",	},	{ .name = NULL, },}; static void pyrf_event__delete(struct pyrf_event *pevent){	if (pevent->al_resolved)		addr_location__exit(&pevent->al);	Py_XDECREF(pevent->callchain);	Py_XDECREF(pevent->brstack);	perf_sample__exit(&pevent->sample);	Py_TYPE(pevent)->tp_free((PyObject *)pevent);} static const char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object."); static PyMemberDef pyrf_mmap_event__members[] = {	sample_members	member_def(perf_event_header, type, T_UINT, "event type"),	member_def(perf_event_header, misc, T_USHORT, "event misc"),	member_def(perf_record_mmap, pid, T_UINT, "event pid"),	member_def(perf_record_mmap, tid, T_UINT, "event tid"),	member_def(perf_record_mmap, start, T_ULONGLONG, "start of the map"),	member_def(perf_record_mmap, len, T_ULONGLONG, "map length"),	member_def(perf_record_mmap, pgoff, T_ULONGLONG, "page offset"),	member_def(perf_record_mmap, filename, T_STRING_INPLACE, "backing store"),	{ .name = NULL, },}; static PyObject *pyrf_mmap_event__repr(const struct pyrf_event *pevent){	PyObject *ret;	char *s; 	if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRI_lx64 ", "			 "length: %#" PRI_lx64 ", offset: %#" PRI_lx64 ", "			 "filename: %s }",		     pevent->event.mmap.pid, pevent->event.mmap.tid,		     pevent->event.mmap.start, pevent->event.mmap.len,		     pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) {		ret = PyErr_NoMemory();	} else {		ret = PyUnicode_FromString(s);		free(s);	}	return ret;} static PyTypeObject pyrf_mmap_event__type = {	PyVarObject_HEAD_INIT(NULL, 0)	.tp_name	= "perf.mmap_event",	.tp_basicsize	= sizeof(struct pyrf_event),	.tp_dealloc	= (destructor)pyrf_event__delete,	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,	.tp_doc		= pyrf_mmap_event__doc,	.tp_members	= pyrf_mmap_event__members,	.tp_getset	= pyrf_event__getset,	.tp_repr	= (reprfunc)pyrf_mmap_event__repr,}; static const char pyrf_mmap2_event__doc[] = PyDoc_STR("perf mmap2 event object."); static PyObject *pyrf_mmap2_event__get_maj(PyObject *self, void *closure __maybe_unused){	struct pyrf_event *pevent = (void *)self; 	if (pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)		Py_RETURN_NONE; 	return PyLong_FromUnsignedLong(pevent->event.mmap2.maj);} static PyObject *pyrf_mmap2_event__get_min(PyObject *self, void *closure __maybe_unused){	struct pyrf_event *pevent = (void *)self; 	if (pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)		Py_RETURN_NONE; 	return PyLong_FromUnsignedLong(pevent->event.mmap2.min);} static PyObject *pyrf_mmap2_event__get_ino(PyObject *self, void *closure __maybe_unused){	struct pyrf_event *pevent = (void *)self; 	if (pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)		Py_RETURN_NONE; 	return PyLong_FromUnsignedLongLong(pevent->event.mmap2.ino);} static PyObject *pyrf_mmap2_event__get_ino_generation(PyObject *self, void *closure __maybe_unused){	struct pyrf_event *pevent = (void *)self; 	if (pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)		Py_RETURN_NONE; 	return PyLong_FromUnsignedLongLong(pevent->event.mmap2.ino_generation);} static PyObject *pyrf_mmap2_event__get_build_id(PyObject *self, void *closure __maybe_unused){	struct pyrf_event *pevent = (void *)self; 	if (!(pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID))		Py_RETURN_NONE; 	int size = pevent->event.mmap2.build_id_size; 	if (size > 20)		size = 20; 	return PyBytes_FromStringAndSize((const char *)pevent->event.mmap2.build_id, size);} static PyGetSetDef pyrf_mmap2_event__getset[] = {	{		.name = "evsel",		.get = pyrf_event__get_evsel,		.set = NULL,		.doc = "tracking event.",	},	{		.name = "maj",		.get = pyrf_mmap2_event__get_maj,		.set = NULL,		.doc = "major number.",	},	{		.name = "min",		.get = pyrf_mmap2_event__get_min,		.set = NULL,		.doc = "minor number.",	},	{		.name = "ino",		.get = pyrf_mmap2_event__get_ino,		.set = NULL,		.doc = "inode number.",	},	{		.name = "ino_generation",		.get = pyrf_mmap2_event__get_ino_generation,		.set = NULL,		.doc = "inode generation.",	},	{		.name = "build_id",		.get = pyrf_mmap2_event__get_build_id,		.set = NULL,		.doc = "binary build ID.",	},	{ .name = NULL, },}; static PyMemberDef pyrf_mmap2_event__members[] = {	sample_members	member_def(perf_event_header, type, T_UINT, "event type"),	member_def(perf_event_header, misc, T_USHORT, "event misc"),	member_def(perf_record_mmap2, pid, T_UINT, "event pid"),	member_def(perf_record_mmap2, tid, T_UINT, "event tid"),	member_def(perf_record_mmap2, start, T_ULONGLONG, "start of the map"),	member_def(perf_record_mmap2, len, T_ULONGLONG, "map length"),	member_def(perf_record_mmap2, pgoff, T_ULONGLONG, "page offset"),	member_def(perf_record_mmap2, prot, T_UINT, "protection"),	member_def(perf_record_mmap2, flags, T_UINT, "flags"),	member_def(perf_record_mmap2, filename, T_STRING_INPLACE, "backing store"),	{ .name = NULL, },}; static PyObject *pyrf_mmap2_event__repr(const struct pyrf_event *pevent){	PyObject *ret;	char *s; 	if (asprintf(&s, "{ type: mmap2, pid: %u, tid: %u, start: %#" PRI_lx64 ", length: %#" PRI_lx64 ", offset: %#" PRI_lx64 ", flags: %#x, prot: %#x, filename: %s }",		     pevent->event.mmap2.pid, pevent->event.mmap2.tid,		     pevent->event.mmap2.start, pevent->event.mmap2.len,		     pevent->event.mmap2.pgoff, pevent->event.mmap2.flags,		     pevent->event.mmap2.prot, pevent->event.mmap2.filename) < 0)		return PyErr_NoMemory(); 	ret = PyUnicode_FromString(s);	free(s);	return ret;} static PyTypeObject pyrf_mmap2_event__type = {	PyVarObject_HEAD_INIT(NULL, 0)	.tp_name	= "perf.mmap2_event",	.tp_basicsize	= sizeof(struct pyrf_event),	.tp_dealloc	= (destructor)pyrf_event__delete,	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,	.tp_doc		= pyrf_mmap2_event__doc,	.tp_members	= pyrf_mmap2_event__members,	.tp_getset	= pyrf_mmap2_event__getset,	.tp_repr	= (reprfunc)pyrf_mmap2_event__repr,}; static const char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object."); static PyMemberDef pyrf_task_event__members[] = {	sample_members	member_def(perf_event_header, type, T_UINT, "event type"),	member_def(perf_record_fork, pid, T_UINT, "event pid"),	member_def(perf_record_fork, ppid, T_UINT, "event ppid"),	member_def(perf_record_fork, tid, T_UINT, "event tid"),	member_def(perf_record_fork, ptid, T_UINT, "event ptid"),	member_def(perf_record_fork, time, T_ULONGLONG, "timestamp"),	{ .name = NULL, },}; static PyObject *pyrf_task_event__repr(const struct pyrf_event *pevent){	return PyUnicode_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "				   "ptid: %u, time: %" PRI_lu64 "}",				   pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",				   pevent->event.fork.pid,				   pevent->event.fork.ppid,				   pevent->event.fork.tid,				   pevent->event.fork.ptid,				   pevent->event.fork.time);} static PyTypeObject pyrf_task_event__type = {	PyVarObject_HEAD_INIT(NULL, 0)	.tp_name	= "perf.task_event",	.tp_basicsize	= sizeof(struct pyrf_event),	.tp_dealloc	= (destructor)pyrf_event__delete,	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,	.tp_doc		= pyrf_task_event__doc,	.tp_members	= pyrf_task_event__members,	.tp_getset	= pyrf_event__getset,	.tp_repr	= (reprfunc)pyrf_task_event__repr,}; static const char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object."); static PyMemberDef pyrf_comm_event__members[] = {	sample_members	member_def(perf_event_header, type, T_UINT, "event type"),	member_def(perf_record_comm, pid, T_UINT, "event pid"),	member_def(perf_record_comm, tid, T_UINT, "event tid"),	member_def(perf_record_comm, comm, T_STRING_INPLACE, "process name"),	{ .name = NULL, },}; static PyObject *pyrf_comm_event__repr(const struct pyrf_event *pevent){	return PyUnicode_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",				   pevent->event.comm.pid,				   pevent->event.comm.tid,				   pevent->event.comm.comm);} static PyTypeObject pyrf_comm_event__type = {	PyVarObject_HEAD_INIT(NULL, 0)	.tp_name	= "perf.comm_event",	.tp_basicsize	= sizeof(struct pyrf_event),	.tp_dealloc	= (destructor)pyrf_event__delete,	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,	.tp_doc		= pyrf_comm_event__doc,	.tp_members	= pyrf_comm_event__members,	.tp_getset	= pyrf_event__getset,	.tp_repr	= (reprfunc)pyrf_comm_event__repr,}; static const char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object."); static PyMemberDef pyrf_throttle_event__members[] = {	sample_members	member_def(perf_event_header, type, T_UINT, "event type"),	member_def(perf_record_throttle, time, T_ULONGLONG, "timestamp"),	member_def(perf_record_throttle, id, T_ULONGLONG, "event id"),	member_def(perf_record_throttle, stream_id, T_ULONGLONG, "event stream id"),	{ .name = NULL, },}; static PyObject *pyrf_throttle_event__repr(const struct pyrf_event *pevent){	const struct perf_record_throttle *te = (const struct perf_record_throttle *)		(&pevent->event.header + 1); 	return PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRI_lu64 ", id: %" PRI_lu64				   ", stream_id: %" PRI_lu64 " }",				   pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",				   te->time, te->id, te->stream_id);} static PyTypeObject pyrf_throttle_event__type = {	PyVarObject_HEAD_INIT(NULL, 0)	.tp_name	= "perf.throttle_event",	.tp_basicsize	= sizeof(struct pyrf_event),	.tp_dealloc	= (destructor)pyrf_event__delete,	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,	.tp_doc		= pyrf_throttle_event__doc,	.tp_members	= pyrf_throttle_event__members,	.tp_getset	= pyrf_event__getset,	.tp_repr	= (reprfunc)pyrf_throttle_event__repr,}; static const char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object."); static PyMemberDef pyrf_lost_event__members[] = {	sample_members	member_def(perf_event_header, type, T_UINT, "event type"),	member_def(perf_record_lost, id, T_ULONGLONG, "event id"),	member_def(perf_record_lost, lost, T_ULONGLONG, "number of lost events"),	{ .name = NULL, },}; static PyObject *pyrf_lost_event__repr(const struct pyrf_event *pevent){	PyObject *ret;	char *s; 	if (asprintf(&s, "{ type: lost, id: %#" PRI_lx64 ", "			 "lost: %#" PRI_lx64 " }",		     pevent->event.lost.id, pevent->event.lost.lost) < 0) {		ret = PyErr_NoMemory();	} else {		ret = PyUnicode_FromString(s);		free(s);	}	return ret;} static PyTypeObject pyrf_lost_event__type = {	PyVarObject_HEAD_INIT(NULL, 0)	.tp_name	= "perf.lost_event",	.tp_basicsize	= sizeof(struct pyrf_event),	.tp_dealloc	= (destructor)pyrf_event__delete,	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,	.tp_doc		= pyrf_lost_event__doc,	.tp_members	= pyrf_lost_event__members,	.tp_getset	= pyrf_event__getset,	.tp_repr	= (reprfunc)pyrf_lost_event__repr,}; static const char pyrf_stat_event__doc[] = PyDoc_STR("perf stat event object."); static PyMemberDef pyrf_stat_event__members[] = {	sample_members	member_def(perf_event_header, type, T_UINT, "event type"),	member_def(perf_record_stat, id, T_ULONGLONG, "event id"),	member_def(perf_record_stat, cpu, T_UINT, "event cpu"),	member_def(perf_record_stat, thread, T_UINT, "event thread"),	member_def(perf_record_stat, val, T_ULONGLONG, "counter value"),	member_def(perf_record_stat, ena, T_ULONGLONG, "enabled time"),	member_def(perf_record_stat, run, T_ULONGLONG, "running time"),	{ .name = NULL, },}; static PyObject *pyrf_stat_event__repr(const struct pyrf_event *pevent){	return PyUnicode_FromFormat(		"{ type: stat, id: %llu, cpu: %u, thread: %u, val: %llu, ena: %llu, run: %llu }",		pevent->event.stat.id,		pevent->event.stat.cpu,		pevent->event.stat.thread,		pevent->event.stat.val,		pevent->event.stat.ena,		pevent->event.stat.run);} static PyTypeObject pyrf_stat_event__type = {	PyVarObject_HEAD_INIT(NULL, 0)	.tp_name	= "perf.stat_event",	.tp_basicsize	= sizeof(struct pyrf_event),	.tp_new		= PyType_GenericNew,	.tp_dealloc	= (destructor)pyrf_event__delete,

Lines 1–500 of 4341.