Commit Graph

1428 Commits

Author SHA1 Message Date
Omar Sandoval
d7204eaa00 libdrgn: python: simplify path_converter()
PyUnicode_FSConverter() already handles os.PathLike, so we only need to
handle None and save the string and length.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-12-06 10:49:00 -08:00
Omar Sandoval
73fea86792 libdrgn: python: add PyLong_From* and PyLong_As* wrappers for stdint.h types
It feels icky to write code that, for example, passes a uint64_t to
PyLong_FromUnsignedLongLong(). In practice it's fine, but it's much
nicer to have conversion functions specifically for the stdint.h types.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-12-05 16:06:22 -08:00
Alastair Robertson
7180304c88 libdrgn: dwarf_info: Support DW_TAG_GNU_template_parameter_pack
This DWARF tag is used by C++ classes which take a variable number
of template parameters, such as std::variant and std::tuple.

Signed-off-by: Alastair Robertson <ajor@meta.com>
2022-12-05 15:33:46 -08:00
Omar Sandoval
220c1c72f5 drgn.helpers.common.stack: fix license identifier
This PR was started before the license change, so I missed updating it.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-12-02 14:46:44 -08:00
Omar Sandoval
32dc31aaca tests: fix rmmod of test kmod
Thanks to commit c08f6be52a ("vmtest: kbuild: add
CONFIG_MODULE_UNLOAD=y"), I was finally able to try unloading the test
kernel module and found a trivial copy-and-paste error. Fix it.

Fixes: 42e7d474d1 ("drgn.helpers.linux.mm: add compound page helpers")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-12-02 14:42:57 -08:00
Omar Sandoval
174b797ae3 libdrgn: platform: add documentation (especially for drgn_architecture_info)
While reviewing #214, I realized that we have very little documentation
for drgn_architecture_info (and platform internals in general). Let's
document all of the important stuff, and in particular how to add
support for new architectures.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-12-02 13:55:38 -08:00
Omar Sandoval
1088ef4a1e libdrgn: platform: replace demangle_return_address() with demangle_cfi_registers()
While documenting struct drgn_architecture_info, I realized that
demangle_return_address() is difficult to explain. It's more
straightforward to define this functionality as demangling any registers
that are mangled when using CFI rather than just the return address
register.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-12-02 13:52:06 -08:00
Omar Sandoval
7cb7ac0fc4 vmtest: kbuild: enable Btrfs, ext4, and XFS
For some upcoming helpers (#218), we're going to want to test against a
few common filesystems.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-12-01 17:47:19 -08:00
Omar Sandoval
845ac5fceb packit: temporarily work around examples directory
Packit is failing because the examples directory doesn't exist since
commit a0a54edc1f ("Create contrib directory"). Let's work around it
in our post-upstream-clone step until we cut the next release and update
the RPM spec.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-29 18:20:16 -08:00
Nhat Pham
05041423c7 drgn.helpers.common.stack: add print_annotated_stack helper function
This helper function shows the content of the stack trace, optionally
annotating each entry with the appropriate tag. Currently, it only
annotates symbols and slab cache objects.

Signed-off-by: Nhat Pham <nphamcs@gmail.com>
2022-11-29 17:08:30 -08:00
Nhat Pham
2a27cfb918 Add missing type annotations for StackTrace dunder methods
StackTrace supports __len__() and __iter__(), but they aren't annotated.
Add them.

Fixes: 80c9fb35ff ("Add type hint stubs and generate documentation from them")
Signed-off-by: Nhat Pham <nphamcs@gmail.com>
2022-11-29 17:08:30 -08:00
Omar Sandoval
0fad8a591a libdrgn: fix finding types beginning in size_t or ptrdiff_t
c_parse_specifier_qualifier_list() checks whether an identifier starts
with "size_t" or "ptrdiff_t" to decide whether to return the size_t or
ptrdiff_t type. This incorrectly matches stuff like like "size_tea" and
"ptrdiff_tee". Fix this by making it an exact comparison.

Fixes: 75c3679147 ("Rewrite drgn core in C")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-28 16:21:56 -08:00
Omar Sandoval
18b12a5c7b libdrgn: get .eh_frame from the correct file
We're currently getting .eh_frame from the debug file. However, since
.eh_frame is an SHF_ALLOC section, it is actually in the loaded file,
and may not be in the debug file. This causes us to fail to unwind in
modules whose debug file was created with objcopy --only-keep-debug
(which is typical for Linux distro debug files).

Fix it by getting .eh_frame from the loaded file. To make this easier,
we split .eh_frame and .debug_frame data into two separate tables. We
also don't bother deduplicating them anymore, since GCC and Clang only
seem to generate one or the other in practice.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-28 13:37:29 -08:00
Omar Sandoval
270375f077 libdrgn: debug_info: get "loaded" ELF file
For upcoming changes, we will need loaded (SHF_ALLOC) sections for
modules. Some separate debug files (e.g., those created with objcopy
--only-keep-debug) don't have those sections. Let's get the loaded file
from libdwfl with dwfl_module_getelf() and save it in a struct
drgn_elf_file.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-28 13:37:29 -08:00
Omar Sandoval
bcb53d712b libdrgn: bypass libdwfl with struct drgn_elf_file
Now that we track the debug file ourselves, we can avoid calling libdwfl
in a bunch of places. By tracking the bias ourselves, we can avoid a
bunch more.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-28 13:37:29 -08:00
Omar Sandoval
34f122144a libdrgn: debug_info: wrap ELF file information in new struct drgn_elf_file
struct drgn_module contains a bunch of information about the debug info
file. Let's pull it out into its own structure, struct drgn_elf_file.
This will be reused for the "main"/"loaded" file in an upcoming change.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-28 13:37:29 -08:00
Omar Sandoval
b3bab1c5b0 libdrgn: make module vs. program platform difference more clear
It's confusing that we have a platform both for the program and for each
module. They usually match, but they're not required to. For example,
the user can manually add a file with a different platform just to read
its debug info. Our rule is that if we're parsing anything from the
module, we use the module platform; and otherwise, use the program
platform. There are a couple of places where the platforms must match:
when using call frame information (CFI) or registers. Let's make all of
this more clear in the code (by using the module's platform even when it
must match the program's platform) and in comments. No functional
change.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-28 12:53:45 -08:00
Omar Sandoval
85f423dfb8 libdrgn: dwarf_info: get default pointer size from CU
If a DW_TAG_pointer_type DIE doesn't specify its size with
DW_AT_byte_size, we currently default to the program's address size.
However, the DWARF we're parsing could be for a platform with a
different address size. It's more correct to use the CU's address size.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-28 12:53:45 -08:00
Omar Sandoval
222680b47a Add StackFrame.sp
We have some generic helpers that we'd like to add (for example, #210)
that need to know the stack pointer of a frame. These shouldn't need to
hard-code register names for different architectures. Add a generic
shortcut, StackFrame.sp.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-22 18:47:16 -08:00
Omar Sandoval
cefe76bc3e contrib: make lsmod.py handle CONFIG_MODULE_UNLOAD=n
This is a nice example for Type.has_member().

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-22 10:25:13 -08:00
Omar Sandoval
344facf0b7 vmtest: build with Ubuntu 20.04
Building the test kernel module is failing in the CI with:

  ./tools/objtool/objtool: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by ./tools/objtool/objtool)
  ./tools/objtool/objtool: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by ./tools/objtool/objtool)

This is because we're building the kernel with Ubuntu 22.04 and building
the test kernel module on Ubuntu 20.04, and 22.04's glibc is newer than
20.04.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-21 11:59:28 -08:00
Omar Sandoval
c08f6be52a vmtest: kbuild: add CONFIG_MODULE_UNLOAD=y
I currently have no idea whether the test kmod can actually unload
successfully because the vmtest kernels don't support unloading modules.
It might also be useful to test unloading other modules in the future.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-21 11:59:21 -08:00
Omar Sandoval
eac49edf79 CI: pin to Ubuntu 20.04
ubuntu-latest was just bumped to Ubuntu 22.04, and actions/setup-python
doesn't package Python 3.6 for Ubuntu 22.04. I'd love to drop Python 3.6
support, but some enterprise distros (e.g., CentOS 8) are still on 3.6.
So, for now, let's stay on Ubuntu 20.04 so that we can keep testing
Python 3.6.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-21 11:21:22 -08:00
Omar Sandoval
375fee8d85 setup.py: add 6.1 to vmtest kernels
No changes are required.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-21 01:17:13 -08:00
Omar Sandoval
818da5b890 CI: add Python 3.11
Python 3.11 was released in October. No changes to drgn are required.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-21 01:15:00 -08:00
Omar Sandoval
fefa613a69 drgn.helpers.common.memory: add more slab object information to identify_address()
Now that we have slab_object_info(), use it to identify the offset of an
address in a slab object and whether the object is allocated.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-21 01:12:31 -08:00
Omar Sandoval
c38801fc10 drgn.helpers.linux.slab: add slab_object_info()
find_containing_slab_cache() is very useful, but there are two
additional pieces of information I've found myself wanting: the offset
of the pointer in the slab object and whether the slab object is
allocated or free. Add a new helper, slab_object_info(), which provides
that information.

The implementation was a challenge because we want to share as much code
as we can between slab_object_info() and
slab_cache_for_each_allocated_object(), but there are a multitude of
slab allocator configuration options and version differences requiring
unique handling. Stephen Brennan provided some code that I stole several
ideas from.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-21 01:04:18 -08:00
Omar Sandoval
a0a54edc1f Create contrib directory
It's come up several times that it'd be nice to have somewhere to dump
drgn scripts that people write while debugging without requiring them to
be cleaned up and scrutinized in code review. Serapheim Dimitropoulos
noted that several projects have a "contrib" directory for this purpose.
See [1]. Let's create one, document it, exclude it from pre-commit, and
move our (mostly unmaintained) examples there.

1: https://drewdevault.com/2020/06/06/Add-a-contrib-directory.html

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-16 13:17:50 -08:00
Omar Sandoval
a45603a884 tests: use test kmod for more stack trace tests
Rather than the fuzzy guesses we do with a task in sigwait, take
Stephen's idea from commit 5f3a91f80d ("Add StackFrame.locals()
method") further and use the test kmod to set up some precise stack
frames that we can test. Also use kthread_park() to make sure we can't
race with the thread not being scheduled out (unlikely as that may be).

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-06 23:24:22 -08:00
Boris Burkov
c8ff8728f7 Support systems without qsort_r
qsort_r is a non-standard glibc extension and turns out to be the only
thing that prevents drgn from working on a musl system. "Fix" the use of
qsort_r by switching it to qsort with a thread local variable for the
parameter.

Tested in a clean chroot install of musl voidlinux.

Signed-off-by: Boris Burkov <boris@bur.io>
2022-11-03 12:57:55 -04:00
Omar Sandoval
8eaf01fe83 Bring back COPYING
Some things want this file to exist (e.g., the Fedora RPM spec, GitHub;
see #221). Let's do what the Linux kernel does and provide a summary of
the licensing situation in COPYING. The REUSE FAQ [1] doesn't discourage
this.

1: https://reuse.software/faq/#tradition

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-02 22:57:40 -07:00
Stephen Brennan
5f3a91f80d Add StackFrame.locals() method
The StackFrame's __getitem__() method allows looking up names in the
scope of a stack frame, which is an incredibly useful tool for
debugging. However, the names are not discoverable -- you must already
be looking at the source code or some other source to know what names
can be queried. To fix this, add a locals() method to StackFrame, which
lists names that can be queried in the scope. Since this method is named
locals(), it stops at the function scope and doesn't include globals or
class members.

Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
2022-11-02 22:40:33 -07:00
Omar Sandoval
b3a5051ff4 libdrgn: dwarf_info: handle DW_TAG_enumerator DIE with missing or invalid DW_AT_name
find_dwarf_enumerator() needs to check that the return value of
dwarf_diename() is not NULL before calling strcmp(). This is similar to
commit 330c71b5b5 ("libdrgn: dwarf_info: fix segfault on anonymous
DIEs during scope search"), although I haven't seen this one happen in
practice.

Fixes: bc85767e5f ("libdrgn: support looking up parameters and variables in stack traces")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-02 22:19:44 -07:00
Omar Sandoval
4031093848 Add some missing copyright/license notices
I wanted to make REUSE pass, but I'm not sure what to do about trivial
files. REUSE suggests using CC0, but Fedora no longer allows CC0. I'll
punt that until later. For now, let's add notices to some code files.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-01 17:14:02 -07:00
Omar Sandoval
87b7292aa5 Relicense drgn from GPLv3+ to LGPLv2.1+
drgn is currently licensed as GPLv3+. Part of the long term vision for
drgn is that other projects can use it as a library providing
programmatic interfaces for debugger functionality. A more permissive
license is better suited to this goal. We decided on LGPLv2.1+ as a good
balance between software freedom and permissiveness.

All contributors not employed by Meta were contacted via email and
consented to the license change. The only exception was the author of
commit c4fbf7e589 ("libdrgn: fix for compilation error"), who did not
respond. That commit reverted a single line of code to one originally
written by me in commit 640b1c011d ("libdrgn: embed DWARF index in
DWARF info cache").

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-01 17:05:16 -07:00
Omar Sandoval
84b0c087d4 License tests/linux_kernel/kmod/drgn_test.c under GPL-2.0-or-later
According to
https://www.kernel.org/doc/html/latest/process/license-rules.html,
MODULE_LICENSE("GPL") means GPL version 2.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-01 16:57:00 -07:00
Omar Sandoval
41c02280e0 Use SPDX for docs/exts/setuptools_config.py
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-01 16:57:00 -07:00
Omar Sandoval
b156d987d7 Move license to LICENSES
In preparation for having multiple licenses.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-01 16:57:00 -07:00
Omar Sandoval
d465071651 libdrgn: replace copies of elfutils headers with generated files
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-01 15:41:53 -07:00
Omar Sandoval
99dc927f38 libdrgn: dwarf_info: rename dw_tag_str constants
Rename DW_TAG_{UNKNOWN_FORMAT,BUF_LEN} to
DW_TAG_STR_{UNKNOWN_FORMAT,BUF_LEN} to make it more clear that they're
for dw_tag_str.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-10-31 14:22:45 -07:00
Michel Alexandre Salim
120f766dc9 Update installation instructions
- add repology link
- add Debian and Ubuntu instructions

Signed-off-by: Michel Alexandre Salim <michel@michel-slm.name>
2022-10-28 16:09:57 -07:00
Omar Sandoval
a4ae67b6b5 libdrgn: replace BUILD_BUG_ON* with static_assert
Our container_of() and array_size() were copied from the Linux kernel
and use some really ugly BUILD_BUG_ON_ZERO() and BUILD_BUG_ON_MSG()
macros. C11 has _Static_assert, which is much nicer. We just have to
shoehorn it into an expression, which we do with clever use of _Generic
and sizeof a struct type definition. (We could accomplish the same idea
with a comma expression, but GCC warns when the left-hand operand of a
comma expression has no effect. We could also do it with a compound
statement, but it's cooler to do it with standard C11.)

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-10-28 13:38:35 -07:00
Stephen Brennan
369e2343c4 helpers: slab: Add get_slab_aliases()
When SLUB is in use, and the CONFIG_SYSFS is enabled (a very common
situation), we are able to identify which slab caches have been merged.
Provide a helper to expose this information so that users can lookup the
correct cache name, or identify all other caches which have been merged
with a given cache.

Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
2022-10-21 12:05:43 -07:00
Omar Sandoval
72f1db7968 drgn.helpers.linux.kconfig: clean up exception if CONFIG_IKCONFIG=n
get_kconfig() on a system with CONFIG_IKCONFIG=n produces a traceback like
this:

  >>> get_kconfig(prog)
  Traceback (most recent call last):
    File "/home/osandov/repos/drgn/drgn/helpers/linux/kconfig.py", line 40, in get_kconfig
      start = prog.symbol("kernel_config_data").address
  LookupError: could not find symbol with name 'kernel_config_data'

  During handling of the above exception, another exception occurred:

  Traceback (most recent call last):
    File "/home/osandov/repos/drgn/drgn/helpers/linux/kconfig.py", line 47, in get_kconfig
      kernel_config_data = prog["kernel_config_data"]
  KeyError: 'kernel_config_data'

  During handling of the above exception, another exception occurred:

  Traceback (most recent call last):
    File "<console>", line 1, in <module>
    File "/home/osandov/repos/drgn/drgn/helpers/linux/kconfig.py", line 49, in get_kconfig
      raise LookupError(
  LookupError: kernel configuration data not found; kernel must be compiled with CONFIG_IKCONFIG

The original exceptions are unnecessary noise; use raise ... from None to
suppress them so that it looks like this instead:

  >>> get_kconfig(prog)
  Traceback (most recent call last):
    File "<console>", line 1, in <module>
    File "/home/osandov/repos/drgn/drgn/helpers/linux/kconfig.py", line 49, in get_kconfig
      raise LookupError(
  LookupError: kernel configuration data not found; kernel must be compiled with CONFIG_IKCONFIG

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-10-18 16:25:14 -07:00
Omar Sandoval
e6f1aa563f tests: make get_kconfig() test case more thorough
Instead of just checking that CONFIG_IKCONFIG_PROC exists, let's parse
/proc/config.gz.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-10-18 16:23:02 -07:00
Omar Sandoval
fb554b32de cli: print nicer messages for common errors
Michel pointed out that running drgn with no arguments without sudo
prints a verbose error:

  $ drgn
  drgn 0.0.21 (using Python 3.10.8, elfutils 0.187, with libkdumpfile)
  Traceback (most recent call last):
    File "/usr/bin/drgn", line 33, in <module>
      sys.exit(load_entry_point('drgn==0.0.21', 'console_scripts', 'drgn')())
    File "/usr/lib/python3.10/site-packages/drgn/internal/cli.py", line 168, in main
      prog.set_kernel()
  PermissionError: [Errno 13] Permission denied: '/proc/kcore'

In fact, any errors that we get when initializing the drgn.Program
result in an ugly traceback. Let's print specific error messages for the
most common errors:

- Trying to debug the live kernel without root.
- Trying to debug a live process without ptrace attach permissions.

There are a lot of details for both of these that could use elaboration,
but that should probably go in the documentation.

Also format other common errors without the traceback.

Suggested-by: Michel Alexandre Salim <michel@michel-slm.name>
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-10-13 10:19:02 -07:00
Omar Sandoval
40f2d4b2aa drgn 0.0.21
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-10-12 12:00:54 -07:00
Omar Sandoval
7d286f15a9 tests: skip ORC unwinding test unless on x86-64
Only x86-64 has ORC, so it's a waste of time to run
tests.linux_kernel.test_stack_trace.TestStackTrace.test_by_pid_orc() on
other architectures.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-10-11 21:40:45 -07:00
Omar Sandoval
6cc41dbcf8 vmtest.vm: support running with root directory different from the host
This will be useful for testing different architectures (e.g., by
creating a rootfs with debootstrap) or different userspace environments.
For example, we can test busybox with something like:

  mkdir busyboxroot busyboxroot/bin busyboxroot/tmp
  cp "$(which busybox)" busyboxroot/bin
  busyboxroot/bin/busybox --install busyboxroot/bin
  python3 -Bm vmtest.vm -k '*' -r busyboxroot

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-10-11 16:13:10 -07:00
Omar Sandoval
9e5fb3ef08 vmtest.vm: don't set PYTHON
This is more appropriately done in the test command in setup.py.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-10-11 16:13:10 -07:00