Helpers

The drgn.helpers package contains subpackages which provide helpers for working with particular types of programs. Currently, there are common helpers and helpers for the Linux kernel. In the future, there may be helpers for, e.g., glibc and libstdc++.

class drgn.helpers.ValidationError

Bases: Exception

Error raised by a validator when an inconsistent or invalid state is detected.

Common

The drgn.helpers.common package provides helpers that can be used with any program. The helpers are available from the individual modules in which they are defined and from this top-level package. E.g., the following are both valid:

>>> from drgn.helpers.common.memory import identify_address
>>> from drgn.helpers.common import identify_address

Some of these helpers may have additional program-specific behavior but are otherwise generic.

Formatting

The drgn.helpers.common.format module provides generic helpers for formatting different things as text.

drgn.helpers.common.format.escape_ascii_character(c: int, escape_single_quote: bool = False, escape_double_quote: bool = False, escape_backslash: bool = False) str

Format an ASCII byte value as a character, possibly escaping it. Non-printable characters are always escaped. Non-printable characters other than \0, \a, \b, \t, \n, \v, \f, and \r are escaped in hexadecimal format (e.g., \x7f). By default, printable characters are never escaped.

Parameters
  • c – Character to escape.

  • escape_single_quote – Whether to escape single quotes to \'.

  • escape_double_quote – Whether to escape double quotes to \".

  • escape_backslash – Whether to escape backslashes to \\.

drgn.helpers.common.format.escape_ascii_string(buffer: Iterable[int], escape_single_quote: bool = False, escape_double_quote: bool = False, escape_backslash: bool = False) str

Escape an iterable of ASCII byte values (e.g., bytes or bytearray). See escape_ascii_character().

Parameters

buffer – Byte array to escape.

drgn.helpers.common.format.decode_flags(value: drgn.IntegerLike, flags: Iterable[Tuple[str, int]], bit_numbers: bool = True) str

Get a human-readable representation of a bitmask of flags.

By default, flags are specified by their bit number:

>>> decode_flags(2, [("BOLD", 0), ("ITALIC", 1), ("UNDERLINE", 2)])
'ITALIC'

They can also be specified by their value:

>>> decode_flags(2, [("BOLD", 1), ("ITALIC", 2), ("UNDERLINE", 4)],
...              bit_numbers=False)
'ITALIC'

Multiple flags are combined with “|”:

>>> decode_flags(5, [("BOLD", 0), ("ITALIC", 1), ("UNDERLINE", 2)])
'BOLD|UNDERLINE'

If there are multiple names for the same bit, they are all included:

>>> decode_flags(2, [("SMALL", 0), ("BIG", 1), ("LARGE", 1)])
'BIG|LARGE'

If there are any unknown bits, their raw value is included:

>>> decode_flags(27, [("BOLD", 0), ("ITALIC", 1), ("UNDERLINE", 2)])
'BOLD|ITALIC|0x18'

Zero is returned verbatim:

>>> decode_flags(0, [("BOLD", 0), ("ITALIC", 1), ("UNDERLINE", 2)])
'0'
Parameters
  • value – Bitmask to decode.

  • flags – List of flag names and their bit numbers or values.

  • bit_numbers – Whether flags specifies the bit numbers (where 0 is the least significant bit) or values of the flags.

drgn.helpers.common.format.decode_enum_type_flags(value: drgn.IntegerLike, type: drgn.Type, bit_numbers: bool = True) str

Get a human-readable representation of a bitmask of flags where the flags are specified by an enumerated drgn.Type.

This supports enums where the values are bit numbers:

>>> print(bits_enum)
enum style_bits {
        BOLD = 0,
        ITALIC = 1,
        UNDERLINE = 2,
}
>>> decode_enum_type_flags(5, bits_enum)
'BOLD|UNDERLINE'

Or the values of the flags:

>>> print(flags_enum)
enum style_flags {
        BOLD = 1,
        ITALIC = 2,
        UNDERLINE = 4,
}
>>> decode_enum_type_flags(5, flags_enum, bit_numbers=False)
'BOLD|UNDERLINE'

See decode_flags().

Parameters
  • value – Bitmask to decode.

  • type – Enumerated type with bit numbers for enumerators.

  • bit_numbers – Whether the enumerator values specify the bit numbers or values of the flags.

drgn.helpers.common.format.number_in_binary_units(n: SupportsFloat, precision: int = 1) str

Format a number in binary units (i.e., “K” is 1024, “M” is 10242, etc.).

>>> binary_units(1280)
'1.2K'

A precision can be specified:

>>> binary_units(1280, precision=2)
'1.25K'

Exact numbers are printed without a fractional part:

>>> binary_units(1024 * 1024)
'1M'

Numbers less than 1024 are not scaled:

>>> binary_units(10)
"10"
Parameters
  • n – Number to format.

  • precision – Number of digits to include in fractional part.

Memory

The drgn.helpers.common.memory module provides helpers for working with memory and addresses.

drgn.helpers.common.memory.identify_address(addr: drgn.Object) Optional[str]
drgn.helpers.common.memory.identify_address(prog: drgn.Program, addr: drgn.IntegerLike) Optional[str]

Try to identify what an address refers to.

For all programs, this will identify addresses as follows:

  • Object symbols (e.g., addresses in global variables): object symbol: {symbol_name}+{hex_offset} (where hex_offset is the offset from the beginning of the symbol in hexadecimal).

  • Function symbols (i.e., addresses in functions): function symbol: {symbol_name}+{hex_offset}.

  • Other symbols: symbol: {symbol_name}+{hex_offset}.

Additionally, for the Linux kernel, this will identify:

  • Allocated slab objects: slab object: {slab_cache_name}+{hex_offset} (where hex_offset is the offset from the beginning of the object in hexadecimal).

  • Free slab objects: free slab object: {slab_cache_name}+{hex_offset}.

This may recognize other types of addresses in the future.

The address can be given as an Object or as a Program and an integer.

Parameters

addrvoid *

Returns

Identity as string, or None if the address is unrecognized.

Stack

The drgn.helpers.common.stack module provides helpers for working with stack traces.

drgn.helpers.common.stack.print_annotated_stack(trace: drgn.StackTrace) None

Print the contents of stack memory in a stack trace, annotating values that can be identified.

Currently, this will identify any addresses on the stack with identify_address().

>>> print_annotated_stack(prog.stack_trace(1))
STACK POINTER     VALUE
[stack frame #0 at 0xffffffff8dc93c41 (__schedule+0x429/0x488) in context_switch at ./kernel/sched/core.c:5209:2 (inlined)]
[stack frame #1 at 0xffffffff8dc93c41 (__schedule+0x429/0x488) in __schedule at ./kernel/sched/core.c:6521:8]
ffffa903c0013d28: ffffffff8d8497bf [function symbol: __flush_tlb_one_user+0x5]
ffffa903c0013d30: 000000008d849eb5
ffffa903c0013d38: 0000000000000001
ffffa903c0013d40: 0000000000000004
ffffa903c0013d48: efdea37bb7cb1f00
ffffa903c0013d50: ffff926641178000 [slab object: task_struct+0x0]
ffffa903c0013d58: ffff926641178000 [slab object: task_struct+0x0]
ffffa903c0013d60: ffffa903c0013e10
ffffa903c0013d68: ffff926641177ff0 [slab object: mm_struct+0x70]
ffffa903c0013d70: ffff926641178000 [slab object: task_struct+0x0]
ffffa903c0013d78: ffff926641178000 [slab object: task_struct+0x0]
ffffa903c0013d80: ffffffff8dc93d29 [function symbol: schedule+0x89]
...
Parameters

trace – Stack trace to print.

Types

The drgn.helpers.common.type module provides generic helpers for working with types in ways that aren’t provided by the core drgn library.

drgn.helpers.common.type.enum_type_to_class(type: drgn.Type, name: str, exclude: Container[str] = (), prefix: str = '') Type[enum.IntEnum]

Get an enum.IntEnum class from an enumerated drgn.Type.

Parameters
  • type – Enumerated type to convert.

  • name – Name of the IntEnum type to create.

  • exclude – Container (e.g., list or set) of enumerator names to exclude from the created IntEnum.

  • prefix – Prefix to strip from the beginning of enumerator names.

Linux Kernel

The drgn.helpers.linux package contains several modules for working with data structures and subsystems in the Linux kernel. The helpers are available from the individual modules in which they are defined and from this top-level package. E.g., the following are both valid:

>>> from drgn.helpers.linux.list import list_for_each_entry
>>> from drgn.helpers.linux import list_for_each_entry

Iterator macros (for_each_foo) are a common idiom in the Linux kernel. The equivalent drgn helpers are implemented as Python generators. For example, the following code in C:

list_for_each(pos, head)
        do_something_with(pos);

Translates to the following code in Python:

for pos in list_for_each(head):
    do_something_with(pos)

Bit Operations

The drgn.helpers.linux.bitops module provides helpers for common bit operations in the Linux kernel.

drgn.helpers.linux.bitops.for_each_set_bit(bitmap: drgn.Object, size: drgn.IntegerLike) Iterator[int]

Iterate over all set (one) bits in a bitmap.

Parameters
  • bitmapunsigned long *

  • size – Size of bitmap in bits.

drgn.helpers.linux.bitops.for_each_clear_bit(bitmap: drgn.Object, size: drgn.IntegerLike) Iterator[int]

Iterate over all clear (zero) bits in a bitmap.

Parameters
  • bitmapunsigned long *

  • size – Size of bitmap in bits.

drgn.helpers.linux.bitops.test_bit(nr: drgn.IntegerLike, bitmap: drgn.Object) bool

Return whether a bit in a bitmap is set.

Parameters
  • nr – Bit number.

  • bitmapunsigned long *

Block Layer

The drgn.helpers.linux.block module provides helpers for working with the Linux block layer, including disks (struct gendisk) and partitions.

Since Linux v5.11, partitions are represented by struct block_device. Before that, they were represented by struct hd_struct.

drgn.helpers.linux.block.disk_devt(disk: drgn.Object) drgn.Object

Get a disk’s device number.

Parameters

diskstruct gendisk *

Returns

dev_t

drgn.helpers.linux.block.disk_name(disk: drgn.Object) bytes

Get the name of a disk (e.g., sda).

Parameters

diskstruct gendisk *

drgn.helpers.linux.block.for_each_disk(prog: drgn.Program) Iterator[drgn.Object]

Iterate over all disks in the system.

Returns

Iterator of struct gendisk * objects.

drgn.helpers.linux.block.print_disks(prog: drgn.Program) None

Print all of the disks in the system.

drgn.helpers.linux.block.part_devt(part: drgn.Object) drgn.Object

Get a partition’s device number.

Parameters

partstruct block_device * or struct hd_struct * depending on the kernel version.

Returns

dev_t

drgn.helpers.linux.block.part_name(part: drgn.Object) bytes

Get the name of a partition (e.g., sda1).

Parameters

partstruct block_device * or struct hd_struct * depending on the kernel version.

drgn.helpers.linux.block.for_each_partition(prog: drgn.Program) Iterator[drgn.Object]

Iterate over all partitions in the system.

Returns

Iterator of struct block_device * or struct hd_struct * objects depending on the kernel version.

drgn.helpers.linux.block.print_partitions(prog: drgn.Program) None

Print all of the partitions in the system.

Boot

The drgn.helpers.linux.boot module provides helpers for inspecting the Linux kernel boot configuration.

drgn.helpers.linux.boot.kaslr_offset(prog: drgn.Program) int

Get the kernel address space layout randomization offset (zero if it is disabled).

drgn.helpers.linux.boot.pgtable_l5_enabled(prog: drgn.Program) bool

Return whether 5-level paging is enabled.

BPF

The drgn.helpers.linux.bpf module provides helpers for working with BPF interface in include/linux/bpf.h, include/linux/bpf-cgroup.h, etc.

drgn.helpers.linux.bpf.bpf_btf_for_each(prog: drgn.Program) Iterator[drgn.Object]

Iterate over all BTF objects.

This is only supported since Linux v4.18.

Returns

Iterator of struct btf * objects.

Iterate over all BPF links.

This is only supported since Linux v5.8.

Returns

Iterator of struct bpf_link * objects.

drgn.helpers.linux.bpf.bpf_map_for_each(prog: drgn.Program) Iterator[drgn.Object]

Iterate over all BPF maps.

This is only supported since Linux v4.13.

Returns

Iterator of struct bpf_map * objects.

drgn.helpers.linux.bpf.bpf_prog_for_each(prog: drgn.Program) Iterator[drgn.Object]

Iterate over all BPF programs.

This is only supported since Linux v4.13.

Returns

Iterator of struct bpf_prog * objects.

drgn.helpers.linux.bpf.cgroup_bpf_prog_for_each(cgrp: drgn.Object, bpf_attach_type: drgn.IntegerLike) Iterator[drgn.Object]

Iterate over all cgroup BPF programs of the given attach type attached to the given cgroup.

Parameters
  • cgrpstruct cgroup *

  • bpf_attach_typeenum bpf_attach_type

Returns

Iterator of struct bpf_prog * objects.

drgn.helpers.linux.bpf.cgroup_bpf_prog_for_each_effective(cgrp: drgn.Object, bpf_attach_type: drgn.IntegerLike) Iterator[drgn.Object]

Iterate over all effective cgroup BPF programs of the given attach type for the given cgroup.

Parameters
  • cgrpstruct cgroup *

  • bpf_attach_typeenum bpf_attach_type

Returns

Iterator of struct bpf_prog * objects.

Cgroup

The drgn.helpers.linux.cgroup module provides helpers for working with the cgroup interface in include/linux/cgroup.h. Only cgroup v2 is supported.

drgn.helpers.linux.cgroup.sock_cgroup_ptr(skcd: drgn.Object) drgn.Object

Get the cgroup for a socket from the given struct sock_cgroup_data * (usually from struct sock::sk_cgrp_data).

Parameters

skcdstruct sock_cgroup_data *

Returns

struct cgroup *

drgn.helpers.linux.cgroup.cgroup_parent(cgrp: drgn.Object) drgn.Object

Return the parent cgroup of the given cgroup if it exists, NULL otherwise.

Parameters

cgrpstruct cgroup *

Returns

struct cgroup *

drgn.helpers.linux.cgroup.cgroup_name(cgrp: drgn.Object) bytes

Get the name of the given cgroup.

Parameters

cgrpstruct cgroup *

drgn.helpers.linux.cgroup.cgroup_path(cgrp: drgn.Object) bytes

Get the full path of the given cgroup.

Parameters

cgrpstruct cgroup *

drgn.helpers.linux.cgroup.cgroup_get_from_path(prog: drgn.Program, path: drgn.Path) drgn.Object

Look up a cgroup from its default hierarchy path .

Parameters

path – Path name.

drgn.helpers.linux.cgroup.css_next_child(pos: drgn.Object, parent: drgn.Object) drgn.Object

Get the next child (or NULL if there is none) of the given parent starting from the given position (NULL to initiate traversal).

Parameters
  • posstruct cgroup_subsys_state *

  • parentstruct cgroup_subsys_state *

Returns

struct cgroup_subsys_state *

drgn.helpers.linux.cgroup.css_next_descendant_pre(pos: drgn.Object, root: drgn.Object) drgn.Object

Get the next pre-order descendant (or NULL if there is none) of the given css root starting from the given position (NULL to initiate traversal).

Parameters
  • posstruct cgroup_subsys_state *

  • rootstruct cgroup_subsys_state *

Returns

struct cgroup_subsys_state *

drgn.helpers.linux.cgroup.css_for_each_child(css: drgn.Object) Iterator[drgn.Object]

Iterate through children of the given css.

Parameters

cssstruct cgroup_subsys_state *

Returns

Iterator of struct cgroup_subsys_state * objects.

drgn.helpers.linux.cgroup.css_for_each_descendant_pre(css: drgn.Object) Iterator[drgn.Object]

Iterate through the given css’s descendants in pre-order.

Parameters

cssstruct cgroup_subsys_state *

Returns

Iterator of struct cgroup_subsys_state * objects.

CPU Masks

The drgn.helpers.linux.cpumask module provides helpers for working with CPU masks from include/linux/cpumask.h.

drgn.helpers.linux.cpumask.for_each_cpu(mask: drgn.Object) Iterator[int]

Iterate over all of the CPUs in the given mask.

Parameters

maskstruct cpumask

drgn.helpers.linux.cpumask.for_each_online_cpu(prog: drgn.Program) Iterator[int]

Iterate over all online CPUs.

drgn.helpers.linux.cpumask.for_each_possible_cpu(prog: drgn.Program) Iterator[int]

Iterate over all possible CPUs.

drgn.helpers.linux.cpumask.for_each_present_cpu(prog: drgn.Program) Iterator[int]

Iterate over all present CPUs.

Devices

The drgn.helpers.linux.device module provides helpers for working with Linux devices, including the kernel encoding of dev_t.

drgn.helpers.linux.device.MAJOR(dev: drgn.IntegerLike) int

Return the major ID of a kernel dev_t.

Parameters

devdev_t object or :class:int.

drgn.helpers.linux.device.MINOR(dev: drgn.IntegerLike) int

Return the minor ID of a kernel dev_t.

Parameters

devdev_t object or :class:int.

drgn.helpers.linux.device.MKDEV(major: drgn.IntegerLike, minor: drgn.IntegerLike) int

Return a kernel dev_t from the major and minor IDs.

Parameters
  • major – Device major ID.

  • minor – Device minor ID.

Virtual Filesystem Layer

The drgn.helpers.linux.fs module provides helpers for working with the Linux virtual filesystem (VFS) layer, including mounts, dentries, and inodes.

drgn.helpers.linux.fs.path_lookup(prog_or_root: Union[drgn.Program, drgn.Object], path: drgn.Path, allow_negative: bool = False) drgn.Object

Look up the given path name.

Parameters
  • prog_or_rootstruct path * object to use as root directory, or Program to use the initial root filesystem.

  • path – Path to lookup.

  • allow_negative – Whether to allow returning a negative dentry (i.e., a dentry for a non-existent path).

Returns

struct path

Raises

Exception – if the dentry is negative and allow_negative is False, or if the path is not present in the dcache. The latter does not necessarily mean that the path does not exist; it may be uncached. On a live system, you can make the kernel cache the path by accessing it (e.g., with open() or os.stat()):

>>> path_lookup(prog, '/usr/include/stdlib.h')
...
Exception: could not find '/usr/include/stdlib.h' in dcache
>>> open('/usr/include/stdlib.h').close()
>>> path_lookup(prog, '/usr/include/stdlib.h')
(struct path){
        .mnt = (struct vfsmount *)0xffff8b70413cdca0,
        .dentry = (struct dentry *)0xffff8b702ac2c480,
}
drgn.helpers.linux.fs.d_path(path: drgn.Object) bytes

Return the full path of a dentry given a struct path.

Parameters

pathstruct path or struct path *

drgn.helpers.linux.fs.d_path(vfsmnt: drgn.Object, dentry: drgn.Object) bytes

Return the full path of a dentry given a mount and dentry.

Parameters
  • vfsmntstruct vfsmount *

  • dentrystruct dentry *

drgn.helpers.linux.fs.dentry_path(dentry: drgn.Object) bytes

Return the path of a dentry from the root of its filesystem.

Parameters

dentrystruct dentry *

drgn.helpers.linux.fs.inode_path(inode: drgn.Object) Optional[bytes]

Return any path of an inode from the root of its filesystem.

Parameters

inodestruct inode *

Returns

Path, or None if the inode has no aliases.

drgn.helpers.linux.fs.inode_paths(inode: drgn.Object) Iterator[bytes]

Return an iterator over all of the paths of an inode from the root of its filesystem.

Parameters

inodestruct inode *

drgn.helpers.linux.fs.mount_src(mnt: drgn.Object) bytes

Get the source device name for a mount.

Parameters

mntstruct mount *

drgn.helpers.linux.fs.mount_dst(mnt: drgn.Object) bytes

Get the path of a mount point.

Parameters

mntstruct mount *

drgn.helpers.linux.fs.mount_fstype(mnt: drgn.Object) bytes

Get the filesystem type of a mount.

Parameters

mntstruct mount *

drgn.helpers.linux.fs.for_each_mount(prog_or_ns: Union[drgn.Program, drgn.Object], src: Optional[drgn.Path] = None, dst: Optional[drgn.Path] = None, fstype: Optional[Union[str, bytes]] = None) Iterator[drgn.Object]

Iterate over all of the mounts in a given namespace.

Parameters
  • prog_or_nsstruct mnt_namespace * to iterate over, or Program to iterate over initial mount namespace.

  • src – Only include mounts with this source device name.

  • dst – Only include mounts with this destination path.

  • fstype – Only include mounts with this filesystem type.

Returns

Iterator of struct mount * objects.

drgn.helpers.linux.fs.print_mounts(prog_or_ns: Union[drgn.Program, drgn.Object], src: Optional[drgn.Path] = None, dst: Optional[drgn.Path] = None, fstype: Optional[Union[str, bytes]] = None) None

Print the mount table of a given namespace. The arguments are the same as for_each_mount(). The output format is similar to /proc/mounts but prints the value of each struct mount *.

drgn.helpers.linux.fs.fget(task: drgn.Object, fd: drgn.IntegerLike) drgn.Object

Return the kernel file descriptor of the fd of a given task.

Parameters
  • taskstruct task_struct *

  • fd – File descriptor.

Returns

struct file *

drgn.helpers.linux.fs.for_each_file(task: drgn.Object) Iterator[Tuple[int, drgn.Object]]

Iterate over all of the files open in a given task.

Parameters

taskstruct task_struct *

Returns

Iterator of (fd, struct file *) tuples.

drgn.helpers.linux.fs.print_files(task: drgn.Object) None

Print the open files of a given task.

Parameters

taskstruct task_struct *

IDR

The drgn.helpers.linux.idr module provides helpers for working with the IDR data structure in include/linux/idr.h. An IDR provides a mapping from an ID to a pointer.

drgn.helpers.linux.idr.idr_find(idr: drgn.Object, id: drgn.IntegerLike) drgn.Object

Look up the entry with the given ID in an IDR.

Parameters
  • idrstruct idr *

  • id – Entry ID.

Returns

void * found entry, or NULL if not found.

drgn.helpers.linux.idr.idr_for_each(idr: drgn.Object) Iterator[Tuple[int, drgn.Object]]

Iterate over all of the entries in an IDR.

Parameters

idrstruct idr *

Returns

Iterator of (index, void *) tuples.

Kconfig

The drgn.helpers.linux.kconfig module provides helpers for reading the Linux kernel build configuration.

drgn.helpers.linux.kconfig.get_kconfig(prog: drgn.Program) Mapping[str, str]

Get the kernel build configuration as a mapping from the option name to the value.

>>> get_kconfig(prog)['CONFIG_SMP']
'y'
>>> get_kconfig(prog)['CONFIG_HZ']
'300'

This is only supported if the kernel was compiled with CONFIG_IKCONFIG. Note that most Linux distributions do not enable this option.

Kernfs

The drgn.helpers.linux.kernfs module provides helpers for working with the kernfs pseudo filesystem interface in include/linux/kernfs.h.

drgn.helpers.linux.kernfs.kernfs_name(kn: drgn.Object) bytes

Get the name of the given kernfs node.

Parameters

knstruct kernfs_node *

drgn.helpers.linux.kernfs.kernfs_path(kn: drgn.Object) bytes

Get full path of the given kernfs node.

Parameters

knstruct kernfs_node *

drgn.helpers.linux.kernfs.kernfs_walk(parent: drgn.Object, path: drgn.Path) drgn.Object

Find the kernfs node with the given path from the given parent kernfs node.

Parameters
  • parentstruct kernfs_node *

  • path – Path name.

Returns

struct kernfs_node * (NULL if not found)

Linked Lists

The drgn.helpers.linux.list module provides helpers for working with the doubly-linked list implementations (struct list_head and struct hlist_head) in include/linux/list.h.

drgn.helpers.linux.list.list_empty(head: drgn.Object) bool

Return whether a list is empty.

Parameters

headstruct list_head *

drgn.helpers.linux.list.list_is_singular(head: drgn.Object) bool

Return whether a list has only one element.

Parameters

headstruct list_head *

drgn.helpers.linux.list.list_first_entry(head: drgn.Object, type: Union[str, drgn.Type], member: str) drgn.Object

Return the first entry in a list.

The list is assumed to be non-empty.

See also list_first_entry_or_null().

Parameters
  • headstruct list_head *

  • type – Entry type.

  • member – Name of list node member in entry type.

Returns

type *

drgn.helpers.linux.list.list_first_entry_or_null(head: drgn.Object, type: Union[str, drgn.Type], member: str) drgn.Object

Return the first entry in a list or NULL if the list is empty.

See also list_first_entry().

Parameters
  • headstruct list_head *

  • type – Entry type.

  • member – Name of list node member in entry type.

Returns

type *

drgn.helpers.linux.list.list_last_entry(head: drgn.Object, type: Union[str, drgn.Type], member: str) drgn.Object

Return the last entry in a list.

The list is assumed to be non-empty.

Parameters
  • headstruct list_head *

  • type – Entry type.

  • member – Name of list node member in entry type.

Returns

type *

drgn.helpers.linux.list.list_next_entry(pos: drgn.Object, member: str) drgn.Object

Return the next entry in a list.

Parameters
  • postype*

  • member – Name of list node member in entry type.

Returns

type *

drgn.helpers.linux.list.list_prev_entry(pos: drgn.Object, member: str) drgn.Object

Return the previous entry in a list.

Parameters
  • postype*

  • member – Name of list node member in entry type.

Returns

type *

drgn.helpers.linux.list.list_for_each(head: drgn.Object) Iterator[drgn.Object]

Iterate over all of the nodes in a list.

Parameters

headstruct list_head *

Returns

Iterator of struct list_head * objects.

drgn.helpers.linux.list.list_for_each_reverse(head: drgn.Object) Iterator[drgn.Object]

Iterate over all of the nodes in a list in reverse order.

Parameters

headstruct list_head *

Returns

Iterator of struct list_head * objects.

drgn.helpers.linux.list.list_for_each_entry(type: Union[str, drgn.Type], head: drgn.Object, member: str) Iterator[drgn.Object]

Iterate over all of the entries in a list.

Parameters
  • type – Entry type.

  • headstruct list_head *

  • member – Name of list node member in entry type.

Returns

Iterator of type * objects.

drgn.helpers.linux.list.list_for_each_entry_reverse(type: Union[str, drgn.Type], head: drgn.Object, member: str) Iterator[drgn.Object]

Iterate over all of the entries in a list in reverse order.

Parameters
  • type – Entry type.

  • headstruct list_head *

  • member – Name of list node member in entry type.

Returns

Iterator of type * objects.

drgn.helpers.linux.list.validate_list(head: drgn.Object) None

Validate that the next and prev pointers in a list are consistent.

Parameters

headstruct list_head *

Raises

ValidationError – if the list is invalid

drgn.helpers.linux.list.validate_list_for_each(head: drgn.Object) Iterator[drgn.Object]

Like list_for_each(), but validates the list like validate_list() while iterating.

Parameters

headstruct list_head *

Raises

ValidationError – if the list is invalid

drgn.helpers.linux.list.validate_list_for_each_entry(type: Union[str, drgn.Type], head: drgn.Object, member: str) Iterator[drgn.Object]

Like list_for_each_entry(), but validates the list like validate_list() while iterating.

Parameters
  • type – Entry type.

  • headstruct list_head *

  • member – Name of list node member in entry type.

Raises

ValidationError – if the list is invalid

drgn.helpers.linux.list.hlist_empty(head: drgn.Object) bool

Return whether a hash list is empty.

Parameters

headstruct hlist_head *

drgn.helpers.linux.list.hlist_for_each(head: drgn.Object) Iterator[drgn.Object]

Iterate over all of the nodes in a hash list.

Parameters

headstruct hlist_head *

Returns

Iterator of struct hlist_node * objects.

drgn.helpers.linux.list.hlist_for_each_entry(type: Union[str, drgn.Type], head: drgn.Object, member: str) Iterator[drgn.Object]

Iterate over all of the entries in a hash list.

Parameters
  • type – Entry type.

  • headstruct hlist_head *

  • member – Name of list node member in entry type.

Returns

Iterator of type * objects.

Nulls Lists

The drgn.helpers.linux.list_nulls module provides helpers for working with the special version of lists (struct hlist_nulls_head and struct hlist_nulls_node) in include/linux/list_nulls.h where the end of list is not a NULL pointer, but a “nulls” marker.

drgn.helpers.linux.list_nulls.is_a_nulls(pos: drgn.Object) bool

Return whether a a pointer is a nulls marker.

Parameters

posstruct hlist_nulls_node *

drgn.helpers.linux.list_nulls.hlist_nulls_empty(head: drgn.Object) bool

Return whether a nulls hash list is empty.

Parameters

headstruct hlist_nulls_head *

drgn.helpers.linux.list_nulls.hlist_nulls_for_each_entry(type: Union[str, drgn.Type], head: drgn.Object, member: str) Iterator[drgn.Object]

Iterate over all the entries in a nulls hash list.

Parameters
  • type – Entry type.

  • headstruct hlist_nulls_head *

  • member – Name of list node member in entry type.

Returns

Iterator of type * objects.

Lockless Lists

The drgn.helpers.linux.llist module provides helpers for working with the lockless, NULL-terminated, singly-linked list implementation in include/linux/llist.h (struct llist_head and struct llist_node).

drgn.helpers.linux.llist.llist_empty(head: drgn.Object) bool

Return whether an llist is empty.

Parameters

headstruct llist_head *

drgn.helpers.linux.llist.llist_is_singular(head: drgn.Object) bool

Return whether an llist has only one element.

Parameters

headstruct llist_head *

drgn.helpers.linux.llist.llist_first_entry(head: drgn.Object, type: Union[str, drgn.Type], member: str) drgn.Object

Return the first entry in an llist.

The list is assumed to be non-empty.

See also llist_first_entry_or_null().

Parameters
  • headstruct llist_head *

  • type – Entry type.

  • member – Name of struct llist_node member in entry type.

Returns

type *

drgn.helpers.linux.llist.llist_first_entry_or_null(head: drgn.Object, type: Union[str, drgn.Type], member: str) drgn.Object

Return the first entry in an llist or NULL if the llist is empty.

See also llist_first_entry().

Parameters
  • headstruct llist_head *

  • type – Entry type.

  • member – Name of struct llist_node member in entry type.

Returns

type *

drgn.helpers.linux.llist.llist_next_entry(pos: drgn.Object, member: str) drgn.Object

Return the next entry in an llist.

Parameters
  • postype*

  • member – Name of struct llist_node member in entry type.

Returns

type *

drgn.helpers.linux.llist.llist_for_each(node: drgn.Object) Iterator[drgn.Object]

Iterate over all of the nodes in an llist starting from a given node.

Parameters

nodestruct llist_node *

Returns

Iterator of struct llist_node * objects.

drgn.helpers.linux.llist.llist_for_each_entry(type: Union[str, drgn.Type], node: drgn.Object, member: str) Iterator[drgn.Object]

Iterate over all of the entries in an llist starting from a given node.

Parameters
  • type – Entry type.

  • nodestruct llist_node *

  • member – Name of struct llist_node member in entry type.

Returns

Iterator of type * objects.

Memory Management

The drgn.helpers.linux.mm module provides helpers for working with the Linux memory management (MM) subsystem. Only AArch64 and x86-64 are currently supported.

drgn.helpers.linux.mm.PageActive(page: drgn.Object) bool

Return whether the PG_active flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageChecked(page: drgn.Object) bool

Return whether the PG_checked flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageDirty(page: drgn.Object) bool

Return whether the PG_dirty flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageDoubleMap(page: drgn.Object) bool

Return whether the PG_double_map flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageError(page: drgn.Object) bool

Return whether the PG_error flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageForeign(page: drgn.Object) bool

Return whether the PG_foreign flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageHWPoison(page: drgn.Object) bool

Return whether the PG_hwpoison flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageHasHWPoisoned(page: drgn.Object) bool

Return whether the PG_has_hwpoisoned flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageIdle(page: drgn.Object) bool

Return whether the PG_idle flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageIsolated(page: drgn.Object) bool

Return whether the PG_isolated flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageLRU(page: drgn.Object) bool

Return whether the PG_lru flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageLocked(page: drgn.Object) bool

Return whether the PG_locked flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageMappedToDisk(page: drgn.Object) bool

Return whether the PG_mappedtodisk flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageMlocked(page: drgn.Object) bool

Return whether the PG_mlocked flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageOwnerPriv1(page: drgn.Object) bool

Return whether the PG_owner_priv_1 flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PagePinned(page: drgn.Object) bool

Return whether the PG_pinned flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PagePrivate(page: drgn.Object) bool

Return whether the PG_private flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PagePrivate2(page: drgn.Object) bool

Return whether the PG_private_2 flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageReadahead(page: drgn.Object) bool

Return whether the PG_readahead flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageReclaim(page: drgn.Object) bool

Return whether the PG_reclaim flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageReferenced(page: drgn.Object) bool

Return whether the PG_referenced flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageReported(page: drgn.Object) bool

Return whether the PG_reported flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageReserved(page: drgn.Object) bool

Return whether the PG_reserved flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageSavePinned(page: drgn.Object) bool

Return whether the PG_savepinned flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageSkipKASanPoison(page: drgn.Object) bool

Return whether the PG_skip_kasan_poison flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageSlab(page: drgn.Object) bool

Return whether the PG_slab flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageSlobFree(page: drgn.Object) bool

Return whether the PG_slob_free flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageSwapBacked(page: drgn.Object) bool

Return whether the PG_swapbacked flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageUncached(page: drgn.Object) bool

Return whether the PG_uncached flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageUnevictable(page: drgn.Object) bool

Return whether the PG_unevictable flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageUptodate(page: drgn.Object) bool

Return whether the PG_uptodate flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageVmemmapSelfHosted(page: drgn.Object) bool

Return whether the PG_vmemmap_self_hosted flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageWaiters(page: drgn.Object) bool

Return whether the PG_waiters flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageWorkingset(page: drgn.Object) bool

Return whether the PG_workingset flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageWriteback(page: drgn.Object) bool

Return whether the PG_writeback flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageXenRemapped(page: drgn.Object) bool

Return whether the PG_xen_remapped flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageYoung(page: drgn.Object) bool

Return whether the PG_young flag is set on a page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageCompound(page: drgn.Object) bool

Return whether a page is part of a compound page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageHead(page: drgn.Object) bool

Return whether a page is a head page in a compound page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.PageTail(page: drgn.Object) bool

Return whether a page is a tail page in a compound page.

Parameters

pagestruct page *

drgn.helpers.linux.mm.compound_head(page: drgn.Object) drgn.Object

Get the head page associated with a page.

If page is a tail page, this returns the head page of the compound page it belongs to. Otherwise, it returns page.

Parameters

pagestruct page *

Returns

struct page *

drgn.helpers.linux.mm.compound_order(page: drgn.Object) drgn.Object

Return the allocation order of a potentially compound page.

Parameters

pagestruct page *

Returns

unsigned int

drgn.helpers.linux.mm.compound_nr(page: drgn.Object) drgn.Object

Return the number of pages in a potentially compound page.

Parameters

pagestruct page *

Returns

unsigned long

drgn.helpers.linux.mm.page_size(page: drgn.Object) drgn.Object

Return the number of bytes in a potentially compound page.

Parameters

pagestruct page *

Returns

unsigned long

drgn.helpers.linux.mm.decode_page_flags(page: drgn.Object) str

Get a human-readable representation of the flags set on a page.

>>> decode_page_flags(page)
'PG_uptodate|PG_dirty|PG_lru|PG_reclaim|PG_swapbacked|PG_readahead|PG_savepinned|PG_isolated|PG_reported'
Parameters

pagestruct page *

drgn.helpers.linux.mm.for_each_page(prog: drgn.Program) Iterator[drgn.Object]

Iterate over every struct page * from the minimum to the maximum page.

Note

This may include offline pages which don’t have a valid struct page. Wrap accesses in a tryexcept drgn.FaultError:

>>> for page in for_each_page(prog):
...     try:
...         if PageLRU(page):
...             print(hex(page))
...     except drgn.FaultError:
...         continue
0xfffffb4a000c0000
0xfffffb4a000c0040
...

This may be fixed in the future.

Returns

Iterator of struct page * objects.

drgn.helpers.linux.mm.PFN_PHYS(pfn: drgn.Object) drgn.Object
drgn.helpers.linux.mm.PFN_PHYS(prog: drgn.Program, pfn: drgn.IntegerLike) drgn.Object

Get the physical address of a page frame number (PFN).

The PFN can be given as an Object or as a Program and an integer.

Parameters

pfnunsigned long

Returns

phys_addr_t

drgn.helpers.linux.mm.PHYS_PFN(addr: drgn.Object) drgn.Object
drgn.helpers.linux.mm.PHYS_PFN(prog: drgn.Program, addr: int) drgn.Object

Get the page frame number (PFN) of a physical address.

The address can be given as an Object or as a Program and an integer.

Parameters

addrphys_addr_t

Returns

unsigned long

drgn.helpers.linux.mm.page_to_pfn(page: drgn.Object) drgn.Object

Get the page frame number (PFN) of a page.

Parameters

pagestruct page *

Returns

unsigned long

drgn.helpers.linux.mm.page_to_phys(page: drgn.Object) drgn.Object

Get the physical address of a page.

Parameters

pagestruct page *

Returns

phys_addr_t

drgn.helpers.linux.mm.page_to_virt(page: drgn.Object) drgn.Object

Get the directly mapped virtual address of a page.

Parameters

pagestruct page *

Returns

void *

drgn.helpers.linux.mm.pfn_to_page(pfn: drgn.Object) drgn.Object
drgn.helpers.linux.mm.pfn_to_page(prog: drgn.Program, pfn: drgn.IntegerLike) drgn.Object

Get the page with a page frame number (PFN).

The PFN can be given as an Object or as a Program and an integer.

Parameters

pfnunsigned long

Returns

struct page *

drgn.helpers.linux.mm.pfn_to_virt(pfn: drgn.Object) drgn.Object
drgn.helpers.linux.mm.pfn_to_virt(prog: drgn.Program, pfn: drgn.IntegerLike) drgn.Object

Get the directly mapped virtual address of a page frame number (PFN).

The PFN can be given as an Object or as a Program and an integer.

Parameters

pfnunsigned long

Returns

void *

drgn.helpers.linux.mm.phys_to_page(addr: drgn.Object) drgn.Object
drgn.helpers.linux.mm.phys_to_page(prog: drgn.Program, addr: drgn.IntegerLike) drgn.Object

Get the page containing a physical address.

The address can be given as an Object or as a Program and an integer.

Parameters

addrphys_addr_t

Returns

struct page *

drgn.helpers.linux.mm.phys_to_virt(addr: drgn.Object) drgn.Object
drgn.helpers.linux.mm.phys_to_virt(prog: drgn.Program, addr: drgn.IntegerLike) drgn.Object

Get the directly mapped virtual address of a physical address.

The address can be given as an Object or as a Program and an integer.

Parameters

addrphys_addr_t

Returns

void *

drgn.helpers.linux.mm.virt_to_page(addr: drgn.Object) drgn.Object
drgn.helpers.linux.mm.virt_to_page(prog: drgn.Program, addr: drgn.IntegerLike) drgn.Object

Get the page containing a directly mapped virtual address.

The address can be given as an Object or as a Program and an integer.

Parameters

addrvoid *

Returns

struct page *

drgn.helpers.linux.mm.virt_to_pfn(addr: drgn.Object) drgn.Object
drgn.helpers.linux.mm.virt_to_pfn(prog: drgn.Program, addr: drgn.IntegerLike) drgn.Object

Get the page frame number (PFN) of a directly mapped virtual address.

The address can be given as an Object or as a Program and an integer.

Parameters

addrvoid *

Returns

unsigned long

drgn.helpers.linux.mm.virt_to_phys(addr: drgn.Object) drgn.Object
drgn.helpers.linux.mm.virt_to_phys(prog: drgn.Program, addr: drgn.IntegerLike) drgn.Object

Get the physical address of a directly mapped virtual address.

The address can be given as an Object or as a Program and an integer.

Parameters

addrvoid *

Returns

phys_addr_t

drgn.helpers.linux.mm.access_process_vm(task: drgn.Object, address: drgn.IntegerLike, size: drgn.IntegerLike) bytes

Read memory from a task’s virtual address space.

>>> task = find_task(prog, 1490152)
>>> access_process_vm(task, 0x7f8a62b56da0, 12)
b'hello, world'
Parameters
  • taskstruct task_struct *

  • address – Starting address.

  • size – Number of bytes to read.

drgn.helpers.linux.mm.access_remote_vm(mm: drgn.Object, address: drgn.IntegerLike, size: drgn.IntegerLike) bytes

Read memory from a virtual address space. This is similar to access_process_vm(), but it takes a struct mm_struct * instead of a struct task_struct *.

>>> task = find_task(prog, 1490152)
>>> access_remote_vm(task.mm, 0x7f8a62b56da0, 12)
b'hello, world'
Parameters
  • mmstruct mm_struct *

  • address – Starting address.

  • size – Number of bytes to read.

drgn.helpers.linux.mm.cmdline(task: drgn.Object) List[bytes]

Get the list of command line arguments of a task.

>>> cmdline(find_task(prog, 1495216))
[b'vim', b'drgn/helpers/linux/mm.py']
$ tr '\0' ' ' < /proc/1495216/cmdline
vim drgn/helpers/linux/mm.py
Parameters

taskstruct task_struct *

drgn.helpers.linux.mm.environ(task: drgn.Object) List[bytes]

Get the list of environment variables of a task.

>>> environ(find_task(prog, 1497797))
[b'HOME=/root', b'PATH=/usr/local/sbin:/usr/local/bin:/usr/bin', b'LOGNAME=root']
$ tr '\0' '\n' < /proc/1497797/environ
HOME=/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin
LOGNAME=root
Parameters

taskstruct task_struct *

Networking

The drgn.helpers.linux.net module provides helpers for working with the Linux kernel networking subsystem.

drgn.helpers.linux.net.SOCKET_I(inode: drgn.Object) drgn.Object

Get a socket from an inode referring to the socket.

Parameters

inodestruct inode *

Returns

struct socket *

Raises

ValueError – If inode does not refer to a socket

drgn.helpers.linux.net.SOCK_INODE(sock: drgn.Object) drgn.Object

Get the inode of a socket.

Parameters

sockstruct socket *

Returns

struct inode *

drgn.helpers.linux.net.for_each_net(prog: drgn.Program) Iterator[drgn.Object]

Iterate over all network namespaces in the system.

Returns

Iterator of struct net * objects.

drgn.helpers.linux.net.get_net_ns_by_inode(inode: drgn.Object) drgn.Object

Get a network namespace from a network namespace NSFS inode, e.g. /proc/$PID/ns/net or /var/run/netns/$NAME.

Parameters

inodestruct inode *

Returns

struct net *

Raises

ValueError – if inode is not a network namespace inode

drgn.helpers.linux.net.get_net_ns_by_fd(task: drgn.Object, fd: drgn.IntegerLike) drgn.Object

Get a network namespace from a task and a file descriptor referring to a network namespace NSFS inode, e.g. /proc/$PID/ns/net or /var/run/netns/$NAME.

Parameters
  • taskstruct task_struct *

  • fd – File descriptor.

Returns

struct net *

Raises

ValueError – If fd does not refer to a network namespace inode

drgn.helpers.linux.net.netdev_for_each_tx_queue(dev: drgn.Object) Iterator[drgn.Object]

Iterate over all TX queues for a network device.

Parameters

devstruct net_device *

Returns

Iterator of struct netdev_queue * objects.

drgn.helpers.linux.net.netdev_get_by_index(prog_or_net: Union[drgn.Program, drgn.Object], ifindex: drgn.IntegerLike) drgn.Object

Get the network device with the given interface index number.

Parameters
  • prog_or_netstruct net * containing the device, or Program to use the initial network namespace.

  • ifindex – Network interface index number.

Returns

struct net_device * (NULL if not found)

drgn.helpers.linux.net.netdev_get_by_name(prog_or_net: Union[drgn.Program, drgn.Object], name: Union[str, bytes]) drgn.Object

Get the network device with the given interface name.

Parameters
  • prog_or_netstruct net * containing the device, or Program to use the initial network namespace.

  • name – Network interface name.

Returns

struct net_device * (NULL if not found)

drgn.helpers.linux.net.sk_fullsock(sk: drgn.Object) bool

Check whether a socket is a full socket, i.e., not a time-wait or request socket.

Parameters

skstruct sock *

drgn.helpers.linux.net.sk_nulls_for_each(head: drgn.Object) Iterator[drgn.Object]

Iterate over all the entries in a nulls hash list of sockets specified by struct hlist_nulls_head head.

Parameters

headstruct hlist_nulls_head *

Returns

Iterator of struct sock * objects.

NUMA Node Masks

The drgn.helpers.linux.nodemask module provides helpers for working with NUMA node masks from include/linux/nodemask.h.

drgn.helpers.linux.nodemask.for_each_node_mask(mask: drgn.Object) Iterator[int]

Iterate over all of the NUMA nodes in the given mask.

Parameters

masknodemask_t

drgn.helpers.linux.nodemask.for_each_node_state(prog: drgn.Program, state: drgn.IntegerLike) Iterator[int]

Iterate over all NUMA nodes in the given state.

Parameters

stateenum node_states (e.g., N_NORMAL_MEMORY)

drgn.helpers.linux.nodemask.for_each_node(prog: drgn.Program) Iterator[int]

Iterate over all possible NUMA nodes.

drgn.helpers.linux.nodemask.for_each_online_node(prog: drgn.Program) Iterator[int]

Iterate over all online NUMA nodes.

drgn.helpers.linux.nodemask.node_state(node: drgn.IntegerLike, state: drgn.Object) bool

Return whether the given NUMA node has the given state.

Parameters
  • node – NUMA node number.

  • stateenum node_states (e.g., N_NORMAL_MEMORY)

Per-CPU

The drgn.helpers.linux.percpu module provides helpers for working with per-CPU allocations from include/linux/percpu.h and per-CPU counters from include/linux/percpu_counter.h.

drgn.helpers.linux.percpu.per_cpu_ptr(ptr: drgn.Object, cpu: drgn.IntegerLike) drgn.Object

Return the per-CPU pointer for a given CPU.

>>> prog["init_net"].loopback_dev.pcpu_refcnt
(int *)0x2c980
>>> per_cpu_ptr(prog["init_net"].loopback_dev.pcpu_refcnt, 7)
*(int *)0xffff925e3ddec980 = 4
Parameters
  • ptr – Per-CPU pointer, i.e., type __percpu *. For global variables, it’s usually easier to use per_cpu().

  • cpu – CPU number.

Returns

type * object.

drgn.helpers.linux.percpu.per_cpu(var: drgn.Object, cpu: drgn.IntegerLike) drgn.Object

Return the per-CPU variable for a given CPU.

>>> print(repr(prog["runqueues"]))
Object(prog, 'struct rq', address=0x278c0)
>>> per_cpu(prog["runqueues"], 6).curr.comm
(char [16])"python3"
Parameters
  • var – Per-CPU variable, i.e., type __percpu (not a pointer; use per_cpu_ptr() for that).

  • cpu – CPU number.

Returns

type object.

drgn.helpers.linux.percpu.percpu_counter_sum(fbc: drgn.Object) int

Return the sum of a per-CPU counter.

Parameters

fbcstruct percpu_counter *

Process IDS

The drgn.helpers.linux.pid module provides helpers for looking up process IDs and processes.

drgn.helpers.linux.pid.find_pid(prog_or_ns: Union[drgn.Program, drgn.Object], pid: drgn.IntegerLike) drgn.Object

Return the struct pid * for the given PID number.

Parameters

prog_or_nsstruct pid_namespace * object, or Program to use initial PID namespace.

Returns

struct pid *

drgn.helpers.linux.pid.find_task(prog_or_ns: Union[drgn.Program, drgn.Object], pid: drgn.IntegerLike) drgn.Object

Return the task with the given PID.

Parameters

prog_or_nsstruct pid_namespace * object, or Program to use initial PID namespace.

Returns

struct task_struct *

drgn.helpers.linux.pid.pid_task(pid: drgn.Object, pid_type: drgn.IntegerLike) drgn.Object

Return the struct task_struct * containing the given struct pid * of the given type.

Parameters
  • pidstruct pid *

  • pid_typeenum pid_type

Returns

struct task_struct *

drgn.helpers.linux.pid.for_each_pid(prog_or_ns: Union[drgn.Program, drgn.Object]) Iterator[drgn.Object]

Iterate over all PIDs in a namespace.

Parameters

prog_or_nsstruct pid_namespace * to iterate over, or Program to iterate over initial PID namespace.

Returns

Iterator of struct pid * objects.

drgn.helpers.linux.pid.for_each_task(prog_or_ns: Union[drgn.Program, drgn.Object]) Iterator[drgn.Object]

Iterate over all of the tasks visible in a namespace.

Parameters

prog_or_nsstruct pid_namespace * to iterate over, or Program to iterate over initial PID namespace.

Returns

Iterator of struct task_struct * objects.

Log Buffer

The drgn.helpers.linux.printk module provides helpers for reading the Linux kernel log buffer.

class drgn.helpers.linux.printk.PrintkRecord

Bases: NamedTuple

Kernel log record.

text: bytes

Message text.

facility: int

syslog(3) facility.

level: int

Log level.

seq: int

Sequence number.

timestamp: int

Timestamp in nanoseconds.

caller_tid: Optional[int]

Thread ID of thread that logged this record, if available.

This is available if the message was logged from task context and if the kernel saves the printk() caller ID.

As of Linux 5.10, the kernel always saves the caller ID. From Linux 5.1 through 5.9, it is saved only if the kernel was compiled with CONFIG_PRINTK_CALLER. Before that, it is never saved.

caller_cpu: Optional[int]

Processor ID of CPU that logged this record, if available.

This is available only if the message was logged when not in task context (e.g., in an interrupt handler) and if the kernel saves the printk() caller ID.

See caller_tid for when the kernel saves the caller ID.

continuation: bool

Whether this record is a continuation of a previous record.

context: Dict[bytes, bytes]

Additional metadata for the message.

See the /dev/kmsg documentation for an explanation of the keys and values.

drgn.helpers.linux.printk.get_printk_records(prog: drgn.Program) List[PrintkRecord]

Get a list of records in the kernel log buffer.

drgn.helpers.linux.printk.get_dmesg(prog: drgn.Program) bytes

Get the contents of the kernel log buffer formatted like dmesg(1).

The format of each line is:

[   timestamp] message

If you need to format the log buffer differently, use get_printk_records() and format it yourself.

Radix Trees

The drgn.helpers.linux.radixtree module provides helpers for working with radix trees from include/linux/radix-tree.h.

See also

XArrays, which were introduced in Linux 4.20 as a replacement for radix trees.

drgn.helpers.linux.radixtree.radix_tree_lookup(root: drgn.Object, index: drgn.IntegerLike) drgn.Object

Look up the entry at a given index in a radix tree.

Parameters
  • rootstruct radix_tree_root *

  • index – Entry index.

Returns

void * found entry, or NULL if not found.

drgn.helpers.linux.radixtree.radix_tree_for_each(root: drgn.Object) Iterator[Tuple[int, drgn.Object]]

Iterate over all of the entries in a radix tree.

Parameters

rootstruct radix_tree_root *

Returns

Iterator of (index, void *) tuples.

Red-Black Trees

The drgn.helpers.linux.rbtree module provides helpers for working with red-black trees from include/linux/rbtree.h.

drgn.helpers.linux.rbtree.RB_EMPTY_ROOT(root: drgn.Object) bool

Return whether a red-black tree is empty.

Parameters

nodestruct rb_root *

drgn.helpers.linux.rbtree.RB_EMPTY_NODE(node: drgn.Object) bool

Return whether a red-black tree node is empty, i.e., not inserted in a tree.

Parameters

nodestruct rb_node *

drgn.helpers.linux.rbtree.rb_parent(node: drgn.Object) drgn.Object

Return the parent node of a red-black tree node.

Parameters

nodestruct rb_node *

Returns

struct rb_node *

drgn.helpers.linux.rbtree.rb_first(root: drgn.Object) drgn.Object

Return the first node (in sort order) in a red-black tree, or NULL if the tree is empty.

Parameters

rootstruct rb_root *

Returns

struct rb_node *

drgn.helpers.linux.rbtree.rb_last(root: drgn.Object) drgn.Object

Return the last node (in sort order) in a red-black tree, or NULL if the tree is empty.

Parameters

rootstruct rb_root *

Returns

struct rb_node *

drgn.helpers.linux.rbtree.rb_next(node: drgn.Object) drgn.Object

Return the next node (in sort order) after a red-black node, or NULL if the node is the last node in the tree or is empty.

Parameters

nodestruct rb_node *

Returns

struct rb_node *

drgn.helpers.linux.rbtree.rb_prev(node: drgn.Object) drgn.Object

Return the previous node (in sort order) before a red-black node, or NULL if the node is the first node in the tree or is empty.

Parameters

nodestruct rb_node *

Returns

struct rb_node *

drgn.helpers.linux.rbtree.rbtree_inorder_for_each(root: drgn.Object) Iterator[drgn.Object]

Iterate over all of the nodes in a red-black tree, in sort order.

Parameters

rootstruct rb_root *

Returns

Iterator of struct rb_node * objects.

drgn.helpers.linux.rbtree.rbtree_inorder_for_each_entry(type: Union[str, drgn.Type], root: drgn.Object, member: str) Iterator[drgn.Object]

Iterate over all of the entries in a red-black tree in sorted order.

Parameters
  • type – Entry type.

  • rootstruct rb_root *

  • member – Name of struct rb_node member in entry type.

Returns

Iterator of type * objects.

drgn.helpers.linux.rbtree.rb_find(type: Union[str, drgn.Type], root: drgn.Object, member: str, key: KeyType, cmp: Callable[[KeyType, drgn.Object], int]) drgn.Object

Find an entry in a red-black tree given a key and a comparator function.

Note that this function does not have an analogue in the Linux kernel source code, as tree searches are all open-coded.

Parameters
  • type – Entry type.

  • rootstruct rb_root *

  • member – Name of struct rb_node member in entry type.

  • key – Key to find.

  • cmp – Callback taking key and entry that returns < 0 if the key is less than the entry, > 0 if the key is greater than the entry, and 0 if the key matches the entry.

Returns

type * found entry, or NULL if not found.

drgn.helpers.linux.rbtree.validate_rbtree(type: Union[str, drgn.Type], root: drgn.Object, member: str, cmp: Callable[[drgn.Object, drgn.Object], int], allow_equal: bool) None

Validate a red-black tree.

This checks that:

  1. The tree is a valid binary search tree ordered according to cmp.

  2. If allow_equal is False, there are no nodes that compare equal according to cmp.

  3. The rb_parent pointers are consistent.

  4. The red-black tree requirements are satisfied: the root node is black, no red node has a red child, and every path from any node to any of its descendant leaf nodes goes through the same number of black nodes.

Parameters
  • type – Entry type.

  • rootstruct rb_root *

  • member – Name of struct rb_node member in entry type.

  • cmp – Callback taking two type * entry objects that returns < 0 if the first entry is less than the second entry, > 0 if the first entry is greater than the second entry, and 0 if they are equal.

  • allow_equal – Whether the tree may contain entries that compare equal to each other.

Raises

ValidationError – if the tree is invalid

drgn.helpers.linux.rbtree.validate_rbtree_inorder_for_each_entry(type: Union[str, drgn.Type], root: drgn.Object, member: str, cmp: Callable[[drgn.Object, drgn.Object], int], allow_equal: bool) Iterator[drgn.Object]

Like rbtree_inorder_for_each_entry(), but validates the red-black tree like validate_rbtree() while iterating.

Parameters
  • type – Entry type.

  • rootstruct rb_root *

  • member – Name of struct rb_node member in entry type.

  • cmp – Callback taking two type * entry objects that returns < 0 if the first entry is less than the second entry, > 0 if the first entry is greater than the second entry, and 0 if they are equal.

  • allow_equal – Whether the tree may contain entries that compare equal to each other.

Raises

ValidationError – if the tree is invalid

CPU Scheduler

The drgn.helpers.linux.sched module provides helpers for working with the Linux CPU scheduler.

drgn.helpers.linux.sched.idle_task(prog: drgn.Program, cpu: drgn.IntegerLike) drgn.Object

Return the idle thread (PID 0, a.k.a swapper) for the given CPU.

>>> idle_task(prog, 1).comm
(char [16])"swapper/1"
Parameters

cpu – CPU number.

Returns

struct task_struct *

drgn.helpers.linux.sched.task_cpu(task: drgn.Object) int

Return the CPU number that the given task last ran on.

Parameters

taskstruct task_struct *

drgn.helpers.linux.sched.task_state_to_char(task: drgn.Object) str

Get the state of the task as a character (e.g., 'R' for running). See ps(1) for a description of the process state codes.

Parameters

taskstruct task_struct *

Slab Allocator

The drgn.helpers.linux.slab module provides helpers for working with the Linux slab allocator.

Warning

Beware of slab merging when using these helpers. See slab_cache_is_merged().

drgn.helpers.linux.slab.slab_cache_is_merged(slab_cache: drgn.Object) bool

Return whether a slab cache has been merged with any other slab caches.

Unless configured otherwise, the kernel may merge slab caches of similar sizes together. See the SLUB users guide and slab_merge/slab_nomerge in the kernel parameters documentation.

This can cause confusion, as only the name of the first cache will be found, and objects of different types will be mixed in the same slab cache.

For example, suppose that we have two types, struct foo and struct bar, which have the same size but are otherwise unrelated. If the kernel creates a slab cache named foo for struct foo, then another slab cache named bar for struct bar, then slab cache foo will be reused instead of creating another cache for bar. So the following will fail:

find_slab_cache(prog, "bar")

And the following will also return struct bar * objects errantly casted to struct foo *:

slab_cache_for_each_allocated_object(
    find_slab_cache(prog, "foo"), "struct foo"
)

Unfortunately, these issues are difficult to work around generally, so one must be prepared to handle them on a case-by-case basis (e.g., by looking up the slab cache by its variable name and by checking that members of the structure make sense for the expected type).

Parameters

slab_cachestruct kmem_cache *

drgn.helpers.linux.slab.get_slab_cache_aliases(prog: drgn.Program) Dict[str, str]

Return a dict mapping slab cache name to the cache it was merged with.

The SLAB and SLUB subsystems can merge caches with similar settings and object sizes, as described in the documentation of slab_cache_is_merged(). In some cases, the information about which caches were merged is lost, but in other cases, we can reconstruct the info. This function reconstructs the mapping, but requires that the kernel is configured with CONFIG_SLUB and CONFIG_SYSFS.

The returned dict maps from original cache name, to merged cache name. You can use this mapping to discover the correct cache to lookup via find_slab_cache(). The dict contains an entry only for caches which were merged into a cache of a different name.

>>> cache_to_merged = get_slab_cache_aliases(prog)
>>> cache_to_merged["dnotify_struct"]
'avc_xperms_data'
>>> "avc_xperms_data" in cache_to_merged
False
>>> find_slab_cache(prog, "dnotify_struct") is None
True
>>> find_slab_cache(prog, "avc_xperms_data") is None
False
Warning

This function will only work on kernels which are built with CONFIG_SLUB and CONFIG_SYSFS enabled.

Parameters

prog – Program to search

Returns

Mapping of slab cache name to final merged name

Raises

LookupError – If the helper fails because the debugged kernel doesn’t have the required configuration

drgn.helpers.linux.slab.for_each_slab_cache(prog: drgn.Program) Iterator[drgn.Object]

Iterate over all slab caches.

Returns

Iterator of struct kmem_cache * objects.

drgn.helpers.linux.slab.find_slab_cache(prog: drgn.Program, name: Union[str, bytes]) Optional[drgn.Object]

Return the slab cache with the given name.

Parameters

name – Slab cache name.

Returns

struct kmem_cache *

drgn.helpers.linux.slab.print_slab_caches(prog: drgn.Program) None

Print the name and struct kmem_cache * value of all slab caches.

drgn.helpers.linux.slab.slab_cache_for_each_allocated_object(slab_cache: drgn.Object, type: Union[str, drgn.Type]) Iterator[drgn.Object]

Iterate over all allocated objects in a given slab cache.

Only the SLUB and SLAB allocators are supported; SLOB does not store enough information to identify objects in a slab cache.

>>> dentry_cache = find_slab_cache(prog, "dentry")
>>> next(slab_cache_for_each_allocated_object(dentry_cache, "struct dentry"))
*(struct dentry *)0xffff905e41404000 = {
    ...
}
Parameters
  • slab_cachestruct kmem_cache *

  • type – Type of object in the slab cache.

Returns

Iterator of type * objects.

drgn.helpers.linux.slab.slab_object_info(addr: drgn.Object) Optional['SlabObjectInfo']
drgn.helpers.linux.slab.slab_object_info(prog: drgn.Program, addr: drgn.IntegerLike) Optional[SlabObjectInfo]

Get information about an address if it is in a slab object.

>>> ptr = find_task(prog, 1).comm.address_of_()
>>> info = slab_object_info(ptr)
>>> info
SlabObjectInfo(slab_cache=Object(prog, 'struct kmem_cache *', address=0xffffdb93c0045e18), slab=Object(prog, 'struct slab *', value=0xffffdb93c0045e00), address=0xffffa2bf81178000, allocated=True)

Note that SlabObjectInfo.address is the start address of the object, which may be less than addr if addr points to a member inside of the object:

>>> ptr.value_() - info.address
1496
>>> offsetof(prog.type("struct task_struct"), "comm")
1496

The address can be given as an Object or as a Program and an integer.

Note that SLOB does not store enough information to identify slab objects, so if the kernel is configured to use SLOB, this will always return None.

Parameters

addrvoid *

Returns

SlabObjectInfo if addr is in a slab object, or None if not.

class drgn.helpers.linux.slab.SlabObjectInfo

Information about an object in the slab allocator.

slab_cache: drgn.Object

struct kmem_cache * that the slab object is from.

slab: drgn.Object

Slab containing the slab object.

Since Linux v5.17, this is a struct slab *. Before that, it is a struct page *.

address: int

Address of the slab object.

allocated: bool

True if the object is allocated, False if it is free.

drgn.helpers.linux.slab.find_containing_slab_cache(addr: drgn.Object) drgn.Object
drgn.helpers.linux.slab.find_containing_slab_cache(prog: drgn.Program, addr: drgn.IntegerLike) drgn.Object

Get the slab cache that an address was allocated from, if any.

The address can be given as an Object or as a Program and an integer.

Note that SLOB does not store enough information to identify objects in a slab cache, so if the kernel is configured to use SLOB, this will always return NULL.

Parameters

addrvoid *

Returns

struct kmem_cache * containing addr, or NULL if addr is not from a slab cache.

Traffic Control (TC)

The drgn.helpers.linux.tc module provides helpers for working with the Linux kernel Traffic Control (TC) subsystem.

drgn.helpers.linux.tc.qdisc_lookup(dev: drgn.Object, major: drgn.IntegerLike) drgn.Object

Get a Qdisc from a device and a major handle number. It is worth noting that conventionally handles are hexadecimal, e.g. 10: in a tc command means major handle 0x10.

Parameters
  • devstruct net_device *

  • major – Qdisc major handle number.

Returns

struct Qdisc * (NULL if not found)

TCP

The drgn.helpers.linux.tcp module provides helpers for working with the TCP protocol in the Linux kernel.

drgn.helpers.linux.tcp.sk_tcpstate(sk: drgn.Object) drgn.Object

Return the TCP protocol state of a socket.

Parameters

skstruct sock *

Returns

TCP state enum value.

Users

The drgn.helpers.linux.user module provides helpers for working with users in the Linux kernel.

drgn.helpers.linux.user.find_user(prog: drgn.Program, uid: Union[drgn.Object, drgn.IntegerLike]) drgn.Object

Return the user structure with the given UID.

Parameters

uidkuid_t object or integer.

Returns

struct user_struct * (NULL if not found)

drgn.helpers.linux.user.for_each_user(prog: drgn.Program) Iterator[drgn.Object]

Iterate over all users in the system.

Returns

Iterator of struct user_struct * objects.

XArrays

The drgn.helpers.linux.xarray module provides helpers for working with the XArray data structure from include/linux/xarray.h.

Note

XArrays were introduced in Linux 4.20 as a replacement for radix trees. To make it easier to work with data structures that were changed from a radix tree to an XArray (like struct address_space::i_pages), drgn treats XArrays and radix trees interchangeably in some cases.

Specifically, xa_load() is equivalent to radix_tree_lookup(), and xa_for_each() is equivalent to radix_tree_for_each(), except that the radix tree helpers assume advanced=False. (Therefore, xa_load() and xa_for_each() also accept a struct radix_tree_root *, and radix_tree_lookup() and radix_tree_for_each() also accept a struct xarray *.)

drgn.helpers.linux.xarray.xa_load(xa: drgn.Object, index: drgn.IntegerLike, *, advanced: bool = False) drgn.Object

Look up the entry at a given index in an XArray.

>>> entry = xa_load(inode.i_mapping.i_pages.address_of_(), 2)
>>> cast("struct page *", entry)
*(struct page *)0xffffed6980306f40 = {
    ...
}
Parameters
  • xastruct xarray *

  • index – Entry index.

  • advanced – Whether to return nodes only visible to the XArray advanced API. If False, zero entries (see xa_is_zero()) will be returned as NULL.

Returns

void * found entry, or NULL if not found.

drgn.helpers.linux.xarray.xa_for_each(xa: drgn.Object, *, advanced: bool = False) Iterator[Tuple[int, drgn.Object]]

Iterate over all of the entries in an XArray.

>>> for index, entry in xa_for_each(inode.i_mapping.i_pages.address_of_()):
...     print(index, entry)
...
0 (void *)0xffffed6980356140
1 (void *)0xffffed6980306f80
2 (void *)0xffffed6980306f40
3 (void *)0xffffed6980355b40
Parameters
  • xastruct xarray *

  • advanced – Whether to return nodes only visible to the XArray advanced API. If False, zero entries (see xa_is_zero()) will be skipped.

Returns

Iterator of (index, void *) tuples.

drgn.helpers.linux.xarray.xa_is_value(entry: drgn.Object) bool

Return whether an XArray entry is a value.

See xa_to_value().

Parameters

entryvoid *

drgn.helpers.linux.xarray.xa_to_value(entry: drgn.Object) drgn.Object

Return the value in an XArray entry.

In addition to pointers, XArrays can store integers between 0 and LONG_MAX. If xa_is_value() returns True, use this to get the stored integer.

>>> entry = xa_load(xa, 9)
>>> entry
(void *)0xc9
>>> xa_is_value(entry)
True
>>> xa_to_value(entry)
(unsigned long)100
Parameters

entryvoid *

Returns

unsigned long

drgn.helpers.linux.xarray.xa_is_zero(entry: drgn.Object) bool

Return whether an XArray entry is a “zero” entry.

A zero entry is an entry that was reserved but is not present. These are only visible to the XArray advanced API, so they are only returned by xa_load() and xa_for_each() when advanced = True.

>>> entry = xa_load(xa, 10, advanced=True)
>>> entry
(void *)0x406
>>> xa_is_zero(entry)
True
>>> xa_load(xa, 10)
(void *)0
Parameters

entryvoid *