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