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