Home | History | Annotate | Download | only in command
      1 # Unwinder commands.
      2 # Copyright 2015-2016 Free Software Foundation, Inc.
      3 
      4 # This program is free software; you can redistribute it and/or modify
      5 # it under the terms of the GNU General Public License as published by
      6 # the Free Software Foundation; either version 3 of the License, or
      7 # (at your option) any later version.
      8 #
      9 # This program is distributed in the hope that it will be useful,
     10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 # GNU General Public License for more details.
     13 #
     14 # You should have received a copy of the GNU General Public License
     15 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16 
     17 import gdb
     18 import re
     19 
     20 
     21 def validate_regexp(exp, idstring):
     22     try:
     23         return re.compile(exp)
     24     except SyntaxError:
     25         raise SyntaxError("Invalid %s regexp: %s." % (idstring, exp))
     26 
     27 
     28 def parse_unwinder_command_args(arg):
     29     """Internal utility to parse unwinder command argv.
     30 
     31     Arguments:
     32         arg: The arguments to the command. The format is:
     33              [locus-regexp [name-regexp]]
     34 
     35     Returns:
     36         A 2-tuple of compiled regular expressions.
     37 
     38     Raises:
     39         SyntaxError: an error processing ARG
     40     """
     41 
     42     argv = gdb.string_to_argv(arg)
     43     argc = len(argv)
     44     if argc > 2:
     45         raise SyntaxError("Too many arguments.")
     46     locus_regexp = ""
     47     name_regexp = ""
     48     if argc >= 1:
     49         locus_regexp = argv[0]
     50         if argc >= 2:
     51             name_regexp = argv[1]
     52     return (validate_regexp(locus_regexp, "locus"),
     53             validate_regexp(name_regexp, "unwinder"))
     54 
     55 
     56 class InfoUnwinder(gdb.Command):
     57     """GDB command to list unwinders.
     58 
     59     Usage: info unwinder [locus-regexp [name-regexp]]
     60 
     61     LOCUS-REGEXP is a regular expression matching the location of the
     62     unwinder.  If it is omitted, all registered unwinders from all
     63     loci are listed.  A locus can be 'global', 'progspace' to list
     64     the unwinders from the current progspace, or a regular expression
     65     matching filenames of objfiles.
     66 
     67     NAME-REGEXP is a regular expression to filter unwinder names.  If
     68     this omitted for a specified locus, then all registered unwinders
     69     in the locus are listed.
     70     """
     71 
     72     def __init__(self):
     73         super(InfoUnwinder, self).__init__("info unwinder",
     74                                             gdb.COMMAND_STACK)
     75 
     76     def list_unwinders(self, title, unwinders, name_re):
     77         """Lists the unwinders whose name matches regexp.
     78 
     79         Arguments:
     80             title: The line to print before the list.
     81             unwinders: The list of the unwinders.
     82             name_re: unwinder name filter.
     83         """
     84         if not unwinders:
     85             return
     86         print(title)
     87         for unwinder in unwinders:
     88             if name_re.match(unwinder.name):
     89                 print("  %s%s" % (unwinder.name,
     90                                   "" if unwinder.enabled else " [disabled]"))
     91 
     92     def invoke(self, arg, from_tty):
     93         locus_re, name_re = parse_unwinder_command_args(arg)
     94         if locus_re.match("global"):
     95             self.list_unwinders("Global:", gdb.frame_unwinders,
     96                                 name_re)
     97         if locus_re.match("progspace"):
     98             cp = gdb.current_progspace()
     99             self.list_unwinders("Progspace %s:" % cp.filename,
    100                                 cp.frame_unwinders, name_re)
    101         for objfile in gdb.objfiles():
    102             if locus_re.match(objfile.filename):
    103                 self.list_unwinders("Objfile %s:" % objfile.filename,
    104                                     objfile.frame_unwinders, name_re)
    105 
    106 
    107 def do_enable_unwinder1(unwinders, name_re, flag):
    108     """Enable/disable unwinders whose names match given regex.
    109 
    110     Arguments:
    111         unwinders: The list of unwinders.
    112         name_re: Unwinder name filter.
    113         flag: Enable/disable.
    114 
    115     Returns:
    116         The number of unwinders affected.
    117     """
    118     total = 0
    119     for unwinder in unwinders:
    120         if name_re.match(unwinder.name):
    121             unwinder.enabled = flag
    122             total += 1
    123     return total
    124 
    125 
    126 def do_enable_unwinder(arg, flag):
    127     """Enable/disable unwinder(s)."""
    128     (locus_re, name_re) = parse_unwinder_command_args(arg)
    129     total = 0
    130     if locus_re.match("global"):
    131         total += do_enable_unwinder1(gdb.frame_unwinders, name_re, flag)
    132     if locus_re.match("progspace"):
    133         total += do_enable_unwinder1(gdb.current_progspace().frame_unwinders,
    134                                      name_re, flag)
    135     for objfile in gdb.objfiles():
    136         if locus_re.match(objfile.filename):
    137             total += do_enable_unwinder1(objfile.frame_unwinders, name_re,
    138                                          flag)
    139     print("%d unwinder%s %s" % (total, "" if total == 1 else "s",
    140                                 "enabled" if flag else "disabled"))
    141 
    142 
    143 class EnableUnwinder(gdb.Command):
    144     """GDB command to enable unwinders.
    145 
    146     Usage: enable unwinder [locus-regexp [name-regexp]]
    147 
    148     LOCUS-REGEXP is a regular expression specifying the unwinders to
    149     enable.  It can 'global', 'progspace', or the name of an objfile
    150     within that progspace.
    151 
    152     NAME_REGEXP is a regular expression to filter unwinder names.  If
    153     this omitted for a specified locus, then all registered unwinders
    154     in the locus are affected.
    155 
    156     """
    157 
    158     def __init__(self):
    159         super(EnableUnwinder, self).__init__("enable unwinder",
    160                                              gdb.COMMAND_STACK)
    161 
    162     def invoke(self, arg, from_tty):
    163         """GDB calls this to perform the command."""
    164         do_enable_unwinder(arg, True)
    165 
    166 
    167 class DisableUnwinder(gdb.Command):
    168     """GDB command to disable the specified unwinder.
    169 
    170     Usage: disable unwinder [locus-regexp [name-regexp]]
    171 
    172     LOCUS-REGEXP is a regular expression specifying the unwinders to
    173     disable.  It can 'global', 'progspace', or the name of an objfile
    174     within that progspace.
    175 
    176     NAME_REGEXP is a regular expression to filter unwinder names.  If
    177     this omitted for a specified locus, then all registered unwinders
    178     in the locus are affected.
    179 
    180     """
    181 
    182     def __init__(self):
    183         super(DisableUnwinder, self).__init__("disable unwinder",
    184                                               gdb.COMMAND_STACK)
    185 
    186     def invoke(self, arg, from_tty):
    187         """GDB calls this to perform the command."""
    188         do_enable_unwinder(arg, False)
    189 
    190 
    191 def register_unwinder_commands():
    192     """Installs the unwinder commands."""
    193     InfoUnwinder()
    194     EnableUnwinder()
    195     DisableUnwinder()
    196 
    197 
    198 register_unwinder_commands()
    199