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