def print_metaslab(prog: drgn.Program, msp, print_header, indent): spacemap = msp.ms_sm if print_header: print( "".ljust(indent), "ADDR".ljust(18), "ID".rjust(4), "OFFSET".rjust(16), "FREE".rjust(8), "FRAG".rjust(5), "UCMU".rjust(8), ) print("".ljust(indent), "-" * 65) free = msp.ms_size if spacemap != drgn.NULL(prog, spacemap.type_): free -= spacemap.sm_phys.smp_alloc ufrees = msp.ms_unflushed_frees.rt_space uallocs = msp.ms_unflushed_allocs.rt_space free = free + ufrees - uallocs uchanges_free_mem = msp.ms_unflushed_frees.rt_root.avl_numnodes uchanges_free_mem *= prog.type("range_seg_t").type.size uchanges_alloc_mem = msp.ms_unflushed_allocs.rt_root.avl_numnodes uchanges_alloc_mem *= prog.type("range_seg_t").type.size uchanges_mem = uchanges_free_mem + uchanges_alloc_mem print( "".ljust(indent), hex(msp).ljust(16), str(int(msp.ms_id)).rjust(4), hex(msp.ms_start).rjust(16), nicenum(free).rjust(8), end="", ) if msp.ms_fragmentation == -1: print("-".rjust(6), end="") else: print((str(msp.ms_fragmentation) + "%").rjust(6), end="") print(nicenum(uchanges_mem).rjust(9))
def _get_printk_records_structured(prog: Program) -> List[PrintkRecord]: printk_logp_type = prog.type("struct printk_log *") have_caller_id = printk_logp_type.type.has_member("caller_id") LOG_CONT = prog["LOG_CONT"].value_() result = [] log_buf = prog["log_buf"].read_() current_idx = prog["log_first_idx"].read_() next_idx = prog["log_next_idx"].read_() seq = prog["log_first_seq"].value_() while current_idx != next_idx: logp = cast(printk_logp_type, log_buf + current_idx) log = logp[0].read_() text_len = log.text_len.value_() dict_len = log.dict_len.value_() text_dict = prog.read(logp + 1, text_len + dict_len) if have_caller_id: caller_tid, caller_cpu = _caller_id(log.caller_id.value_()) else: caller_tid = caller_cpu = None context = {} if dict_len: for elmt in text_dict[text_len:].split(b"\0"): key, value = elmt.split(b"=", 1) context[key] = value result.append( PrintkRecord( text=text_dict[:text_len], facility=log.facility.value_(), level=log.level.value_(), seq=seq, timestamp=log.ts_nsec.value_(), caller_tid=caller_tid, caller_cpu=caller_cpu, continuation=bool(log.flags.value_() & LOG_CONT), context=context, )) log_len = log.len.read_() if log_len: current_idx += log_len else: # Zero means the buffer wrapped around. if current_idx < next_idx: # Avoid getting into an infinite loop if the buffer is # corrupted. break current_idx -= current_idx seq += 1 return result
def _for_each_block_device(prog: Program) -> Iterator[Object]: try: class_in_private = prog.cache["knode_class_in_device_private"] except KeyError: # Linux kernel commit 570d0200123f ("driver core: move # device->knode_class to device_private") (in v5.1) moved the list # node. class_in_private = prog.type("struct device_private").has_member("knode_class") prog.cache["knode_class_in_device_private"] = class_in_private devices = prog["block_class"].p.klist_devices.k_list.address_of_() if class_in_private: for device_private in list_for_each_entry( "struct device_private", devices, "knode_class.n_node" ): yield device_private.device else: yield from list_for_each_entry("struct device", devices, "knode_class.n_node")
def _for_each_block_device(prog: Program) -> Iterator[Object]: try: class_in_private = prog.cache["knode_class_in_device_private"] except KeyError: # We need a proper has_member(), but this is fine for now. class_in_private = any( member.name == "knode_class" for member in prog.type( "struct device_private").members # type: ignore[union-attr] ) prog.cache["knode_class_in_device_private"] = class_in_private devices = prog["block_class"].p.klist_devices.k_list.address_of_() if class_in_private: for device_private in list_for_each_entry("struct device_private", devices, "knode_class.n_node"): yield device_private.device else: yield from list_for_each_entry("struct device", devices, "knode_class.n_node")
def _get_printk_records_lockless(prog: Program, prb: Object) -> List[PrintkRecord]: ulong_size = sizeof(prog.type("unsigned long")) DESC_SV_BITS = ulong_size * 8 DESC_FLAGS_SHIFT = DESC_SV_BITS - 2 DESC_FLAGS_MASK = 3 << DESC_FLAGS_SHIFT DESC_ID_MASK = DESC_FLAGS_MASK ^ ((1 << DESC_SV_BITS) - 1) LOG_CONT = prog["LOG_CONT"].value_() desc_committed = prog["desc_committed"].value_() desc_finalized = prog["desc_finalized"].value_() def record_committed(current_id: int, state_var: int) -> bool: state_desc_id = state_var & DESC_ID_MASK state = 3 & (state_var >> DESC_FLAGS_SHIFT) return (current_id == state_desc_id) and (state == desc_committed or state == desc_finalized) desc_ring = prb.desc_ring descs = desc_ring.descs.read_() infos = desc_ring.infos.read_() desc_ring_mask = (1 << desc_ring.count_bits.value_()) - 1 text_data_ring = prb.text_data_ring text_data_ring_data = text_data_ring.data.read_() text_data_ring_mask = (1 << text_data_ring.size_bits) - 1 result = [] def add_record(current_id: int) -> None: idx = current_id & desc_ring_mask desc = descs[idx].read_() if not record_committed(current_id, desc.state_var.counter.value_()): return lpos_begin = desc.text_blk_lpos.begin & text_data_ring_mask lpos_next = desc.text_blk_lpos.next & text_data_ring_mask lpos_begin += ulong_size if lpos_begin == lpos_next: # Data-less record. return if lpos_begin > lpos_next: # Data wrapped. lpos_begin -= lpos_begin info = infos[idx].read_() text_len = info.text_len if lpos_next - lpos_begin < text_len: # Truncated record. text_len = lpos_next - lpos_begin caller_tid, caller_cpu = _caller_id(info.caller_id.value_()) context = {} subsystem = info.dev_info.subsystem.string_() device = info.dev_info.device.string_() if subsystem: context[b"SUBSYSTEM"] = subsystem if device: context[b"DEVICE"] = device result.append( PrintkRecord( text=prog.read(text_data_ring_data + lpos_begin, text_len), facility=info.facility.value_(), level=info.level.value_(), seq=info.seq.value_(), timestamp=info.ts_nsec.value_(), caller_tid=caller_tid, caller_cpu=caller_cpu, continuation=bool(info.flags.value_() & LOG_CONT), context=context, )) head_id = desc_ring.head_id.counter.value_() current_id = desc_ring.tail_id.counter.value_() while current_id != head_id: add_record(current_id) current_id = (current_id + 1) & DESC_ID_MASK add_record(current_id) return result