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