The test for print_annotated_memory() shouldn't assert anything when
CONFIG_SLOB is enabled, because we can't find slab objects. However, the
test shouldn't be skipped entirely, because print_annotated_memory()
should run without error in this case. Skip the assertion only.
Fixes: c7717280 ("helpers.common.memory: add print_annotated_memory() helper")
Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
There are a few common use cases that I find myself re-writing:
iterating over the list of modules, looking up a module by name, and
getting memory addresses related to modules (or vice versa). Add helpers
for each.
Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
This one doesn't need any changes to the callback signature, just the
new interface. We also keep add_object_finder() for compatibility.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Like for symbol finders, we want extra flexibility around configuring
type finders. The type finder callback signature also has a couple of
warts: it doesn't take the program since it was added before types
needed to be constructed from a program, and it is called separately for
each type kind since originally type lookups were for only one kind.
While we're adding a new interface, let's fix these warts: pass the
program and a set of type kinds. However, we need to keep the old
add_type_finder() interface for backwards compatibility.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
C type finders are passed a bitset of type kinds, but Python type
finders currently get called for each type kind. An upcoming update to
the type finder interface will fix this, but we need a set of TypeKinds,
and we'd rather not construct a real Python set for it. Instead, add a
TypeKindSet bitset that satisfies the collections.abc.Set interface.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Currently, the bare-bones add_symbol_finder() interface only allows
adding a symbol finder that is called before any existing finders. It'd
be useful to be able to specify the order that symbol finders should be
called in and to selectively enable and disable them. To do that, we
also need finders to have a name to identify them by. So, replace
add_symbol_finder() (which hasn't been in a release yet) with a set of
interfaces providing this flexibility: register_symbol_finder(),
set_enabled_symbol_finders(), registered_symbol_finders(), and
enabled_symbol_finders(). Also change the callback signature to take the
program.
In particular, this flexibility will be very useful for a plugin system:
pre-installed plugins can register symbol finders that the user can
choose to enable or disable.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
To try out our new testing framework, move some simple Python unit tests
for the internal lexer API to C unit tests.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
I thought I had forgotten to handle these cases. Turns out I handled
them, but I didn't have test cases for them.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
This is basically the opposite of offsetof(). I've wanted it to figure
out what member an offset returned by slab_object_info() or
identify_address() corresponds to.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
This requires rearranging a couple of things: symbols from modules are
also vmap addresses, so we need to check for symbols first, and we need
to open-code slab_object_info to avoid some redundant operations.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
This is similar to print_annotated_stack() except that it works on an
arbitrary memory range. It's useful for trying to find some context in
mystery memory.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
We currently only have one test resource file, sample.coredump.zst, but
the tests for #332 will add more. Create a package, tests.resources, to
contain test resources and a function, get_resource(), to decompress
them. It can also be used on the command line:
python3 -m tests.resources $resource_name
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Specify a "fake" symbol finder and then test that its results are
plumbed through the API successfully. While this is a contrived test, it
helps build confidence in the plumbing of the API.
Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
Previously, Symbol objects could not be constructed in Python. However,
in order to allow Python Symbol finders, this needs to be changed.
Unfortunately, Symbol name lifetimes are tricky to manage. We introduce
a lifetime enumeration to handle this. The lifetime may be "static",
i.e. longer than the life of the program; "external", i.e. longer than
the life of the symbol, but no guarantees beyond that; or "owned", i.e.
owned by the Symbol itself.
Symbol objects constructed in Python are "external". The Symbol struct
owns the pointer to the drgn_symbol, and it holds a reference to the
Python object keeping the name valid (either the program, or a PyUnicode
object).
The added complexity is justified by the fact that most symbols are from
the ELF file, and thus share a lifetime with the Program. It would be a
waste to constantly strdup() these strings, just to support a small
number of Symbols created by Python code.
Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
Before Linux kernel commit 4e57a4ddf6b0 ("ARM: 9107/1: syscall: always
store thread_info->abi_syscall") (in v5.15), on Arm, the syscall number
in /proc/<pid>/syscall is unreliable unless the process is being traced.
fork_and_sigwait() relies on this to detect when the created process has
scheduled out for good. Instead, we can have the created process raise
SIGSTOP and wait for it to be stopped. This is simpler and also doesn't
require us to care about the sigwait syscall numbers. While we're
reworking it, let's also consolidate it with fork_and_call().
test_task_state_to_char() can't use the new function because it wants
the function to sleep, then stop, then die, but it's easy enough to
open-code that one special case.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
elfutils commit c1c1c06e30f0 ("libebl: Add ebl_func_addr_mask plus ARM
backend implementation.") has a bug that I haven't gotten around to
fixing: it masks the least significant bit of all symbol values, not
just function symbol values. This breaks the get_kconfig() helper: if
the kernel_config_data_end symbol value is odd, then the length of the
compressed config data is truncated by one byte and gzip decompression
fails. Disable the test on Arm until we get it fixed.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
It can be confusing and misleading to see a FaultError for a strange
address that is actually physical.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Like fork_and_sigwait(), but returns the called function's return value,
and only waits for the function to return, not sigwait.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
In this mode, we print the paths of the referenced files. Now that we
have multiple "checks" we're doing, also add an option to enable or
disable specific checks.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
I ran into plists in the swap code, but they're also used in the
real-time scheduler and futexes. The helpers are trivial wrappers around
the list helpers.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
My team and I have investigated many issues that turned out to be caused
by a stray reference to a file or filesystem, either by user error or
due to a kernel bug. Userspace tools like lsof and fuser can't find all
of these. This adds a drgn-based tool similar to lsof/fuser. This
initial version only checks the basics: file descriptors, task working
directories, task root directories, task executables, and VMAs. Upcoming
changes will check additional, more obscure places.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Now that we enable CONFIG_VIRTIO_BLK in our kconfig, there's no need to
use a loop device. Configure a virtio-blk device in vmtest.vm so that
the block helper tests have a disk to test with.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
We don't allow this because "value objects with a scalar type cannot be
reinterpreted, as their memory layout in the program is not known". That
doesn't really make sense: we already support reconstructing the
in-memory representation with drgn_object_read_bytes().
Implement this by making drgn_object_slice() support slicing all
objects, using drgn_object_read_bytes() when necessary, then make
drgn_object_reinterpret() a trivial wrapper around it.
Closes#378.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Just like we have the higher-level for_each_vma() on top of
mt_for_each(). For now, it only does a point query. We may want to
extend it to allow for range queries like the kernel's vma_iterator.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
To simplify converting helpers to allow omitting the prog argument, add
a couple of decorators that take care all of the messy details.
@takes_program_or_default is based on an example from Stephen Brennan,
and the rest handle progressively more complex calling conventions.
Also update drgndoc to be aware of these decorators and add some
boilerplate to the generated documentation.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Some feedback that I've gotten that resonated with me was that it feels
silly and too verbose to always pass prog to helpers, like
for_each_task(prog), find_task(prog, pid), etc. Passing prog makes sense
from the library point of view, but it's not great for interactive
usability. And even when you include usage as a library, the vast
majority of use cases only need one program.
So, let's introduce the concept of the "default program". It has a
getter (get_default_prog()) and a setter (set_default_prog()). The CLI
sets it automatically. Library users can do it manually if they want to.
It is a per-thread setting.
Upcoming commits will update all of our helpers and functions that take
a Program to make it optional and default to the default program.
P.S. This was inspired by asyncio, which has many interfaces that take
an optional loop parameter but default to the current loop. Cf.
asyncio.get_event_loop() and asyncio.set_event_loop().
Signed-off-by: Omar Sandoval <osandov@osandov.com>
This is for upcoming tests using the
unittest.mock.Mock.assert_called_with() family of functions, which
compares with ==.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Require exact type matches, not subclasses, and fail hard for types we
don't explicitly handle. This caught one place where we weren't testing
what we thought we were.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
There's no reason to go through the trouble of checking the task_struct
if we were given a PRSTATUS note; it must be a thread that was running
at the time of the core dump. Refactor drgn_get_initial_registers() so
that we can use PRSTATUS earlier.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Maple trees have been around and used for VMAs for almost a year now
(since Linux 6.1). Finally add helpers and tests for them.
Closes#261.
Signed-off-by: Omar Sandoval <osandov@osandov.com>