# 0.0.33 (Released October 30th, 2025)

These are some of the highlights of drgn 0.0.33. See the GitHub release for the full release notes, including more improvements and bug fixes.

## Lots of New Helpers

This release adds over 80 new helpers! The majority are for the Linux kernel memory management subsystem:

- `identify_address_all()`

- `nr_blockdev_pages()`

- `for_each_hstate()`

- `huge_page_size()`

- `hugetlb_total_pages()`

- `hugetlb_total_usage()`

- `decode_memory_block_state()`

- `decode_page_flags_value()`

- `for_each_memory_block()`

- `for_each_valid_page_range()`

- `for_each_valid_pfn_and_page()`

- `memory_block_size_bytes()`

- `page_flags()`

- `page_index()`

- `task_rss()`

- `vm_commit_limit()`

- `vm_memory_committed()`

- `NODE_DATA()`

- `decode_section_flags()`

- `early_section_nr()`

- `early_section()`

- `for_each_online_pgdat()`

- `for_each_present_section()`

- `high_wmark_pages()`

- `low_wmark_pages()`

- `min_wmark_pages()`

- `nr_to_section()`

- `online_section_nr()`

- `online_section()`

- `pfn_to_section_nr()`

- `pfn_to_section()`

- `present_section_nr()`

- `present_section()`

- `section_decode_mem_map()`

- `section_mem_map_addr()`

- `section_nr_to_pfn()`

- `valid_section_nr()`

- `valid_section()`

- `wmark_pages()`

- `slab_cache_objects_per_slab()`

- `slab_cache_order()`

- `slab_cache_pages_per_slab()`

- `slab_cache_usage()`

- `slab_total_usage()`

- `for_each_swap_info()`

- `swap_file_path()`

- `swap_is_file()`

- `swap_total_usage()`

- `swap_usage_in_pages()`

- `total_swapcache_pages()`

- `global_node_page_state()`

- `global_numa_event_state()`

- `global_vm_event_state()`

- `global_zone_page_state()`

- `nr_free_pages()`

- `zone_page_state()`

But there are many others for devices, the CPU scheduler, and more:

- `double_quote_ascii_string()`

- `typeof_member()`

- `bus_for_each_dev()`

- `bus_to_subsys()`

- `class_for_each_device()`

- `class_to_subsys()`

- `dev_name()`

- `super_block_for_each_mount()`

- `module_kallsyms()`

- `kernfs_children()`

- `validate_list_count_nodes()`

- `module_taints()`

- `nr_node_ids()`

- `panic_message()`

- `panic_task()`

- `tainted()`

- `percpu_counter_sum_positive()`

- `for_each_task_in_group()`

- `rbtree_preorder_for_each_entry()`

- `rbtree_preorder_for_each()`

- `cpu_rq()`

- `get_task_state()`

- `task_on_cpu()`

- `task_rq()`

- `task_since_last_arrival_ns()`

- `set_bit()`

- `clear_bit()`

## Address Identification Improvements

`identify_address()` can now identify addresses from the kernel memory map (i.e., addresses in a `struct page`) and addresses in a `struct task_struct`:

    >>> identify_address(pfn_to_page(0))
    'page: pfn 0'
    >>> identify_address(find_task(4))
    'task: 4 (kworker/R-rcu_g)'

The new `identify_address_all()` helper provides a programmatic interface for identifying addresses:

    >>> for identity in identify_address_all(find_task(4)):
    ...     print(repr(identity))
    ...
    IdentifiedTaskStruct(address=18446622477834301568, task=Object(prog, 'struct task_struct *', value=0xffff9168c10cb080))
    IdentifiedSlabObject(address=18446622477834301568, slab_object_info=SlabObjectInfo(slab_cache=Object(prog, 'struct kmem_cache *', value=0xffff9168c0206c00), slab=Object(prog, 'struct slab *', value=0xffffd26b04043200), address=0xffff9168c10cb080, allocated=True))

## Array Slices

Array and pointer objects can now be sliced. This is especially useful for converting a flexible array member or pointer to a fixed-length array:

    >>> poll_list
    *(struct poll_list *)0xffffad92459a39a0 = {
            .next = (struct poll_list *)0x0,
            .len = (unsigned int)2,
            .entries = (struct pollfd []){},
    }
    >>> poll_list.entries[:poll_list.len]
    (struct pollfd [2]){
            {
                    .fd = (int)4,
                    .events = (short)1,
                    .revents = (short)0,
            },
            {
                    .fd = (int)9,
                    .events = (short)1,
                    .revents = (short)0,
            },
    }

## More Reliable Interrupt Stack Traces

Stephen Brennan improved stack tracing on x86-64 kernels that use the frame pointer unwinder (Ubuntu kernels, for example) and AArch64 so that it reliably unwinds through interrupts.

## Kmodify Bit Field Fix

`drgn.helpers.experimental.kmodify.write_object()` was found to have a major bug when writing to bit fields. It didn’t take the field’s bit offset or bit size into account, meaning that it wrote to the wrong bits and overwrote additional memory, too.

This release fixes it to handle bit fields of size 1 (atomically) and reject larger bit fields. Support for larger bit fields can be added if requested.

## Linux 6.17 and 6.18 Support

A change in Linux 6.17 broke drgn’s timekeeping helpers. This error is fixed in this release:

    KeyError: 'tk_core'

A change in Linux 6.17 broke `tools/fsrefs.py --super-block-on-block-device` on Btrfs. This error is fixed in this release:

    no filesystem found on /dev/...

A change in Linux 6.18 broke `d_path()` when passing only a `struct dentry *`. This error is fixed in this release:

    AttributeError: '_drgn.Object' object has no attribute 'next'

A change in Linux 6.18 broke `get_net_ns_by_inode()`. This error is fixed in this release:

    AttributeError: 'struct proc_ns_operations' has no member 'type'. Did you mean: 'type_'?

## No More Python 3.6 & 3.7 Support

As previously announced, this release dropped support for Python 3.6 and 3.7.