0.0.28 & 0.0.29 (Released October 7th & 8th, 2024)¶
These are some of the highlights of drgn 0.0.28. See the GitHub release for the full release notes, including more improvements and bug fixes.
drgn 0.0.29 was released shortly after 0.0.28 with a single bug fix for the
drgn.helpers.experimental.kmodify
module. See the release notes.
Calling Arbitrary Functions in the Running Kernel¶
This release added call_function()
,
which calls a function in the running kernel. This is the first ever feature in
drgn that allows modifying the state of the kernel. Its primary use cases are
experimentation in development environments and mitigating kernel bugs in
production. For example, this
recent lost wake-up bug could be mitigated with something like:
from drgn.helpers.experimental.kmodify import call_function
for task in for_each_task():
for frame in stack_trace(task):
if frame.name == "perf_event_free_task":
call_function("wake_up_process", task)
break
Note that this feature is currently experimental, only supported on x86-64, and may have a different API in the future.
There is a blog post about how this feature works.
Writing to Kernel Memory¶
In a similar vein, drgn can now write to kernel memory, either via an address
(with write_memory()
):
>>> import os
>>> from drgn.helpers.experimental.kmodify import write_memory
>>> os.uname().sysname
'Linux'
>>> write_memory(prog["init_uts_ns"].name.sysname.address_, b"Lol\\0")
>>> os.uname().sysname
'Lol'
or an object (with write_object()
):
>>> from drgn.helpers.experimental.kmodify import write_object
>>> 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
This feature is also experimental. It uses the same underlying mechanism as
call_function()
.
More C Operators¶
This release added a couple of new functions corresponding to operators in C.
The alignof()
function is analogous to the _Alignof()
operator
in C:
>>> alignof(prog.type("long long"))
8
The implicit_convert()
function implements implicit conversions
in C, like when assigning a variable, passing an argument to a function call,
or returning a value:
>>> implicit_convert("unsigned int", Object(prog, "float", 2.0))
(unsigned int)2
>>> implicit_convert("void *", Object(prog, "int", 0))
Traceback (most recent call last):
...
TypeError: cannot convert 'int' to incompatible type 'void *'
Kernel Module Helpers¶
Stephen Brennan contributed several helpers for working with Linux kernel modules.
for_each_module()
iterates over loaded modules:
>>> for module in for_each_module():
... print(module.name.string_().decode())
...
overlay
vhost_net
vhost
...
find_module()
finds the module with a given name:
>>> module = find_module("overlay")
>>> module
*(struct module *)0xffffffffc23dae00 = {
...
}
module_address_regions()
and
module_percpu_region()
return all of the
memory regions associated with a module, and
address_to_module()
finds the module containing an address:
>>> for start, size in module_address_regions(module):
... print(hex(start), size)
...
0xffffffffc23be000 102400
0xffffffffc23d8000 65536
0xffffffffc23e9000 73728
0xffffffffc2385000 4096
0x0 0
0x0 0
0x0 0
>>> address_to_module(0xffffffffc23bf000) == module
True
Thread Names¶
Ryan Wilson added the name
attribute to
drgn.Thread
. This provides a consistent interface for getting the name
of a thread regardless of whether you’re debugging the kernel or a userspace
program. (Unfortunately, userspace core dumps on Linux don’t save the name of
any threads other than the main thread.)
Full 32-Bit Arm Support¶
This release added support for virtual address translation and stack traces on 32-bit Arm. This is the state of architecture support in this release:
Architecture |
Linux Kernel Modules |
Stack Traces |
Virtual Address Translation |
---|---|---|---|
x86-64 |
✓ |
✓ |
✓ |
AArch64 |
✓ |
✓ |
✓ |
s390x |
✓ |
✓ |
✓ |
ppc64 |
✓ |
✓ |
✓ |
i386 |
✓ |
||
Arm |
✓ |
✓ |
✓ |
RISC-V |
✓ |
Note that there are known Linux kernel issues with debugging 32-bit Arm, both live and in kdump. Please reach out to the linux-debuggers@vger.kernel.org mailing list if these affect you.
AArch64 and s390x Virtual Address Translation Fixes¶
As of Linux 6.9, the default AArch64 kernel configuration enables 52-bit virtual addresses and falls back to a smaller virtual address size if the hardware does not support 52 bits. This required updates to drgn that were missed in v0.0.27.
As of Linux 6.10, on s390x, virtual addresses in the direct mapping are no longer equal to physical addresses. This also required updates to drgn that were missed in v0.0.27.
Linux 6.11 and 6.12 Support¶
A change in Linux 6.12 broke tools/fsrefs.py
. This error from
visit_uprobes()
is fixed in this release:
TypeError: cannot convert 'struct list_head' to bool
No other changes were required to support Linux 6.11 and 6.12.