We need to set the value after we've reinitialized the object, otherwise
drgn_object_deinit() may try to free a buffer that we've already
overwritten. This also adds a test which triggers the crash.
There's a bug that we don't allow comparisons between void * and other
pointer types, so let's fix it by allowing all pointer comparisons
regardless of the referenced type. Although this isn't valid by the C
standard, GCC and Clang both allow it by default (with a warning).
Commit 48c5f37d01 ("Make read_once() a method again, as
Object.read_()") mistakenly changed fs_inodes.py to a benchmark I was
running. Additionally, commit 393a1f3149 ("Document with Sphinx")
changed the for_each_mount() helper to only yield the struct mount *.
drgn has pretty thorough in-program documentation, but it doesn't have a
nice overview or introduction to the basic concepts. This commit adds
that using Sphinx. In order to avoid documenting everything in two
places, the libdrgn bindings have their docstrings generated from the
API documentation. The alternative would be to use Sphinx's autodoc
extension, but that's not as flexible and would also require building
the extension to build the docs. The documentation for the helpers is
generated using autodoc and a small custom extension.
I went back and forth on using setuptools or autotools for the Python
extension, but I eventually settled on using only setuptools after
fighting to get the two to integrate well. However, setuptools is kind
of crappy; for one, it rebuilds every source file when rebuilding the
extension, which is really annoying for development. automake is a
better designed build system overall, so let's use that for the
extension. We override the build_ext command to build using autotools
and copy things where setuptools expects them.
The declaration file name of a DIE depends on the compilation directory,
which may not always be what the user expects. Instead, make the search
match as long as the full declaration file name ends with the given file
name. This is more convenient and more intuitive.
Running tests with Clang's AddressSanitizer fails with "runtime error:
index 1 out of bounds for type 'struct drgn_type_member [0]'". Zero
length arrays are a GCC extension and aren't buying us much anyways, so
just add a helper function that gets the array payload using pointer
arithmetic.
If libelf or libdw are statically linked or not in the usual search
path, ctypes won't be able to find them. Add the required functions to
the wrappers in the libdrgn bindings so that we can easily find them.
Older versions of Clang generate a call to __muloti4() for
__builtin_mul_overflow() with mixed signed and unsigned types. However,
Clang doesn't link to compiler-rt by default. Work around it by making
all of our calls to __builtin_mul_overflow() use unsigned types only.
1: https://bugs.llvm.org/show_bug.cgi?id=16404
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
After using it a few times, this operation is more fundamental than the
read_once() function lets on: it converts an lvalue to an rvalue. Make
it a method again, but rename it to read_().
It's silly to have these trival factory methods. Instead, directly
construct with Object() and add a new NULL() function. We also
automatically import these in interactive mode.
Linux kernel commit 2c4704756cab ("pids: Move the pgrp and session pid
pointers from task_struct to signal_struct") in v4.19 changed the method
of mapping a struct pid back to a struct task_struct. The radix tree
data structure was also replaced by a new XArray data structure in
v4.20. Handle both of those changes.
The DIE generated by GCC for a zero-length array doesn't have a
DW_AT_upper_bound or DW_AT_count attribute; it looks identical to that
of a flexible array. See
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86985.
The semantics of zero-length and flexible arrays are slightly different
(see https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html), so there are
a few specific cases where replacing a zero-length array with a flexible
array creates an invalid type. We can tell when the type must have been
a zero-length array; in other cases, we will just assume the type is a
flexible array. This ambiguity will hopefully be fixed in a future
version of GCC.