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