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