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