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