diff options
Diffstat (limited to 'gdb/python/py-record-btrace.c')
-rw-r--r-- | gdb/python/py-record-btrace.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c index 49b6c74..68b474c 100644 --- a/gdb/python/py-record-btrace.c +++ b/gdb/python/py-record-btrace.c @@ -808,6 +808,109 @@ recpy_bt_function_call_history (PyObject *self, void *closure) return btpy_list_new (tinfo, first, last, 1, &recpy_func_type); } +/* Helper function that calls PTW_FILTER with PAYLOAD and IP as arguments. + Returns the string that will be printed, if there is a filter to call. */ +static std::optional<std::string> +recpy_call_filter (const uint64_t payload, const uint64_t ip, + const void *ptw_filter) +{ + std::optional<std::string> result; + + gdb_assert (ptw_filter != nullptr); + if ((PyObject *) ptw_filter == Py_None) + return result; + + gdbpy_enter enter_py; + + gdbpy_ref<> py_payload = gdb_py_object_from_ulongest (payload); + + gdbpy_ref<> py_ip; + if (ip == 0) + py_ip = gdbpy_ref<>::new_reference (Py_None); + else + py_ip = gdb_py_object_from_ulongest (ip); + + gdbpy_ref<> py_result (PyObject_CallFunctionObjArgs ((PyObject *) ptw_filter, + py_payload.get (), + py_ip.get (), + nullptr)); + + if (py_result == nullptr) + { + gdbpy_print_stack (); + gdbpy_error (_("Couldn't call the ptwrite filter.")); + } + + /* Py_None is valid and results in no output. */ + if (py_result == Py_None) + { + result = ""; + return result; + } + + gdb::unique_xmalloc_ptr<char> user_string + = gdbpy_obj_to_string (py_result.get ()); + + if (user_string == nullptr) + { + gdbpy_print_stack (); + gdbpy_error (_("The ptwrite filter didn't return a string.")); + } + else + result = user_string.get (); + + return result; +} + +/* Helper function returning the current ptwrite filter. */ + +static PyObject * +get_ptwrite_filter () +{ + gdbpy_ref<> module (PyImport_ImportModule ("gdb.ptwrite")); + + if (PyErr_Occurred ()) + { + gdbpy_print_stack (); + gdbpy_error (_("Couldn't import gdb.ptwrite.")); + } + + /* We need to keep the reference count. */ + gdbpy_ref<> ptw_filter (gdbpy_call_method (module.get (), "get_filter")); + + if (PyErr_Occurred ()) + { + gdbpy_print_stack (); + gdbpy_error (_("Couldn't get the ptwrite filter.")); + } + + return ptw_filter.get(); +} + +/* Used for registering any python ptwrite filter to the current thread. A + pointer to this function is stored in the python extension interface. */ + +void +gdbpy_load_ptwrite_filter (const struct extension_language_defn *extlang, + struct btrace_thread_info *btinfo) +{ + gdb_assert (btinfo != nullptr); + + gdbpy_enter enter_py; + + btinfo->ptw_context = get_ptwrite_filter (); + +#if defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) + if (!btinfo->target->conf.pt.ptwrite && btinfo->ptw_context != Py_None) + warning (_("The target doesn't support decoding ptwrite events.")); +#else + if (btinfo->ptw_context != Py_None) + warning (_("Libipt doesn't support decoding ptwrite events.")); +#endif /* defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) */ + + btinfo->ptw_callback_fun = &recpy_call_filter; +} + /* Implementation of BtraceRecord.goto (self, BtraceInstruction) -> None. */ PyObject * |