New Features
Numerous Linux kernel memory management-related helpers were added:
nr_blockdev_pages()was added todrgn.helpers.linux.block. It returns the amount of memory used for block device buffers.- A new
drgn.helpers.linux.hugetlbhelper module was added.for_each_hstate()iterates over all HugeTLB page sizes.huge_page_size()returns the size of a HugeTLB state.hugetlb_total_pages()returns the total number of HugeTLB pages.hugetlb_total_usage()returns global HugeTLB usage information.
- A new
drgn.helpers.linux.swaphelper module was added.for_each_swap_info()iterates over all swap devices.swap_file_path()returns the path of a swap device.swap_is_file()returns whether a swap device is a regular file.swap_usage_in_pages()returns the number of pages currently used on a given swap device.swap_total_usage()returns global swap usage information.total_swapcache_pages()returns the number of swap cached pages.
slab_cache_objects_per_slab(),slab_cache_pages_per_slab(), andslab_cache_order()were added todrgn.helpers.linux.slab. They return information about the layout of slab allocations.slab_cache_usage()was added todrgn.helpers.linux.slab. It returns statistics on how many objects and slabs are allocated for a slab cache.slab_total_usage()was added todrgn.helpers.linux.slab. It returns the total amount of memory used by the slab allocator.for_each_valid_page_range()andfor_each_valid_pfn_and_page()were added todrgn.helpers.linux.mm. They iterate over all valid pages.task_rss()was added todrgn.helpers.linux.mm. It returns a task's resident set size. Contributed by Yassine Larhrissi.vm_commit_limit()andvm_memory_committed()were added todrgn.helpers.linux.mm. They return virtual memory overcommit information.decode_page_flags_value()was added todrgn.helpers.linux.mm. It is likedecode_page_flags()but takes the flags value instead of the page.- Helpers for accessing common
struct pagefields regardless of kernel version were added todrgn.helpers.linux.mm.page_flags()returns a page's flags. Contributed by Ye Liu.page_index()returns a page's offset in its containing mapping.
- Memory hotplug-related helpers were added to
drgn.helpers.linux.mm.for_each_memory_block()iterates over all memory hotplug blocks.decode_memory_block_state()gets the state of a memory hotplug block.memory_block_size_bytes()returns the size of a memory hotplug block.
- A new
drgn.helpers.linux.mmzonehelper module was added.NODE_DATA()gets the NUMA node memory layout data of a given node.for_each_online_pgdat()iterates over the NUMA node data for each online node.nr_to_section(),pfn_to_section_nr(),section_nr_to_pfn(),pfn_to_section(),section_mem_map_addr(),section_decode_mem_map()andfor_each_present_section()look up SPARSEMEM sections.present_section{,_nr}(),valid_section{,_nr}(),online_section{,_nr}(),early_section{,_nr}(), anddecode_section_flags()check SPARSEMEM section flags.{min_,low_,high_,}wmark_pages()get memory reclaim watermarks.
- A new
drgn.helpers.linux.vmstathelper module was added.global_node_page_state(),zone_page_state(),global_zone_page_state(),nr_free_pages(),global_numa_event_state(), andglobal_vm_event_state()return various VM statistic counters.
identify_address_all()was added todrgn.helpers.common.memory. It is a programmatic variant ofidentify_address()that can return multiple matches and returns matches as objects with additional attributes instead of strings.set_bit()andclear_bit()were added todrgn.helpers.experimental.kmodify. They atomically set or clear a bit in kernel memory, respectively.
Many other helpers were also added.
dev_name()was added todrgn.helpers.linux.device. It returns the name of a device.super_block_for_each_mount()was added todrgn.helpers.linux.fs. It iterates over all mounts of a super block (filesystem).bus_to_subsys()andclass_to_subsys()were added todrgn.helpers.linux.device. They get the private data for a device bus or class, respectively.bus_for_each_dev()andclass_for_each_device()were added todrgn.helpers.linux.device. They iterate over all devices on a given bus or of a given class, respectively.module_kallsyms()was added todrgn.helpers.linux.kallsyms. It returns a list of symbols for a given module from its kallsyms data. Originally contributed by Stephen Brennan.kernfs_children()was added todrgn.helpers.linux.kernfs. It returns the children of a kernfs directory. Contributed by Joanne Koong.validate_list_count_nodes()was added todrgn.helpers.linux.list. It returns the length of a Linux kernel list while validating it.nr_node_ids()was added todrgn.helpers.linux.nodemask. It returns the upper bound on NUMA node ID numbers.- A new
drgn.helpers.linux.panichelper module was added.panic_task()returns thestruct task_struct *that caused a crash.panic_message()returns the message logged during a panic.tainted()gets the kernel's taint flags as a string.
module_taints()was added todrgn.helpers.linux.module. It returns a kernel module's taint flags as a string.percpu_counter_sum_positive()was added todrgn.helpers.linux.percpu. It returns the sum of a per-CPU counter, or 0 if it is negative.for_each_task_in_group()was added todrgn.helpers.linux.pid. It iterates over the threads of a process. Contributed by Stephen Brennan.rbtree_preorder_for_each{,_entry}()were added todrgn.helpers.linux.rbtree. These do a pre-order traversal instead of the in-order traversal thatrbtree_inorder_for_each{,_entry()}do.- Runqueue-related helpers were added to
drgn.helpers.linux.sched. Contributed by Richard Li.cpu_rq()gets the runqueue for a given CPU.task_rq()gets the runqueue that a given task is on.task_since_last_arrival_ns()returns approximately how long a task has been in its current running status.
get_task_state()was added todrgn.helpers.linux.sched. It returns a human-readable description of a task's state ("R (running)", "S (sleeping)", etc.).task_on_cpu()was added todrgn.helpers.linux.sched. It returns whether a given task is currently running.double_quote_ascii_string()was added todrgn.helpers.common.format. It formats a byte string as a double-quoted string literal.typeof_member()was added todrgn.helpers.common.type. It returns the type of a given member in another type.
Several helpers were extended.
drgn.helpers.common.memory.identify_address()(and the newidentify_address_all()) now recognizes page and task addresses. It also now recognizes stack addresses on kernels configured withoutCONFIG_VMAP_STACK.drgn.helpers.linux.slab.slab_object_info()anddrgn.helpers.common.memory.identify_address()now return as much information as possible for the SLOB allocator instead of always returningNone.drgn.helpers.linux.printk.{get,print}_dmesg()now take atimestampsparameter controlling how timestamps are formatted. Contributed by Yassine Larhrissi.drgn.helpers.linux.kernfs.kernfs_walk()can now follow symlinks. Contributed by Joanne Koong.drgn.helpers.linux.timekeeping.ktime_get_real_seconds()can now get the time from theVMCOREINFOcrash dump metadata, which is more reliable.drgn.helpers.common.format.print_table()can now align interleaved rows in groups.
Finally, quite a few other features were added.
- Array and pointer objects can now be sliced (e.g.,
arr[1:2]) to construct a new array with a different start and length. - The kernel stack size is now available as
prog["THREAD_SIZE"]. Contributed by Stephen Brennan. - Various SPARSEMEM parameters are now available with
prog["name"]:NR_SECTION_ROOTS,SECTIONS_PER_ROOT,SECTION_SIZE_BITS,MAX_PHYSMEM_BITS. drgn.Type.variable_declaration()was added. It formats a variable declaration with a given type.drgn.Type.unaliased()anddrgn.Type.unaliased_kind()were added. They get information about a type with top-level typedefs removed.drgn.Object.format_()now takes ainteger_baseparameter to control whether integers are printed in decimal, hexadecimal, or octal.drgn.Object.subobject_()was added. It does one or more member or element lookups from a string.drgn.Program.read_c_string()was added. It reads a null-terminated string from program memory.drgn.Program.address_size()was added. It returns the size of an address in the program.drgn.Program.configwas added. It is a dictionary that can be used internally and by users to store arbitrary configuration information.drgn.Program.core_dump_pathwas added. It is the path of the core dump file being debugged.- Object lookups (e.g.,
drgn.Program[],drgn.Program.object()) now raisedrgn.ObjectNotFoundErrorinstead ofKeyErrororLookupError.ObjectNotFoundErroris a subclass ofKeyError, so this should not break existing code. - Linux 6.17 and 6.18 are now supported.
- The
drgn.helpers.linux.timekeepinghelpers were updated to handle the core timekeeping structure being changed in Linux 6.17. tools/fsrefs.pywas updated to handle a change in how block devices used by Btrfs were tracked in Linux 6.17.drgn.helpers.linux.fs.d_path()when passed only a dentry was updated to handle a change to the list of super block mounts in Linux 6.18.drgn.helpers.linux.net.get_net_ns_by_inode()was updated to handle a moved structure member in Linux 6.18.- drgn now handles empty ELF program headers in vmlinux, which were observed on some Linux 6.18 builds.
- The
Incompatible Changes
- Support for Python 3.6 and 3.7 was removed.
drgn.helpers.common.memory.identify_address()now returns"task stack: ..."instead of"vmap stack: ..."when it identifies an address as belonging to a vmapped task stack.
Bug Fixes
- Stack traces on x86-64 kernels using the frame pointer unwinder (instead of ORC) and on AArch64 can now unwind through an interrupt. Contributed by Stephen Brennan.
drgn.helpers.linux.mm.for_each_page()was fixed to not return invalid pages that can't be dereferenced.drgn.helpers.experimental.kmodify.write_object()was fixed to handle bit fields of size 1 and reject larger bit fields. Previously, it would write to the wrong bits and overwrite additional memory.- Symbol lookups of Linux kernel per-CPU symbols (
drgn.Program.symbol{,s}()) now return the correct address instead of incorrectly applying the KASLR offset. - An
UnboundLocalErrorfromdrgn.helpers.linux.cgroup.css_next_child()when racing with a cgroup being released was fixed. drgn.helpers.linux.percpu.percpu_counter_sum()was fixed on !SMP kernels. It would previously fail with anAttributeError.slab_cache_for_each_allocated_object()andslab_object_info()indrgn.helpers.linux.slabwere made more resilient to races with slab allocator activity on live kernels.slab_cache_for_each_allocated_object()andslab_object_info()indrgn.helpers.linux.slabwere fixed to consider per-node caches in the old SLAB allocator.tools/fsrefs.pywas fixed to not print "unknown uprobe" warnings when the uprobe was actually found.- Subscripting an array with a negative index was fixed. It previously computed an incorrect address.
- A buffer underwrite when creating an object with size 0 from bytes was fixed.
- A race leaving the GIL in an invalid state on Python versions before 3.12 was fixed.
- A deprecation warning when building for Python 3.14 was fixed.
contrib Directory
contrib/pstack.pywas added. It collects stack traces of userspace tasks when debugging the kernel. Contributed by Stephen Brennan.contrib/bt_by_pid_and_frame.pywas added. It is convenience script for getting stack traces and local variables from the kernel. Contributed by Ye Liu.contrib/show_page_info.pywas added. It dumps the page state of a given virtual address in a given PID. Contributed by Ye Liu.contrib/mutex_owner.pywas added. It lists what task holds a mutex and what tasks are waiting. Contributed by Matt Fleming.contrib/search_kernel_memory.pynow handles kernel core dumps (as long as the kernel was configured withCONFIG_PROC_KCORE=y). It can also now accept the value to search for as a string or address-sized integer.
Internal
- A system for CLI-like commands was implemented, and several commands from the crash utility were ported to drgn. This is not quite polished yet, so it is not enabled by default. It can be enabled for alpha testing by running
import drgn.commands._builtin. Commands are accessed by starting a line in the REPL with%. This contains contributions from Stephen Brennan, Ye Liu, and Srikanth C S.