diff options
Diffstat (limited to 'tools/perf/util/scripting-engines/trace-event-python.c')
| -rw-r--r-- | tools/perf/util/scripting-engines/trace-event-python.c | 197 |
1 files changed, 174 insertions, 23 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 1c419321f707..cbce2545da45 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
| @@ -27,11 +27,13 @@ | |||
| 27 | #include <errno.h> | 27 | #include <errno.h> |
| 28 | 28 | ||
| 29 | #include "../../perf.h" | 29 | #include "../../perf.h" |
| 30 | #include "../debug.h" | ||
| 30 | #include "../evsel.h" | 31 | #include "../evsel.h" |
| 31 | #include "../util.h" | 32 | #include "../util.h" |
| 32 | #include "../event.h" | 33 | #include "../event.h" |
| 33 | #include "../thread.h" | 34 | #include "../thread.h" |
| 34 | #include "../trace-event.h" | 35 | #include "../trace-event.h" |
| 36 | #include "../machine.h" | ||
| 35 | 37 | ||
| 36 | PyMODINIT_FUNC initperf_trace_context(void); | 38 | PyMODINIT_FUNC initperf_trace_context(void); |
| 37 | 39 | ||
| @@ -50,10 +52,14 @@ static int zero_flag_atom; | |||
| 50 | 52 | ||
| 51 | static PyObject *main_module, *main_dict; | 53 | static PyObject *main_module, *main_dict; |
| 52 | 54 | ||
| 55 | static void handler_call_die(const char *handler_name) NORETURN; | ||
| 53 | static void handler_call_die(const char *handler_name) | 56 | static void handler_call_die(const char *handler_name) |
| 54 | { | 57 | { |
| 55 | PyErr_Print(); | 58 | PyErr_Print(); |
| 56 | Py_FatalError("problem in Python trace event handler"); | 59 | Py_FatalError("problem in Python trace event handler"); |
| 60 | // Py_FatalError does not return | ||
| 61 | // but we have to make the compiler happy | ||
| 62 | abort(); | ||
| 57 | } | 63 | } |
| 58 | 64 | ||
| 59 | /* | 65 | /* |
| @@ -97,6 +103,7 @@ static void define_value(enum print_arg_type field_type, | |||
| 97 | retval = PyObject_CallObject(handler, t); | 103 | retval = PyObject_CallObject(handler, t); |
| 98 | if (retval == NULL) | 104 | if (retval == NULL) |
| 99 | handler_call_die(handler_name); | 105 | handler_call_die(handler_name); |
| 106 | Py_DECREF(retval); | ||
| 100 | } | 107 | } |
| 101 | 108 | ||
| 102 | Py_DECREF(t); | 109 | Py_DECREF(t); |
| @@ -143,6 +150,7 @@ static void define_field(enum print_arg_type field_type, | |||
| 143 | retval = PyObject_CallObject(handler, t); | 150 | retval = PyObject_CallObject(handler, t); |
| 144 | if (retval == NULL) | 151 | if (retval == NULL) |
| 145 | handler_call_die(handler_name); | 152 | handler_call_die(handler_name); |
| 153 | Py_DECREF(retval); | ||
| 146 | } | 154 | } |
| 147 | 155 | ||
| 148 | Py_DECREF(t); | 156 | Py_DECREF(t); |
| @@ -231,15 +239,133 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) | |||
| 231 | return event; | 239 | return event; |
| 232 | } | 240 | } |
| 233 | 241 | ||
| 242 | static PyObject *get_field_numeric_entry(struct event_format *event, | ||
| 243 | struct format_field *field, void *data) | ||
| 244 | { | ||
| 245 | bool is_array = field->flags & FIELD_IS_ARRAY; | ||
| 246 | PyObject *obj, *list = NULL; | ||
| 247 | unsigned long long val; | ||
| 248 | unsigned int item_size, n_items, i; | ||
| 249 | |||
| 250 | if (is_array) { | ||
| 251 | list = PyList_New(field->arraylen); | ||
| 252 | item_size = field->size / field->arraylen; | ||
| 253 | n_items = field->arraylen; | ||
| 254 | } else { | ||
| 255 | item_size = field->size; | ||
| 256 | n_items = 1; | ||
| 257 | } | ||
| 258 | |||
| 259 | for (i = 0; i < n_items; i++) { | ||
| 260 | |||
| 261 | val = read_size(event, data + field->offset + i * item_size, | ||
| 262 | item_size); | ||
| 263 | if (field->flags & FIELD_IS_SIGNED) { | ||
| 264 | if ((long long)val >= LONG_MIN && | ||
| 265 | (long long)val <= LONG_MAX) | ||
| 266 | obj = PyInt_FromLong(val); | ||
| 267 | else | ||
| 268 | obj = PyLong_FromLongLong(val); | ||
| 269 | } else { | ||
| 270 | if (val <= LONG_MAX) | ||
| 271 | obj = PyInt_FromLong(val); | ||
| 272 | else | ||
| 273 | obj = PyLong_FromUnsignedLongLong(val); | ||
| 274 | } | ||
| 275 | if (is_array) | ||
| 276 | PyList_SET_ITEM(list, i, obj); | ||
| 277 | } | ||
| 278 | if (is_array) | ||
| 279 | obj = list; | ||
| 280 | return obj; | ||
| 281 | } | ||
| 282 | |||
| 283 | |||
| 284 | static PyObject *python_process_callchain(struct perf_sample *sample, | ||
| 285 | struct perf_evsel *evsel, | ||
| 286 | struct addr_location *al) | ||
| 287 | { | ||
| 288 | PyObject *pylist; | ||
| 289 | |||
| 290 | pylist = PyList_New(0); | ||
| 291 | if (!pylist) | ||
| 292 | Py_FatalError("couldn't create Python list"); | ||
| 293 | |||
| 294 | if (!symbol_conf.use_callchain || !sample->callchain) | ||
| 295 | goto exit; | ||
| 296 | |||
| 297 | if (machine__resolve_callchain(al->machine, evsel, al->thread, | ||
| 298 | sample, NULL, NULL, | ||
| 299 | PERF_MAX_STACK_DEPTH) != 0) { | ||
| 300 | pr_err("Failed to resolve callchain. Skipping\n"); | ||
| 301 | goto exit; | ||
| 302 | } | ||
| 303 | callchain_cursor_commit(&callchain_cursor); | ||
| 304 | |||
| 305 | |||
| 306 | while (1) { | ||
| 307 | PyObject *pyelem; | ||
| 308 | struct callchain_cursor_node *node; | ||
| 309 | node = callchain_cursor_current(&callchain_cursor); | ||
| 310 | if (!node) | ||
| 311 | break; | ||
| 312 | |||
| 313 | pyelem = PyDict_New(); | ||
| 314 | if (!pyelem) | ||
| 315 | Py_FatalError("couldn't create Python dictionary"); | ||
| 316 | |||
| 317 | |||
| 318 | pydict_set_item_string_decref(pyelem, "ip", | ||
| 319 | PyLong_FromUnsignedLongLong(node->ip)); | ||
| 320 | |||
| 321 | if (node->sym) { | ||
| 322 | PyObject *pysym = PyDict_New(); | ||
| 323 | if (!pysym) | ||
| 324 | Py_FatalError("couldn't create Python dictionary"); | ||
| 325 | pydict_set_item_string_decref(pysym, "start", | ||
| 326 | PyLong_FromUnsignedLongLong(node->sym->start)); | ||
| 327 | pydict_set_item_string_decref(pysym, "end", | ||
| 328 | PyLong_FromUnsignedLongLong(node->sym->end)); | ||
| 329 | pydict_set_item_string_decref(pysym, "binding", | ||
| 330 | PyInt_FromLong(node->sym->binding)); | ||
| 331 | pydict_set_item_string_decref(pysym, "name", | ||
| 332 | PyString_FromStringAndSize(node->sym->name, | ||
| 333 | node->sym->namelen)); | ||
| 334 | pydict_set_item_string_decref(pyelem, "sym", pysym); | ||
| 335 | } | ||
| 336 | |||
| 337 | if (node->map) { | ||
| 338 | struct map *map = node->map; | ||
| 339 | const char *dsoname = "[unknown]"; | ||
| 340 | if (map && map->dso && (map->dso->name || map->dso->long_name)) { | ||
| 341 | if (symbol_conf.show_kernel_path && map->dso->long_name) | ||
| 342 | dsoname = map->dso->long_name; | ||
| 343 | else if (map->dso->name) | ||
| 344 | dsoname = map->dso->name; | ||
| 345 | } | ||
| 346 | pydict_set_item_string_decref(pyelem, "dso", | ||
| 347 | PyString_FromString(dsoname)); | ||
| 348 | } | ||
| 349 | |||
| 350 | callchain_cursor_advance(&callchain_cursor); | ||
| 351 | PyList_Append(pylist, pyelem); | ||
| 352 | Py_DECREF(pyelem); | ||
| 353 | } | ||
| 354 | |||
| 355 | exit: | ||
| 356 | return pylist; | ||
| 357 | } | ||
| 358 | |||
| 359 | |||
| 234 | static void python_process_tracepoint(struct perf_sample *sample, | 360 | static void python_process_tracepoint(struct perf_sample *sample, |
| 235 | struct perf_evsel *evsel, | 361 | struct perf_evsel *evsel, |
| 236 | struct thread *thread, | 362 | struct thread *thread, |
| 237 | struct addr_location *al) | 363 | struct addr_location *al) |
| 238 | { | 364 | { |
| 239 | PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; | 365 | PyObject *handler, *retval, *context, *t, *obj, *callchain; |
| 366 | PyObject *dict = NULL; | ||
| 240 | static char handler_name[256]; | 367 | static char handler_name[256]; |
| 241 | struct format_field *field; | 368 | struct format_field *field; |
| 242 | unsigned long long val; | ||
| 243 | unsigned long s, ns; | 369 | unsigned long s, ns; |
| 244 | struct event_format *event; | 370 | struct event_format *event; |
| 245 | unsigned n = 0; | 371 | unsigned n = 0; |
| @@ -280,18 +406,23 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
| 280 | PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); | 406 | PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); |
| 281 | PyTuple_SetItem(t, n++, context); | 407 | PyTuple_SetItem(t, n++, context); |
| 282 | 408 | ||
| 409 | /* ip unwinding */ | ||
| 410 | callchain = python_process_callchain(sample, evsel, al); | ||
| 411 | |||
| 283 | if (handler) { | 412 | if (handler) { |
| 284 | PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); | 413 | PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); |
| 285 | PyTuple_SetItem(t, n++, PyInt_FromLong(s)); | 414 | PyTuple_SetItem(t, n++, PyInt_FromLong(s)); |
| 286 | PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); | 415 | PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); |
| 287 | PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); | 416 | PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); |
| 288 | PyTuple_SetItem(t, n++, PyString_FromString(comm)); | 417 | PyTuple_SetItem(t, n++, PyString_FromString(comm)); |
| 418 | PyTuple_SetItem(t, n++, callchain); | ||
| 289 | } else { | 419 | } else { |
| 290 | pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); | 420 | pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); |
| 291 | pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); | 421 | pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); |
| 292 | pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); | 422 | pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); |
| 293 | pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); | 423 | pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); |
| 294 | pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); | 424 | pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); |
| 425 | pydict_set_item_string_decref(dict, "common_callchain", callchain); | ||
| 295 | } | 426 | } |
| 296 | for (field = event->format.fields; field; field = field->next) { | 427 | for (field = event->format.fields; field; field = field->next) { |
| 297 | if (field->flags & FIELD_IS_STRING) { | 428 | if (field->flags & FIELD_IS_STRING) { |
| @@ -303,20 +434,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
| 303 | offset = field->offset; | 434 | offset = field->offset; |
| 304 | obj = PyString_FromString((char *)data + offset); | 435 | obj = PyString_FromString((char *)data + offset); |
| 305 | } else { /* FIELD_IS_NUMERIC */ | 436 | } else { /* FIELD_IS_NUMERIC */ |
| 306 | val = read_size(event, data + field->offset, | 437 | 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 | } | 438 | } |
| 321 | if (handler) | 439 | if (handler) |
| 322 | PyTuple_SetItem(t, n++, obj); | 440 | PyTuple_SetItem(t, n++, obj); |
| @@ -324,6 +442,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
| 324 | pydict_set_item_string_decref(dict, field->name, obj); | 442 | pydict_set_item_string_decref(dict, field->name, obj); |
| 325 | 443 | ||
| 326 | } | 444 | } |
| 445 | |||
| 327 | if (!handler) | 446 | if (!handler) |
| 328 | PyTuple_SetItem(t, n++, dict); | 447 | PyTuple_SetItem(t, n++, dict); |
| 329 | 448 | ||
| @@ -334,6 +453,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
| 334 | retval = PyObject_CallObject(handler, t); | 453 | retval = PyObject_CallObject(handler, t); |
| 335 | if (retval == NULL) | 454 | if (retval == NULL) |
| 336 | handler_call_die(handler_name); | 455 | handler_call_die(handler_name); |
| 456 | Py_DECREF(retval); | ||
| 337 | } else { | 457 | } else { |
| 338 | handler = PyDict_GetItemString(main_dict, "trace_unhandled"); | 458 | handler = PyDict_GetItemString(main_dict, "trace_unhandled"); |
| 339 | if (handler && PyCallable_Check(handler)) { | 459 | if (handler && PyCallable_Check(handler)) { |
| @@ -341,6 +461,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
| 341 | retval = PyObject_CallObject(handler, t); | 461 | retval = PyObject_CallObject(handler, t); |
| 342 | if (retval == NULL) | 462 | if (retval == NULL) |
| 343 | handler_call_die("trace_unhandled"); | 463 | handler_call_die("trace_unhandled"); |
| 464 | Py_DECREF(retval); | ||
| 344 | } | 465 | } |
| 345 | Py_DECREF(dict); | 466 | Py_DECREF(dict); |
| 346 | } | 467 | } |
| @@ -353,7 +474,7 @@ static void python_process_general_event(struct perf_sample *sample, | |||
| 353 | struct thread *thread, | 474 | struct thread *thread, |
| 354 | struct addr_location *al) | 475 | struct addr_location *al) |
| 355 | { | 476 | { |
| 356 | PyObject *handler, *retval, *t, *dict; | 477 | PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample; |
| 357 | static char handler_name[64]; | 478 | static char handler_name[64]; |
| 358 | unsigned n = 0; | 479 | unsigned n = 0; |
| 359 | 480 | ||
| @@ -369,6 +490,10 @@ static void python_process_general_event(struct perf_sample *sample, | |||
| 369 | if (!dict) | 490 | if (!dict) |
| 370 | Py_FatalError("couldn't create Python dictionary"); | 491 | Py_FatalError("couldn't create Python dictionary"); |
| 371 | 492 | ||
| 493 | dict_sample = PyDict_New(); | ||
| 494 | if (!dict_sample) | ||
| 495 | Py_FatalError("couldn't create Python dictionary"); | ||
| 496 | |||
| 372 | snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); | 497 | snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); |
| 373 | 498 | ||
| 374 | handler = PyDict_GetItemString(main_dict, handler_name); | 499 | handler = PyDict_GetItemString(main_dict, handler_name); |
| @@ -378,8 +503,21 @@ static void python_process_general_event(struct perf_sample *sample, | |||
| 378 | pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); | 503 | pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); |
| 379 | pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( | 504 | pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( |
| 380 | (const char *)&evsel->attr, sizeof(evsel->attr))); | 505 | (const char *)&evsel->attr, sizeof(evsel->attr))); |
| 381 | pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize( | 506 | |
| 382 | (const char *)sample, sizeof(*sample))); | 507 | pydict_set_item_string_decref(dict_sample, "pid", |
| 508 | PyInt_FromLong(sample->pid)); | ||
| 509 | pydict_set_item_string_decref(dict_sample, "tid", | ||
| 510 | PyInt_FromLong(sample->tid)); | ||
| 511 | pydict_set_item_string_decref(dict_sample, "cpu", | ||
| 512 | PyInt_FromLong(sample->cpu)); | ||
| 513 | pydict_set_item_string_decref(dict_sample, "ip", | ||
| 514 | PyLong_FromUnsignedLongLong(sample->ip)); | ||
| 515 | pydict_set_item_string_decref(dict_sample, "time", | ||
| 516 | PyLong_FromUnsignedLongLong(sample->time)); | ||
| 517 | pydict_set_item_string_decref(dict_sample, "period", | ||
| 518 | PyLong_FromUnsignedLongLong(sample->period)); | ||
| 519 | pydict_set_item_string_decref(dict, "sample", dict_sample); | ||
| 520 | |||
| 383 | pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( | 521 | pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( |
| 384 | (const char *)sample->raw_data, sample->raw_size)); | 522 | (const char *)sample->raw_data, sample->raw_size)); |
| 385 | pydict_set_item_string_decref(dict, "comm", | 523 | pydict_set_item_string_decref(dict, "comm", |
| @@ -393,6 +531,10 @@ static void python_process_general_event(struct perf_sample *sample, | |||
| 393 | PyString_FromString(al->sym->name)); | 531 | PyString_FromString(al->sym->name)); |
| 394 | } | 532 | } |
| 395 | 533 | ||
| 534 | /* ip unwinding */ | ||
| 535 | callchain = python_process_callchain(sample, evsel, al); | ||
| 536 | pydict_set_item_string_decref(dict, "callchain", callchain); | ||
| 537 | |||
| 396 | PyTuple_SetItem(t, n++, dict); | 538 | PyTuple_SetItem(t, n++, dict); |
| 397 | if (_PyTuple_Resize(&t, n) == -1) | 539 | if (_PyTuple_Resize(&t, n) == -1) |
| 398 | Py_FatalError("error resizing Python tuple"); | 540 | Py_FatalError("error resizing Python tuple"); |
| @@ -400,6 +542,7 @@ static void python_process_general_event(struct perf_sample *sample, | |||
| 400 | retval = PyObject_CallObject(handler, t); | 542 | retval = PyObject_CallObject(handler, t); |
| 401 | if (retval == NULL) | 543 | if (retval == NULL) |
| 402 | handler_call_die(handler_name); | 544 | handler_call_die(handler_name); |
| 545 | Py_DECREF(retval); | ||
| 403 | exit: | 546 | exit: |
| 404 | Py_DECREF(dict); | 547 | Py_DECREF(dict); |
| 405 | Py_DECREF(t); | 548 | Py_DECREF(t); |
| @@ -521,8 +664,7 @@ static int python_stop_script(void) | |||
| 521 | retval = PyObject_CallObject(handler, NULL); | 664 | retval = PyObject_CallObject(handler, NULL); |
| 522 | if (retval == NULL) | 665 | if (retval == NULL) |
| 523 | handler_call_die("trace_end"); | 666 | handler_call_die("trace_end"); |
| 524 | else | 667 | Py_DECREF(retval); |
| 525 | Py_DECREF(retval); | ||
| 526 | out: | 668 | out: |
| 527 | Py_XDECREF(main_dict); | 669 | Py_XDECREF(main_dict); |
| 528 | Py_XDECREF(main_module); | 670 | Py_XDECREF(main_module); |
| @@ -589,6 +731,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
| 589 | fprintf(ofp, "common_nsecs, "); | 731 | fprintf(ofp, "common_nsecs, "); |
| 590 | fprintf(ofp, "common_pid, "); | 732 | fprintf(ofp, "common_pid, "); |
| 591 | fprintf(ofp, "common_comm,\n\t"); | 733 | fprintf(ofp, "common_comm,\n\t"); |
| 734 | fprintf(ofp, "common_callchain, "); | ||
| 592 | 735 | ||
| 593 | not_first = 0; | 736 | not_first = 0; |
| 594 | count = 0; | 737 | count = 0; |
| @@ -632,7 +775,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
| 632 | fprintf(ofp, "%%u"); | 775 | fprintf(ofp, "%%u"); |
| 633 | } | 776 | } |
| 634 | 777 | ||
| 635 | fprintf(ofp, "\\n\" %% \\\n\t\t("); | 778 | fprintf(ofp, "\" %% \\\n\t\t("); |
| 636 | 779 | ||
| 637 | not_first = 0; | 780 | not_first = 0; |
| 638 | count = 0; | 781 | count = 0; |
| @@ -668,7 +811,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
| 668 | fprintf(ofp, "%s", f->name); | 811 | fprintf(ofp, "%s", f->name); |
| 669 | } | 812 | } |
| 670 | 813 | ||
| 671 | fprintf(ofp, "),\n\n"); | 814 | fprintf(ofp, ")\n\n"); |
| 815 | |||
| 816 | fprintf(ofp, "\t\tfor node in common_callchain:"); | ||
| 817 | fprintf(ofp, "\n\t\t\tif 'sym' in node:"); | ||
| 818 | fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])"); | ||
| 819 | fprintf(ofp, "\n\t\t\telse:"); | ||
| 820 | fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n"); | ||
| 821 | fprintf(ofp, "\t\tprint \"\\n\"\n\n"); | ||
| 822 | |||
| 672 | } | 823 | } |
| 673 | 824 | ||
| 674 | fprintf(ofp, "def trace_unhandled(event_name, context, " | 825 | fprintf(ofp, "def trace_unhandled(event_name, context, " |
