| Index: gdb/python/lib/gdb/frames.py
|
| diff --git a/gdb/python/lib/gdb/frames.py b/gdb/python/lib/gdb/frames.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c148b9826e84727437756e07e4eaafcb99c67ff9
|
| --- /dev/null
|
| +++ b/gdb/python/lib/gdb/frames.py
|
| @@ -0,0 +1,228 @@
|
| +# Frame-filter commands.
|
| +# Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
|
| +
|
| +"""Internal functions for working with frame-filters."""
|
| +
|
| +import gdb
|
| +from gdb.FrameIterator import FrameIterator
|
| +from gdb.FrameDecorator import FrameDecorator
|
| +import itertools
|
| +import collections
|
| +
|
| +def get_priority(filter_item):
|
| + """ Internal worker function to return the frame-filter's priority
|
| + from a frame filter object. This is a fail free function as it is
|
| + used in sorting and filtering. If a badly implemented frame
|
| + filter does not implement the priority attribute, return zero
|
| + (otherwise sorting/filtering will fail and prevent other frame
|
| + filters from executing).
|
| +
|
| + Arguments:
|
| + filter_item: An object conforming to the frame filter
|
| + interface.
|
| +
|
| + Returns:
|
| + The priority of the frame filter from the "priority"
|
| + attribute, or zero.
|
| + """
|
| + # Do not fail here, as the sort will fail. If a filter has not
|
| + # (incorrectly) set a priority, set it to zero.
|
| + return getattr(filter_item, "priority", 0)
|
| +
|
| +def set_priority(filter_item, priority):
|
| + """ Internal worker function to set the frame-filter's priority.
|
| +
|
| + Arguments:
|
| + filter_item: An object conforming to the frame filter
|
| + interface.
|
| + priority: The priority to assign as an integer.
|
| + """
|
| +
|
| + filter_item.priority = priority
|
| +
|
| +def get_enabled(filter_item):
|
| + """ Internal worker function to return a filter's enabled state
|
| + from a frame filter object. This is a fail free function as it is
|
| + used in sorting and filtering. If a badly implemented frame
|
| + filter does not implement the enabled attribute, return False
|
| + (otherwise sorting/filtering will fail and prevent other frame
|
| + filters from executing).
|
| +
|
| + Arguments:
|
| + filter_item: An object conforming to the frame filter
|
| + interface.
|
| +
|
| + Returns:
|
| + The enabled state of the frame filter from the "enabled"
|
| + attribute, or False.
|
| + """
|
| +
|
| + # If the filter class is badly implemented when called from the
|
| + # Python filter command, do not cease filter operations, just set
|
| + # enabled to False.
|
| + return getattr(filter_item, "enabled", False)
|
| +
|
| +def set_enabled(filter_item, state):
|
| + """ Internal Worker function to set the frame-filter's enabled
|
| + state.
|
| +
|
| + Arguments:
|
| + filter_item: An object conforming to the frame filter
|
| + interface.
|
| + state: True or False, depending on desired state.
|
| + """
|
| +
|
| + filter_item.enabled = state
|
| +
|
| +def return_list(name):
|
| + """ Internal Worker function to return the frame filter
|
| + dictionary, depending on the name supplied as an argument. If the
|
| + name is not "all", "global" or "progspace", it is assumed to name
|
| + an object-file.
|
| +
|
| + Arguments:
|
| + name: The name of the list, as specified by GDB user commands.
|
| +
|
| + Returns:
|
| + A dictionary object for a single specified dictionary, or a
|
| + list containing all the items for "all"
|
| +
|
| + Raises:
|
| + gdb.GdbError: A dictionary of that name cannot be found.
|
| + """
|
| +
|
| + # If all dictionaries are wanted in the case of "all" we
|
| + # cannot return a combined dictionary as keys() may clash in
|
| + # between different dictionaries. As we just want all the frame
|
| + # filters to enable/disable them all, just return the combined
|
| + # items() as a chained iterator of dictionary values.
|
| + if name == "all":
|
| + glob = gdb.frame_filters.values()
|
| + prog = gdb.current_progspace().frame_filters.values()
|
| + return_iter = itertools.chain(glob, prog)
|
| + for objfile in gdb.objfiles():
|
| + return_iter = itertools.chain(return_iter, objfile.frame_filters.values())
|
| +
|
| + return return_iter
|
| +
|
| + if name == "global":
|
| + return gdb.frame_filters
|
| + else:
|
| + if name == "progspace":
|
| + cp = gdb.current_progspace()
|
| + return cp.frame_filters
|
| + else:
|
| + for objfile in gdb.objfiles():
|
| + if name == objfile.filename:
|
| + return objfile.frame_filters
|
| +
|
| + msg = "Cannot find frame-filter dictionary for '" + name + "'"
|
| + raise gdb.GdbError(msg)
|
| +
|
| +def _sort_list():
|
| + """ Internal Worker function to merge all known frame-filter
|
| + lists, prune any filters with the state set to "disabled", and
|
| + sort the list on the frame-filter's "priority" attribute.
|
| +
|
| + Returns:
|
| + sorted_list: A sorted, pruned list of frame filters to
|
| + execute.
|
| + """
|
| +
|
| + all_filters = return_list("all")
|
| + sorted_frame_filters = sorted(all_filters, key = get_priority,
|
| + reverse = True)
|
| +
|
| + sorted_frame_filters = filter(get_enabled,
|
| + sorted_frame_filters)
|
| +
|
| + return sorted_frame_filters
|
| +
|
| +def execute_frame_filters(frame, frame_low, frame_high):
|
| + """ Internal function called from GDB that will execute the chain
|
| + of frame filters. Each filter is executed in priority order.
|
| + After the execution completes, slice the iterator to frame_low -
|
| + frame_high range.
|
| +
|
| + Arguments:
|
| + frame: The initial frame.
|
| +
|
| + frame_low: The low range of the slice. If this is a negative
|
| + integer then it indicates a backward slice (ie bt -4) which
|
| + counts backward from the last frame in the backtrace.
|
| +
|
| + frame_high: The high range of the slice. If this is -1 then
|
| + it indicates all frames until the end of the stack from
|
| + frame_low.
|
| +
|
| + Returns:
|
| + frame_iterator: The sliced iterator after all frame
|
| + filters have had a change to execute, or None if no frame
|
| + filters are registered.
|
| + """
|
| +
|
| + # Get a sorted list of frame filters.
|
| + sorted_list = list(_sort_list())
|
| +
|
| + # Check to see if there are any frame-filters. If not, just
|
| + # return None and let default backtrace printing occur.
|
| + if len(sorted_list) == 0:
|
| + return None
|
| +
|
| + frame_iterator = FrameIterator(frame)
|
| +
|
| + # Apply a basic frame decorator to all gdb.Frames. This unifies
|
| + # the interface. Python 3.x moved the itertools.imap
|
| + # functionality to map(), so check if it is available.
|
| + if hasattr(itertools,"imap"):
|
| + frame_iterator = itertools.imap(FrameDecorator, frame_iterator)
|
| + else:
|
| + frame_iterator = map(FrameDecorator, frame_iterator)
|
| +
|
| + for ff in sorted_list:
|
| + frame_iterator = ff.filter(frame_iterator)
|
| +
|
| + # Slicing
|
| +
|
| + # Is this a slice from the end of the backtrace, ie bt -2?
|
| + if frame_low < 0:
|
| + count = 0
|
| + slice_length = abs(frame_low)
|
| + # We cannot use MAXLEN argument for deque as it is 2.6 onwards
|
| + # and some GDB versions might be < 2.6.
|
| + sliced = collections.deque()
|
| +
|
| + for frame_item in frame_iterator:
|
| + if count >= slice_length:
|
| + sliced.popleft();
|
| + count = count + 1
|
| + sliced.append(frame_item)
|
| +
|
| + return iter(sliced)
|
| +
|
| + # -1 for frame_high means until the end of the backtrace. Set to
|
| + # None if that is the case, to indicate to itertools.islice to
|
| + # slice to the end of the iterator.
|
| + if frame_high == -1:
|
| + frame_high = None
|
| + else:
|
| + # As frames start from 0, add one to frame_high so islice
|
| + # correctly finds the end
|
| + frame_high = frame_high + 1;
|
| +
|
| + sliced = itertools.islice(frame_iterator, frame_low, frame_high)
|
| +
|
| + return sliced
|
|
|