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