Beispiel #1
0
    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))
Beispiel #2
0
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
Beispiel #3
0
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")
Beispiel #4
0
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")
Beispiel #5
0
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