Commit Graph

1321 Commits

Author SHA1 Message Date
Omar Sandoval
ad119cc1a6 libdrgn: ppc64: fix fallback unwinding
Reading the ABI specification, I realized that fallback_unwind_ppc64()
is completely wrong. Fix it.

Fixes: eec67768aa ("libdrgn: replace elfutils DWARF unwinder with our own")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-06-25 22:39:30 -07:00
Omar Sandoval
deabe2cb56 libdrgn: register_state: add and use drgn_register_state_get_u64()
This factors out some boilerplate for getting registers as a uint64_t.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-06-25 22:39:30 -07:00
Omar Sandoval
0a7849d791 libdrgn: rename drgn_register_state_set_from_integer() -> from_u64()
This is for consistency with drgn_register_state_get_u64() that we're
about to add.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-06-25 22:39:30 -07:00
Omar Sandoval
cbdf6094b7 libdrgn: ppc64: fix DWARF link register confusion
The usage of the link register in DWARF is a little confusing. On entry
to a function, the link register contains the address that should be
returned to. However, for DWARF, the link register is usually used as
the CFI return_address_register, which means that in an unwound frame,
it will contain the same thing as the program counter. I initially
thought that this was a mistake, believing that the link register should
contain the _next_ return address. However, after a return (with the blr
instruction), the link register will indeed contain the same address as
the program counter. This is consistent with our documentation of
register values for function call frames: "the register values are the
values when control returns to this frame".

So, rename our internal "ra" register to "lr", expose it to the API, and
add a little more documentation to the ppc64 initial register code.

Fixes: 221a218704 ("libdrgn: add powerpc stack trace support")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-06-25 22:39:30 -07:00
Omar Sandoval
49ae42ccfd libdrgn: x86-64: add a few more register definitions
In additional to the general-purpose registers, struct pt_regs also
provides the cs and ss segment registers and the rflags register.
elf_gregset_t provides the other segment registers as well. We should
expose all of those.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-06-25 22:39:30 -07:00
Omar Sandoval
33d14f7703 libdrgn: rework architecture definition files
Currently, register definitions are split across two files:
arch_foo.defs lists the names of registers, and arch_foo.c defines the
layout used to store registers in memory. The main rationale for this
was that the layout could be processed entirely by the C preprocessor,
but the register names needed an AWK script that we wanted to keep
minimal. But since commit af6f5a887d ("libdrgn: replace gen_arch.awk
with gen_arch_inc_strswitch.py"), arch_foo.defs is processed by a Python
script.

Let's define both the register names and the register layout in a new
file, arch_foo_defs.py, which is processed by gen_arch_inc_strswitch.py
This has a few benefits:

* It puts all of the register definitions for an architecture in one
  place.
* It is easier to maintain than preprocessor magic. (It also makes it
  trivial to support registers that don't exist in DWARF, which would've
  been harder to do with our preprocessor code.)
* It gets rid of our DSL in favor of Python (which also lets us reduce
  repetition for the ppc64 definitions).

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-06-25 22:39:26 -07:00
Omar Sandoval
5681b99c3a libdrgn: remove unused struct drgn_register::dwarf_number
This hasn't been used since commit eec67768aa ("libdrgn: replace
elfutils DWARF unwinder with our own").

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-06-24 09:17:56 -07:00
Omar Sandoval
42e37e72c1 libdrgn: stack_trace: fix byte order for drgn_stack_frame_register()
drgn_stack_frame_register() gets the register value with copy_lsbytes()
and then byte swaps it if the program's byte order is different from the
host's. But, copy_lsbytes() already fixes the byte order, so this ends
up with the original (wrong) byte order. We also don't need to zero out
the integer that we copy into since copy_lsbytes() also does that.

Fixes: eec67768aa ("libdrgn: replace elfutils DWARF unwinder with our own")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-06-24 09:17:56 -07:00
Logan Gunthorpe
bde8ab92c7 cli: Set path when importing a script
When running a python script with the drgn cli, an import of
a module in the current directory does not find that module.
This is surprising for regular python users.

According to the python documentation, sys.path is modified when
a script is passed on the command line:

  "If the script name refers directly to a Python file, the
   directory containing that file is added to the start of
   sys.path, and the file is executed as the __main__ module."

However, it does not set the path if the passed in script is a
zipfile. Use pkgutil.get_importer() to check if this is the case
and only add the path if it returns None.

Add the same operation in drgn so that importing modules from
the same directory as the script work as expected.

Link: https://docs.python.org/3/using/cmdline.html#using-on-interface-options
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
2022-06-23 13:49:10 -07:00
Omar Sandoval
05395422eb setup.py: add 5.19 to vmtest kernels
This needed the previous small update to
tests.linux_kernel.test_debug_info.TestModuleDebugInfo.
tests.linux_kernel.helpers.test_tc.TestTc will also only work with
pyroute2 >= 0.6.10 (see svinota/pyroute2#899). No changes needed to drgn
itself.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-06-09 14:35:01 -07:00
Omar Sandoval
0eccc61b30 tests: fix kernel module debug info test on v5.19
Linux kernel commit a0e286b6a5b6 ("loop: remove lo_refcount and avoid
lo_mutex in ->open / ->release") (in v5.19-rc1) removed the lo_open
symbol that we use for
tests.linux_kernel.test_debug_info.TestModuleDebugInfo. Replace it with
a symbol from the test kernel module so we don't need to worry about it
going away.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-06-09 14:27:19 -07:00
Omar Sandoval
a000eed8f4 vmtest: kbuild: add scripts/check-local-export to module build files
Linux kernel commit 31cb50b5590f ("kbuild: check static EXPORT_SYMBOL*
by script instead of modpost") (in v5.19-rc1) added this script to the
build process, and the latest vmtest kernel build failed without it.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-06-06 02:08:23 -07:00
Omar Sandoval
ebfcabd5a8 libdrgn: linux_kernel: match explicitly-reported kernel modules by build ID
Currently, we identify explicitly-reported kernel modules by the module
name that we get from the .modinfo or the .gnu.linkonce.this_module
section. However, objcopy --only-keep-debug (used for some Linux distro's
separate debug files) does not keep these sections. This means that
passing a file processed by objcopy --only-keep-debug to, e.g., drgn -s,
fails with "could not find kernel module name".

Instead of using the module name as the identifier, let's use the
module's GNU build ID. We can get it on a live system from
/sys/module/<module>/notes/, and on a core dump from struct
module::notes_attrs (which is the implementation of that sysfs
directory).

This was split out of my larger debug info discovery rework, which will
make more use of the build ID.

Closes #178.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-06-01 14:21:12 -07:00
Omar Sandoval
c9265ef6d6 libdrgn: move alloc_or_reuse() to util.h
Preparation for using it elsewhere. Also make it take a size_t instead
of uint64_t.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-06-01 05:11:58 -07:00
Omar Sandoval
3595c81a8c libdrgn: binary_search_tree: move member and entry_to_key to DEFINE_BINARY_SEARCH_TREE_FUNCTIONS()
DEFINE_BINARY_SEARCH_TREE_TYPE() doesn't need these. This is preparation
for a potential new use of a BST. But, it's also a good cleanup on its
own and allows us to move some code out of memory_reader.h and into
memory_reader.c. (This is similar to commit 1339dc6a2f ("libdrgn:
hash_table: move entry_to_key to DEFINE_HASH_TABLE_FUNCTIONS()").)

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-24 15:26:39 -07:00
Omar Sandoval
931d9c999d libdrgn: linux_kernel: get module address range directly
Instead of getting the address range from the sections we find, get it
directly from /proc/modules or from the `struct module`. (We already had
partial code to get the address range, but I can't remember why I didn't
use it.)

The real motivation for this is the upcoming module rework: it'll allow
us to report the module and its address range before iterating through
its sections. But it also means that we don't need the heuristic to
ignore special sections that shouldn't be considered part of the address
range (e.g., .init, .data..percpu [the latter of which we should be
ignoring but get away with not because it's excluded from sysfs]).

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-23 16:27:49 -07:00
Omar Sandoval
7bbe0bc1c6 libdrgn: add drgn_error_dwrite()
Like drgn_error_fwrite(), but writes to a file descriptor instead of a
stdio stream. This will be used for logging.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-23 11:09:10 -07:00
Omar Sandoval
09ee4daed3 libdrgn: fix drgn_error_fwrite() for DRGN_ERROR_FAULT
drgn_error_fwrite() only calls string_builder_append_error() to get
special formatting for DRGN_ERROR_OS, but DRGN_ERROR_FAULT also needs
special formatting. Rather than needing to keep drgn_error_fwrite() and
string_builder_append_error() in sync, define them both in terms of a
common macro.

Fixes: 80fef04c70 ("Add address attribute to FaultError exception")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-23 11:08:54 -07:00
Omar Sandoval
32687f8f9c helpers: fix slab_cache_for_each_allocated_object() on Linux < 5.17
I forgot to account for the page -> slab rename.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-20 15:48:01 -07:00
Omar Sandoval
1d766c4e34 vmtest: kbuild: add CONFIG_SLAB_FREELIST_HARDENED=y to kernel config
Since most Linux distros enable this, we should make sure we test it. It
was added for SLUB in Linux kernel commit 2482ddec670f ("mm: add SLUB
free list pointer obfuscation") (in v4.14), so we'll still get test
coverage of the non-hardened codepath while 4.9 is around.

It was also added for SLAB in Linux kernel commit 3404be67bf73
("mm/slab: expand CONFIG_SLAB_FREELIST_HARDENED to include SLAB") (in
v5.9), although that currently doesn't change the in-memory data
structures.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-20 15:33:18 -07:00
Omar Sandoval
1e2ba05059 vmtest: kbuild: exclude .cmd files from package
The include directories contain these dependency files for generated
header files.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-20 15:22:05 -07:00
Omar Sandoval
200d7eb80c helpers: fix slab_cache_for_each_allocated_object() with CONFIG_SLAB_FREELIST_HARDENED
Most Linux distros (I checked Fedora, Debian, and Arch) enable this,
which requires us to de-obfuscate the pointers in the freelist.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-20 15:16:45 -07:00
Omar Sandoval
57320ac181 helpers: add documentation for rbtree validators
This wasn't added by mistake.

Fixes: 243abf59e5 ("helpers: add red-black tree validators")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-18 17:40:04 -07:00
Omar Sandoval
34dfaabb2d helpers: add slab_cache_is_merged() to __all__
Fixes: cb3bb6cc2b ("helpers: add slab cache merging helper and documentation")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-18 17:32:12 -07:00
Omar Sandoval
bc582b8a58 drgn 0.0.19
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-18 13:57:02 -07:00
Omar Sandoval
1c8ed7189a setup.py: run local tests even if there are no kernels to test
The previous commit broke this.

Fixes: 8c7eb701bd ("setup.py: group test logs on GitHub Actions")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-18 10:12:51 -07:00
Omar Sandoval
8c7eb701bd setup.py: group test logs on GitHub Actions
The test logs on GitHub Actions are getting pretty big. GitHub Actions
has a workflow command that can be used to group log lines together:
https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#grouping-log-lines.
Use it when running tests to make the logs easier to peruse.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-17 16:10:04 -07:00
Omar Sandoval
1c0dbcd917 pre-commit: add flake8
This has been useful to run manually before, but I haven't added it to
the CI because it was somewhat noisy. But, it reports some really useful
warnings, so let's configure it for our needs and add it to pre-commit.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-17 15:26:41 -07:00
Omar Sandoval
a3b72e33c8 Fix some more flake8 errors
Several have snuck in since the last time I did this in commit
5541fad063 ("Fix some flake8 errors"). Prepare for adding flake8 to
pre-commit by fixing them.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-17 15:23:42 -07:00
Omar Sandoval
c4220f21cd tests: move Linux kernel helper tests under tests/linux_kernel
Splitting the tests between tests/linux_kernel and tests/helpers/linux
means that we have to set up the unit tests twice, including loading
debug info. Python 3.7 and newer have a way to get around this, but
we're still sort of supporting Python 3.6. Move them under one path to
speed up test runs.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-17 14:20:34 -07:00
Omar Sandoval
243abf59e5 helpers: add red-black tree validators
This one is considerably more complicated than the linked list one, but
it should catch lots of kinds of red-black tree mistakes.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-17 14:20:34 -07:00
Omar Sandoval
9ae36fd12e helpers: add validators, starting with linked lists
At LSF/MM+BPF 2022, Ted Ts'o pitched me the idea of using drgn to
validate the consistency of kernel data structures. I really liked this
idea, especially for big, complicated data structures. But first, let's
start small: document the concept of a "validator", which is just a
special kind of helper, and add some basic validator versions of linked
list helpers.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-17 14:20:16 -07:00
Omar Sandoval
4a6b499811 helpers: add RB_EMPTY_ROOT to __all__
Fixes: 755f79012e ("helpers: add RB_EMPTY_ROOT")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-17 13:58:41 -07:00
Omar Sandoval
053b9da325 tests: use test kernel module for slab_cache_for_each_allocated_object() test
The current test case for slab_cache_for_each_allocated_object() is
barely more than a smoke test. It missed the bug fixed by the previous
commit. Now that we have the test kernel module, we can do a lot better
by comparing against the exact list of objects that are allocated.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-16 16:50:38 -07:00
Omar Sandoval
c936b699eb helpers: fix slab_cache_for_each_allocated_object() to check per-CPU caches
SLUB and SLAB both have a mechanism where they'll remove some objects
from the per-slab freelist to keep them in a per-CPU cache. SLUB's is a
per-CPU freelist just like the per-slab one, and SLAB's is a per-CPU
array of free entries. We're not checking those lists, which means that
we're returning free objects as allocated. Fix it by checking against
the per-CPU lists in addition to the per-slab freelist.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-16 16:50:30 -07:00
Omar Sandoval
5ca063b921 setup.py: add option to test all kernel flavors
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-16 16:47:35 -07:00
Omar Sandoval
755f79012e helpers: add RB_EMPTY_ROOT
We couldn't test this before, but now that we can we might as well add
it.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-16 16:47:35 -07:00
Omar Sandoval
3b9fb8bfb0 tests: use test kernel module for Linux rbtree helper tests
Just like we did for lists, use a test data structure instead of the vma
tree for a process. This also allows us to test RB_EMPTY_NODE, which we
couldn't test before.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-16 16:47:35 -07:00
Omar Sandoval
a9815bb287 tests: add test cases for Linux hlist helpers
We didn't have a good target for these tests before, but with the test
module, it's easy now.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-16 16:47:35 -07:00
Omar Sandoval
042c98be4a tests: use test kernel module for Linux list helper tests
Rather than picking a couple of lists which we hope won't change, use
the newly added test kernel module to define a few lists and test
against those. This also gives us proper tests for list_is_singular().

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-16 16:47:31 -07:00
Omar Sandoval
6a3dcad19b tests: add framework for test kernel module
Now that commit d999703f94 ("vmtest: add kernel module build
dependencies to kernel packages") added the files necessary to build a
test kernel module, add the module (currently a stub) and the
scaffolding necessary to build and load it.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-16 14:27:35 -07:00
Omar Sandoval
8afa7ea6d8 Remove vmtest/config from MANIFEST.in
This was removed in commit 841a3dae88 ("Move vmtest assets to GitHub
releases").

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-13 16:41:33 -07:00
Omar Sandoval
d999703f94 vmtest: add kernel module build dependencies to kernel packages
We have several helpers that are difficult to test because there are no
userspace APIs to test them against. Radix trees, slab objects, and
hlists are a few examples. For lists and rbtrees, luckily we can find
instances of those data structures exposed to userspace in some way, but
this is somewhat brittle.

We'd like a way to be able to unit test directly against kernel code
that sets things up in a way that is easy to test against. The easiest
way to do this is with a custom kernel module.

There are two options for how to enable this:

1. Build the custom kernel module as part of the vmtest kernel build and
   package it with the vmtest kernel package.
2. Include the artifacts needed for kernel module builds in the vmtest
   kernel package, then build the kernel module when running tests.

The latter makes the kernel packages significantly larger (on a build of
v5.18-rc6, 46M -> 53M compressed, 173M -> 217M decompressed), but it has
the huge advantage that it does not require a vmtest kernel rebuild to
add or modify tests. In order to optimize for making it easy to add new
helpers with test cases, this is the approach I chose.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-13 11:05:45 -07:00
Omar Sandoval
80e5cc52ae vmtest: manage: add option to not build anything
Now `python3 -m vmtest.manage -K --no-build` can be used to get the list
of latest kernel releases that need to be built. Also rename --dry-run
to --no-upload since --no-build is also a dry run in a way.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-12 13:25:14 -07:00
Omar Sandoval
cb3bb6cc2b helpers: add slab cache merging helper and documentation
Slab cache merging can cause major confusion when debugging using slab
cache helpers. Add a helper to detect whether a slab cache is merged and
an explanation of the implications.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-09 16:27:24 -07:00
alexlzhu
5c66aab23f helpers: add helpers for iterating over allocated slab objects
These are ported from https://github.com/josefbacik/debug-scripts.

Signed-off-by: alexlzhu <alexlzhu@fb.com>
[Omar: make test case check for exception on SLOB]
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-09 16:05:16 -07:00
Omar Sandoval
f3f51942e2 docs: document that StackFrame.name requires debugging information
And how to get a reasonable name for, e.g., functions implemented in
assembly.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-05-05 08:22:34 -07:00
Omar Sandoval
a541e9b170 libdrgn: support reference and absent objects with >64-bit integer types
GCC and Clang have 128-bit integer types on 64-bit targets: __int128 and
unsigned __int128. Clang additionally has N-bit integers of up to 2<<24
bits with _ExtInt(N), which was standardized in C23 as _BitInt(N).

Currently, we disallow creating objects with a >64-bit integer type. Jay
Kamat reported that this would cause errors when examining some
binaries. The reason we disallow this is that we don't have a way to
represent or do operations on >64-bit values. We could make use of a
bignum library like GMP to do this in the future.

However, for now, we can loosen this restriction and at least allow
reference and absent objects with big integer types. This requires
enforcing two things: that we never create a value object with a >64-bit
integer type, and that we never read the value of a reference object
with a >64-bit integer type.

Co-authored-by: Jay Kamat <jaygkamat@gmail.com>
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-04-28 13:38:38 -07:00
Omar Sandoval
084e636341 libdrgn: add DRGN_ERROR_NOT_IMPLEMENTED
This will be used for partial 128-bit object support. There are other
places that should probably be converted to use it.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-04-28 13:38:38 -07:00
Omar Sandoval
ad7e64d9d8 libdrgn: make memdup() take a const void *
Just like strdup(), memdup() doesn't modify the thing it's copying, so
mark it const.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-04-27 00:37:46 -07:00