Home | History | Annotate | Download | only in gdb
      1 # Copyright (C) 2015-2016 Free Software Foundation, Inc.
      2 
      3 # This program is free software; you can redistribute it and/or modify
      4 # it under the terms of the GNU General Public License as published by
      5 # the Free Software Foundation; either version 3 of the License, or
      6 # (at your option) any later version.
      7 #
      8 # This program is distributed in the hope that it will be useful,
      9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11 # GNU General Public License for more details.
     12 #
     13 # You should have received a copy of the GNU General Public License
     14 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15 
     16 """Unwinder class and register_unwinder function."""
     17 
     18 import gdb
     19 
     20 
     21 class Unwinder(object):
     22     """Base class (or a template) for frame unwinders written in Python.
     23 
     24     An unwinder has a single method __call__ and the attributes
     25     described below.
     26 
     27     Attributes:
     28         name: The name of the unwinder.
     29         enabled: A boolean indicating whether the unwinder is enabled.
     30     """
     31 
     32     def __init__(self, name):
     33         """Constructor.
     34 
     35         Args:
     36             name: An identifying name for the unwinder.
     37         """
     38         self.name = name
     39         self.enabled = True
     40 
     41     def __call__(self, pending_frame):
     42         """GDB calls this method to unwind a frame.
     43 
     44         Arguments:
     45             pending_frame: gdb.PendingFrame instance.
     46 
     47         Returns:
     48             gdb.UnwindInfo instance.
     49         """
     50         raise NotImplementedError("Unwinder __call__.")
     51 
     52 
     53 def register_unwinder(locus, unwinder, replace=False):
     54     """Register unwinder in given locus.
     55 
     56     The unwinder is prepended to the locus's unwinders list. Unwinder
     57     name should be unique.
     58 
     59     Arguments:
     60         locus: Either an objfile, progspace, or None (in which case
     61                the unwinder is registered globally).
     62         unwinder: An object of a gdb.Unwinder subclass
     63         replace: If True, replaces existing unwinder with the same name.
     64                  Otherwise, raises exception if unwinder with the same
     65                  name already exists.
     66 
     67     Returns:
     68         Nothing.
     69 
     70     Raises:
     71         RuntimeError: Unwinder name is not unique
     72         TypeError: Bad locus type
     73     """
     74     if locus is None:
     75         if gdb.parameter("verbose"):
     76             gdb.write("Registering global %s unwinder ...\n" % unwinder.name)
     77         locus = gdb
     78     elif isinstance(locus, gdb.Objfile) or isinstance(locus, gdb.Progspace):
     79         if gdb.parameter("verbose"):
     80             gdb.write("Registering %s unwinder for %s ...\n" %
     81                       (unwinder.name, locus.filename))
     82     else:
     83         raise TypeError("locus should be gdb.Objfile or gdb.Progspace or None")
     84 
     85     i = 0
     86     for needle in locus.frame_unwinders:
     87         if needle.name == unwinder.name:
     88             if replace:
     89                 del locus.frame_unwinders[i]
     90             else:
     91                 raise RuntimeError("Unwinder %s already exists." %
     92                                    unwinder.name)
     93         i += 1
     94     locus.frame_unwinders.insert(0, unwinder)
     95