1*d4514f0bSApple OSS Distributionsimport struct 2*d4514f0bSApple OSS Distributions 3*d4514f0bSApple OSS Distributionsfrom core import ( 4*d4514f0bSApple OSS Distributions gettype, 5*d4514f0bSApple OSS Distributions xnu_format, 6*d4514f0bSApple OSS Distributions SBValueFormatter, 7*d4514f0bSApple OSS Distributions) 8*d4514f0bSApple OSS Distributionsfrom core.iterators import ( 9*d4514f0bSApple OSS Distributions RB_HEAD, 10*d4514f0bSApple OSS Distributions) 11*d4514f0bSApple OSS Distributions 12*d4514f0bSApple OSS Distributionsfrom .kmem import MemoryRange 13*d4514f0bSApple OSS Distributionsfrom .btlog import BTLog, BTLibrary 14*d4514f0bSApple OSS Distributionsfrom .whatis import * 15*d4514f0bSApple OSS Distributions 16*d4514f0bSApple OSS Distributions 17*d4514f0bSApple OSS Distributions@SBValueFormatter.converter("vm_prot") 18*d4514f0bSApple OSS Distributionsdef vm_prot_converter(prot): 19*d4514f0bSApple OSS Distributions PROT_STR = "-rw?x" 20*d4514f0bSApple OSS Distributions return PROT_STR[prot & 1] + PROT_STR[prot & 2] + PROT_STR[prot & 4] 21*d4514f0bSApple OSS Distributions 22*d4514f0bSApple OSS Distributions 23*d4514f0bSApple OSS Distributionsclass VMMap(object): 24*d4514f0bSApple OSS Distributions """ Helper class to manipulate a vm_map_t """ 25*d4514f0bSApple OSS Distributions 26*d4514f0bSApple OSS Distributions def __init__(self, vm_map, name=None): 27*d4514f0bSApple OSS Distributions self.sbv = vm_map 28*d4514f0bSApple OSS Distributions self.name = name 29*d4514f0bSApple OSS Distributions self.rb = RB_HEAD( 30*d4514f0bSApple OSS Distributions vm_map.chkGetValueForExpressionPath(".hdr.rb_head_store"), 31*d4514f0bSApple OSS Distributions "entry", 32*d4514f0bSApple OSS Distributions self.entry_compare 33*d4514f0bSApple OSS Distributions ) 34*d4514f0bSApple OSS Distributions 35*d4514f0bSApple OSS Distributions vme_type = gettype('struct vm_map_entry') 36*d4514f0bSApple OSS Distributions self.to_entry = vme_type.xContainerOfTransform('store') 37*d4514f0bSApple OSS Distributions 38*d4514f0bSApple OSS Distributions def entry_compare(self, rb_entry, address): 39*d4514f0bSApple OSS Distributions vme = self.to_entry(rb_entry) 40*d4514f0bSApple OSS Distributions 41*d4514f0bSApple OSS Distributions if vme.xGetScalarByPath(".links.end") <= address: 42*d4514f0bSApple OSS Distributions return 1 43*d4514f0bSApple OSS Distributions if address < vme.xGetScalarByPath(".links.start"): 44*d4514f0bSApple OSS Distributions return -1 45*d4514f0bSApple OSS Distributions return 0 46*d4514f0bSApple OSS Distributions 47*d4514f0bSApple OSS Distributions def find(self, address): 48*d4514f0bSApple OSS Distributions ent = self.rb.find(address) 49*d4514f0bSApple OSS Distributions return self.to_entry(ent) if ent else None 50*d4514f0bSApple OSS Distributions 51*d4514f0bSApple OSS Distributions def describe(self, verbose=False): 52*d4514f0bSApple OSS Distributions fmt = ( 53*d4514f0bSApple OSS Distributions "VM Map Info\n" 54*d4514f0bSApple OSS Distributions " vm map : {&v:#x} \n" 55*d4514f0bSApple OSS Distributions ) 56*d4514f0bSApple OSS Distributions if self.name: 57*d4514f0bSApple OSS Distributions fmt += ( 58*d4514f0bSApple OSS Distributions " vm map name : {m.name:s} \n" 59*d4514f0bSApple OSS Distributions ) 60*d4514f0bSApple OSS Distributions fmt += ( 61*d4514f0bSApple OSS Distributions " pmap : {$v.pmap:#x} \n" 62*d4514f0bSApple OSS Distributions " vm size : {$v.size|human_size} ({$v.size:,d} bytes) \n" 63*d4514f0bSApple OSS Distributions " entries : {$v.hdr.nentries} \n" 64*d4514f0bSApple OSS Distributions " map range : " 65*d4514f0bSApple OSS Distributions "{$v.hdr.links.start:#x} - {$v.hdr.links.end:#x}\n" 66*d4514f0bSApple OSS Distributions " map pgshift : {$v.hdr.page_shift}\n" 67*d4514f0bSApple OSS Distributions ) 68*d4514f0bSApple OSS Distributions print(xnu_format(fmt, m=self, v=self.sbv)) 69*d4514f0bSApple OSS Distributions 70*d4514f0bSApple OSS Distributions 71*d4514f0bSApple OSS Distributionsclass VMMapEntry(MemoryObject): 72*d4514f0bSApple OSS Distributions """ Memory Object for a kernel map memory entry """ 73*d4514f0bSApple OSS Distributions 74*d4514f0bSApple OSS Distributions MO_KIND = "kernel map entry" 75*d4514f0bSApple OSS Distributions 76*d4514f0bSApple OSS Distributions def __init__(self, kmem, address, vm_map): 77*d4514f0bSApple OSS Distributions super().__init__(kmem, address) 78*d4514f0bSApple OSS Distributions self.vm_map = vm_map 79*d4514f0bSApple OSS Distributions self.sbv = vm_map.find(address) 80*d4514f0bSApple OSS Distributions 81*d4514f0bSApple OSS Distributions @property 82*d4514f0bSApple OSS Distributions def object_range(self): 83*d4514f0bSApple OSS Distributions sbv = self.sbv 84*d4514f0bSApple OSS Distributions if sbv: 85*d4514f0bSApple OSS Distributions return MemoryRange( 86*d4514f0bSApple OSS Distributions sbv.xGetScalarByPath('.links.start'), 87*d4514f0bSApple OSS Distributions sbv.xGetScalarByPath('.links.end') 88*d4514f0bSApple OSS Distributions ) 89*d4514f0bSApple OSS Distributions 90*d4514f0bSApple OSS Distributions base = self.address & ~self.kmem.page_mask 91*d4514f0bSApple OSS Distributions return MemoryRange(base, base + self.kmem.page_size) 92*d4514f0bSApple OSS Distributions 93*d4514f0bSApple OSS Distributions @property 94*d4514f0bSApple OSS Distributions def vme_offset(self): 95*d4514f0bSApple OSS Distributions return self.sbv.xGetScalarByName('vme_offset') << 12 96*d4514f0bSApple OSS Distributions 97*d4514f0bSApple OSS Distributions @property 98*d4514f0bSApple OSS Distributions def vme_object_type(self): 99*d4514f0bSApple OSS Distributions sbv = self.sbv 100*d4514f0bSApple OSS Distributions if sbv.xGetScalarByName('is_sub_map'): 101*d4514f0bSApple OSS Distributions return "submap" 102*d4514f0bSApple OSS Distributions if sbv.xGetScalarByName('vme_kernel_object'): 103*d4514f0bSApple OSS Distributions return "kobject" 104*d4514f0bSApple OSS Distributions return "vm object" 105*d4514f0bSApple OSS Distributions 106*d4514f0bSApple OSS Distributions @property 107*d4514f0bSApple OSS Distributions def vme_object(self): 108*d4514f0bSApple OSS Distributions kmem = self.kmem 109*d4514f0bSApple OSS Distributions sbv = self.sbv 110*d4514f0bSApple OSS Distributions 111*d4514f0bSApple OSS Distributions if sbv.xGetScalarByName('is_sub_map'): 112*d4514f0bSApple OSS Distributions addr = sbv.xGetScalarByName('vme_submap') << 2 113*d4514f0bSApple OSS Distributions return (addr, kmem.vm_map_type) 114*d4514f0bSApple OSS Distributions 115*d4514f0bSApple OSS Distributions if sbv.xGetScalarByName('vme_kernel_object'): 116*d4514f0bSApple OSS Distributions return (kmem.vm_kobject.GetLoadAddress(), kmem.vmo_type) 117*d4514f0bSApple OSS Distributions 118*d4514f0bSApple OSS Distributions packed = sbv.xGetScalarByName('vme_object_or_delta') 119*d4514f0bSApple OSS Distributions addr = kmem.vm_page_packing.unpack(packed) 120*d4514f0bSApple OSS Distributions return (addr, kmem.vmo_type) 121*d4514f0bSApple OSS Distributions 122*d4514f0bSApple OSS Distributions @property 123*d4514f0bSApple OSS Distributions def pages(self): 124*d4514f0bSApple OSS Distributions return self.object_range.size >> self.kmem.page_shift 125*d4514f0bSApple OSS Distributions 126*d4514f0bSApple OSS Distributions def describe(self, verbose=False): 127*d4514f0bSApple OSS Distributions 128*d4514f0bSApple OSS Distributions self.vm_map.describe() 129*d4514f0bSApple OSS Distributions 130*d4514f0bSApple OSS Distributions if not self.sbv: 131*d4514f0bSApple OSS Distributions fmt = ( 132*d4514f0bSApple OSS Distributions "Kernel Map Entry Info\n" 133*d4514f0bSApple OSS Distributions " No memory mapped at this address\n" 134*d4514f0bSApple OSS Distributions ) 135*d4514f0bSApple OSS Distributions print(xnu_format(fmt)) 136*d4514f0bSApple OSS Distributions return 137*d4514f0bSApple OSS Distributions 138*d4514f0bSApple OSS Distributions fmt = ( 139*d4514f0bSApple OSS Distributions "VM Map Entry Info\n" 140*d4514f0bSApple OSS Distributions " vm entry : {&v:#x}\n" 141*d4514f0bSApple OSS Distributions " start / end : " 142*d4514f0bSApple OSS Distributions "{$v.links.start:#x} - {$v.links.end:#x} " 143*d4514f0bSApple OSS Distributions "({0.pages:,d} pages)\n" 144*d4514f0bSApple OSS Distributions " vm tag : {$v.vme_alias|vm_kern_tag}\n" 145*d4514f0bSApple OSS Distributions ) 146*d4514f0bSApple OSS Distributions range_id = next(( 147*d4514f0bSApple OSS Distributions i 148*d4514f0bSApple OSS Distributions for i, r in enumerate(self.kmem.kmem_ranges) 149*d4514f0bSApple OSS Distributions if r.contains(self.address) 150*d4514f0bSApple OSS Distributions ), None) 151*d4514f0bSApple OSS Distributions if range_id: 152*d4514f0bSApple OSS Distributions fmt += ( 153*d4514f0bSApple OSS Distributions " vm range id : {range_id}\n" 154*d4514f0bSApple OSS Distributions ) 155*d4514f0bSApple OSS Distributions fmt += ( 156*d4514f0bSApple OSS Distributions " protection : " 157*d4514f0bSApple OSS Distributions "{$v.protection|vm_prot}/{$v.max_protection|vm_prot}\n" 158*d4514f0bSApple OSS Distributions " vm object : " 159*d4514f0bSApple OSS Distributions "{0.vme_object_type} ({0.vme_object[0]:#x})\n" 160*d4514f0bSApple OSS Distributions " entry offset : {0.vme_offset:#x}\n" 161*d4514f0bSApple OSS Distributions ) 162*d4514f0bSApple OSS Distributions print(xnu_format(fmt, self, v=self.sbv, range_id=range_id)) 163*d4514f0bSApple OSS Distributions 164*d4514f0bSApple OSS Distributions 165*d4514f0bSApple OSS Distributions@whatis_provider 166*d4514f0bSApple OSS Distributionsclass KernelMapWhatisProvider(WhatisProvider): 167*d4514f0bSApple OSS Distributions """ 168*d4514f0bSApple OSS Distributions Whatis Provider for the kernel map ranges 169*d4514f0bSApple OSS Distributions """ 170*d4514f0bSApple OSS Distributions 171*d4514f0bSApple OSS Distributions def claims(self, address): 172*d4514f0bSApple OSS Distributions kmem = self.kmem 173*d4514f0bSApple OSS Distributions 174*d4514f0bSApple OSS Distributions return any(r.contains(address) for r in kmem.kmem_ranges) or \ 175*d4514f0bSApple OSS Distributions any(r.contains(address) for r in kmem.iokit_ranges) 176*d4514f0bSApple OSS Distributions 177*d4514f0bSApple OSS Distributions def lookup(self, address): 178*d4514f0bSApple OSS Distributions kmem = self.kmem 179*d4514f0bSApple OSS Distributions 180*d4514f0bSApple OSS Distributions if any(r.contains(address) for r in kmem.kmem_ranges): 181*d4514f0bSApple OSS Distributions return VMMapEntry(kmem, address, VMMap(kmem.kernel_map, 'kernel_map')) 182*d4514f0bSApple OSS Distributions 183*d4514f0bSApple OSS Distributions idx = next(idx 184*d4514f0bSApple OSS Distributions for idx, r 185*d4514f0bSApple OSS Distributions in enumerate(kmem.iokit_ranges) 186*d4514f0bSApple OSS Distributions if r.contains(address)) 187*d4514f0bSApple OSS Distributions gps = kmem.target.chkFindFirstGlobalVariable('gIOKitPageableSpace') 188*d4514f0bSApple OSS Distributions map = gps.chkGetValueForExpressionPath('.maps[{}].map'.format(idx)).Dereference() 189*d4514f0bSApple OSS Distributions name = 'gIOKitPageableFixed{}'.format(idx) 190*d4514f0bSApple OSS Distributions return VMMapEntry(kmem, address, VMMap(map, name)) 191*d4514f0bSApple OSS Distributions 192*d4514f0bSApple OSS Distributions 193*d4514f0bSApple OSS Distributions 194*d4514f0bSApple OSS Distributions__all__ = [ 195*d4514f0bSApple OSS Distributions VMMap.__name__, 196*d4514f0bSApple OSS Distributions VMMapEntry.__name__, 197*d4514f0bSApple OSS Distributions KernelMapWhatisProvider.__name__, 198*d4514f0bSApple OSS Distributions] 199