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