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