xref: /xnu-10002.61.3/tools/lldbmacros/kmemory/vm.py (revision 0f4c859e951fba394238ab619495c4e1d54d0f34)
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