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