Advanced Usage¶
The User Guide covers basic usage of drgn, but drgn also supports more advanced use cases which are covered here.
Loading Debugging Symbols¶
drgn will automatically load debugging information based on the debugged
program (e.g., from loaded kernel modules or loaded shared libraries).
drgn.Program.load_debug_info()
can be used to load additional debugging
information:
>>> prog.load_debug_info(['./libfoo.so', '/usr/lib/libbar.so'])
Library¶
In addition to the CLI, drgn is also available as a library.
drgn.program_from_core_dump()
, drgn.program_from_kernel()
, and
drgn.program_from_pid()
correspond to the -c
, -k
, and -p
command line options, respectively; they return a drgn.Program
that
can be used just like the one initialized by the CLI:
>>> import drgn
>>> prog = drgn.program_from_kernel()
C Library¶
The core functionality of drgn is implemented in C and is available as a C
library, libdrgn
. See drgn.h
.
Full documentation can be generated by running doxygen
in the libdrgn
directory of the source code. Note that the API and ABI are not yet stable.
Custom Programs¶
The main components of a drgn.Program
are the program memory, types,
and symbols. The CLI and equivalent library interfaces automatically determine
these. However, it is also possible to create a “blank” Program
and plug in
the main components. The drgn.cli.run_interactive()
function allows you
to run the same drgn CLI once you’ve created a drgn.Program
, so it’s
easy to make a custom program which allows interactive debugging.
drgn.Program.add_memory_segment()
defines a range of memory and how to
read that memory. The following example uses a Btrfs filesystem image as the
program “memory”:
import drgn
import os
import sys
from drgn.cli import run_interactive
def btrfs_debugger(dev):
file = open(dev, 'rb')
size = file.seek(0, 2)
def read_file(address, count, offset, physical):
file.seek(offset)
return file.read(count)
platform = drgn.Platform(drgn.Architecture.UNKNOWN,
drgn.PlatformFlags.IS_LITTLE_ENDIAN)
prog = drgn.Program(platform)
prog.add_memory_segment(0, size, read_file)
prog.load_debug_info([f'/lib/modules/{os.uname().release}/kernel/fs/btrfs/btrfs.ko'])
return prog
prog = btrfs_debugger(sys.argv[1] if len(sys.argv) >= 2 else '/dev/sda')
print(drgn.Object(prog, 'struct btrfs_super_block', address=65536))
run_interactive(prog, banner_func=lambda _: "BTRFS debugger")
drgn.Program.register_type_finder()
and
drgn.Program.register_object_finder()
are the equivalent methods for
plugging in types and objects.
Environment Variables¶
Some of drgn’s behavior can be modified through environment variables:
DRGN_MAX_DEBUG_INFO_ERRORS
The maximum number of individual errors to report in a
drgn.MissingDebugInfoError
. Any additional errors are truncated. The default is 5; -1 is unlimited.DRGN_PREFER_ORC_UNWINDER
Whether to prefer using ORC over DWARF for stack unwinding (0 or 1). The default is 0. Note that drgn will always fall back to ORC for functions lacking DWARF call frame information and vice versa. This environment variable is mainly intended for testing and may be ignored in the future.
DRGN_USE_LIBDWFL_REPORT
Whether drgn should use libdwfl to find debugging information for core dumps instead of its own implementation (0 or 1). The default is 0. This environment variable is mainly intended as an escape hatch in case of bugs in drgn’s implementation and will be ignored in the future.
DRGN_USE_LIBKDUMPFILE_FOR_ELF
Whether drgn should use libkdumpfile for ELF vmcores (0 or 1). The default is 0. This functionality will be removed in the future.
DRGN_USE_SYS_MODULE
Whether drgn should use
/sys/module
to find information about loaded kernel modules for the running kernel instead of getting them from the core dump (0 or 1). The default is 1. This environment variable is mainly intended for testing and may be ignored in the future.
Linux Kernel Special Objects¶
When debugging the Linux kernel, there are some special drgn.Object
s
accessible with drgn.Program.object()
and drgn.Program[]
. Some of these are available even without debugging
information, thanks to metadata called “vmcoreinfo” which is present in kernel
core dumps. These special objects include:
UTS_RELEASE
Object type:
const char []
This corresponds to the
UTS_RELEASE
macro in the Linux kernel source code. This is the exact kernel release (i.e., the output ofuname -r
).To use this as a Python string, you must convert it:
>>> release = prog["UTS_RELEASE"].string_().decode("ascii")
This is available without debugging information.
PAGE_SIZE
Object type:
unsigned long
PAGE_SHIFT
Object type:
unsigned int
PAGE_MASK
Object type:
unsigned long
These correspond to the macros of the same name in the Linux kernel source code. The page size is the smallest contiguous unit of physical memory which can be allocated or mapped by the kernel.
>>> prog['PAGE_SIZE'] (unsigned long)4096 >>> prog['PAGE_SHIFT'] (int)12 >>> prog['PAGE_MASK'] (unsigned long)18446744073709547520 >>> 1 << prog['PAGE_SHIFT'] == prog['PAGE_SIZE'] True >>> ~(prog['PAGE_SIZE'] - 1) == prog['PAGE_MASK'] True
These are available without debugging information.
jiffies
Object type:
volatile unsigned long
This is a counter of timer ticks. It is actually an alias of
jiffies_64
on 64-bit architectures, or the least significant 32 bits ofjiffies_64
on 32-bit architectures. Since this alias is defined via the linker, drgn handles it specially.This is not available without debugging information.
vmemmap
Object type:
struct page *
This is a pointer to the “virtual memory map”, an array of
struct page
for each physical page of memory. While the purpose and implementation details of this array are beyond the scope of this documentation, it is enough to say that it is represented in the kernel source in an architecture-dependent way, frequently as a macro or constant. The definition provided by drgn ensures that users can access it without resorting to architecture-specific logic.This is not available without debugging information.
VMCOREINFO
Object type:
const char []
This is the data contained in the vmcoreinfo note, which is present either as an ELF note in
/proc/kcore
or ELF vmcores, or as a special data section in kdump-formatted vmcores. The vmcoreinfo note contains critical data necessary for interpreting the kernel image, such as KASLR offsets and data structure locations.In the Linux kernel, this data is normally stored in a variable called
vmcoreinfo_data
. However, drgn reads this information from ELF note or from the diskdump header. It is possible (in rare cases, usually with vmcores created by hypervisors) for a vmcore to contain vmcoreinfo which differs from the data invmcoreinfo_data
, so it is important to distinguish the contents. For that reason, we use the nameVMCOREINFO
to distinguish it from the kernel variablevmcoreinfo_data
.This is available without debugging information.