From 6be9971c93f3bbcd4b779e5591697748da6b093e Mon Sep 17 00:00:00 2001 From: Felix Willgerodt Date: Tue, 15 May 2018 15:42:24 +0200 Subject: btrace, python: Enable ptwrite filter registration. By default GDB will be printing the hex payload of the ptwrite package as auxiliary information. To customize this, the user can register a ptwrite filter function in python, that takes the payload and the PC as arguments and returns a string which will be printed instead. Registering the filter function is done using a factory pattern to make per-thread filtering easier. Approved-By: Markus Metzger --- gdb/python/lib/gdb/ptwrite.py | 77 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 gdb/python/lib/gdb/ptwrite.py (limited to 'gdb/python/lib') diff --git a/gdb/python/lib/gdb/ptwrite.py b/gdb/python/lib/gdb/ptwrite.py new file mode 100644 index 0000000..3be65fe --- /dev/null +++ b/gdb/python/lib/gdb/ptwrite.py @@ -0,0 +1,77 @@ +# Ptwrite utilities. +# Copyright (C) 2023 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Utilities for working with ptwrite filters.""" + +import gdb + +# _ptwrite_filter contains the per thread copies of the filter function. +# The keys are tuples of inferior id and thread id. +# The filter functions are created for each thread by calling the +# _ptwrite_filter_factory. +_ptwrite_filter = {} +_ptwrite_filter_factory = None + + +def _ptwrite_exit_handler(event): + """Exit handler to prune _ptwrite_filter on thread exit.""" + _ptwrite_filter.pop(event.inferior_thread.ptid, None) + + +gdb.events.thread_exited.connect(_ptwrite_exit_handler) + + +def _clear_traces(): + """Helper function to clear the trace of all threads.""" + current_thread = gdb.selected_thread() + + for inferior in gdb.inferiors(): + for thread in inferior.threads(): + thread.switch() + recording = gdb.current_recording() + if recording is not None: + recording.clear() + + current_thread.switch() + + +def register_filter_factory(filter_factory_): + """Register the ptwrite filter factory.""" + if filter_factory_ is not None and not callable(filter_factory_): + raise TypeError("The filter factory must be callable or 'None'.") + + # Clear the traces of all threads of all inferiors to force + # re-decoding with the new filter. + _clear_traces() + + _ptwrite_filter.clear() + global _ptwrite_filter_factory + _ptwrite_filter_factory = filter_factory_ + + +def get_filter(): + """Returns the filter of the current thread.""" + thread = gdb.selected_thread() + key = thread.ptid + + # Create a new filter for new threads. + if key not in _ptwrite_filter: + if _ptwrite_filter_factory is not None: + _ptwrite_filter[key] = _ptwrite_filter_factory(thread) + else: + return None + + return _ptwrite_filter[key] -- cgit v1.1