gdb/python: make the gdb.unwinder.Unwinder class more robust

This commit makes a few related changes to the gdb.unwinder.Unwinder
class attributes:

  1. The 'name' attribute is now a read-only attribute.  This prevents
  user code from changing the name after registering the unwinder.  It
  seems very unlikely that any user is actually trying to do this in
  the wild, so I'm not very worried that this will upset anyone,

  2. We now validate that the name is a string in the
  Unwinder.__init__ method, and throw an error if this is not the
  case.  Hopefully nobody was doing this in the wild.  This should
  make it easier to ensure the 'info unwinder' command shows sane
  output (how to display a non-string name for an unwinder?),

  3. The 'enabled' attribute is now implemented with a getter and
  setter.  In the setter we ensure that the new value is a boolean,
  but the real important change is that we call
  'gdb.invalidate_cached_frames()'.  This means that the backtrace
  will be updated if a user manually disables an unwinder (rather than
  calling the 'disable unwinder' command).  It is not unreasonable to
  think that a user might register multiple unwinders (relating to
  some project) and have one command that disables/enables all the
  related unwinders.  This command might operate by poking the enabled
  attribute of each unwinder object directly, after this commit, this
  would now work correctly.

There's tests for all the changes, and lots of documentation updates
that both cover the new changes, but also further improve (I think)
the general documentation for GDB's Unwinder API.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Reviewed-By: Tom Tromey <tom@tromey.com>
This commit is contained in:
Andrew Burgess 2023-03-08 16:11:30 +00:00
parent c22d38baef
commit 6bf5f25bb1
5 changed files with 193 additions and 14 deletions

View file

@ -35,8 +35,27 @@ class Unwinder(object):
Args:
name: An identifying name for the unwinder.
"""
self.name = name
self.enabled = True
if not isinstance(name, str):
raise TypeError("incorrect type for name: %s" % type(name))
self._name = name
self._enabled = True
@property
def name(self):
return self._name
@property
def enabled(self):
return self._enabled
@enabled.setter
def enabled(self, value):
if not isinstance(value, bool):
raise TypeError("incorrect type for enabled attribute: %s" % type(value))
self._enabled = value
gdb.invalidate_cached_frames()
def __call__(self, pending_frame):
"""GDB calls this method to unwind a frame.