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