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