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