legacy_tracing.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. /* Support for legacy tracing on top of PEP 669 instrumentation
  2. * Provides callables to forward PEP 669 events to legacy events.
  3. */
  4. #include <stddef.h>
  5. #include "Python.h"
  6. #include "opcode.h"
  7. #include "pycore_ceval.h"
  8. #include "pycore_object.h"
  9. #include "pycore_sysmodule.h"
  10. typedef struct _PyLegacyEventHandler {
  11. PyObject_HEAD
  12. vectorcallfunc vectorcall;
  13. int event;
  14. } _PyLegacyEventHandler;
  15. /* The Py_tracefunc function expects the following arguments:
  16. * obj: the trace object (PyObject *)
  17. * frame: the current frame (PyFrameObject *)
  18. * kind: the kind of event, see PyTrace_XXX #defines (int)
  19. * arg: The arg (a PyObject *)
  20. */
  21. static PyObject *
  22. call_profile_func(_PyLegacyEventHandler *self, PyObject *arg)
  23. {
  24. PyThreadState *tstate = _PyThreadState_GET();
  25. if (tstate->c_profilefunc == NULL) {
  26. Py_RETURN_NONE;
  27. }
  28. PyFrameObject *frame = PyEval_GetFrame();
  29. if (frame == NULL) {
  30. PyErr_SetString(PyExc_SystemError,
  31. "Missing frame when calling profile function.");
  32. return NULL;
  33. }
  34. Py_INCREF(frame);
  35. int err = tstate->c_profilefunc(tstate->c_profileobj, frame, self->event, arg);
  36. Py_DECREF(frame);
  37. if (err) {
  38. return NULL;
  39. }
  40. Py_RETURN_NONE;
  41. }
  42. static PyObject *
  43. sys_profile_func2(
  44. _PyLegacyEventHandler *self, PyObject *const *args,
  45. size_t nargsf, PyObject *kwnames
  46. ) {
  47. assert(kwnames == NULL);
  48. assert(PyVectorcall_NARGS(nargsf) == 2);
  49. return call_profile_func(self, Py_None);
  50. }
  51. static PyObject *
  52. sys_profile_func3(
  53. _PyLegacyEventHandler *self, PyObject *const *args,
  54. size_t nargsf, PyObject *kwnames
  55. ) {
  56. assert(kwnames == NULL);
  57. assert(PyVectorcall_NARGS(nargsf) == 3);
  58. return call_profile_func(self, args[2]);
  59. }
  60. static PyObject *
  61. sys_profile_unwind(
  62. _PyLegacyEventHandler *self, PyObject *const *args,
  63. size_t nargsf, PyObject *kwnames
  64. ) {
  65. assert(kwnames == NULL);
  66. assert(PyVectorcall_NARGS(nargsf) == 3);
  67. return call_profile_func(self, Py_None);
  68. }
  69. static PyObject *
  70. sys_profile_call_or_return(
  71. _PyLegacyEventHandler *self, PyObject *const *args,
  72. size_t nargsf, PyObject *kwnames
  73. ) {
  74. assert(kwnames == NULL);
  75. assert(PyVectorcall_NARGS(nargsf) == 4);
  76. PyObject *callable = args[2];
  77. if (PyCFunction_Check(callable)) {
  78. return call_profile_func(self, callable);
  79. }
  80. if (Py_TYPE(callable) == &PyMethodDescr_Type) {
  81. PyObject *self_arg = args[3];
  82. /* For backwards compatibility need to
  83. * convert to builtin method */
  84. /* If no arg, skip */
  85. if (self_arg == &_PyInstrumentation_MISSING) {
  86. Py_RETURN_NONE;
  87. }
  88. PyObject *meth = Py_TYPE(callable)->tp_descr_get(
  89. callable, self_arg, (PyObject*)Py_TYPE(self_arg));
  90. if (meth == NULL) {
  91. return NULL;
  92. }
  93. PyObject *res = call_profile_func(self, meth);
  94. Py_DECREF(meth);
  95. return res;
  96. }
  97. else if (Py_TYPE(callable) == &PyMethod_Type) {
  98. // CALL instruction will grab the function from the method,
  99. // so if the function is a C function, the return event will
  100. // be emitted. However, CALL event happens before CALL
  101. // instruction, so we need to handle this case here.
  102. PyObject* func = PyMethod_GET_FUNCTION(callable);
  103. if (func == NULL) {
  104. return NULL;
  105. }
  106. if (PyCFunction_Check(func)) {
  107. return call_profile_func(self, func);
  108. }
  109. }
  110. Py_RETURN_NONE;
  111. }
  112. static PyObject *
  113. call_trace_func(_PyLegacyEventHandler *self, PyObject *arg)
  114. {
  115. PyThreadState *tstate = _PyThreadState_GET();
  116. if (tstate->c_tracefunc == NULL) {
  117. Py_RETURN_NONE;
  118. }
  119. PyFrameObject *frame = PyEval_GetFrame();
  120. if (frame == NULL) {
  121. PyErr_SetString(PyExc_SystemError,
  122. "Missing frame when calling trace function.");
  123. return NULL;
  124. }
  125. Py_INCREF(frame);
  126. int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, arg);
  127. Py_DECREF(frame);
  128. if (err) {
  129. return NULL;
  130. }
  131. Py_RETURN_NONE;
  132. }
  133. static PyObject *
  134. sys_trace_exception_func(
  135. _PyLegacyEventHandler *self, PyObject *const *args,
  136. size_t nargsf, PyObject *kwnames
  137. ) {
  138. assert(kwnames == NULL);
  139. assert(PyVectorcall_NARGS(nargsf) == 3);
  140. PyObject *exc = args[2];
  141. assert(PyExceptionInstance_Check(exc));
  142. PyObject *type = (PyObject *)Py_TYPE(exc);
  143. PyObject *tb = PyException_GetTraceback(exc);
  144. if (tb == NULL) {
  145. tb = Py_NewRef(Py_None);
  146. }
  147. PyObject *tuple = PyTuple_Pack(3, type, exc, tb);
  148. Py_DECREF(tb);
  149. if (tuple == NULL) {
  150. return NULL;
  151. }
  152. PyObject *res = call_trace_func(self, tuple);
  153. Py_DECREF(tuple);
  154. return res;
  155. }
  156. static PyObject *
  157. sys_trace_func2(
  158. _PyLegacyEventHandler *self, PyObject *const *args,
  159. size_t nargsf, PyObject *kwnames
  160. ) {
  161. assert(kwnames == NULL);
  162. assert(PyVectorcall_NARGS(nargsf) == 2);
  163. return call_trace_func(self, Py_None);
  164. }
  165. static PyObject *
  166. sys_trace_func3(
  167. _PyLegacyEventHandler *self, PyObject *const *args,
  168. size_t nargsf, PyObject *kwnames
  169. ) {
  170. assert(kwnames == NULL);
  171. assert(PyVectorcall_NARGS(nargsf) == 3);
  172. return call_trace_func(self, Py_None);
  173. }
  174. static PyObject *
  175. sys_trace_return(
  176. _PyLegacyEventHandler *self, PyObject *const *args,
  177. size_t nargsf, PyObject *kwnames
  178. ) {
  179. assert(!PyErr_Occurred());
  180. assert(kwnames == NULL);
  181. assert(PyVectorcall_NARGS(nargsf) == 3);
  182. assert(PyCode_Check(args[0]));
  183. PyObject *val = args[2];
  184. PyObject *res = call_trace_func(self, val);
  185. return res;
  186. }
  187. static PyObject *
  188. sys_trace_yield(
  189. _PyLegacyEventHandler *self, PyObject *const *args,
  190. size_t nargsf, PyObject *kwnames
  191. ) {
  192. assert(kwnames == NULL);
  193. assert(PyVectorcall_NARGS(nargsf) == 3);
  194. return call_trace_func(self, args[2]);
  195. }
  196. static PyObject *
  197. sys_trace_instruction_func(
  198. _PyLegacyEventHandler *self, PyObject *const *args,
  199. size_t nargsf, PyObject *kwnames
  200. ) {
  201. assert(kwnames == NULL);
  202. assert(PyVectorcall_NARGS(nargsf) == 2);
  203. PyFrameObject *frame = PyEval_GetFrame();
  204. if (frame == NULL) {
  205. PyErr_SetString(PyExc_SystemError,
  206. "Missing frame when calling trace function.");
  207. return NULL;
  208. }
  209. if (!frame->f_trace_opcodes) {
  210. Py_RETURN_NONE;
  211. }
  212. Py_INCREF(frame);
  213. PyThreadState *tstate = _PyThreadState_GET();
  214. int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, Py_None);
  215. frame->f_lineno = 0;
  216. Py_DECREF(frame);
  217. if (err) {
  218. return NULL;
  219. }
  220. Py_RETURN_NONE;
  221. }
  222. static PyObject *
  223. trace_line(
  224. PyThreadState *tstate, _PyLegacyEventHandler *self,
  225. PyFrameObject *frame, int line
  226. ) {
  227. if (!frame->f_trace_lines) {
  228. Py_RETURN_NONE;
  229. }
  230. if (line < 0) {
  231. Py_RETURN_NONE;
  232. }
  233. Py_INCREF(frame);
  234. frame->f_lineno = line;
  235. int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, Py_None);
  236. frame->f_lineno = 0;
  237. Py_DECREF(frame);
  238. if (err) {
  239. return NULL;
  240. }
  241. Py_RETURN_NONE;
  242. }
  243. static PyObject *
  244. sys_trace_line_func(
  245. _PyLegacyEventHandler *self, PyObject *const *args,
  246. size_t nargsf, PyObject *kwnames
  247. ) {
  248. assert(kwnames == NULL);
  249. PyThreadState *tstate = _PyThreadState_GET();
  250. if (tstate->c_tracefunc == NULL) {
  251. Py_RETURN_NONE;
  252. }
  253. assert(PyVectorcall_NARGS(nargsf) == 2);
  254. int line = _PyLong_AsInt(args[1]);
  255. assert(line >= 0);
  256. PyFrameObject *frame = PyEval_GetFrame();
  257. if (frame == NULL) {
  258. PyErr_SetString(PyExc_SystemError,
  259. "Missing frame when calling trace function.");
  260. return NULL;
  261. }
  262. assert(args[0] == (PyObject *)frame->f_frame->f_code);
  263. return trace_line(tstate, self, frame, line);
  264. }
  265. /* sys.settrace generates line events for all backward
  266. * edges, even if on the same line.
  267. * Handle that case here */
  268. static PyObject *
  269. sys_trace_jump_func(
  270. _PyLegacyEventHandler *self, PyObject *const *args,
  271. size_t nargsf, PyObject *kwnames
  272. ) {
  273. assert(kwnames == NULL);
  274. PyThreadState *tstate = _PyThreadState_GET();
  275. if (tstate->c_tracefunc == NULL) {
  276. Py_RETURN_NONE;
  277. }
  278. assert(PyVectorcall_NARGS(nargsf) == 3);
  279. int from = _PyLong_AsInt(args[1])/sizeof(_Py_CODEUNIT);
  280. assert(from >= 0);
  281. int to = _PyLong_AsInt(args[2])/sizeof(_Py_CODEUNIT);
  282. assert(to >= 0);
  283. if (to > from) {
  284. /* Forward jump */
  285. return &_PyInstrumentation_DISABLE;
  286. }
  287. PyCodeObject *code = (PyCodeObject *)args[0];
  288. assert(PyCode_Check(code));
  289. /* We can call _Py_Instrumentation_GetLine because we always set
  290. * line events for tracing */
  291. int to_line = _Py_Instrumentation_GetLine(code, to);
  292. int from_line = _Py_Instrumentation_GetLine(code, from);
  293. if (to_line != from_line) {
  294. /* Will be handled by target INSTRUMENTED_LINE */
  295. return &_PyInstrumentation_DISABLE;
  296. }
  297. PyFrameObject *frame = PyEval_GetFrame();
  298. if (frame == NULL) {
  299. PyErr_SetString(PyExc_SystemError,
  300. "Missing frame when calling trace function.");
  301. return NULL;
  302. }
  303. assert(code == frame->f_frame->f_code);
  304. if (!frame->f_trace_lines) {
  305. Py_RETURN_NONE;
  306. }
  307. return trace_line(tstate, self, frame, to_line);
  308. }
  309. PyTypeObject _PyLegacyEventHandler_Type = {
  310. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  311. "sys.legacy_event_handler",
  312. sizeof(_PyLegacyEventHandler),
  313. .tp_dealloc = (destructor)PyObject_Free,
  314. .tp_vectorcall_offset = offsetof(_PyLegacyEventHandler, vectorcall),
  315. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
  316. Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_DISALLOW_INSTANTIATION,
  317. .tp_call = PyVectorcall_Call,
  318. };
  319. static int
  320. set_callbacks(int tool, vectorcallfunc vectorcall, int legacy_event, int event1, int event2)
  321. {
  322. _PyLegacyEventHandler *callback =
  323. PyObject_NEW(_PyLegacyEventHandler, &_PyLegacyEventHandler_Type);
  324. if (callback == NULL) {
  325. return -1;
  326. }
  327. callback->vectorcall = vectorcall;
  328. callback->event = legacy_event;
  329. Py_XDECREF(_PyMonitoring_RegisterCallback(tool, event1, (PyObject *)callback));
  330. if (event2 >= 0) {
  331. Py_XDECREF(_PyMonitoring_RegisterCallback(tool, event2, (PyObject *)callback));
  332. }
  333. Py_DECREF(callback);
  334. return 0;
  335. }
  336. #ifndef NDEBUG
  337. /* Ensure that tstate is valid: sanity check for PyEval_AcquireThread() and
  338. PyEval_RestoreThread(). Detect if tstate memory was freed. It can happen
  339. when a thread continues to run after Python finalization, especially
  340. daemon threads. */
  341. static int
  342. is_tstate_valid(PyThreadState *tstate)
  343. {
  344. assert(!_PyMem_IsPtrFreed(tstate));
  345. assert(!_PyMem_IsPtrFreed(tstate->interp));
  346. return 1;
  347. }
  348. #endif
  349. int
  350. _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
  351. {
  352. assert(is_tstate_valid(tstate));
  353. /* The caller must hold the GIL */
  354. assert(PyGILState_Check());
  355. /* Call _PySys_Audit() in the context of the current thread state,
  356. even if tstate is not the current thread state. */
  357. PyThreadState *current_tstate = _PyThreadState_GET();
  358. if (_PySys_Audit(current_tstate, "sys.setprofile", NULL) < 0) {
  359. return -1;
  360. }
  361. /* Setup PEP 669 monitoring callbacks and events. */
  362. if (!tstate->interp->sys_profile_initialized) {
  363. tstate->interp->sys_profile_initialized = true;
  364. if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
  365. (vectorcallfunc)sys_profile_func2, PyTrace_CALL,
  366. PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RESUME)) {
  367. return -1;
  368. }
  369. if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
  370. (vectorcallfunc)sys_profile_func3, PyTrace_CALL,
  371. PY_MONITORING_EVENT_PY_THROW, -1)) {
  372. return -1;
  373. }
  374. if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
  375. (vectorcallfunc)sys_profile_func3, PyTrace_RETURN,
  376. PY_MONITORING_EVENT_PY_RETURN, PY_MONITORING_EVENT_PY_YIELD)) {
  377. return -1;
  378. }
  379. if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
  380. (vectorcallfunc)sys_profile_unwind, PyTrace_RETURN,
  381. PY_MONITORING_EVENT_PY_UNWIND, -1)) {
  382. return -1;
  383. }
  384. if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
  385. (vectorcallfunc)sys_profile_call_or_return, PyTrace_C_CALL,
  386. PY_MONITORING_EVENT_CALL, -1)) {
  387. return -1;
  388. }
  389. if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
  390. (vectorcallfunc)sys_profile_call_or_return, PyTrace_C_RETURN,
  391. PY_MONITORING_EVENT_C_RETURN, -1)) {
  392. return -1;
  393. }
  394. if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
  395. (vectorcallfunc)sys_profile_call_or_return, PyTrace_C_EXCEPTION,
  396. PY_MONITORING_EVENT_C_RAISE, -1)) {
  397. return -1;
  398. }
  399. }
  400. int delta = (func != NULL) - (tstate->c_profilefunc != NULL);
  401. tstate->c_profilefunc = func;
  402. PyObject *old_profileobj = tstate->c_profileobj;
  403. tstate->c_profileobj = Py_XNewRef(arg);
  404. Py_XDECREF(old_profileobj);
  405. tstate->interp->sys_profiling_threads += delta;
  406. assert(tstate->interp->sys_profiling_threads >= 0);
  407. uint32_t events = 0;
  408. if (tstate->interp->sys_profiling_threads) {
  409. events =
  410. (1 << PY_MONITORING_EVENT_PY_START) | (1 << PY_MONITORING_EVENT_PY_RESUME) |
  411. (1 << PY_MONITORING_EVENT_PY_RETURN) | (1 << PY_MONITORING_EVENT_PY_YIELD) |
  412. (1 << PY_MONITORING_EVENT_CALL) | (1 << PY_MONITORING_EVENT_PY_UNWIND) |
  413. (1 << PY_MONITORING_EVENT_PY_THROW);
  414. }
  415. return _PyMonitoring_SetEvents(PY_MONITORING_SYS_PROFILE_ID, events);
  416. }
  417. int
  418. _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
  419. {
  420. assert(is_tstate_valid(tstate));
  421. /* The caller must hold the GIL */
  422. assert(PyGILState_Check());
  423. /* Call _PySys_Audit() in the context of the current thread state,
  424. even if tstate is not the current thread state. */
  425. PyThreadState *current_tstate = _PyThreadState_GET();
  426. if (_PySys_Audit(current_tstate, "sys.settrace", NULL) < 0) {
  427. return -1;
  428. }
  429. assert(tstate->interp->sys_tracing_threads >= 0);
  430. /* Setup PEP 669 monitoring callbacks and events. */
  431. if (!tstate->interp->sys_trace_initialized) {
  432. tstate->interp->sys_trace_initialized = true;
  433. if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
  434. (vectorcallfunc)sys_trace_func2, PyTrace_CALL,
  435. PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RESUME)) {
  436. return -1;
  437. }
  438. if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
  439. (vectorcallfunc)sys_trace_func3, PyTrace_CALL,
  440. PY_MONITORING_EVENT_PY_THROW, -1)) {
  441. return -1;
  442. }
  443. if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
  444. (vectorcallfunc)sys_trace_return, PyTrace_RETURN,
  445. PY_MONITORING_EVENT_PY_RETURN, -1)) {
  446. return -1;
  447. }
  448. if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
  449. (vectorcallfunc)sys_trace_yield, PyTrace_RETURN,
  450. PY_MONITORING_EVENT_PY_YIELD, -1)) {
  451. return -1;
  452. }
  453. if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
  454. (vectorcallfunc)sys_trace_exception_func, PyTrace_EXCEPTION,
  455. PY_MONITORING_EVENT_RAISE, PY_MONITORING_EVENT_STOP_ITERATION)) {
  456. return -1;
  457. }
  458. if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
  459. (vectorcallfunc)sys_trace_line_func, PyTrace_LINE,
  460. PY_MONITORING_EVENT_LINE, -1)) {
  461. return -1;
  462. }
  463. if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
  464. (vectorcallfunc)sys_trace_func3, PyTrace_RETURN,
  465. PY_MONITORING_EVENT_PY_UNWIND, -1)) {
  466. return -1;
  467. }
  468. if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
  469. (vectorcallfunc)sys_trace_jump_func, PyTrace_LINE,
  470. PY_MONITORING_EVENT_JUMP, -1)) {
  471. return -1;
  472. }
  473. if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
  474. (vectorcallfunc)sys_trace_instruction_func, PyTrace_OPCODE,
  475. PY_MONITORING_EVENT_INSTRUCTION, -1)) {
  476. return -1;
  477. }
  478. }
  479. int delta = (func != NULL) - (tstate->c_tracefunc != NULL);
  480. tstate->c_tracefunc = func;
  481. PyObject *old_traceobj = tstate->c_traceobj;
  482. tstate->c_traceobj = Py_XNewRef(arg);
  483. Py_XDECREF(old_traceobj);
  484. tstate->interp->sys_tracing_threads += delta;
  485. assert(tstate->interp->sys_tracing_threads >= 0);
  486. uint32_t events = 0;
  487. if (tstate->interp->sys_tracing_threads) {
  488. events =
  489. (1 << PY_MONITORING_EVENT_PY_START) | (1 << PY_MONITORING_EVENT_PY_RESUME) |
  490. (1 << PY_MONITORING_EVENT_PY_RETURN) | (1 << PY_MONITORING_EVENT_PY_YIELD) |
  491. (1 << PY_MONITORING_EVENT_RAISE) | (1 << PY_MONITORING_EVENT_LINE) |
  492. (1 << PY_MONITORING_EVENT_JUMP) | (1 << PY_MONITORING_EVENT_BRANCH) |
  493. (1 << PY_MONITORING_EVENT_PY_UNWIND) | (1 << PY_MONITORING_EVENT_PY_THROW) |
  494. (1 << PY_MONITORING_EVENT_STOP_ITERATION) |
  495. (1 << PY_MONITORING_EVENT_EXCEPTION_HANDLED);
  496. if (tstate->interp->f_opcode_trace_set) {
  497. events |= (1 << PY_MONITORING_EVENT_INSTRUCTION);
  498. }
  499. }
  500. return _PyMonitoring_SetEvents(PY_MONITORING_SYS_TRACE_ID, events);
  501. }