crash.util.symbols module
*************************

The crash.util.symbols module provides a mechanism to simply discover
and resolve symbols, types, minimal symbols, and values.

A typical use is declaring a DelayedCollection at the top of a module
and using the DelayedCollection within the classes and functions that
are a part of the module.

Each of the collections defined here are instantiated using a list of
names that each collection type will resolve into a type, a symbol, a
minimal symbol, etc.  The names will by available as dictionary keys
and also as attribute names.  In the latter case, the names will be
resolved into a form usable as an attribute name.  See "Types" for
more information.

class crash.util.symbols.CallbackCollection(cls: Type[NamedCallback], cbs: List[Tuple[str, Callable]] | Tuple[str, Callable], wait_for_target: bool)

   Bases: "object"

class crash.util.symbols.DelayedCollection(cls: Type[DelayedValue], names: List[str] | str, wait_for_target: bool)

   Bases: "object"

   A generic container for delayed lookups.

   In addition to the "get()" method, the names are also accessible
   via attribute names ("__getattr__") or dictionary keys
   ("__getitem__").

   Parameters:
      * **cls** -- The type of "DelayedValue" to be collected

      * **names** -- The names of all the symbols to be collected

   attrs

      A dictionary that maps the attribute names to the "DelayedValue"
      object associated with each one. While the "__getattr__" and
      "__getitem__" methods will return the contained object.  This
      dictionary will contain the container object *or* the contained
      object if it has been overridden via "override()".

      Type:
         "dict"

   get(name: str) -> Type | Value | Symbol | MinSymbol | Any

      Obtain the object associated with name

      Parameters:
         **name** -- The attribute name associated with the
         "DelayedValue"

      Returns:
         The underlying object associated with this name.

      Return type:
         "object"

      Raises:
         * **NameError** -- The name does not exist.

         * **.DelayedAttributeError** -- The name exists but the value
           has not been resolved yet.

   override(name: str, value: Type | Value | Symbol | MinSymbol | Any) -> None

      Override the "DelayedValue" stored in the collection

      At times it may be required to override the value kept in the
      collection.

class crash.util.symbols.DelayedValues(names: List[str] | str, wait_for_target: bool = True)

   Bases: "DelayedCollection"

   A container to keep generic "DelayedValue" objects.

   These will raise "DelayedAttributeError" until
   "DelayedValue.callback()" is called with a value to populate it.

   The callback must be accessed via "DelayedCollection.attrs" or the
   "DelayedValue" object will be evaluated first, also raising
   "DelayedAttributeError".

   Example:


   >>> from crash.util.symbols import DelayedValues
   >>> dvals = DelayedValues(['generic_value', 'another_value'])
   >>> dvals.attrs['generic_value'].callback(True)
   >>> print(dvals.generic_value)
   True
   >>> print(dvals.another_value)
   Traceback (most recent call last):
     File "<string>", line 4, in <module>
     File "./build/lib/crash/util/symbols.py", line 107, in __getattr__
       return self.get(name)
     File "./build/lib/crash/util/symbols.py", line 85, in get
       raise DelayedAttributeError(name)
   crash.exceptions.DelayedAttributeError: Delayed attribute another_value has not been completed.

   Parameters:
      **names** -- The names to use for the "DelayedValue" objects.

class crash.util.symbols.MinimalSymbolCallbacks(cbs: List[Tuple[str, Callable]] | Tuple[str, Callable], wait_for_target: bool = True)

   Bases: "CallbackCollection"

class crash.util.symbols.MinimalSymbols(names: List[str] | str, wait_for_target: bool = True)

   Bases: "DelayedCollection"

   A container to resolve "gdb.MinSymbol" objects from the symbol
   table as they become available.  Minimal symbols don't have any
   type information associated with them so they are mostly used to
   resolve names to addresses.

   Example:


   >>> import gdb
   >>> from crash.util.symbols import MinimalSymbols
   >>> msymbols = MinimalSymbols(['modules', 'super_block'])
   >>> print(msymbols.modules.type)
   11
   >>> print(gdb.MINSYMBOL_TYPE_FILE_BSS)
   11
   >>> print(msymbols['modules'])
   modules
   >>> print(msymbols['modules'].value())
   <data variable, no debug info>
   >>> print(msymbols['modules'].value().address)
   0xffffffff820ff030 <modules>
   >>> print(type(msymbols['modules']))
   <class 'gdb.MinSymbol'>

   Parameters:
      **names** -- A "str" or "list" of "str" containing the names of
      the minimal symbols to resolve.

class crash.util.symbols.MinimalSymvals(names: List[str] | str, wait_for_target: bool = True)

   Bases: "DelayedCollection"

   A container to resolve "gdb.MinSymbol" objects from the symbol
   table as they become available and uses the address of the values
   associated with them as the stored object.  Minimal symbols don't
   have any type information associated with them so they are mostly
   used to resolve names to addresses.

   Example:


   >>> import gdb
   from crash.util.symbols import MinimalSymvals
   >>> msymvals = MinimalSymvals(['modules', 'super_block'])
   >>> print(f"{msymvals.modules:#x}")
   0xffffffff820ff030
   >>> print(f"{msymvals['modules']:#x}")
   0xffffffff820ff030
   >>> print(type(msymvals['modules']))
   <class 'int'>

   Parameters:
      **names** -- A "str" or "list" of "str" containing the names of
      the minimal symbols to resolve.

class crash.util.symbols.SymbolCallbacks(cbs: List[Tuple[str, Callable]] | Tuple[str, Callable], wait_for_target: bool = True)

   Bases: "CallbackCollection"

class crash.util.symbols.Symbols(names: List[str] | str, wait_for_target: bool = True)

   Bases: "DelayedCollection"

   A container to resolve "gdb.Symbol" objects from the symbol table
   as they become available.

   Example:

      >>> from crash.util.symbols import Symvals
      >>> symbols = Symbols(["modules", "super_blocks"])
      >>> print(symbols.modules)
      modules
      >>> print(symbols['modules'])
      modules
      >>> print(symbols.modules.type)
      <class 'gdb.Symbol'>

   Parameters:
      **names** -- A "str" or "list" of "str" containing the names of
      the symbols to resolve.

class crash.util.symbols.Symvals(names: List[str] | str, wait_for_target: bool = True)

   Bases: "DelayedCollection"

   A container to resolve "gdb.Symbol" objects from the symbol table
   as they become available and use the associated values as the
   stored object.

   Example:

      >>> from crash.util.symbols import Symvals
      >>> symvals = Symvals(["modules", "super_blocks"])
      >>> print(symvals.modules)
      {
        next = 0xffffffffc0675208 <__this_module+8>,
        prev = 0xffffffffc00e8b48 <__this_module+8>
      }
      >>> print(symvals.modules.address)
      0xffffffffab0ff030 <modules>
      >>> print(symvals['modules'])
      {
        next = 0xffffffffc0675208 <__this_module+8>,
        prev = 0xffffffffc00e8b48 <__this_module+8>
      }
      >>> print(symvals.modules.type)
      <class 'gdb.Value'>

   Parameters:
      **names** -- A "str" or "list" of "str" containing the names of
      the symbols to resolve.

class crash.util.symbols.TypeCallbacks(cbs: List[Tuple[str, Callable]] | Tuple[str, Callable], wait_for_target: bool = True)

   Bases: "CallbackCollection"

class crash.util.symbols.Types(names: List[str] | str, wait_for_target: bool = True)

   Bases: "DelayedCollection"

   A container to resolve "gdb.Type" objects from the symbol table as
   they become available.

   Example:

      >>> from crash.util.symbols import Types
      >>> types = Types(["struct foo", "struct foo *"])
      >>> ex1 = types.foo_type
      >>> ex2 = types.foo_p_type
      >>> ex3 = types['foo_type']
      >>> ex4 = types['struct foo']

   See "resolve_type()" for details.

   Parameters:
      **names** -- A "str" or "list" of "str" containing the names of
      the types to resolve.

   override(name: str, value: Type) -> None

      Override the type value, resolving the type name first.

      The *real* type name is used, not the attribute name.

      >>> t = gdb.lookup_type('struct foo')
      >>> types.override('struct foo', t)
