xref: /xnu-10002.81.5/tools/lldbmacros/log.py (revision 5e3eaea39dcf651e66cb99ba7d70e32cc4a99587)
1*5e3eaea3SApple OSS Distributionsfrom __future__ import absolute_import, division, print_function
2*5e3eaea3SApple OSS Distributions
3*5e3eaea3SApple OSS Distributionsfrom builtins import object
4*5e3eaea3SApple OSS Distributionsfrom collections import namedtuple
5*5e3eaea3SApple OSS Distributionsfrom itertools import chain
6*5e3eaea3SApple OSS Distributions
7*5e3eaea3SApple OSS Distributionsfrom xnu import *
8*5e3eaea3SApple OSS Distributions
9*5e3eaea3SApple OSS DistributionsLogBlock = namedtuple('LogBlock', ['blk_id', 'blk'])
10*5e3eaea3SApple OSS DistributionsLQEntry = namedtuple('LQEntry', ['state', 'size', 'lmid', 'data'])
11*5e3eaea3SApple OSS DistributionsLogStreamElem = namedtuple(
12*5e3eaea3SApple OSS Distributions    'LogStreamElem', ['blk_id', 'offset', 'lsm', 'ftid'])
13*5e3eaea3SApple OSS Distributions
14*5e3eaea3SApple OSS Distributions
15*5e3eaea3SApple OSS Distributionsclass PPrinter(object):
16*5e3eaea3SApple OSS Distributions    """ Naive yet helpful pretty printer. """
17*5e3eaea3SApple OSS Distributions
18*5e3eaea3SApple OSS Distributions    def __init__(self, O, kv_indent=17):
19*5e3eaea3SApple OSS Distributions        self._O = O
20*5e3eaea3SApple OSS Distributions        self._kv_fmt = "{:<" + str(kv_indent) + "}"
21*5e3eaea3SApple OSS Distributions
22*5e3eaea3SApple OSS Distributions    def header(self, title, upper_case=False):
23*5e3eaea3SApple OSS Distributions        """ Prints out a header with a given text. """
24*5e3eaea3SApple OSS Distributions        if upper_case:
25*5e3eaea3SApple OSS Distributions            title = title.upper()
26*5e3eaea3SApple OSS Distributions        print(self._O.format("{VT.Bold}{:s}{VT.EndBold}", title))
27*5e3eaea3SApple OSS Distributions
28*5e3eaea3SApple OSS Distributions    def table(self, args):
29*5e3eaea3SApple OSS Distributions        """ Switches to a table mode. """
30*5e3eaea3SApple OSS Distributions        return self._O.table(args)
31*5e3eaea3SApple OSS Distributions
32*5e3eaea3SApple OSS Distributions    @staticmethod
33*5e3eaea3SApple OSS Distributions    def print(*values):
34*5e3eaea3SApple OSS Distributions        """ A simple wrapper around `print` providing same functionality. """
35*5e3eaea3SApple OSS Distributions        print(*values)
36*5e3eaea3SApple OSS Distributions
37*5e3eaea3SApple OSS Distributions    def kvprint(self, key, fmt, *values):
38*5e3eaea3SApple OSS Distributions        """ Pretty prints aligned `key: values`. The `fmt` argument specifies
39*5e3eaea3SApple OSS Distributions            value(s) format string.
40*5e3eaea3SApple OSS Distributions        """
41*5e3eaea3SApple OSS Distributions        print(self._kv_fmt.format(key), end=": ")
42*5e3eaea3SApple OSS Distributions        print(fmt.format(*values))
43*5e3eaea3SApple OSS Distributions
44*5e3eaea3SApple OSS Distributions    @staticmethod
45*5e3eaea3SApple OSS Distributions    def empty_line():
46*5e3eaea3SApple OSS Distributions        """ Prints an empty line. """
47*5e3eaea3SApple OSS Distributions        print(" \n")
48*5e3eaea3SApple OSS Distributions
49*5e3eaea3SApple OSS Distributions
50*5e3eaea3SApple OSS Distributionsclass FTID(object):
51*5e3eaea3SApple OSS Distributions    """ Represents a firehose tracepoint identifier. Decodes the tracepoint
52*5e3eaea3SApple OSS Distributions        and provides details on its fields.
53*5e3eaea3SApple OSS Distributions    """
54*5e3eaea3SApple OSS Distributions
55*5e3eaea3SApple OSS Distributions    TYPE = {
56*5e3eaea3SApple OSS Distributions        0x00: "default",
57*5e3eaea3SApple OSS Distributions        0x01: "info",
58*5e3eaea3SApple OSS Distributions        0x02: "debug",
59*5e3eaea3SApple OSS Distributions        0x10: "error",
60*5e3eaea3SApple OSS Distributions        0x11: "fault"
61*5e3eaea3SApple OSS Distributions    }
62*5e3eaea3SApple OSS Distributions
63*5e3eaea3SApple OSS Distributions    def __init__(self, ftid):
64*5e3eaea3SApple OSS Distributions        self._ftid = ftid
65*5e3eaea3SApple OSS Distributions
66*5e3eaea3SApple OSS Distributions    @property
67*5e3eaea3SApple OSS Distributions    def value(self):
68*5e3eaea3SApple OSS Distributions        """ Returns a firehose tracepoint id compound value. """
69*5e3eaea3SApple OSS Distributions        return self._ftid.ftid_value
70*5e3eaea3SApple OSS Distributions
71*5e3eaea3SApple OSS Distributions    @property
72*5e3eaea3SApple OSS Distributions    def namespace(self):
73*5e3eaea3SApple OSS Distributions        """ Returns a tuple of a namespace identifier and its name. """
74*5e3eaea3SApple OSS Distributions        ns_id = int(self._ftid.ftid._namespace)
75*5e3eaea3SApple OSS Distributions        ns_name = GetEnumName('firehose_tracepoint_namespace_t',
76*5e3eaea3SApple OSS Distributions                              ns_id, 'firehose_tracepoint_namespace')
77*5e3eaea3SApple OSS Distributions        return (ns_id, ns_name.split('_')[-1])
78*5e3eaea3SApple OSS Distributions
79*5e3eaea3SApple OSS Distributions    @property
80*5e3eaea3SApple OSS Distributions    def code(self):
81*5e3eaea3SApple OSS Distributions        """ Returns a tracepoint code value. """
82*5e3eaea3SApple OSS Distributions        return int(self._ftid.ftid._code)
83*5e3eaea3SApple OSS Distributions
84*5e3eaea3SApple OSS Distributions    @property
85*5e3eaea3SApple OSS Distributions    def flags(self):
86*5e3eaea3SApple OSS Distributions        """ Returns a tuple of a tracepoint flag and its name. """
87*5e3eaea3SApple OSS Distributions        flag_id = unsigned(self._ftid.ftid._flags)
88*5e3eaea3SApple OSS Distributions        flag_name = GetEnumName('firehose_tracepoint_flags_t',
89*5e3eaea3SApple OSS Distributions                                flag_id, '_firehose_tracepoint_flags_')
90*5e3eaea3SApple OSS Distributions        parts = flag_name.split('_')
91*5e3eaea3SApple OSS Distributions        flag_name = parts[0] + ":" + " ".join(parts[2:])
92*5e3eaea3SApple OSS Distributions        return (flag_id, flag_name)
93*5e3eaea3SApple OSS Distributions
94*5e3eaea3SApple OSS Distributions    @property
95*5e3eaea3SApple OSS Distributions    def type(self):
96*5e3eaea3SApple OSS Distributions        """ Returns a tuple of a tracepoint type and its name.  """
97*5e3eaea3SApple OSS Distributions        # GetEnumName cannot be used because _firehose_tracepoint_type_trace_t
98*5e3eaea3SApple OSS Distributions        # is defined as OS_ENUM which defines values as anonymous enum
99*5e3eaea3SApple OSS Distributions        # unrelated to the type name whatsoever.
100*5e3eaea3SApple OSS Distributions        code_id = int(self._ftid.ftid._type)
101*5e3eaea3SApple OSS Distributions        return (code_id, self.TYPE.get(code_id, "<unknown>"))
102*5e3eaea3SApple OSS Distributions
103*5e3eaea3SApple OSS Distributions
104*5e3eaea3SApple OSS Distributionsclass LogBlocks(object):
105*5e3eaea3SApple OSS Distributions    """ A base class for objects using log blocks. """
106*5e3eaea3SApple OSS Distributions    BLOCK_SIZE = 64
107*5e3eaea3SApple OSS Distributions
108*5e3eaea3SApple OSS Distributions    def __init__(self, buf, blk, blk_count, is_ringbuffer):
109*5e3eaea3SApple OSS Distributions        self._buf = buf
110*5e3eaea3SApple OSS Distributions        self._blk = blk
111*5e3eaea3SApple OSS Distributions        self._blk_count = blk_count
112*5e3eaea3SApple OSS Distributions        self._is_ringbuffer = is_ringbuffer
113*5e3eaea3SApple OSS Distributions
114*5e3eaea3SApple OSS Distributions    @property
115*5e3eaea3SApple OSS Distributions    def block_count(self):
116*5e3eaea3SApple OSS Distributions        """ Returns a total block count. """
117*5e3eaea3SApple OSS Distributions        return self._blk_count
118*5e3eaea3SApple OSS Distributions
119*5e3eaea3SApple OSS Distributions    def block_size(self, block_count=1):
120*5e3eaea3SApple OSS Distributions        """ Returns a space size occupied by a given number of blocks. """
121*5e3eaea3SApple OSS Distributions        return self.BLOCK_SIZE * block_count
122*5e3eaea3SApple OSS Distributions
123*5e3eaea3SApple OSS Distributions    def block_position(self, cursor):
124*5e3eaea3SApple OSS Distributions        """ Returns a block number and a buffer offset of a log at
125*5e3eaea3SApple OSS Distributions            a provided position (block sequence number).
126*5e3eaea3SApple OSS Distributions        """
127*5e3eaea3SApple OSS Distributions        blk_id = cursor % self.block_count if self.block_count > 0 else 0
128*5e3eaea3SApple OSS Distributions        return (blk_id, self.block_size(blk_id))
129*5e3eaea3SApple OSS Distributions
130*5e3eaea3SApple OSS Distributions    def blocks(self, head_block=0):
131*5e3eaea3SApple OSS Distributions        """ Returns a generator of log blocks starting at a provided
132*5e3eaea3SApple OSS Distributions            block position.
133*5e3eaea3SApple OSS Distributions        """
134*5e3eaea3SApple OSS Distributions        blocks = self._blocks_range(head_block, self.block_count)
135*5e3eaea3SApple OSS Distributions        if self._is_ringbuffer:
136*5e3eaea3SApple OSS Distributions            blocks = chain(blocks, self._blocks_range(0, head_block))
137*5e3eaea3SApple OSS Distributions        return blocks
138*5e3eaea3SApple OSS Distributions
139*5e3eaea3SApple OSS Distributions    def logs(self, head_block=0):
140*5e3eaea3SApple OSS Distributions        """ Returns a generator of `LogStreamMsg` elements starting at
141*5e3eaea3SApple OSS Distributions            a given block position.
142*5e3eaea3SApple OSS Distributions        """
143*5e3eaea3SApple OSS Distributions        return (self._log_stream_msg(b.blk_id) for b in self.blocks(head_block) if b.blk)
144*5e3eaea3SApple OSS Distributions
145*5e3eaea3SApple OSS Distributions    def _blocks_range(self, s, e):
146*5e3eaea3SApple OSS Distributions        return (LogBlock(blk_id=i, blk=self._blk[i]) for i in range(s, e))
147*5e3eaea3SApple OSS Distributions
148*5e3eaea3SApple OSS Distributions    def _log_stream_msg(self, blk_id):
149*5e3eaea3SApple OSS Distributions        lsm_offset = self.block_size(blk_id)
150*5e3eaea3SApple OSS Distributions        lsm = Cast(addressof(self._buf[lsm_offset]), 'log_stream_msg_t *')
151*5e3eaea3SApple OSS Distributions        return LogStreamElem(blk_id=blk_id,
152*5e3eaea3SApple OSS Distributions                             offset=lsm_offset,
153*5e3eaea3SApple OSS Distributions                             lsm=lsm,
154*5e3eaea3SApple OSS Distributions                             ftid=FTID(addressof(lsm.lsm_ft.ft_id)))
155*5e3eaea3SApple OSS Distributions
156*5e3eaea3SApple OSS Distributions
157*5e3eaea3SApple OSS Distributionsclass LogStream(LogBlocks):
158*5e3eaea3SApple OSS Distributions    """ Represents an OSLog Stream buffer. """
159*5e3eaea3SApple OSS Distributions
160*5e3eaea3SApple OSS Distributions    def __init__(self, log_stream):
161*5e3eaea3SApple OSS Distributions        super(LogStream, self).__init__(log_stream.ls_buf,
162*5e3eaea3SApple OSS Distributions                                        log_stream.ls_blk,
163*5e3eaea3SApple OSS Distributions                                        log_stream.ls_blk_count,
164*5e3eaea3SApple OSS Distributions                                        True)
165*5e3eaea3SApple OSS Distributions        self._stream = log_stream
166*5e3eaea3SApple OSS Distributions
167*5e3eaea3SApple OSS Distributions    @property
168*5e3eaea3SApple OSS Distributions    def address(self):
169*5e3eaea3SApple OSS Distributions        """ Returns a log stream address. """
170*5e3eaea3SApple OSS Distributions        return int(self._stream)
171*5e3eaea3SApple OSS Distributions
172*5e3eaea3SApple OSS Distributions    @property
173*5e3eaea3SApple OSS Distributions    def enabled(self):
174*5e3eaea3SApple OSS Distributions        """ Returns true for enabled log stream, false otherwise. """
175*5e3eaea3SApple OSS Distributions        return self._stream.ls_enabled
176*5e3eaea3SApple OSS Distributions
177*5e3eaea3SApple OSS Distributions    @property
178*5e3eaea3SApple OSS Distributions    def reserved(self):
179*5e3eaea3SApple OSS Distributions        """ Returns a total number of reserved bytes. """
180*5e3eaea3SApple OSS Distributions        return self._stream.ls_reserved
181*5e3eaea3SApple OSS Distributions
182*5e3eaea3SApple OSS Distributions    @property
183*5e3eaea3SApple OSS Distributions    def logged(self):
184*5e3eaea3SApple OSS Distributions        """ Returns a number of commited bytes and an actual number
185*5e3eaea3SApple OSS Distributions            of logged bytes.
186*5e3eaea3SApple OSS Distributions        """
187*5e3eaea3SApple OSS Distributions        return (self._stream.ls_commited.v,
188*5e3eaea3SApple OSS Distributions                self._stream.ls_commited.v - self._stream.ls_commited_wraps)
189*5e3eaea3SApple OSS Distributions
190*5e3eaea3SApple OSS Distributions    def sync_cursor(self, cursor):
191*5e3eaea3SApple OSS Distributions        """ Aligns read cursor so it points to the actual beginning
192*5e3eaea3SApple OSS Distributions            of a log stream.
193*5e3eaea3SApple OSS Distributions        """
194*5e3eaea3SApple OSS Distributions        commited, logged = self.logged
195*5e3eaea3SApple OSS Distributions        read = cursor
196*5e3eaea3SApple OSS Distributions        if read + self.block_count < logged:
197*5e3eaea3SApple OSS Distributions            read = logged
198*5e3eaea3SApple OSS Distributions            if commited >= self.block_count:
199*5e3eaea3SApple OSS Distributions                read -= self.block_count
200*5e3eaea3SApple OSS Distributions        return read % self.block_count
201*5e3eaea3SApple OSS Distributions
202*5e3eaea3SApple OSS Distributions
203*5e3eaea3SApple OSS Distributionsclass LogStreamCache(LogBlocks):
204*5e3eaea3SApple OSS Distributions    """ Represents an OSLog Stream Cache.
205*5e3eaea3SApple OSS Distributions    """
206*5e3eaea3SApple OSS Distributions
207*5e3eaea3SApple OSS Distributions    def __init__(self, log_cache):
208*5e3eaea3SApple OSS Distributions        super(LogStreamCache, self).__init__(log_cache.lc_buf,
209*5e3eaea3SApple OSS Distributions                                             log_cache.lc_blk,
210*5e3eaea3SApple OSS Distributions                                             log_cache.lc_blk_count,
211*5e3eaea3SApple OSS Distributions                                             False)
212*5e3eaea3SApple OSS Distributions        self._cache = log_cache
213*5e3eaea3SApple OSS Distributions
214*5e3eaea3SApple OSS Distributions    @property
215*5e3eaea3SApple OSS Distributions    def address(self):
216*5e3eaea3SApple OSS Distributions        """ Returns a log stream cache address. """
217*5e3eaea3SApple OSS Distributions        return addressof(self._cache)
218*5e3eaea3SApple OSS Distributions
219*5e3eaea3SApple OSS Distributions    @property
220*5e3eaea3SApple OSS Distributions    def stream(self):
221*5e3eaea3SApple OSS Distributions        """ Returns a log stream cached by this instance.
222*5e3eaea3SApple OSS Distributions        """
223*5e3eaea3SApple OSS Distributions        return LogStream(self._cache.lc_stream) if self._cache.lc_stream else None
224*5e3eaea3SApple OSS Distributions
225*5e3eaea3SApple OSS Distributions    @property
226*5e3eaea3SApple OSS Distributions    def stream_cursor(self):
227*5e3eaea3SApple OSS Distributions        """ Returns a current log stream read cursor. The value is
228*5e3eaea3SApple OSS Distributions            a block sequence of a block to read from next.
229*5e3eaea3SApple OSS Distributions        """
230*5e3eaea3SApple OSS Distributions        if not self.stream:
231*5e3eaea3SApple OSS Distributions            return 0
232*5e3eaea3SApple OSS Distributions        return self.stream.sync_cursor(self._cache.lc_stream_pos)
233*5e3eaea3SApple OSS Distributions
234*5e3eaea3SApple OSS Distributions    @property
235*5e3eaea3SApple OSS Distributions    def cache_cursor(self):
236*5e3eaea3SApple OSS Distributions        """ Returns a current log cache cursor. The value is a number
237*5e3eaea3SApple OSS Distributions            of a block to read from next.
238*5e3eaea3SApple OSS Distributions        """
239*5e3eaea3SApple OSS Distributions        return self._cache.lc_blk_pos
240*5e3eaea3SApple OSS Distributions
241*5e3eaea3SApple OSS Distributions
242*5e3eaea3SApple OSS Distributionsclass MsgBuffer(object):
243*5e3eaea3SApple OSS Distributions    """ Provides access to msgbuf_t ring buffer which is primarily
244*5e3eaea3SApple OSS Distributions        a data type behind system message buffer accessible via dmesg
245*5e3eaea3SApple OSS Distributions        CLI command.
246*5e3eaea3SApple OSS Distributions    """
247*5e3eaea3SApple OSS Distributions    MSG_MAGIC = 0x063061
248*5e3eaea3SApple OSS Distributions
249*5e3eaea3SApple OSS Distributions    def __init__(self, msgbuf):
250*5e3eaea3SApple OSS Distributions        self._msgbuf = msgbuf
251*5e3eaea3SApple OSS Distributions        size = int(self._msgbuf.msg_size)
252*5e3eaea3SApple OSS Distributions        self._buffer = self._msgbuf.msg_bufc.GetSBValue().GetPointeeData(0, size)
253*5e3eaea3SApple OSS Distributions
254*5e3eaea3SApple OSS Distributions    def __eq__(self, other):
255*5e3eaea3SApple OSS Distributions        return unsigned(self._msgbuf) == unsigned(other._msgbuf)
256*5e3eaea3SApple OSS Distributions
257*5e3eaea3SApple OSS Distributions    def __hash__(self):
258*5e3eaea3SApple OSS Distributions        return hash(unsigned(self._msgbuf))
259*5e3eaea3SApple OSS Distributions
260*5e3eaea3SApple OSS Distributions    @dyn_cached_property
261*5e3eaea3SApple OSS Distributions    def values(self, target=None):
262*5e3eaea3SApple OSS Distributions        """ Returns a list of all log messages. """
263*5e3eaea3SApple OSS Distributions
264*5e3eaea3SApple OSS Distributions        return list(self._values())
265*5e3eaea3SApple OSS Distributions
266*5e3eaea3SApple OSS Distributions    def __len__(self):
267*5e3eaea3SApple OSS Distributions        """ Returns a number of log messages in the message buffer. """
268*5e3eaea3SApple OSS Distributions        return len(self.values)
269*5e3eaea3SApple OSS Distributions
270*5e3eaea3SApple OSS Distributions    def __getitem__(self, i):
271*5e3eaea3SApple OSS Distributions        """ Returns a log message at a given index. """
272*5e3eaea3SApple OSS Distributions        return self.values[i]
273*5e3eaea3SApple OSS Distributions
274*5e3eaea3SApple OSS Distributions    def __iter__(self):
275*5e3eaea3SApple OSS Distributions        """ Returns an iterator object of log messages. """
276*5e3eaea3SApple OSS Distributions        return iter(self.values)
277*5e3eaea3SApple OSS Distributions
278*5e3eaea3SApple OSS Distributions    def _values(self):
279*5e3eaea3SApple OSS Distributions        """ Returns a generator object of log messages. """
280*5e3eaea3SApple OSS Distributions        chars = (c for c in (self._at(i) for i in self._range()) if c != 0)
281*5e3eaea3SApple OSS Distributions        line = bytearray()
282*5e3eaea3SApple OSS Distributions        for c in chars:
283*5e3eaea3SApple OSS Distributions            line.append(c)
284*5e3eaea3SApple OSS Distributions            if chr(c) == '\n':
285*5e3eaea3SApple OSS Distributions                yield six.ensure_str(line.decode('utf-8'))
286*5e3eaea3SApple OSS Distributions                line = bytearray()
287*5e3eaea3SApple OSS Distributions        yield six.ensure_str(line.decode('utf-8'))
288*5e3eaea3SApple OSS Distributions
289*5e3eaea3SApple OSS Distributions    def _at(self, i):
290*5e3eaea3SApple OSS Distributions        """ Returns a character at a given index. """
291*5e3eaea3SApple OSS Distributions        err = lldb.SBError()
292*5e3eaea3SApple OSS Distributions        c = self._buffer.GetUnsignedInt8(err, i)
293*5e3eaea3SApple OSS Distributions        if not err.Success():
294*5e3eaea3SApple OSS Distributions            raise ValueError(
295*5e3eaea3SApple OSS Distributions                "Failed to read character at offset " + str(i) + ": " + err.GetCString())
296*5e3eaea3SApple OSS Distributions        return c
297*5e3eaea3SApple OSS Distributions
298*5e3eaea3SApple OSS Distributions    def _range(self):
299*5e3eaea3SApple OSS Distributions        """ Returns character indices starting at a ring buffer head. """
300*5e3eaea3SApple OSS Distributions        start = int(self._msgbuf.msg_bufx)
301*5e3eaea3SApple OSS Distributions        size = int(self._msgbuf.msg_size)
302*5e3eaea3SApple OSS Distributions        return ((start + i) % size for i in range(0, size))
303*5e3eaea3SApple OSS Distributions
304*5e3eaea3SApple OSS Distributions
305*5e3eaea3SApple OSS Distributionsclass LogQueue(object):
306*5e3eaea3SApple OSS Distributions    """ Represents a kernel log queue. """
307*5e3eaea3SApple OSS Distributions
308*5e3eaea3SApple OSS Distributions    def __init__(self, cpu, lq):
309*5e3eaea3SApple OSS Distributions        self._cpu = cpu
310*5e3eaea3SApple OSS Distributions        self._lq = lq
311*5e3eaea3SApple OSS Distributions
312*5e3eaea3SApple OSS Distributions    @property
313*5e3eaea3SApple OSS Distributions    def cpu(self):
314*5e3eaea3SApple OSS Distributions        """ Returns a CPU number the log queue is associated with. """
315*5e3eaea3SApple OSS Distributions        return self._cpu
316*5e3eaea3SApple OSS Distributions
317*5e3eaea3SApple OSS Distributions    @property
318*5e3eaea3SApple OSS Distributions    def ptr(self):
319*5e3eaea3SApple OSS Distributions        """ Returns a pointer to enclosed log_queue_s. """
320*5e3eaea3SApple OSS Distributions        return self._lq
321*5e3eaea3SApple OSS Distributions
322*5e3eaea3SApple OSS Distributions    @property
323*5e3eaea3SApple OSS Distributions    def address(self):
324*5e3eaea3SApple OSS Distributions        """ Returns a log queue address. """
325*5e3eaea3SApple OSS Distributions        return int(self.ptr)
326*5e3eaea3SApple OSS Distributions
327*5e3eaea3SApple OSS Distributions    @property
328*5e3eaea3SApple OSS Distributions    def size(self):
329*5e3eaea3SApple OSS Distributions        """ Returns an actual total log queue size. """
330*5e3eaea3SApple OSS Distributions        slot_size = 1 << unsigned(self._lq.lq_mem_size_order)
331*5e3eaea3SApple OSS Distributions        return self._lq.lq_cnt_mem_active * slot_size
332*5e3eaea3SApple OSS Distributions
333*5e3eaea3SApple OSS Distributions    @property
334*5e3eaea3SApple OSS Distributions    def enqueued(self):
335*5e3eaea3SApple OSS Distributions        """ Returns a generator of logs enqueued in the log queue. """
336*5e3eaea3SApple OSS Distributions        return self._lq_entries(addressof(self._lq.lq_log_list))
337*5e3eaea3SApple OSS Distributions
338*5e3eaea3SApple OSS Distributions    @property
339*5e3eaea3SApple OSS Distributions    def dispatched(self):
340*5e3eaea3SApple OSS Distributions        """ Returns a generator of logs dispatched by the log queue. """
341*5e3eaea3SApple OSS Distributions        return self._lq_entries(addressof(self._lq.lq_dispatch_list))
342*5e3eaea3SApple OSS Distributions
343*5e3eaea3SApple OSS Distributions    @staticmethod
344*5e3eaea3SApple OSS Distributions    def _lq_entries(lqe_list):
345*5e3eaea3SApple OSS Distributions        """ Returns a generator of LQEntry elements representing given single-linked list. """
346*5e3eaea3SApple OSS Distributions        def lq_entry(lqe):
347*5e3eaea3SApple OSS Distributions            lqe_state = GetEnumName('log_queue_entry_state_t',
348*5e3eaea3SApple OSS Distributions                                    lqe.lqe_state, 'LOG_QUEUE_ENTRY_STATE_')
349*5e3eaea3SApple OSS Distributions            return LQEntry(state=lqe_state, size=lqe.lqe_size, lmid=lqe.lqe_lm_id, data=lqe.lqe_payload)
350*5e3eaea3SApple OSS Distributions        return (lq_entry(e) for e in IterateTAILQ_HEAD(lqe_list, 'lqe_link', 's') if e)
351*5e3eaea3SApple OSS Distributions
352*5e3eaea3SApple OSS Distributions    @staticmethod
353*5e3eaea3SApple OSS Distributions    def collect():
354*5e3eaea3SApple OSS Distributions        """ Returns a list of all per-CPU log queues. """
355*5e3eaea3SApple OSS Distributions        pcpu_lqs = addressof(kern.GetGlobalVariable('percpu_slot_oslog_queue'))
356*5e3eaea3SApple OSS Distributions        cpus = range(0, kern.globals.zpercpu_early_count)
357*5e3eaea3SApple OSS Distributions
358*5e3eaea3SApple OSS Distributions        def PCPUSlot(pcpu_var, i):
359*5e3eaea3SApple OSS Distributions            addr = unsigned(pcpu_var) + kern.PERCPU_BASE(i)
360*5e3eaea3SApple OSS Distributions            return kern.GetValueFromAddress(addr, pcpu_var)
361*5e3eaea3SApple OSS Distributions
362*5e3eaea3SApple OSS Distributions        return [LogQueue(cpu, PCPUSlot(pcpu_lqs, cpu)) for cpu in cpus]
363*5e3eaea3SApple OSS Distributions
364*5e3eaea3SApple OSS Distributions
365*5e3eaea3SApple OSS Distributionsdef show_log_stream_logs(pp, logs):
366*5e3eaea3SApple OSS Distributions    """ Pretty prints logs metadata.
367*5e3eaea3SApple OSS Distributions    """
368*5e3eaea3SApple OSS Distributions    hdr = "{0:>5s} {1:>7s} {2:>6s} {3:>12s} {4:>16s} {5:>8s} {6:>9s} {7:>7s} {8:>8s} {9:>18s}"
369*5e3eaea3SApple OSS Distributions    hdr_labels = (
370*5e3eaea3SApple OSS Distributions        "BLOCK", "OFFSET", "LENGTH", "TIMESTAMP", "FTID",
371*5e3eaea3SApple OSS Distributions        "TID", "NAMESPACE", "TYPE", "CODE", "FLAGS"
372*5e3eaea3SApple OSS Distributions    )
373*5e3eaea3SApple OSS Distributions    log_hdr = (
374*5e3eaea3SApple OSS Distributions        "{log.blk_id:>5d} {log.offset:>7d} {ft.ft_length:>6d} {ts:>12d} "
375*5e3eaea3SApple OSS Distributions        "{ftid.value:>16x} {ft.ft_thread:>8d} {ftid.namespace[1]:>9s} "
376*5e3eaea3SApple OSS Distributions        "{ftid.type[1]:>7s} {ftid.code:>08x} {ftid.flags[1]:>18s}"
377*5e3eaea3SApple OSS Distributions    )
378*5e3eaea3SApple OSS Distributions
379*5e3eaea3SApple OSS Distributions    log_count = 0
380*5e3eaea3SApple OSS Distributions    with pp.table(hdr.format(*hdr_labels)):
381*5e3eaea3SApple OSS Distributions        for log in logs:
382*5e3eaea3SApple OSS Distributions            pp.print(log_hdr.format(log=log, ts=log.lsm.lsm_ts,
383*5e3eaea3SApple OSS Distributions                                    ft=log.lsm.lsm_ft, ftid=log.ftid))
384*5e3eaea3SApple OSS Distributions            log_count += 1
385*5e3eaea3SApple OSS Distributions    pp.print("(Shown {:d} logs)".format(log_count))
386*5e3eaea3SApple OSS Distributions
387*5e3eaea3SApple OSS Distributions
388*5e3eaea3SApple OSS Distributionsdef show_log_stream_cache(pp, lsc):
389*5e3eaea3SApple OSS Distributions    """ Pretty prints configuration details of a given log cache.
390*5e3eaea3SApple OSS Distributions    """
391*5e3eaea3SApple OSS Distributions    pp.header("Stream Cache")
392*5e3eaea3SApple OSS Distributions
393*5e3eaea3SApple OSS Distributions    pp.kvprint("Address", "{:#0x}", lsc.address)
394*5e3eaea3SApple OSS Distributions    pp.kvprint("Size", "{:>d} bytes ({:d} blocks)",
395*5e3eaea3SApple OSS Distributions               lsc.block_size(lsc.block_count), lsc.block_count)
396*5e3eaea3SApple OSS Distributions    pp.kvprint("Next Read Block", "{:d} (Offset: {:d})",
397*5e3eaea3SApple OSS Distributions               *lsc.block_position(lsc.cache_cursor))
398*5e3eaea3SApple OSS Distributions
399*5e3eaea3SApple OSS Distributions
400*5e3eaea3SApple OSS Distributionsdef show_log_stream(pp, ls, read_pos):
401*5e3eaea3SApple OSS Distributions    """ Pretty prints configuration details of a given log stream.
402*5e3eaea3SApple OSS Distributions    """
403*5e3eaea3SApple OSS Distributions    pp.header("Stream")
404*5e3eaea3SApple OSS Distributions
405*5e3eaea3SApple OSS Distributions    if not ls:
406*5e3eaea3SApple OSS Distributions        pp.print("No log stream configured.")
407*5e3eaea3SApple OSS Distributions        return
408*5e3eaea3SApple OSS Distributions
409*5e3eaea3SApple OSS Distributions    commited, logged_bytes = ls.logged
410*5e3eaea3SApple OSS Distributions    pp.kvprint("Address", "{:#0x}", ls.address)
411*5e3eaea3SApple OSS Distributions    pp.kvprint("State", "{:s}", "Enabled" if ls.enabled else "Disabled")
412*5e3eaea3SApple OSS Distributions    pp.kvprint("Size", "{:>d} bytes ({:d} blocks)",
413*5e3eaea3SApple OSS Distributions               ls.block_size(ls.block_count), ls.block_count)
414*5e3eaea3SApple OSS Distributions    pp.kvprint("Reserved", "{:d}", ls.reserved)
415*5e3eaea3SApple OSS Distributions    pp.kvprint("Commited", "{:d}", commited)
416*5e3eaea3SApple OSS Distributions
417*5e3eaea3SApple OSS Distributions    block, offset = ls.block_position(commited)
418*5e3eaea3SApple OSS Distributions    pp.kvprint("Written", "{:d} bytes", logged_bytes)
419*5e3eaea3SApple OSS Distributions    pp.kvprint("Next Write Block", "{:d} (Offset: {:d})", block, offset)
420*5e3eaea3SApple OSS Distributions
421*5e3eaea3SApple OSS Distributions    block, offset = ls.block_position(read_pos)
422*5e3eaea3SApple OSS Distributions    pp.kvprint("Read", "{:d} bytes", read_pos)
423*5e3eaea3SApple OSS Distributions    pp.kvprint("Next Read Block", "{:d} (Offset: {:d})", block, offset)
424*5e3eaea3SApple OSS Distributions
425*5e3eaea3SApple OSS Distributions
426*5e3eaea3SApple OSS Distributionsdef show_log_stream_stats(pp):
427*5e3eaea3SApple OSS Distributions    """ Pretty prints values of log stream counters. """
428*5e3eaea3SApple OSS Distributions    pp.header("Statistics")
429*5e3eaea3SApple OSS Distributions
430*5e3eaea3SApple OSS Distributions    pp.kvprint("Total Count", "{:s}",
431*5e3eaea3SApple OSS Distributions               GetSimpleCounter(kern.globals.oslog_s_total_msgcount))
432*5e3eaea3SApple OSS Distributions    pp.kvprint("Metadata Count", "{:s}",
433*5e3eaea3SApple OSS Distributions               GetSimpleCounter(kern.globals.oslog_s_metadata_msgcount))
434*5e3eaea3SApple OSS Distributions    pp.kvprint("Streamed Logs", "{:s}",
435*5e3eaea3SApple OSS Distributions               GetSimpleCounter(kern.globals.oslog_s_streamed_msgcount))
436*5e3eaea3SApple OSS Distributions    pp.kvprint("Dropped Logs", "{:s}",
437*5e3eaea3SApple OSS Distributions               GetSimpleCounter(kern.globals.oslog_s_dropped_msgcount))
438*5e3eaea3SApple OSS Distributions    pp.kvprint("Invalid Logs", "{:s}",
439*5e3eaea3SApple OSS Distributions               GetSimpleCounter(kern.globals.oslog_s_error_count))
440*5e3eaea3SApple OSS Distributions
441*5e3eaea3SApple OSS Distributions
442*5e3eaea3SApple OSS Distributionsdef show_log_stream_info(show_meta, O=None):
443*5e3eaea3SApple OSS Distributions    """ Pretty prints configuration details of OSLog Streaming and
444*5e3eaea3SApple OSS Distributions        its current content.
445*5e3eaea3SApple OSS Distributions    """
446*5e3eaea3SApple OSS Distributions    pp = PPrinter(O)
447*5e3eaea3SApple OSS Distributions    log_cache = LogStreamCache(kern.globals.log_stream_cache)
448*5e3eaea3SApple OSS Distributions
449*5e3eaea3SApple OSS Distributions    pp.empty_line()
450*5e3eaea3SApple OSS Distributions    pp.header("Overview", True)
451*5e3eaea3SApple OSS Distributions    show_log_stream_stats(pp)
452*5e3eaea3SApple OSS Distributions    show_log_stream_cache(pp, log_cache)
453*5e3eaea3SApple OSS Distributions    show_log_stream(pp, log_cache.stream, log_cache.stream_cursor)
454*5e3eaea3SApple OSS Distributions
455*5e3eaea3SApple OSS Distributions    if not show_meta:
456*5e3eaea3SApple OSS Distributions        return
457*5e3eaea3SApple OSS Distributions
458*5e3eaea3SApple OSS Distributions    pp.empty_line()
459*5e3eaea3SApple OSS Distributions    pp.header("Cached Stream Logs", True)
460*5e3eaea3SApple OSS Distributions    show_log_stream_logs(pp, log_cache.logs(0))
461*5e3eaea3SApple OSS Distributions
462*5e3eaea3SApple OSS Distributions    if log_cache.stream:
463*5e3eaea3SApple OSS Distributions        pp.empty_line()
464*5e3eaea3SApple OSS Distributions        pp.header("Stream Logs", True)
465*5e3eaea3SApple OSS Distributions        show_log_stream_logs(
466*5e3eaea3SApple OSS Distributions            pp, log_cache.stream.logs(log_cache.stream_cursor))
467*5e3eaea3SApple OSS Distributions
468*5e3eaea3SApple OSS Distributions
469*5e3eaea3SApple OSS Distributionsdef show_log_queues(pp, log_queues, show_logs):
470*5e3eaea3SApple OSS Distributions    """ Pretty prints log queue summary and logs. """
471*5e3eaea3SApple OSS Distributions    hdr = "{:>3s} {:>16s} {:>2s} {:>10s} {:>10s} {:>5s} {:>8s} {:>6s} {:>6s} {:>8s}"
472*5e3eaea3SApple OSS Distributions    hdr_labels = (
473*5e3eaea3SApple OSS Distributions        "CPU", "ADDRESS", "ON", "STATE", "RECONF", "SLOTS",
474*5e3eaea3SApple OSS Distributions        "SIZE", "AVAIL", "STORED", "EN_ROUTE"
475*5e3eaea3SApple OSS Distributions    )
476*5e3eaea3SApple OSS Distributions    hdr_lq = (
477*5e3eaea3SApple OSS Distributions        "{cpu:>3s} {lq.address:>16x} {lq.ptr.lq_ready:>2d} {state:>10s} {reconf:>10s} "
478*5e3eaea3SApple OSS Distributions        "{lq.ptr.lq_cnt_mem_active:>5d} {size:>8d} {lq.ptr.lq_cnt_mem_avail:>6d} "
479*5e3eaea3SApple OSS Distributions        "{enq:>6d} {disp:>8d}"
480*5e3eaea3SApple OSS Distributions    )
481*5e3eaea3SApple OSS Distributions
482*5e3eaea3SApple OSS Distributions    def show_log_queue(lq, enqueued, dispatched):
483*5e3eaea3SApple OSS Distributions        state = GetEnumName(
484*5e3eaea3SApple OSS Distributions            'lq_mem_state_t', lq._lq.lq_mem_state, 'LQ_MEM_STATE_')
485*5e3eaea3SApple OSS Distributions        reconf = GetEnumName(
486*5e3eaea3SApple OSS Distributions            'lq_req_state_t', lq._lq.lq_req_state, 'LQ_REQ_STATE_')
487*5e3eaea3SApple OSS Distributions        cpu = "N/A" if lq.cpu is None else str(lq.cpu)
488*5e3eaea3SApple OSS Distributions        pp.print(hdr_lq.format(lq=lq, state=state, size=lq.size, reconf=reconf, cpu=cpu,
489*5e3eaea3SApple OSS Distributions                               enq=len(enqueued),
490*5e3eaea3SApple OSS Distributions                               disp=len(dispatched)))
491*5e3eaea3SApple OSS Distributions
492*5e3eaea3SApple OSS Distributions    if show_logs:
493*5e3eaea3SApple OSS Distributions        for lq in log_queues:
494*5e3eaea3SApple OSS Distributions            lq_enqueued = list(lq.enqueued)
495*5e3eaea3SApple OSS Distributions            lq_dispatched = list(lq.dispatched)
496*5e3eaea3SApple OSS Distributions            pp.empty_line()
497*5e3eaea3SApple OSS Distributions            with pp.table(hdr.format(*hdr_labels)):
498*5e3eaea3SApple OSS Distributions                show_log_queue(lq, lq_enqueued, lq_dispatched)
499*5e3eaea3SApple OSS Distributions
500*5e3eaea3SApple OSS Distributions            pp.empty_line()
501*5e3eaea3SApple OSS Distributions            pp.header("Enqueues Log Messages")
502*5e3eaea3SApple OSS Distributions            show_log_queue_logs(pp, lq_enqueued)
503*5e3eaea3SApple OSS Distributions
504*5e3eaea3SApple OSS Distributions            pp.empty_line()
505*5e3eaea3SApple OSS Distributions            pp.header("Dispatched Log Messages")
506*5e3eaea3SApple OSS Distributions            show_log_queue_logs(pp, lq_dispatched)
507*5e3eaea3SApple OSS Distributions
508*5e3eaea3SApple OSS Distributions            pp.empty_line()
509*5e3eaea3SApple OSS Distributions        return
510*5e3eaea3SApple OSS Distributions
511*5e3eaea3SApple OSS Distributions    with pp.table(hdr.format(*hdr_labels)):
512*5e3eaea3SApple OSS Distributions        for lq in log_queues:
513*5e3eaea3SApple OSS Distributions            show_log_queue(lq, list(lq.enqueued), list(lq.dispatched))
514*5e3eaea3SApple OSS Distributions
515*5e3eaea3SApple OSS Distributions
516*5e3eaea3SApple OSS Distributionsdef show_log_queue_logs(pp, lqe_list):
517*5e3eaea3SApple OSS Distributions    """ Pretty prints log queue logs. """
518*5e3eaea3SApple OSS Distributions    if not lqe_list:
519*5e3eaea3SApple OSS Distributions        pp.print("No log messages present")
520*5e3eaea3SApple OSS Distributions        return
521*5e3eaea3SApple OSS Distributions
522*5e3eaea3SApple OSS Distributions    hdr = ("{:>5s} {:>7s} {:>10s} "
523*5e3eaea3SApple OSS Distributions           "{:>12s} {:>8s} "
524*5e3eaea3SApple OSS Distributions           "{:>16s} {:>9s} {:>7s} {:>8s} {:>18s}")
525*5e3eaea3SApple OSS Distributions    hdr_labels = (
526*5e3eaea3SApple OSS Distributions        "LM_ID", "LM_SIZE", "STATE", "TIMESTAMP", "LOG_SIZE",
527*5e3eaea3SApple OSS Distributions        "FTID", "NAMESPACE", "TYPE", "CODE", "FLAGS"
528*5e3eaea3SApple OSS Distributions    )
529*5e3eaea3SApple OSS Distributions    log_hdr = (
530*5e3eaea3SApple OSS Distributions        "{lqe.lmid:>5x} {lqe.size:>7d} {lqe.state:>10s} "
531*5e3eaea3SApple OSS Distributions        "{d.lp_timestamp:>12d} {d.lp_data_size:>8d} "
532*5e3eaea3SApple OSS Distributions        "{ftid.value:>16x} {ftid.namespace[1]:>9s} "
533*5e3eaea3SApple OSS Distributions        "{ftid.type[1]:>7s} {ftid.code:>08x} {ftid.flags[1]:>18s}"
534*5e3eaea3SApple OSS Distributions    )
535*5e3eaea3SApple OSS Distributions    with pp.table(hdr.format(*hdr_labels)):
536*5e3eaea3SApple OSS Distributions        for lqe in lqe_list:
537*5e3eaea3SApple OSS Distributions            pp.print(log_hdr.format(lqe=lqe, d=lqe.data,
538*5e3eaea3SApple OSS Distributions                                    ftid=FTID(lqe.data.lp_ftid)))
539*5e3eaea3SApple OSS Distributions    pp.print("(Shown {:d} logs)".format(len(lqe_list)))
540*5e3eaea3SApple OSS Distributions
541*5e3eaea3SApple OSS Distributions
542*5e3eaea3SApple OSS Distributions@lldb_command('showlogstream', 'L', fancy=True)
543*5e3eaea3SApple OSS Distributionsdef showLogStream(cmd_args=None, cmd_options=None, O=None):
544*5e3eaea3SApple OSS Distributions    """ Displays the contents of the log stream and the log stream cache.
545*5e3eaea3SApple OSS Distributions
546*5e3eaea3SApple OSS Distributions    showlogstream [-L]
547*5e3eaea3SApple OSS Distributions
548*5e3eaea3SApple OSS Distributions    Options:
549*5e3eaea3SApple OSS Distributions    -L: Show metadata of logs stored in the log stream and the cache
550*5e3eaea3SApple OSS Distributions    """
551*5e3eaea3SApple OSS Distributions
552*5e3eaea3SApple OSS Distributions    show_meta = "-L" in cmd_options
553*5e3eaea3SApple OSS Distributions
554*5e3eaea3SApple OSS Distributions    show_log_stream_info(show_meta, O)
555*5e3eaea3SApple OSS Distributions
556*5e3eaea3SApple OSS Distributions
557*5e3eaea3SApple OSS Distributions@lldb_command('showlq', 'LC:A:', fancy=True)
558*5e3eaea3SApple OSS Distributionsdef showLogQueue(cmd_args=None, cmd_options=None, O=None):
559*5e3eaea3SApple OSS Distributions    """ Displays the contents of the log queue.
560*5e3eaea3SApple OSS Distributions
561*5e3eaea3SApple OSS Distributions    usage: showlq [-C cpu_num][-A addr][-L]
562*5e3eaea3SApple OSS Distributions
563*5e3eaea3SApple OSS Distributions        -C n    Shows a log queue summary of a selected CPU.
564*5e3eaea3SApple OSS Distributions        -A a    Shows a log queue summary at a given address.
565*5e3eaea3SApple OSS Distributions        -L      Show metadata of enqueued and dispatched logs
566*5e3eaea3SApple OSS Distributions
567*5e3eaea3SApple OSS Distributions    Options -A and -C are mutually exclusive.
568*5e3eaea3SApple OSS Distributions    If no options provided summaries of all per-CPU log queues are shown.
569*5e3eaea3SApple OSS Distributions
570*5e3eaea3SApple OSS Distributions    Examples:
571*5e3eaea3SApple OSS Distributions        showlq
572*5e3eaea3SApple OSS Distributions        showlq -C 2 -L
573*5e3eaea3SApple OSS Distributions        showlq -A 0xfffffff123456789 -L
574*5e3eaea3SApple OSS Distributions    """
575*5e3eaea3SApple OSS Distributions
576*5e3eaea3SApple OSS Distributions    log_queues = LogQueue.collect()
577*5e3eaea3SApple OSS Distributions
578*5e3eaea3SApple OSS Distributions    if "-C" in cmd_options and "-A" in cmd_options:
579*5e3eaea3SApple OSS Distributions        raise ArgumentError("Options -A and -C are mutually exclusive.")
580*5e3eaea3SApple OSS Distributions
581*5e3eaea3SApple OSS Distributions    if "-C" in cmd_options:
582*5e3eaea3SApple OSS Distributions        cpu_no = ArgumentStringToInt(cmd_options['-C'])
583*5e3eaea3SApple OSS Distributions        if cpu_no not in range(0, len(log_queues)):
584*5e3eaea3SApple OSS Distributions            print("CPU number out of [0, {:d}) range".format(len(log_queues)))
585*5e3eaea3SApple OSS Distributions            return
586*5e3eaea3SApple OSS Distributions        log_queues = [lq for lq in log_queues if lq.cpu == cpu_no]
587*5e3eaea3SApple OSS Distributions    elif "-A" in cmd_options:
588*5e3eaea3SApple OSS Distributions        addr = ArgumentStringToInt(cmd_options['-A'])
589*5e3eaea3SApple OSS Distributions        log_queues = [lq for lq in log_queues if addr == lq.address]
590*5e3eaea3SApple OSS Distributions        if not log_queues:
591*5e3eaea3SApple OSS Distributions            lq = kern.GetValueFromAddress(addr, 'log_queue_t')
592*5e3eaea3SApple OSS Distributions            log_queues = [LogQueue(None, lq)]
593*5e3eaea3SApple OSS Distributions
594*5e3eaea3SApple OSS Distributions    show_logs = "-L" in cmd_options
595*5e3eaea3SApple OSS Distributions
596*5e3eaea3SApple OSS Distributions    show_log_queues(PPrinter(O), log_queues, show_logs)
597*5e3eaea3SApple OSS Distributions
598*5e3eaea3SApple OSS Distributions
599*5e3eaea3SApple OSS Distributions@lldb_command('showmsgbuf', 'C:F')
600*5e3eaea3SApple OSS Distributionsdef showMsgBuf(cmd_args=None, cmd_options=None):
601*5e3eaea3SApple OSS Distributions    """ Displays the contents of msgbuf_t type at a given address.
602*5e3eaea3SApple OSS Distributions
603*5e3eaea3SApple OSS Distributions        usage: showmsgbuf [-C <num>][-F] addr
604*5e3eaea3SApple OSS Distributions
605*5e3eaea3SApple OSS Distributions        -C <num>    Shows first or last (if negative) specified number of logs.
606*5e3eaea3SApple OSS Distributions        -F          Show the content even if the magic key indicates data corruption.
607*5e3eaea3SApple OSS Distributions    """
608*5e3eaea3SApple OSS Distributions
609*5e3eaea3SApple OSS Distributions    if not cmd_args:
610*5e3eaea3SApple OSS Distributions        print(showMsgBuf.__doc__)
611*5e3eaea3SApple OSS Distributions        return
612*5e3eaea3SApple OSS Distributions
613*5e3eaea3SApple OSS Distributions    addr = kern.GetValueFromAddress(cmd_args[0], 'struct msgbuf *')
614*5e3eaea3SApple OSS Distributions
615*5e3eaea3SApple OSS Distributions    if addr.msg_magic != MsgBuffer.MSG_MAGIC:
616*5e3eaea3SApple OSS Distributions        print("Error: Invalid msgbuf_t magic key {:#x} (expected {:#x}). "
617*5e3eaea3SApple OSS Distributions              "Invalid address or the content is corrupted.".format(addr.msg_magic, MsgBuffer.MSG_MAGIC))
618*5e3eaea3SApple OSS Distributions        if not "-F" in cmd_options:
619*5e3eaea3SApple OSS Distributions            return
620*5e3eaea3SApple OSS Distributions
621*5e3eaea3SApple OSS Distributions    msgbuf = MsgBuffer(addr)
622*5e3eaea3SApple OSS Distributions
623*5e3eaea3SApple OSS Distributions    if "-C" in cmd_options:
624*5e3eaea3SApple OSS Distributions        count = ArgumentStringToInt(cmd_options['-C'])
625*5e3eaea3SApple OSS Distributions        n = min(abs(count), len(msgbuf))
626*5e3eaea3SApple OSS Distributions        msgbuf = msgbuf[:n] if count > 0 else msgbuf[-n:]
627*5e3eaea3SApple OSS Distributions
628*5e3eaea3SApple OSS Distributions    for msg in msgbuf:
629*5e3eaea3SApple OSS Distributions        print(msg.rstrip("\n"))
630*5e3eaea3SApple OSS Distributions
631*5e3eaea3SApple OSS Distributions
632*5e3eaea3SApple OSS Distributions@lldb_command('systemlog', 'C:F')
633*5e3eaea3SApple OSS Distributionsdef systemLog(cmd_args=None, cmd_options=None):
634*5e3eaea3SApple OSS Distributions    """ Displays the contents of the system message buffer.
635*5e3eaea3SApple OSS Distributions
636*5e3eaea3SApple OSS Distributions        usage: systemlog [-C <num>][-F]
637*5e3eaea3SApple OSS Distributions
638*5e3eaea3SApple OSS Distributions        -C <num>    Shows first or last (if negative) specified number of logs.
639*5e3eaea3SApple OSS Distributions        -F          Show the content even if the magic key indicates data corruption.
640*5e3eaea3SApple OSS Distributions    """
641*5e3eaea3SApple OSS Distributions    showMsgBuf([unsigned(kern.globals.msgbufp)], cmd_options)
642