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