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