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