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