xref: /xnu-10002.41.9/tools/lldbmacros/kmemory/vm.py (revision 699cd48037512bf4380799317ca44ca453c82f57)
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