xref: /xnu-12377.41.6/tools/lldbmacros/kmemory/whatis.py (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1*bbb1b6f9SApple OSS Distributionsimport operator
2*bbb1b6f9SApple OSS Distributions
3*bbb1b6f9SApple OSS Distributionsfrom abc import ABCMeta, abstractmethod
4*bbb1b6f9SApple OSS Distributionsfrom core import (
5*bbb1b6f9SApple OSS Distributions    caching,
6*bbb1b6f9SApple OSS Distributions    gettype,
7*bbb1b6f9SApple OSS Distributions)
8*bbb1b6f9SApple OSS Distributions
9*bbb1b6f9SApple OSS Distributionsfrom .kmem import KMem, MemoryRange
10*bbb1b6f9SApple OSS Distributions
11*bbb1b6f9SApple OSS Distributions
12*bbb1b6f9SApple OSS Distributionsclass MemoryObject(object, metaclass=ABCMeta):
13*bbb1b6f9SApple OSS Distributions    """
14*bbb1b6f9SApple OSS Distributions    Abstract class for any memory object resolved by Whatis
15*bbb1b6f9SApple OSS Distributions    """
16*bbb1b6f9SApple OSS Distributions
17*bbb1b6f9SApple OSS Distributions    MO_KIND = None
18*bbb1b6f9SApple OSS Distributions
19*bbb1b6f9SApple OSS Distributions    def __init__(self, kmem, address):
20*bbb1b6f9SApple OSS Distributions        self.kmem    = kmem
21*bbb1b6f9SApple OSS Distributions        self.address = address
22*bbb1b6f9SApple OSS Distributions
23*bbb1b6f9SApple OSS Distributions    @property
24*bbb1b6f9SApple OSS Distributions    @abstractmethod
25*bbb1b6f9SApple OSS Distributions    def object_range(self):
26*bbb1b6f9SApple OSS Distributions        """
27*bbb1b6f9SApple OSS Distributions        Returns the MemoryRange for this object if any
28*bbb1b6f9SApple OSS Distributions        """
29*bbb1b6f9SApple OSS Distributions        pass
30*bbb1b6f9SApple OSS Distributions
31*bbb1b6f9SApple OSS Distributions    @abstractmethod
32*bbb1b6f9SApple OSS Distributions    def describe(self, verbose=False):
33*bbb1b6f9SApple OSS Distributions        """
34*bbb1b6f9SApple OSS Distributions        Method to describe oneself for whatis
35*bbb1b6f9SApple OSS Distributions        """
36*bbb1b6f9SApple OSS Distributions        pass
37*bbb1b6f9SApple OSS Distributions
38*bbb1b6f9SApple OSS Distributions
39*bbb1b6f9SApple OSS Distributionsclass UnknownMemoryObject(MemoryObject):
40*bbb1b6f9SApple OSS Distributions    """ Fallback Memory Object for unclaimed addresses """
41*bbb1b6f9SApple OSS Distributions
42*bbb1b6f9SApple OSS Distributions    MO_KIND = "<unknown>"
43*bbb1b6f9SApple OSS Distributions
44*bbb1b6f9SApple OSS Distributions    @property
45*bbb1b6f9SApple OSS Distributions    def object_range(self):
46*bbb1b6f9SApple OSS Distributions        return None
47*bbb1b6f9SApple OSS Distributions
48*bbb1b6f9SApple OSS Distributions    def describe(self, verbose=False):
49*bbb1b6f9SApple OSS Distributions        print("Unknown Memory Object Info")
50*bbb1b6f9SApple OSS Distributions        print(" this address is not recognized, please implement/extend")
51*bbb1b6f9SApple OSS Distributions        print(" a WhatisProvider to recognize it in the future")
52*bbb1b6f9SApple OSS Distributions        print()
53*bbb1b6f9SApple OSS Distributions
54*bbb1b6f9SApple OSS Distributions
55*bbb1b6f9SApple OSS Distributionsclass WhatisProvider(object):
56*bbb1b6f9SApple OSS Distributions    """ Base class for Whatis Providers """
57*bbb1b6f9SApple OSS Distributions
58*bbb1b6f9SApple OSS Distributions    """
59*bbb1b6f9SApple OSS Distributions    List of direct subclasses, used for resolution
60*bbb1b6f9SApple OSS Distributions    """
61*bbb1b6f9SApple OSS Distributions    subproviders = []
62*bbb1b6f9SApple OSS Distributions
63*bbb1b6f9SApple OSS Distributions    """
64*bbb1b6f9SApple OSS Distributions    Evaluation cost of this provider
65*bbb1b6f9SApple OSS Distributions
66*bbb1b6f9SApple OSS Distributions    the higher the cost, the later it gets evaluated.
67*bbb1b6f9SApple OSS Distributions    """
68*bbb1b6f9SApple OSS Distributions
69*bbb1b6f9SApple OSS Distributions    COST = 10
70*bbb1b6f9SApple OSS Distributions
71*bbb1b6f9SApple OSS Distributions    def __init__(self, target):
72*bbb1b6f9SApple OSS Distributions        self._children = list(cls(target) for cls in self.__class__.subproviders)
73*bbb1b6f9SApple OSS Distributions        self.kmem      = KMem.get_shared()
74*bbb1b6f9SApple OSS Distributions        self.target    = target
75*bbb1b6f9SApple OSS Distributions
76*bbb1b6f9SApple OSS Distributions    @staticmethod
77*bbb1b6f9SApple OSS Distributions    @caching.cache_statically
78*bbb1b6f9SApple OSS Distributions    def get_shared(target=None):
79*bbb1b6f9SApple OSS Distributions        return WhatisProvider(target)
80*bbb1b6f9SApple OSS Distributions
81*bbb1b6f9SApple OSS Distributions    def find_provider(self, address):
82*bbb1b6f9SApple OSS Distributions        return next(iter(c for c in self._children if c.claims(address)), self)
83*bbb1b6f9SApple OSS Distributions
84*bbb1b6f9SApple OSS Distributions    def claims(self, address):
85*bbb1b6f9SApple OSS Distributions        """
86*bbb1b6f9SApple OSS Distributions        Returns whether this provider "claims" the address
87*bbb1b6f9SApple OSS Distributions
88*bbb1b6f9SApple OSS Distributions        @param address (int)
89*bbb1b6f9SApple OSS Distributions            The addrress being considered
90*bbb1b6f9SApple OSS Distributions        """
91*bbb1b6f9SApple OSS Distributions
92*bbb1b6f9SApple OSS Distributions        pass
93*bbb1b6f9SApple OSS Distributions
94*bbb1b6f9SApple OSS Distributions    def lookup(self, address):
95*bbb1b6f9SApple OSS Distributions        """
96*bbb1b6f9SApple OSS Distributions        Lookup a memory object by address
97*bbb1b6f9SApple OSS Distributions
98*bbb1b6f9SApple OSS Distributions        @param address (int)
99*bbb1b6f9SApple OSS Distributions            The addrress being considered
100*bbb1b6f9SApple OSS Distributions
101*bbb1b6f9SApple OSS Distributions        @returns (MemoryObject)
102*bbb1b6f9SApple OSS Distributions        """
103*bbb1b6f9SApple OSS Distributions
104*bbb1b6f9SApple OSS Distributions        return UnknownMemoryObject(self.kmem, address)
105*bbb1b6f9SApple OSS Distributions
106*bbb1b6f9SApple OSS Distributions    def describe(self, mo):
107*bbb1b6f9SApple OSS Distributions        """
108*bbb1b6f9SApple OSS Distributions        Describe a memory object
109*bbb1b6f9SApple OSS Distributions
110*bbb1b6f9SApple OSS Distributions        Providers can override this method to add more information.
111*bbb1b6f9SApple OSS Distributions        """
112*bbb1b6f9SApple OSS Distributions
113*bbb1b6f9SApple OSS Distributions        print((
114*bbb1b6f9SApple OSS Distributions            "Basic Info\n"
115*bbb1b6f9SApple OSS Distributions            " kind                 : {0.__class__.MO_KIND}\n"
116*bbb1b6f9SApple OSS Distributions            " address              : {0.address:#x}"
117*bbb1b6f9SApple OSS Distributions        ).format(mo))
118*bbb1b6f9SApple OSS Distributions
119*bbb1b6f9SApple OSS Distributions        mem_r = mo.object_range
120*bbb1b6f9SApple OSS Distributions        if mem_r is None:
121*bbb1b6f9SApple OSS Distributions            print(" {:<21s}: Unknown".format("object range"))
122*bbb1b6f9SApple OSS Distributions        else:
123*bbb1b6f9SApple OSS Distributions            print(" {:<21s}: {r.start:#x} - {r.end:#x} ({r.size:,d} bytes)".format(
124*bbb1b6f9SApple OSS Distributions                "object range", r = mem_r))
125*bbb1b6f9SApple OSS Distributions            address = mo.address
126*bbb1b6f9SApple OSS Distributions            if address != mem_r.start:
127*bbb1b6f9SApple OSS Distributions                print(" {:<21s}: {:,d} from start, {:,d} to end".format(
128*bbb1b6f9SApple OSS Distributions                    "offset", address - mem_r.start, mem_r.end - address))
129*bbb1b6f9SApple OSS Distributions
130*bbb1b6f9SApple OSS Distributions        print()
131*bbb1b6f9SApple OSS Distributions
132*bbb1b6f9SApple OSS Distributions
133*bbb1b6f9SApple OSS Distributionsdef whatis_provider(cls):
134*bbb1b6f9SApple OSS Distributions    """
135*bbb1b6f9SApple OSS Distributions    Class decorator for Whatis providers
136*bbb1b6f9SApple OSS Distributions    """
137*bbb1b6f9SApple OSS Distributions
138*bbb1b6f9SApple OSS Distributions    if not issubclass(cls, WhatisProvider):
139*bbb1b6f9SApple OSS Distributions        raise TypeError("{} is not a subclass of WhatisProvider".format(cls.__name__))
140*bbb1b6f9SApple OSS Distributions
141*bbb1b6f9SApple OSS Distributions    cls.subproviders = []
142*bbb1b6f9SApple OSS Distributions    base = cls.__base__
143*bbb1b6f9SApple OSS Distributions
144*bbb1b6f9SApple OSS Distributions    if base != object:
145*bbb1b6f9SApple OSS Distributions        k = next((
146*bbb1b6f9SApple OSS Distributions            k for k in ['claims', 'lookup']
147*bbb1b6f9SApple OSS Distributions            if getattr(cls, k) == getattr(base, k)
148*bbb1b6f9SApple OSS Distributions        ), None)
149*bbb1b6f9SApple OSS Distributions        if k:
150*bbb1b6f9SApple OSS Distributions            raise TypeError("{} must reimplement function '{}'".format(cls.__name__, k))
151*bbb1b6f9SApple OSS Distributions
152*bbb1b6f9SApple OSS Distributions        base.subproviders.append(cls)
153*bbb1b6f9SApple OSS Distributions        base.subproviders.sort(key=operator.attrgetter('COST'))
154*bbb1b6f9SApple OSS Distributions
155*bbb1b6f9SApple OSS Distributions    return cls
156*bbb1b6f9SApple OSS Distributions
157*bbb1b6f9SApple OSS Distributions
158*bbb1b6f9SApple OSS Distributions__all__ = [
159*bbb1b6f9SApple OSS Distributions    whatis_provider.__name__,
160*bbb1b6f9SApple OSS Distributions
161*bbb1b6f9SApple OSS Distributions    MemoryObject.__name__,
162*bbb1b6f9SApple OSS Distributions    WhatisProvider.__name__,
163*bbb1b6f9SApple OSS Distributions]
164