Viewing file: unwinders.py (6.47 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# Unwinder commands. # Copyright 2015-2018 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/>.
import gdb import re
def validate_regexp(exp, idstring): try: return re.compile(exp) except SyntaxError: raise SyntaxError("Invalid %s regexp: %s." % (idstring, exp))
def parse_unwinder_command_args(arg): """Internal utility to parse unwinder command argv.
Arguments: arg: The arguments to the command. The format is: [locus-regexp [name-regexp]]
Returns: A 2-tuple of compiled regular expressions.
Raises: SyntaxError: an error processing ARG """
argv = gdb.string_to_argv(arg) argc = len(argv) if argc > 2: raise SyntaxError("Too many arguments.") locus_regexp = "" name_regexp = "" if argc >= 1: locus_regexp = argv[0] if argc >= 2: name_regexp = argv[1] return (validate_regexp(locus_regexp, "locus"), validate_regexp(name_regexp, "unwinder"))
class InfoUnwinder(gdb.Command): """GDB command to list unwinders.
Usage: info unwinder [locus-regexp [name-regexp]]
LOCUS-REGEXP is a regular expression matching the location of the unwinder. If it is omitted, all registered unwinders from all loci are listed. A locus can be 'global', 'progspace' to list the unwinders from the current progspace, or a regular expression matching filenames of objfiles.
NAME-REGEXP is a regular expression to filter unwinder names. If this omitted for a specified locus, then all registered unwinders in the locus are listed. """
def __init__(self): super(InfoUnwinder, self).__init__("info unwinder", gdb.COMMAND_STACK)
def list_unwinders(self, title, unwinders, name_re): """Lists the unwinders whose name matches regexp.
Arguments: title: The line to print before the list. unwinders: The list of the unwinders. name_re: unwinder name filter. """ if not unwinders: return print(title) for unwinder in unwinders: if name_re.match(unwinder.name): print(" %s%s" % (unwinder.name, "" if unwinder.enabled else " [disabled]"))
def invoke(self, arg, from_tty): locus_re, name_re = parse_unwinder_command_args(arg) if locus_re.match("global"): self.list_unwinders("Global:", gdb.frame_unwinders, name_re) if locus_re.match("progspace"): cp = gdb.current_progspace() self.list_unwinders("Progspace %s:" % cp.filename, cp.frame_unwinders, name_re) for objfile in gdb.objfiles(): if locus_re.match(objfile.filename): self.list_unwinders("Objfile %s:" % objfile.filename, objfile.frame_unwinders, name_re)
def do_enable_unwinder1(unwinders, name_re, flag): """Enable/disable unwinders whose names match given regex.
Arguments: unwinders: The list of unwinders. name_re: Unwinder name filter. flag: Enable/disable.
Returns: The number of unwinders affected. """ total = 0 for unwinder in unwinders: if name_re.match(unwinder.name): unwinder.enabled = flag total += 1 return total
def do_enable_unwinder(arg, flag): """Enable/disable unwinder(s).""" (locus_re, name_re) = parse_unwinder_command_args(arg) total = 0 if locus_re.match("global"): total += do_enable_unwinder1(gdb.frame_unwinders, name_re, flag) if locus_re.match("progspace"): total += do_enable_unwinder1(gdb.current_progspace().frame_unwinders, name_re, flag) for objfile in gdb.objfiles(): if locus_re.match(objfile.filename): total += do_enable_unwinder1(objfile.frame_unwinders, name_re, flag) if total > 0: gdb.invalidate_cached_frames() print("%d unwinder%s %s" % (total, "" if total == 1 else "s", "enabled" if flag else "disabled"))
class EnableUnwinder(gdb.Command): """GDB command to enable unwinders.
Usage: enable unwinder [locus-regexp [name-regexp]]
LOCUS-REGEXP is a regular expression specifying the unwinders to enable. It can 'global', 'progspace', or the name of an objfile within that progspace.
NAME_REGEXP is a regular expression to filter unwinder names. If this omitted for a specified locus, then all registered unwinders in the locus are affected.
"""
def __init__(self): super(EnableUnwinder, self).__init__("enable unwinder", gdb.COMMAND_STACK)
def invoke(self, arg, from_tty): """GDB calls this to perform the command.""" do_enable_unwinder(arg, True)
class DisableUnwinder(gdb.Command): """GDB command to disable the specified unwinder.
Usage: disable unwinder [locus-regexp [name-regexp]]
LOCUS-REGEXP is a regular expression specifying the unwinders to disable. It can 'global', 'progspace', or the name of an objfile within that progspace.
NAME_REGEXP is a regular expression to filter unwinder names. If this omitted for a specified locus, then all registered unwinders in the locus are affected.
"""
def __init__(self): super(DisableUnwinder, self).__init__("disable unwinder", gdb.COMMAND_STACK)
def invoke(self, arg, from_tty): """GDB calls this to perform the command.""" do_enable_unwinder(arg, False)
def register_unwinder_commands(): """Installs the unwinder commands.""" InfoUnwinder() EnableUnwinder() DisableUnwinder()
register_unwinder_commands()
|