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
orbytearray
). Seeescape_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.).
>>> number_in_binary_units(1280) '1.2K'
A precision can be specified:
>>> number_in_binary_units(1280, precision=2) '1.25K'
Exact numbers are printed without a fractional part:
>>> number_in_binary_units(1024 * 1024) '1M'
Numbers less than 1024 are not scaled:
>>> number_in_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(prog: drgn.Program, addr: drgn.IntegerLike, *, cache: Optional[Dict[Any, Any]] = None) 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}
(wherehex_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}
(wherehex_offset
is the offset from the beginning of the object in hexadecimal).Free slab objects:
free slab object: {slab_cache_name}+{hex_offset}
.Vmap addresses (e.g., vmalloc, ioremap):
vmap: {hex_start_address}-{hex_end_address}
. If the function that allocated the vmap is known, this also includescaller {function_name}+{hex_offset}
.Vmap kernel stacks:
vmap stack: {pid} ({comm}) +{hex_offset}
(wherepid
andcomm
identify the task andhex_offset
is the offset from the beginning of the stack in hexadecimal).
This may recognize other types of addresses in the future.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
addr –
void *
cache – Opaque cache used to amortize expensive lookups. If you’re going to call this function many times in a short period, create an empty dictionary and pass the same dictionary as cache to each call. Don’t reuse it indefinitely or you may get stale results.
- Returns:
Identity as string, or
None
if the address is unrecognized.
- drgn.helpers.common.memory.print_annotated_memory(prog: drgn.Program, address: drgn.IntegerLike, size: drgn.IntegerLike, physical: bool = False) None ¶
Print the contents of a range of memory, annotating values that can be identified.
Currently, this will identify any addresses in the memory range with
identify_address()
.See
print_annotated_stack()
for a similar function that annotates stack traces.>>> print_annotated_memory(0xffffffff963eb200, 56) ADDRESS VALUE ffffffff963eb200: 00000000000000b8 ffffffff963eb208: 000000000000a828 ffffffff963eb210: 0000000000000000 ffffffff963eb218: ffff8881042948e0 [slab object: mnt_cache+0x20] ffffffff963eb220: ffff88810074a540 [slab object: dentry+0x0] ffffffff963eb228: ffff8881042948e0 [slab object: mnt_cache+0x20] ffffffff963eb230: ffff88810074a540 [slab object: dentry+0x0]
- Parameters:
prog – Program, which may be omitted to use the default program argument.
address – Starting address.
size – Number of bytes to read.
physical – Whether address is a physical memory address. If
False
, then it is a virtual memory address.
Program Decorators¶
The drgn.helpers.common.prog
module provides decorators to transparently
use the default program argument.
- drgn.helpers.common.prog.takes_program_or_default(f: TakesProgram[P, R]) TakesProgramOrDefault[P, R] ¶
Wrap a function taking a
Program
so that it uses the default program argument if omitted.@takes_program_or_default def my_helper(prog: Program, n: IntegerLike) -> Foo: ... my_helper(1) # is equivalent to my_helper(get_default_prog(), 1) obj = Object(...) my_helper(obj) # is equivalent to my_helper(obj.prog_, obj)
- drgn.helpers.common.prog.takes_object_or_program_or_default(f: Callable[Concatenate[drgn.Program, Optional[drgn.Object], P], R]) TakesObjectOrProgramOrDefault[P, R] ¶
Wrap a function taking a
Program
and an optionalObject
so that it accepts aProgram
or anObject
or neither, in which case the default program argument is used.@takes_object_or_program_or_default def my_helper(prog: Program, obj: Optional[Object], n: IntegerLike) -> Foo: ... my_helper(prog, 1) # is equivalent to my_helper.__wrapped__(prog, None, 1) obj = Object(...) my_helper(obj, 1) # is equivalent to my_helper.__wrapped__(obj.prog_, obj, 1) my_helper(1) # is equivalent to my_helper.__wrapped__(get_default_prog(), None, 1) one_obj = Object(..., 1) my_helper(one_obj) # is equivalent to my_helper.__wrapped__(one_obj.prog_, None, one_obj)
Warning
This cannot be used with positional parameters with a default value, as that would create ambiguity. Keyword-only parameters with a default value are OK.
# NOT ALLOWED @takes_object_or_program_or_default def my_helper(prog: Program, obj: Optional[Object], foo: str = ""): ... # OK @takes_object_or_program_or_default def my_helper(prog: Program, obj: Optional[Object], *, foo: str = ""): ...
Note
The object parameter can be passed as a keyword, but because of limitations of the Python type system, type checkers do not recognize this.
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()
.See
print_annotated_memory()
for a similar function that annotates arbitrary memory ranges.>>> print_annotated_stack(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 enumerateddrgn.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.
- drgn.helpers.common.type.member_at_offset(type: drgn.Type, offset: drgn.IntegerLike) str ¶
Return the name of the member at an offset in a type.
This is effectively the opposite of
offsetof()
.>>> prog.type('struct list_head') struct list_head { struct list_head *next; struct list_head *prev; } >>> member_at_offset(prog.type('struct list_head'), 0) 'next' >>> member_at_offset(prog.type('struct list_head'), 8) 'prev'
This includes nested structures and array elements:
>>> prog.type('struct sigpending') struct sigpending { struct list_head list; sigset_t signal; } >>> prog.type('sigset_t') typedef struct { unsigned long sig[1]; } sigset_t >>> member_at_offset(prog.type('struct sigpending'), 0) 'list.next' >>> member_at_offset(prog.type('struct sigpending'), 8) 'list.prev' >>> member_at_offset(prog.type('struct sigpending'), 16) 'signal.sig[0]'
This also includes all possible matches for a union:
>>> prog.type('union mc_target') union mc_target { struct folio *folio; swp_entry_t ent; } >>> prog.type('swp_entry_t') typedef struct { unsigned long val; } swp_entry_t >>> member_at_offset(prog.type('union mc_target'), 0) 'folio or ent.val'
Offsets in the middle of a member are represented:
>>> member_at_offset(prog.type('struct list_head'), 4) 'next+0x4'
Offsets in padding or past the end of the type are also represented:
>>> prog.type('struct autogroup') struct autogroup { struct kref kref; struct task_group *tg; struct rw_semaphore lock; unsigned long id; int nice; } >>> member_at_offset(prog.type('struct autogroup'), 4) '<padding between kref and tg>' >>> member_at_offset(prog.type('struct autogroup'), 70) '<padding at end>' >>> member_at_offset(prog.type('struct autogroup'), 72) '<end>' >>> member_at_offset(prog.type('struct autogroup'), 80) '<past end>'
- Parameters:
type – Type to check.
offset – Offset in bytes.
- Raises:
TypeError – if type is not a structure, union, class, or array type (or a typedef of one of those)
Experimental¶
The drgn.helpers.experimental
package contains experimental helpers with no
stability guarantees. They may change, move to another package, or be removed.
They are not automatically imported by the CLI.
Kmodify¶
The drgn.helpers.experimental.kmodify
module provides experimental helpers
for modifying the state of the running kernel. This works by loading a
temporary kernel module, so the kernel must support loadable kernel modules
(CONFIG_MODULES=y
) and allow loading unsigned modules
(CONFIG_MODULE_SIG_FORCE=n
). It is currently only implemented for x86-64.
Warning
These helpers are powerful but extremely dangerous. Use them with care.
- drgn.helpers.experimental.kmodify.write_memory(prog: drgn.Program, address: drgn.IntegerLike, value: bytes) None ¶
Write a byte string to kernel memory.
>>> os.uname().sysname 'Linux' >>> write_memory(prog["init_uts_ns"].name.sysname.address_, b"Lol\0") >>> os.uname().sysname 'Lol'
Warning
This attempts to detect writes to bad addresses and raise a
FaultError
, but this is best-effort and may still crash the kernel. Writing bad data can of course also cause a crash when the data is used. Additionally, this is not atomic, so the data may be accessed while it is partially written.- Parameters:
prog – Program, which may be omitted to use the default program argument.
address – Address to write to.
value – Byte string to write.
- Raises:
FaultError – if the address cannot be written to
- drgn.helpers.experimental.kmodify.write_object(object: drgn.Object, value: Any, *, dereference: Optional[bool] = None) None ¶
Write to an object in kernel memory.
>>> os.system("uptime -p") up 12 minutes >>> write_object(prog["init_time_ns"].offsets.boottime.tv_sec, 1000000000) >>> os.system("uptime -p") up 3 decades, 1 year, 37 weeks, 1 hour, 59 minutes
Warning
The warnings about
write_memory()
also apply towrite_object()
.- Parameters:
object – Object to write to.
value – Value to write. This may be an
Object
or a Python value. Either way, it will be converted to the type of object.dereference – If object is a pointer, whether to dereference it. If
True
, then write to the object pointed to by object (*ptr = value
). IfFalse
, then write to the pointer itself (ptr = value
). This is a common source of confusion, so it is required if object is a pointer.
- Raises:
ValueError – if object is not a reference object (i.e., its address is not known)
TypeError – if object is a pointer and dereference is not given
TypeError – if object is not a pointer and dereference is
True
- drgn.helpers.experimental.kmodify.call_function(prog: drgn.Program, func: Union[str, drgn.Object], *args: Any) drgn.Object ¶
Call a function in the kernel.
Arguments can be either
Object
s or Python values. The function return value is returned as anObject
:>>> # GFP_KERNEL isn't in the kernel debug info >>> # We have to use this trick to get it. >>> for flag in prog["gfpflag_names"]: ... if flag.name.string_() == b"GFP_KERNEL": ... GFP_KERNEL = flag.mask ... break ... >>> # kmalloc() is actually a macro. >>> # We have to call the underlying function. >>> p = call_function("__kmalloc_noprof", 13, GFP_KERNEL) >>> p (void *)0xffff991701ef43c0 >>> identify_address(p) 'slab object: kmalloc-16+0x0' >>> call_function("kfree", p) (void)<absent> >>> identify_address(p) 'free slab object: kmalloc-16+0x0'
Variadic functions are also supported:
>>> call_function("_printk", "Hello, world! %d\n", Object(prog, "int", 1234)) (int)18 >>> os.system("dmesg | tail -1") [ 1138.223004] Hello, world! 1234
Constructed values can be passed by pointer using
pass_pointer()
:>>> sb = prog["init_fs"].root.mnt.mnt_sb >>> sb.s_shrink.scan_objects (unsigned long (*)(struct shrinker *, struct shrink_control *))super_cache_scan+0x0 = 0xffffffffbda4c487 >>> sc = pass_pointer(Object(prog, "struct shrink_control", ... {"gfp_mask": GFP_KERNEL, "nr_to_scan": 100, "nr_scanned": 100})) >>> call_function(sb.s_shrink.scan_objects, sb.s_shrink, sc) (unsigned long)31
If the function modifies the passed value, the
pass_pointer
object is updated:>>> sc.object (struct shrink_control){ .gfp_mask = (gfp_t)3264, .nid = (int)0, .nr_to_scan = (unsigned long)1, .nr_scanned = (unsigned long)100, .memcg = (struct mem_cgroup *)0x0, }
Note
It is not possible to call some functions, including inlined functions and function-like macros. If the unavailable function is a wrapper around another function, sometimes the wrapped function can be called instead.
Warning
Calling a function incorrectly may cause the kernel to crash or misbehave in various ways.
The function is called from process context. Note that the function may have context, locking, or reference counting requirements.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
func – Function to call. May be a function name, function object, or function pointer object.
args – Function arguments.
int
,float
, andbool
arguments are converted as “literals” withObject(prog, value=...)
.str
andbytes
arguments are converted tochar
array objects.pass_pointer
arguments are copied to the kernel, passed by pointer, and copied back.
- Returns:
Function return value.
- Raises:
TypeError – if the passed arguments have incorrect types for the function
ObjectAbsentError – if the function cannot be called because it is inlined
LookupError – if a function with the given name is not found (possibly because it is actually a function-like macro)
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:
bitmap –
unsigned 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:
bitmap –
unsigned 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.
bitmap –
unsigned 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:
disk –
struct gendisk *
- Returns:
dev_t
- drgn.helpers.linux.block.disk_name(disk: drgn.Object) bytes ¶
Get the name of a disk (e.g.,
sda
).- Parameters:
disk –
struct gendisk *
- drgn.helpers.linux.block.bdev_partno(bdev: drgn.Object) drgn.Object ¶
Get the partition number of a block device.
- Parameters:
bdev –
struct block_device *
- Returns:
u8
- drgn.helpers.linux.block.for_each_disk(prog: drgn.Program) Iterator[drgn.Object] ¶
Iterate over all disks in the system.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- Returns:
Iterator of
struct gendisk *
objects.
- drgn.helpers.linux.block.print_disks(prog: drgn.Program) None ¶
Print all of the disks in the system.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- drgn.helpers.linux.block.part_devt(part: drgn.Object) drgn.Object ¶
Get a partition’s device number.
- Parameters:
part –
struct block_device *
orstruct 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:
part –
struct block_device *
orstruct 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.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- Returns:
Iterator of
struct block_device *
orstruct 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.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
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).
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- drgn.helpers.linux.boot.pgtable_l5_enabled(prog: drgn.Program) bool ¶
Return whether 5-level paging is enabled.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
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.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- Returns:
Iterator of
struct btf *
objects.
- drgn.helpers.linux.bpf.bpf_link_for_each(prog: drgn.Program) Iterator[drgn.Object] ¶
Iterate over all BPF links.
This is only supported since Linux v5.8.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- 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.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- 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.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- 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:
cgrp –
struct cgroup *
bpf_attach_type –
enum cgroup_bpf_attach_type
(enum bpf_attach_type
before Linux 5.15)
- 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:
cgrp –
struct cgroup *
bpf_attach_type –
enum 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 fromstruct sock::sk_cgrp_data
).- Parameters:
skcd –
struct 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:
cgrp –
struct cgroup *
- Returns:
struct cgroup *
- drgn.helpers.linux.cgroup.cgroup_name(cgrp: drgn.Object) bytes ¶
Get the name of the given cgroup.
- Parameters:
cgrp –
struct cgroup *
- drgn.helpers.linux.cgroup.cgroup_path(cgrp: drgn.Object) bytes ¶
Get the full path of the given cgroup.
- Parameters:
cgrp –
struct 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:
prog – Program, which may be omitted to use the default program argument.
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:
pos –
struct cgroup_subsys_state *
parent –
struct 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:
pos –
struct cgroup_subsys_state *
root –
struct 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 (offline included) of the given css.
- Parameters:
css –
struct 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 (offline included) in pre-order.
- Parameters:
css –
struct 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.cpu_online_mask(prog: drgn.Program) drgn.Object ¶
Return the mask of online CPUs.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- Returns:
struct cpumask *
- drgn.helpers.linux.cpumask.cpu_possible_mask(prog: drgn.Program) drgn.Object ¶
Return the mask of possible CPUs.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- Returns:
struct cpumask *
- drgn.helpers.linux.cpumask.cpu_present_mask(prog: drgn.Program) drgn.Object ¶
Return the mask of present CPUs.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- Returns:
struct cpumask *
- drgn.helpers.linux.cpumask.for_each_cpu(mask: drgn.Object) Iterator[int] ¶
Iterate over all of the CPUs in the given mask.
- Parameters:
mask –
struct cpumask *
- drgn.helpers.linux.cpumask.for_each_online_cpu(prog: drgn.Program) Iterator[int] ¶
Iterate over all online CPUs.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- drgn.helpers.linux.cpumask.for_each_possible_cpu(prog: drgn.Program) Iterator[int] ¶
Iterate over all possible CPUs.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- drgn.helpers.linux.cpumask.for_each_present_cpu(prog: drgn.Program) Iterator[int] ¶
Iterate over all present CPUs.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- drgn.helpers.linux.cpumask.cpumask_to_cpulist(mask: drgn.Object) str ¶
Return a CPU mask as a CPU list string.
>>> cpumask_to_cpulist(mask) 0-3,8-11
- Parameters:
mask –
struct cpumask *
- Returns:
String in the CPU list format.
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:
dev –
dev_t
object orint
.
- drgn.helpers.linux.device.MINOR(dev: drgn.IntegerLike) int ¶
Return the minor ID of a kernel
dev_t
.- Parameters:
dev –
dev_t
object orint
.
- 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(root: Union[drgn.Object, drgn.Program], path: drgn.Path, *, allow_negative: bool = False) drgn.Object ¶
Look up the given path name.
- Parameters:
- Returns:
struct path
- Raises:
Exception – if the dentry is negative and
allow_negative
isFalse
, 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., withopen()
oros.stat()
):
>>> path_lookup('/usr/include/stdlib.h') ... Exception: could not find '/usr/include/stdlib.h' in dcache >>> open('/usr/include/stdlib.h').close() >>> path_lookup('/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:
path –
struct path
orstruct 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:
vfsmnt –
struct vfsmount *
dentry –
struct dentry *
- drgn.helpers.linux.fs.d_path(dentry: drgn.Object) bytes
Return the full path of a dentry.
Since a mount is not provided, this arbitrarily selects a mount to determine the path.
- Parameters:
dentry –
struct dentry *
- drgn.helpers.linux.fs.dentry_path(dentry: drgn.Object) bytes ¶
Return the path of a dentry from the root of its filesystem.
- Parameters:
dentry –
struct 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:
inode –
struct 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:
inode –
struct inode *
- drgn.helpers.linux.fs.mount_src(mnt: drgn.Object) bytes ¶
Get the source device name for a mount.
- Parameters:
mnt –
struct mount *
- drgn.helpers.linux.fs.mount_dst(mnt: drgn.Object) bytes ¶
Get the path of a mount point.
- Parameters:
mnt –
struct mount *
- drgn.helpers.linux.fs.mount_fstype(mnt: drgn.Object) bytes ¶
Get the filesystem type of a mount.
- Parameters:
mnt –
struct mount *
- drgn.helpers.linux.fs.for_each_mount(ns: Union[drgn.Object, drgn.Program], *, 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:
- Returns:
Iterator of
struct mount *
objects.
- drgn.helpers.linux.fs.print_mounts(ns: Union[drgn.Object, drgn.Program], *, 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 eachstruct 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:
task –
struct 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:
task –
struct 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:
task –
struct 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:
idr –
struct idr *
id – Entry ID.
- Returns:
void *
found entry, orNULL
if not found.
- drgn.helpers.linux.idr.idr_for_each(idr: drgn.Object) Iterator[Tuple[int, drgn.Object]] ¶
Iterate over all of the pointers in an IDR.
- Parameters:
idr –
struct idr *
- Returns:
Iterator of (index,
void *
) tuples.
- drgn.helpers.linux.idr.idr_for_each_entry(idr: drgn.Object, type: Union[str, drgn.Type]) Iterator[Tuple[int, drgn.Object]] ¶
Iterate over all of the entries with the given type in an IDR.
- Parameters:
idr –
struct idr *
type – Entry type.
- Returns:
Iterator of (index,
type *
) tuples.
Kallsyms¶
The drgn.helpers.linux.kallsyms
module contains helpers which allow you to
use the built-in kallsyms symbol table for drgn symbol lookup. Combined with an
alternative type information source, this can enable debugging Linux kernel core
dumps without the corresponding DWARF debuginfo files. Even without type
information, kallsyms can be used to help locate objects, and drgn’s low-level
memory reading functions can be used to do basic debugging tasks.
- drgn.helpers.linux.kallsyms.load_vmlinux_kallsyms(prog: drgn.Program) drgn.SymbolIndex ¶
Create a kallsyms index for vmlinux
This function loads the kallsyms for the core kernel and returns a symbol index. This function does not require that any debuginfo is loaded for the kernel: it either relies on
/proc/kallsyms
(which requires running drgn as root) or it parses internal data structures using information found from the VMCOREINFO note (which requires Linux 6.0 or later, or a backport of commitf09bddbd86619 ("vmcoreinfo: add kallsyms_num_syms symbol")
and its dependencies).- Returns:
a symbol index containing kallsyms for the core kernel (vmlinux)
- drgn.helpers.linux.kallsyms.load_module_kallsyms(prog: drgn.Program) drgn.SymbolIndex ¶
Return a symbol index containing all module symbols from kallsyms
For kernels built with
CONFIG_KALLSYMS
, loaded kernel modules contain an ELF symbol table in kernel memory. This function can parse those data structures and create a symbol index usable by drgn. However, it requires that you already have debuginfo for the vmlinux image.- Returns:
a symbol index containing all symbols from module kallsyms
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()['CONFIG_SMP'] 'y' >>> get_kconfig()['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.- Parameters:
prog – Program, which may be omitted to use the default program argument.
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:
kn –
struct kernfs_node *
- drgn.helpers.linux.kernfs.kernfs_path(kn: drgn.Object) bytes ¶
Get full path of the given kernfs node.
- Parameters:
kn –
struct 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:
parent –
struct 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:
head –
struct list_head *
- drgn.helpers.linux.list.list_is_singular(head: drgn.Object) bool ¶
Return whether a list has only one element.
- Parameters:
head –
struct list_head *
- drgn.helpers.linux.list.list_count_nodes(head: drgn.Object) int ¶
Return the number of nodes in a list.
- Parameters:
head –
struct 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:
head –
struct 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:
head –
struct 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:
head –
struct 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:
pos –
type*
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:
pos –
type*
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:
head –
struct 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:
head –
struct 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.
head –
struct 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.
head –
struct 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
andprev
pointers in a list are consistent.- Parameters:
head –
struct 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 likevalidate_list()
while iterating.- Parameters:
head –
struct 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 likevalidate_list()
while iterating.- Parameters:
type – Entry type.
head –
struct 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:
head –
struct 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:
head –
struct 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.
head –
struct 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:
pos –
struct hlist_nulls_node *
- drgn.helpers.linux.list_nulls.hlist_nulls_empty(head: drgn.Object) bool ¶
Return whether a nulls hash list is empty.
- Parameters:
head –
struct 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.
head –
struct 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:
head –
struct llist_head *
- drgn.helpers.linux.llist.llist_is_singular(head: drgn.Object) bool ¶
Return whether an llist has only one element.
- Parameters:
head –
struct 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:
head –
struct 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:
head –
struct 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:
pos –
type*
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:
node –
struct 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.
node –
struct llist_node *
member – Name of
struct llist_node
member in entry type.
- Returns:
Iterator of
type *
objects.
Maple Trees¶
The drgn.helpers.linux.mapletree
module provides helpers for working with
maple trees from include/linux/maple_tree.h
.
Maple trees were introduced in Linux 6.1.
- drgn.helpers.linux.mapletree.mtree_load(mt: drgn.Object, index: drgn.IntegerLike, *, advanced: bool = False) drgn.Object ¶
Look up the entry at a given index in a maple tree.
>>> entry = mtree_load(task.mm.mm_mt.address_of_(), 0x55d65cfaa000) >>> cast("struct vm_area_struct *", entry) *(struct vm_area_struct *)0xffff97ad82bfc930 = { ... }
- Parameters:
mt –
struct maple_tree *
index – Entry index.
advanced – Whether to return nodes only visible to the maple tree advanced API. If
False
, zero entries (seexa_is_zero()
) will be returned asNULL
.
- Returns:
void *
found entry, orNULL
if not found.
- drgn.helpers.linux.mapletree.mt_for_each(mt: drgn.Object, *, advanced: bool = False) Iterator[Tuple[int, int, drgn.Object]] ¶
Iterate over all of the entries and their ranges in a maple tree.
>>> for first_index, last_index, entry in mt_for_each(task.mm.mm_mt.address_of_()): ... print(hex(first_index), hex(last_index), entry) ... 0x55d65cfaa000 0x55d65cfaafff (void *)0xffff97ad82bfc930 0x55d65cfab000 0x55d65cfabfff (void *)0xffff97ad82bfc0a8 0x55d65cfac000 0x55d65cfacfff (void *)0xffff97ad82bfc000 0x55d65cfad000 0x55d65cfadfff (void *)0xffff97ad82bfcb28 ...
- Parameters:
mt –
struct maple_tree *
advanced – Whether to return nodes only visible to the maple tree advanced API. If
False
, zero entries (seexa_is_zero()
) will be skipped.
- Returns:
Iterator of (first_index, last_index,
void *
) tuples. Both indices are inclusive.
Memory Management¶
The drgn.helpers.linux.mm
module provides helpers for working with the
Linux memory management (MM) subsystem.
Helpers that translate virtual addresses or read virtual memory may fail for multiple reasons:
If the address is invalid.
If the address is swapped or paged out.
If the address is in high memory. High memory is only used for userspace memory by 32-bit systems with a lot of physical memory, and only if
CONFIG_HIGHMEM
is enabled.3a. If the page table is in high memory. This is only possible if
CONFIG_HIGHPTE
is enabled.
- drgn.helpers.linux.mm.PageActive(page: drgn.Object) bool ¶
Return whether the
PG_active
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageChecked(page: drgn.Object) bool ¶
Return whether the
PG_checked
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageDirty(page: drgn.Object) bool ¶
Return whether the
PG_dirty
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageDoubleMap(page: drgn.Object) bool ¶
Return whether the
PG_double_map
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageError(page: drgn.Object) bool ¶
Return whether the
PG_error
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageForeign(page: drgn.Object) bool ¶
Return whether the
PG_foreign
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageHWPoison(page: drgn.Object) bool ¶
Return whether the
PG_hwpoison
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageHasHWPoisoned(page: drgn.Object) bool ¶
Return whether the
PG_has_hwpoisoned
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageIdle(page: drgn.Object) bool ¶
Return whether the
PG_idle
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageIsolated(page: drgn.Object) bool ¶
Return whether the
PG_isolated
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageLRU(page: drgn.Object) bool ¶
Return whether the
PG_lru
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageLocked(page: drgn.Object) bool ¶
Return whether the
PG_locked
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageMappedToDisk(page: drgn.Object) bool ¶
Return whether the
PG_mappedtodisk
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageMlocked(page: drgn.Object) bool ¶
Return whether the
PG_mlocked
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageOwnerPriv1(page: drgn.Object) bool ¶
Return whether the
PG_owner_priv_1
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PagePinned(page: drgn.Object) bool ¶
Return whether the
PG_pinned
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PagePrivate(page: drgn.Object) bool ¶
Return whether the
PG_private
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PagePrivate2(page: drgn.Object) bool ¶
Return whether the
PG_private_2
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageReadahead(page: drgn.Object) bool ¶
Return whether the
PG_readahead
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageReclaim(page: drgn.Object) bool ¶
Return whether the
PG_reclaim
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageReferenced(page: drgn.Object) bool ¶
Return whether the
PG_referenced
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageReported(page: drgn.Object) bool ¶
Return whether the
PG_reported
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageReserved(page: drgn.Object) bool ¶
Return whether the
PG_reserved
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageSavePinned(page: drgn.Object) bool ¶
Return whether the
PG_savepinned
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageSkipKASanPoison(page: drgn.Object) bool ¶
Return whether the
PG_skip_kasan_poison
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageSlobFree(page: drgn.Object) bool ¶
Return whether the
PG_slob_free
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageSwapBacked(page: drgn.Object) bool ¶
Return whether the
PG_swapbacked
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageUncached(page: drgn.Object) bool ¶
Return whether the
PG_uncached
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageUnevictable(page: drgn.Object) bool ¶
Return whether the
PG_unevictable
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageUptodate(page: drgn.Object) bool ¶
Return whether the
PG_uptodate
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageVmemmapSelfHosted(page: drgn.Object) bool ¶
Return whether the
PG_vmemmap_self_hosted
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageWaiters(page: drgn.Object) bool ¶
Return whether the
PG_waiters
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageWorkingset(page: drgn.Object) bool ¶
Return whether the
PG_workingset
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageWriteback(page: drgn.Object) bool ¶
Return whether the
PG_writeback
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageXenRemapped(page: drgn.Object) bool ¶
Return whether the
PG_xen_remapped
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageYoung(page: drgn.Object) bool ¶
Return whether the
PG_young
flag is set on a page.- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageSlab(page: drgn.Object) bool ¶
Return whether a page belongs to the slab allocator.
- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageCompound(page: drgn.Object) bool ¶
Return whether a page is part of a compound page.
- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageHead(page: drgn.Object) bool ¶
Return whether a page is a head page in a compound page.
- Parameters:
page –
struct page *
- drgn.helpers.linux.mm.PageTail(page: drgn.Object) bool ¶
Return whether a page is a tail page in a compound page.
- Parameters:
page –
struct 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:
page –
struct 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:
page –
struct 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:
page –
struct 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:
page –
struct 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:
page –
struct 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 atry
…except
drgn.FaultError
:>>> for page in for_each_page(): ... try: ... if PageLRU(page): ... print(hex(page)) ... except drgn.FaultError: ... continue 0xfffffb4a000c0000 0xfffffb4a000c0040 ...
This may be fixed in the future.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- Returns:
Iterator of
struct page *
objects.
- drgn.helpers.linux.mm.PFN_PHYS(prog: drgn.Program, pfn: drgn.IntegerLike) drgn.Object ¶
Get the physical address of a page frame number (PFN).
- Parameters:
prog – Program, which may be omitted to use the default program argument.
pfn –
unsigned long
- Returns:
phys_addr_t
- drgn.helpers.linux.mm.PHYS_PFN(prog: drgn.Program, addr: drgn.IntegerLike) drgn.Object ¶
Get the page frame number (PFN) of a physical address.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
addr –
phys_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:
page –
struct page *
- Returns:
unsigned long
- drgn.helpers.linux.mm.page_to_phys(page: drgn.Object) drgn.Object ¶
Get the physical address of a page.
- Parameters:
page –
struct 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:
page –
struct page *
- Returns:
void *
- drgn.helpers.linux.mm.pfn_to_page(prog: drgn.Program, pfn: drgn.IntegerLike) drgn.Object ¶
Get the page with a page frame number (PFN).
- Parameters:
prog – Program, which may be omitted to use the default program argument.
pfn –
unsigned long
- Returns:
struct page *
- 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).
- Parameters:
prog – Program, which may be omitted to use the default program argument.
pfn –
unsigned long
- Returns:
void *
- drgn.helpers.linux.mm.phys_to_page(prog: drgn.Program, addr: drgn.IntegerLike) drgn.Object ¶
Get the page containing a physical address.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
addr –
phys_addr_t
- Returns:
struct page *
- 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.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
addr –
phys_addr_t
- Returns:
void *
- drgn.helpers.linux.mm.virt_to_page(prog: drgn.Program, addr: drgn.IntegerLike) drgn.Object ¶
Get the page containing a directly mapped virtual address.
Note
This only works for virtual addresses from the “direct map”. This includes address from:
kmalloc
Slab allocator
Page allocator
But not:
vmalloc
vmap
ioremap
Symbols (function pointers, global variables)
For vmalloc or vmap addresses, use
vmalloc_to_page(addr)
. For arbitrary kernel addresses, usefollow_page(prog["init_mm"].address_of_(), addr)
.- Parameters:
prog – Program, which may be omitted to use the default program argument.
addr –
void *
- Returns:
struct page *
- 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.
Note
This only works for virtual addresses from the “direct map”. For vmalloc or vmap addresses, use
vmalloc_to_pfn(addr)
. For arbitrary kernel addresses, usefollow_pfn(prog["init_mm"].address_of_(), addr)
.- Parameters:
prog – Program, which may be omitted to use the default program argument.
addr –
void *
- Returns:
unsigned long
- 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.
Note
This only works for virtual addresses from the “direct map”. For arbitrary kernel addresses, use
follow_phys(prog["init_mm"].address_of_(), addr)
.- Parameters:
prog – Program, which may be omitted to use the default program argument.
addr –
void *
- Returns:
phys_addr_t
- drgn.helpers.linux.mm.follow_page(mm: drgn.Object, addr: drgn.IntegerLike) drgn.Object ¶
Get the page that a virtual address maps to in a virtual address space.
>>> task = find_task(113) >>> follow_page(task.mm, 0x7fffbbb6d4d0) *(struct page *)0xffffbe4bc0337b80 = { ... }
- Parameters:
mm –
struct mm_struct *
addr –
void *
- Returns:
struct page *
- Raises:
FaultError – if the virtual address cannot be translated
NotImplementedError – if virtual address translation is not supported for this architecture yet
- drgn.helpers.linux.mm.follow_pfn(mm: drgn.Object, addr: drgn.IntegerLike) drgn.Object ¶
Get the page frame number (PFN) that a virtual address maps to in a virtual address space.
>>> task = find_task(113) >>> follow_pfn(task.mm, 0x7fffbbb6d4d0) (unsigned long)52718
- Parameters:
mm –
struct mm_struct *
addr –
void *
- Returns:
unsigned long
- Raises:
FaultError – if the virtual address cannot be translated
NotImplementedError – if virtual address translation is not supported for this architecture yet
- drgn.helpers.linux.mm.follow_phys(mm: drgn.Object, addr: drgn.IntegerLike) drgn.Object ¶
Get the physical address that a virtual address maps to in a virtual address space.
>>> task = find_task(113) >>> follow_phys(task.mm, 0x7fffbbb6d4d0) (phys_addr_t)215934160
- Parameters:
mm –
struct mm_struct *
addr –
void *
- Returns:
phys_addr_t
- Raises:
FaultError – if the virtual address cannot be translated
NotImplementedError – if virtual address translation is not supported for this architecture yet
- drgn.helpers.linux.mm.vmalloc_to_page(prog: drgn.Program, addr: drgn.IntegerLike) drgn.Object ¶
Get the page containing a vmalloc or vmap address.
>>> task = find_task(113) >>> vmalloc_to_page(task.stack) *(struct page *)0xffffbe4bc00a2200 = { ... }
- Parameters:
prog – Program, which may be omitted to use the default program argument.
addr –
void *
- Returns:
struct page *
- drgn.helpers.linux.mm.vmalloc_to_pfn(prog: drgn.Program, addr: drgn.IntegerLike) drgn.Object ¶
Get the page frame number (PFN) containing a vmalloc or vmap address.
>>> task = find_task(113) >>> vmalloc_to_pfn(task.stack) (unsigned long)10376
- Parameters:
prog – Program, which may be omitted to use the default program argument.
addr –
void *
- Returns:
unsigned long
- drgn.helpers.linux.mm.find_vmap_area(prog: drgn.Program, addr: drgn.IntegerLike) drgn.Object ¶
Return the
struct vmap_area *
containing an address.>>> find_vmap_area(0xffffa2b680081000) *(struct vmap_area *)0xffffa16541046b40 = { ... }
- Parameters:
prog – Program, which may be omitted to use the default program argument.
addr – Address to look up.
- Returns:
struct vmap_area *
(NULL
if not found)
- drgn.helpers.linux.mm.for_each_vmap_area(prog: drgn.Program) Iterator[drgn.Object] ¶
Iterate over every
struct vmap_area *
on the system.>>> for va in for_each_vmap_area(): ... caller = "" ... if va.vm: ... sym = prog.symbol(va.vm.caller) ... if sym: ... caller = f" {sym.name}" ... print(f"{hex(va.va_start)}-{hex(va.va_end)}{caller}") ... 0xffffa2b680000000-0xffffa2b680005000 irq_init_percpu_irqstack 0xffffa2b680005000-0xffffa2b680007000 acpi_os_map_iomem 0xffffa2b68000b000-0xffffa2b68000d000 hpet_enable 0xffffa2b680080000-0xffffa2b680085000 kernel_clone ...
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- Returns:
Iterator of
struct vmap_area *
objects.
- 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(1490152) >>> access_process_vm(task, 0x7f8a62b56da0, 12) b'hello, world'
- Parameters:
task –
struct task_struct *
address – Starting address.
size – Number of bytes to read.
- Raises:
FaultError – if the virtual address cannot be translated
NotImplementedError – if virtual address translation is not supported for this architecture yet
- 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 astruct mm_struct *
instead of astruct task_struct *
.>>> task = find_task(1490152) >>> access_remote_vm(task.mm, 0x7f8a62b56da0, 12) b'hello, world'
- Parameters:
mm –
struct mm_struct *
address – Starting address.
size – Number of bytes to read.
- Raises:
FaultError – if the virtual address cannot be translated
NotImplementedError – if virtual address translation is not supported for this architecture yet
- drgn.helpers.linux.mm.cmdline(task: drgn.Object) Optional[List[bytes]] ¶
Get the list of command line arguments of a task, or
None
for kernel tasks.>>> cmdline(find_task(1495216)) [b'vim', b'drgn/helpers/linux/mm.py']
$ tr '\0' ' ' < /proc/1495216/cmdline vim drgn/helpers/linux/mm.py
- Parameters:
task –
struct task_struct *
- Raises:
FaultError – if the virtual address containing the command line cannot be translated
NotImplementedError – if virtual address translation is not supported for this architecture yet
- drgn.helpers.linux.mm.environ(task: drgn.Object) Optional[List[bytes]] ¶
Get the list of environment variables of a task, or
None
for kernel tasks.>>> environ(find_task(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:
task –
struct task_struct *
- Raises:
FaultError – if the virtual address containing the environment cannot be translated
NotImplementedError – if virtual address translation is not supported for this architecture yet
- drgn.helpers.linux.mm.vma_find(mm: drgn.Object, addr: drgn.IntegerLike) drgn.Object ¶
Return the virtual memory area (VMA) containing an address.
- Parameters:
mm –
struct mm_struct *
addr – Address to look up.
- Returns:
struct vm_area_struct *
(NULL
if not found)
- drgn.helpers.linux.mm.for_each_vma(mm: drgn.Object) Iterator[drgn.Object] ¶
Iterate over every virtual memory area (VMA) in a virtual address space.
>>> for vma in for_each_vma(task.mm): ... print(vma) ... *(struct vm_area_struct *)0xffff97ad82bfc930 = { ... } *(struct vm_area_struct *)0xffff97ad82bfc0a8 = { ... } ...
- Parameters:
mm –
struct mm_struct *
- Returns:
Iterator of
struct vm_area_struct *
objects.
- drgn.helpers.linux.mm.totalram_pages(prog: drgn.Program) int ¶
Return the total number of RAM pages.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- drgn.helpers.linux.mm.in_direct_map(prog: drgn.Program, addr: drgn.IntegerLike) bool ¶
Return True if an address is within the kernel’s direct memory mapping :param prog: Program, which may be omitted to use the default program argument.:param addr: address to check
Modules¶
The drgn.helpers.linux.module
module contains helpers for working with
loaded kernel modules.
- drgn.helpers.linux.module.for_each_module(prog: drgn.Program) Iterable[drgn.Object] ¶
Returns all loaded kernel modules
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- Returns:
Iterable of
struct module *
objects
- drgn.helpers.linux.module.find_module(prog: drgn.Program, name: Union[str, bytes]) drgn.Object ¶
Lookup a kernel module by name, or return NULL if not found
- Parameters:
prog – Program, which may be omitted to use the default program argument.
name – name to search for
- Returns:
the
struct module *
by that name, or NULL
- drgn.helpers.linux.module.module_percpu_region(mod: drgn.Object) Tuple[int, int] ¶
Lookup the percpu memory region of a module.
Given a
struct module *
, return the address (as a an int) and the length of the percpu memory region. Modules may have a NULL percpu region, in which case (0, 0) is returned. Rarely, on kernels withoutCONFIG_SMP
, there is no percpu region at all, and this function returns (0, 0)- Parameters:
mod – Object of type
struct module *
- Returns:
(base, size) of the module percpu region
- drgn.helpers.linux.module.module_address_regions(mod: drgn.Object) List[Tuple[int, int]] ¶
Returns a list of address ranges for a module
Given a
struct module *
, return every address range associated with the module. Note that the number of address ranges and their interpretations vary across kernel versions. Some kernel versions provide additional information about some regions (e.g. text, data, R/O, init). This API doesn’t distinguish. However, this API does not provide the module’s percpu region: usemodule_percpu_region()
for that.- Parameters:
mod – Object of type
struct module *
- Returns:
list of tuples: (starting memory address, length of address range)
- drgn.helpers.linux.module.address_to_module(prog: drgn.Program, addr: drgn.IntegerLike) drgn.Object ¶
Return the
struct module *
associated with a memory addressIf the address is a text, data, or read-only data address associated with a kernel module, then this function returns the module it is associated with. Otherwise, returns NULL. Note that dynamic memory (e.g. slab objects) generally can’t be associated with the module that allocated it. Further, static & dynamic per-cpu address cannot be associated with their associated module either.
Normally, this lookup is efficient, thanks to
CONFIG_MODULES_TREE_LOOKUP
, which provides a red-black tree of module address ranges, and is very commonly enabled. However, on some uncommon configurations the rbtree may not be present. In those cases, we fall back to a linear search of each kernel module’s memory regions.- Parameters:
prog – Program, which may be omitted to use the default program argument.
addr – memory address to lookup
- Returns:
the
struct module *
associated with the memory, or NULL
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:
inode –
struct 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:
sock –
struct 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.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- 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:
inode –
struct 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:
task –
struct 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:
dev –
struct net_device *
- Returns:
Iterator of
struct netdev_queue *
objects.
- drgn.helpers.linux.net.netdev_get_by_index(net: Union[drgn.Object, drgn.Program], ifindex: drgn.IntegerLike) drgn.Object ¶
Get the network device with the given interface index number.
- drgn.helpers.linux.net.netdev_get_by_name(net: Union[drgn.Object, drgn.Program], name: Union[str, bytes]) drgn.Object ¶
Get the network device with the given interface name.
- drgn.helpers.linux.net.netdev_priv(dev: drgn.Object, type: Union[str, drgn.Type] = 'void') drgn.Object ¶
Return the private data of a network device.
>>> dev = netdev_get_by_name("wlp0s20f3") >>> netdev_priv(dev) (void *)0xffff9419c9dec9c0 >>> netdev_priv(dev, "struct ieee80211_sub_if_data") *(struct ieee80211_sub_if_data *)0xffff9419c9dec9c0 = { ... }
- Parameters:
dev –
struct net_device *
type – Type of private data.
- Returns:
type *
- 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:
sk –
struct 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:
head –
struct hlist_nulls_head *
- Returns:
Iterator of
struct sock *
objects.
- drgn.helpers.linux.net.skb_shinfo(skb: drgn.Object) drgn.Object ¶
Get the shared info for a socket buffer.
- Parameters:
skb –
struct sk_buff *
- Returns:
struct skb_shared_info *
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:
mask –
nodemask_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:
prog – Program, which may be omitted to use the default program argument.
state –
enum 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.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- drgn.helpers.linux.nodemask.for_each_online_node(prog: drgn.Program) Iterator[int] ¶
Iterate over all online NUMA nodes.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- 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.
state –
enum 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 useper_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; useper_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:
fbc –
struct percpu_counter *
Process IDS¶
The drgn.helpers.linux.pid
module provides helpers for looking up process
IDs and processes.
- drgn.helpers.linux.pid.pid_task(pid: drgn.Object, pid_type: drgn.IntegerLike) drgn.Object ¶
Return the
struct task_struct *
containing the givenstruct pid *
of the given type.- Parameters:
pid –
struct pid *
pid_type –
enum pid_type
- Returns:
struct task_struct *
- drgn.helpers.linux.pid.find_pid(ns: drgn.Object | drgn.Program, pid: drgn.IntegerLike) drgn.Object ¶
Return the
struct pid *
for the given PID number.
- drgn.helpers.linux.pid.for_each_pid(ns: drgn.Object | drgn.Program) Iterator[drgn.Object] ¶
Iterate over all PIDs in a namespace.
- drgn.helpers.linux.pid.find_task(ns: drgn.Object | drgn.Program, pid: drgn.IntegerLike) drgn.Object ¶
Return the task with the given PID.
- drgn.helpers.linux.pid.for_each_task(ns: drgn.Object | drgn.Program) Iterator[drgn.Object] ¶
Iterate over all of the tasks visible in a namespace.
Priority-Sorted Lists¶
The drgn.helpers.linux.plist
module provides helpers for working with
descending-priority-sorted doubly-linked lists (struct plist_head
and
struct plist_node
) from include/linux/plist.h
.
- drgn.helpers.linux.plist.plist_head_empty(head: drgn.Object) bool ¶
Return whether a plist is empty.
- Parameters:
head –
struct plist_head *
- drgn.helpers.linux.plist.plist_node_empty(node: drgn.Object) bool ¶
Return whether a plist node is empty (i.e., not on a list).
- Parameters:
node –
struct plist_node *
- drgn.helpers.linux.plist.plist_first_entry(head: drgn.Object, type: Union[str, drgn.Type], member: str) drgn.Object ¶
Return the first (highest priority) entry in a plist.
The list is assumed to be non-empty.
- Parameters:
head –
struct plist_head *
type – Entry type.
member – Name of list node member in entry type.
- Returns:
type *
- drgn.helpers.linux.plist.plist_last_entry(head: drgn.Object, type: Union[str, drgn.Type], member: str) drgn.Object ¶
Return the last (lowest priority) entry in a plist.
The list is assumed to be non-empty.
- Parameters:
head –
struct plist_head *
type – Entry type.
member – Name of list node member in entry type.
- Returns:
type *
- drgn.helpers.linux.plist.plist_for_each(head: drgn.Object) Iterator[drgn.Object] ¶
Iterate over all of the nodes in a plist.
- Parameters:
head –
struct plist_head *
- Returns:
Iterator of
struct plist_node *
objects.
- drgn.helpers.linux.plist.plist_for_each_entry(type: Union[str, drgn.Type], head: drgn.Object, member: str) Iterator[drgn.Object] ¶
Iterate over all of the entries in a plist.
- Parameters:
type – Entry type.
head –
struct plist_head *
member – Name of plist node member in entry type.
- Returns:
Iterator of
type *
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.
- 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.
- 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.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- drgn.helpers.linux.printk.get_dmesg(prog: drgn.Program) bytes ¶
Get the contents of the kernel log buffer formatted like dmesg(1).
If you just want to print the log buffer, use
print_dmesg()
.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.- Parameters:
prog – Program, which may be omitted to use the default program argument.
- drgn.helpers.linux.printk.print_dmesg(prog: drgn.Program, *, file: Optional[SupportsWrite[str]] = None) None ¶
Print the contents of the kernel log buffer.
>>> print_dmesg() [ 0.000000] Linux version 6.8.0-vmtest28.1default (drgn@drgn) (x86_64-linux-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.39) #1 SMP PREEMPT_DYNAMIC Mon Mar 11 06:38:45 UTC 2024 [ 0.000000] Command line: rootfstype=9p rootflags=trans=virtio,cache=loose,msize=1048576 ro console=ttyS0,115200 panic=-1 crashkernel=256M init=/tmp/drgn-vmtest-rudzppeo/init [ 0.000000] BIOS-provided physical RAM map: ...
- Parameters:
prog – Program, which may be omitted to use the default program argument.
file – File to print to. Defaults to
sys.stdout
.
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:
root –
struct radix_tree_root *
index – Entry index.
- Returns:
void *
found entry, orNULL
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:
root –
struct 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:
node –
struct 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:
node –
struct rb_node *
- drgn.helpers.linux.rbtree.rb_parent(node: drgn.Object) drgn.Object ¶
Return the parent node of a red-black tree node.
- Parameters:
node –
struct 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:
root –
struct 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:
root –
struct 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:
node –
struct 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:
node –
struct 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:
root –
struct 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.
root –
struct 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.
root –
struct 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, orNULL
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:
The tree is a valid binary search tree ordered according to cmp.
If allow_equal is
False
, there are no nodes that compare equal according to cmp.The
rb_parent
pointers are consistent.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.
root –
struct 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 likevalidate_rbtree()
while iterating.- Parameters:
type – Entry type.
root –
struct 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.task_cpu(task: drgn.Object) int ¶
Return the CPU number that the given task last ran on.
- Parameters:
task –
struct task_struct *
- drgn.helpers.linux.sched.task_thread_info(task: drgn.Object) drgn.Object ¶
Return the thread information structure for a task.
- Parameters:
task –
struct task_struct *
- Returns:
struct thread_info *
- drgn.helpers.linux.sched.cpu_curr(prog: drgn.Program, cpu: drgn.IntegerLike) drgn.Object ¶
Return the task running on the given CPU.
>>> cpu_curr(7).comm (char [16])"python3"
- Parameters:
prog – Program, which may be omitted to use the default program argument.
cpu – CPU number.
- Returns:
struct task_struct *
- 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(1).comm (char [16])"swapper/1"
- Parameters:
prog – Program, which may be omitted to use the default program argument.
cpu – CPU number.
- Returns:
struct 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:
task –
struct task_struct *
- drgn.helpers.linux.sched.loadavg(prog: drgn.Program) Tuple[float, float, float] ¶
Return system load averaged over 1, 5 and 15 minutes as tuple of three float values.
>>> loadavg() (2.34, 0.442, 1.33)
- Parameters:
prog – Program, which may be omitted to use the default program argument.
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
andstruct bar
, which have the same size but are otherwise unrelated. If the kernel creates a slab cache namedfoo
forstruct foo
, then another slab cache namedbar
forstruct bar
, then slab cachefoo
will be reused instead of creating another cache forbar
. So the following will fail:find_slab_cache("bar")
And the following will also return
struct bar *
objects errantly casted tostruct foo *
:slab_cache_for_each_allocated_object(find_slab_cache("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_cache –
struct 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 withCONFIG_SLUB
andCONFIG_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() >>> cache_to_merged["dnotify_struct"] 'avc_xperms_data' >>> "avc_xperms_data" in cache_to_merged False >>> find_slab_cache("dnotify_struct") is None True >>> find_slab_cache("avc_xperms_data") is None False
- Warning:
This function will only work on kernels which are built with
CONFIG_SLUB
andCONFIG_SYSFS
enabled.- Parameters:
prog – Program, which may be omitted to use the default program argument.
- 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.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- 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:
prog – Program, which may be omitted to use the default program argument.
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.- Parameters:
prog – Program, which may be omitted to use the default program argument.
- class drgn.helpers.linux.slab.SlabCorruptionError¶
Bases:
drgn.helpers.ValidationError
Error raised when a corruption is encountered in a slab allocator data structure.
- class drgn.helpers.linux.slab.SlabFreelistCycleError¶
Bases:
SlabCorruptionError
Error raised when a cycle is encountered in a slab allocator freelist.
- 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("dentry") >>> next(slab_cache_for_each_allocated_object(dentry_cache, "struct dentry")) *(struct dentry *)0xffff905e41404000 = { ... }
- Parameters:
slab_cache –
struct kmem_cache *
type – Type of object in the slab cache.
- Returns:
Iterator of
type *
objects.
- 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(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
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:
prog – Program, which may be omitted to use the default program argument.
addr –
void *
- Returns:
SlabObjectInfo
if addr is in a slab object, orNone
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 astruct page *
.
- 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.
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:
prog – Program, which may be omitted to use the default program argument.
addr –
void *
- Returns:
struct kmem_cache *
containing addr, orNULL
if addr is not from a slab cache.
Stack Depot¶
The drgn.helpers.linux.stackdepot
module provides helpers for working with
the stack trace storage from include/linux/stackdepot.h
used by KASAN
and other kernel debugging tools.
- drgn.helpers.linux.stackdepot.stack_depot_fetch(handle: drgn.Object) Optional[drgn.StackTrace] ¶
Returns a stack trace for the given stack handle.
- Parameters:
handle –
depot_stack_handle_t
- Returns:
The stack trace, or
None
if not available.
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 atc
command means major handle 0x10.- Parameters:
dev –
struct 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:
sk –
struct 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:
prog – Program, which may be omitted to use the default program argument.
uid –
kuid_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.
- Parameters:
prog – Program, which may be omitted to use the default program argument.
- Returns:
Iterator of
struct user_struct *
objects.
Wait Queues¶
The drgn.helpers.linux.wait
module provides helpers for working with wait
queues (wait_queue_head_t
and wait_queue_entry_t
) from
include/linux/wait.h
.
Note
Since Linux 4.13, entries in a wait queue have type wait_queue_entry_t
.
Before that, the type was named wait_queue_t
.
- drgn.helpers.linux.wait.waitqueue_active(wq: drgn.Object) bool ¶
Return whether a wait queue has any waiters.
- Parameters:
wq –
wait_queue_head_t *
- drgn.helpers.linux.wait.waitqueue_for_each_entry(wq: drgn.Object) Iterator[drgn.Object] ¶
Iterate over all entries in a wait queue.
- Parameters:
wq –
wait_queue_head_t *
- Returns:
Iterator of
wait_queue_entry_t *
orwait_queue_t *
objects depending on the kernel version.
- drgn.helpers.linux.wait.waitqueue_for_each_task(wq: drgn.Object) Iterator[drgn.Object] ¶
Iterate over all tasks waiting on a wait queue.
Warning
This comes from
wait_queue_entry_t::private
, which usually stores a task. However, some wait queue entries store a different pointer type, in which case this will return garbage.- Parameters:
wq –
wait_queue_head_t *
- Returns:
Iterator of
struct task_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:
xa –
struct xarray *
index – Entry index.
advanced – Whether to return nodes only visible to the XArray advanced API. If
False
, zero entries (seexa_is_zero()
) will be returned asNULL
.
- Returns:
void *
found entry, orNULL
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:
xa –
struct xarray *
advanced – Whether to return nodes only visible to the XArray advanced API. If
False
, zero entries (seexa_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:
entry –
void *
- 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
. Ifxa_is_value()
returnsTrue
, 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:
entry –
void *
- 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()
andxa_for_each()
whenadvanced = True
.>>> entry = xa_load(xa, 10, advanced=True) >>> entry (void *)0x406 >>> xa_is_zero(entry) True >>> xa_load(xa, 10) (void *)0
- Parameters:
entry –
void *