Extract for_each_set_bit() that was added internally for the cpumask and
nodemask helpers, and add for_each_clear_bit() and test_bit() to go with
it.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
The API reference has all of the details, but add a short example to the
user guide (and move it before symbols, as stack traces are probably
more interesting/important).
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Add an example of stack traces and parameters/local variables and use
some more interesting helpers.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Commit a97f6c4fa2 ("Associate types with program") changed repr() for
drgn.Type to include a "prog." prefix, but it didn't update the
documentation to reflect that. It also forgot to update a global type
constructor to the new Program methods.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Sometimes we want to traverse numa nodes in the system,
so add kernel nodemask helpers to support this.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Add a way to create an object from raw bytes. One example where I've
wanted this is creating a struct pt_regs from a PRSTATUS note or other
source.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
If the kernel is compiled with CONFIG_CPUMASK_OFFSTACK, then the full
struct cpumask::bits array may not be allocated. Use nr_cpu_ids as the
limit instead of the length of the array.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
These were added in DWARF 5. They need to know the CU that they're being
evaluated in, but the parameters for drgn_eval_dwarf_expression() were
already getting unwieldy. Wrap the evaluation context in a new struct
drgn_dwarf_expression_context, add the additional CU information, and
implement the operations.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
The main changes are:
1. Skipping the new attribute forms.
2. Handling DW_FORM_strx*, DW_FORM_line_strp, and DW_FORM_implicit_const
for the attributes that we care about.
3. Parsing the new unit header format.
4. Parsing the new line number program header format.
Note that Clang currently produces an incorrect DWARF 5 line number
program header for the Linux kernel (https://reviews.llvm.org/D105662),
so some types are not properly deduplicated in that case.
Closes#104.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
dwfl_module_getsrc() relies on .debug_aranges to find the CU containing
the PC. If the module has a missing or incomplete .debug_aranges, it
fails. This lookup is actually redundant since we already found the CU
when we unwound the stack. Use the libdw helpers that take the CU DIE
instead to avoid this. We also need to save the CU for frames where we
found it but couldn't find the subprogram (typically assembly files).
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Clang does not generate .debug_aranges by default, but the GNU toolchain
does. This means that a Linux kernel binary compiled with Clang and GNU
binutils will have ranges in .debug_aranges for assembly files and
nothing else. This breaks our assumption that a non-empty .debug_aranges
has ranges for every compilation unit. Fix it by always falling back to
checking every CU if a range was not found in .debug_aranges.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
LEB128 allows for redundant zero/sign bits, but we currently always
treat extra bytes as overflow. Let's check those bytes correctly.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Somehow I missed this form, and I've never seen it used. It's the same
as DW_FORM_exprloc for our purposes, so it's an easy fix.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
There are a few places in the DWARF indexing code that we skip a 64-bit
size. On 32-bit systems, this can wrap if the count is greater than
SIZE_MAX. Rather than requiring vigilance against this, change the size
to uint64_t.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Older versions of GCC and Clang don't accept const variables for
initializers ("error: initializer element is not constant"), so #define
the FNV constants instead.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
We currently don't include the compilation directory when hashing file
names for deduplication. This can cause us to incorrectly deduplicate a
definition if, for example, two libraries have a definition with the
same name in files with the same name. Fix this by hashing the full file
path including the compilation directory.
This also requires reworking our strategy for path normalization to
better handle ".." components, since directories may end up outside of
the compilation directory. The new strategy keeps a linked list of
hashes (now FNV-1a instead of SipHash) for each parent directory. This
is actually more efficient than the previous approach, offsetting the
cost of the extra hash computations for the compilation directory. It
also correctly handles file names in the line number program header
which consist of multiple components.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
I missed the drgn_program_set_kdump() code path when making sure that we
set the platform before adding memory segments.
Fixes: 0e3054a0ba ("libdrgn: make addresses wrap around when reading memory")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
This workaround was originally present in commit e5874ad18a ("libdrgn:
use libdwfl"). We dropped in in commit 6a13d74c0c ("libdrgn: build
with bundled elfutils") because the bundled version of elfutils had the
fix. We forgot to bring it back in commit 4c5c5f3842 ("Remove bundled
version of elfutils") even though we support versions without the fix.
Reported-by: Serapheim Dimitropoulos <serapheim@delphix.com>
Signed-off-by: Omar Sandoval <osandov@osandov.com>
copy_lsbytes() doesn't copy enough bytes when copying from a smaller
little-endian value to a larger big-endian value. This was caught by the
test cases for DW_OP_deref{,_size}, but it can affect other places when
debugging a little-endian target from a big-endian host or vice-versa.
Closes#105.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
The stack trace variable work introduced a regression that causes
objects with size zero to always be marked absent even if they have an
address. This matters because GCC sometimes seems to omit the complete
array type for arrays declared without a length, so an array variable
can end up with an incomplete array type. I saw this with the
"swapper_spaces" variable in mm/swap_state.c from the Linux kernel.
Make sure to use the address of an empty piece if the variable is also
empty.
Fixes: ffcb9ccb19 ("libdrgn: debug_info: implement creating objects from DWARF location descriptions")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
drgn depends heavily on libelf and libdw, so it's useful to know what
version we're using. Add drgn._elfutils_version and use that in the CLI
and in the test cases where we currently check the libdw version.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
After all of the preparatory work, the last two missing pieces are a way
to find a variable by name in the list of scopes that we saved while
unwinding, and a way to find the containing scopes of an inlined
function. With that, we can finally look up parameters and variables in
stack traces.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
If we want to access a parameter or local variable in an inlined
function, then we need a stack frame for that function. It's also much
more useful to see inlined functions in the stack trace in general. So,
when we've unwound the registers for a stack frame, walk the debugging
information to find all of the (possibly inlined) functions at the
program counter, and add a drgn stack frame for each of those.
Also add StackFrame.name and StackFrame.is_inline so that we can
distinguish inline frames. Also add StackFrame.source() to get the
filename and line and column numbers. Finally, add the source code
location to pretty-printed stack traces and add pretty-printing for
individual stack frames that includes extra information.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
This will be used for finding the ancestors of the abstract instance
root corresponding to a concrete inlined instance root for variable
lookups in inlined functions.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
This will be used for finding functions, inlined functions, and blocks
containing a PC for stack unwinding and variable lookups.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
We have a couple of upcoming use cases for iterating through all of the
DIEs in a module: searching for scopes and searching for a DIE's
ancestors. Add a DIE iterator interface to abstract away the details of
walking DIEs and allows us to efficiently track ancestors.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Add support for evaluating a DWARF location description and translating
it into a drgn object. In this commit, this is just used for global
variables, but an upcoming commit will wire this up to stack traces for
parameters and local variables.
There are a few locations that drgn's object model can't represent yet.
DW_OP_piece/DW_OP_bit_piece can describe objects that are only partially
known or partially in memory; we approximate these where we can. We
don't have a good way to support DW_OP_implicit_pointer at all yet.
This also adds test cases for DWARF expressions, which we couldn't
easily test before.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Implement looking up location descriptions and evaluating DW_OP_fbreg.
This isn't actually used yet since CFI expressions don't have a current
function DIE, but it will be used for parameters/local variables in
stack traces.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
It doesn't make a difference anywhere it's currently used, but let's do
it just in case that changes in the future.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
A malformed DWARF expression can easily get us into an infinite loop.
Avoid this by capping the number of operations that we'll execute.
Signed-off-by: Omar Sandoval <osandov@osandov.com>