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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>