Commit Graph

1101 Commits

Author SHA1 Message Date
Omar Sandoval
8a41adc1b0 libdrgn: language_c: add missing error check in c_parse_abstract_declarator()
Found with clang-static-analyzer.

Reported-by: Kevin Svetlitski <svetlitski@fb.com>
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-12-08 13:56:15 -08:00
Omar Sandoval
f09fd13ef6 libdrgn: helpers: add missing error check in linux_helper_pid_task()
Found with clang-static-analyzer.

Reported-by: Kevin Svetlitski <svetlitski@fb.com>
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-12-08 13:56:06 -08:00
Omar Sandoval
e6abfeac03 libdrgn: debug_info: report userspace core dump debug info ourselves
There are a few reasons for this:

1. dwfl_core_file_report() crashes on elfutils 0.183-0.185. Those
   versions are still used by several distros.
2. In order to support --main-symbols and --symbols properly, we need to
   report things ourselves.
3. I'm considering moving away from libdwfl in the long term.

We provide an escape hatch for now: setting the environment variable
DRGN_USE_LIBDWFL_REPORT=1 opts out of drgn's reporting and uses
libdwfl's.

Fixes #130.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-12-08 12:11:10 -08:00
Omar Sandoval
02912ca7d0 libdrgn: fix handling of p_filesz < p_memsz in core dumps
I implemented the case of a segment in a core file with p_filesz <
p_memsz by treating the difference as zero bytes. This is correct for
ET_EXEC and ET_DYN, but for ET_CORE, it actually means that the memory
existed in the program but was not saved. For userspace core dumps, this
typically happens for read-only file mappings. For kernel core dumps,
makedumpfile does this to indicate memory that was excluded.

Instead, let's return a DRGN_FAULT_ERROR if an attempt is made to read
from these bytes. In the future, we need to read from the
executable/library files when we can.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-12-08 00:02:44 -08:00
Omar Sandoval
844d82848c libdrgn: add partial support for .gnu_debugaltlink
Issue #130 reported an "unknown attribute form 0x1f20" from drgn. 0x1f20
is DW_FORM_GNU_ref_alt, which is a reference to a DIE in an alternate
file. Similarly, DW_FORM_GNU_strp_alt is a string in an alternate file.
The alternate file is specified by the .gnu_debugaltlink section. This
is generated by dwz, which is used by at least Fedora and Debian.

libdwfl already finds the alternate debug info file, so we can save its
.debug_info and .debug_str and use those to support DW_FORM_GNU_ref_alt
and DW_FORM_GNU_strp_alt in the DWARF index.

Imported units are going to be more work to support in the DWARF index,
but this at least lets drgn start up.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-12-07 13:49:09 -08:00
Omar Sandoval
aef144c944 libdrgn: debug_info: improve elf_address_range()
Instead of iterating through every segment, we can just look at the
first and last loadable segments. This even works for vmlinux on x86-64
and Arm which have some special, relocatable segments.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-12-06 13:33:55 -08:00
Omar Sandoval
10c66d4e99 libdrgn: get correct error when dwelf_elf_gnu_build_id() fails
The documentation for libdwelf states that "functions starting with
dwelf_elf will take a (libelf) Elf object as first argument and might
set elf_errno on error". So, we should be using drgn_error_libelf(), not
drgn_error_libdwfl(). While we're here, close the Elf handle before the
file descriptor for consistency.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-12-06 01:51:54 -08:00
Omar Sandoval
2c6e36847f Remove some include-what-you-use workarounds
include-what-you-use 0.17 fixed a couple of issues we were working
around with a mapping file.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-12-06 01:51:54 -08:00
Omar Sandoval
91f6d03ee8 libdrgn: fix note name matching
The current code matches the desired note name as a prefix, but we need
an exact match.

Fixes: 75c3679147 ("Rewrite drgn core in C")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-12-03 12:03:19 -08:00
Omar Sandoval
0e318754fe libdrgn: don't swallow errors in relocate_elf_file()
Fixes: 62d98b3016 ("libdrgn: fold ELF relocation code into dwarf_index")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-12-03 11:31:05 -08:00
Omar Sandoval
0315ade709 tests: handle CONFIG_KALLSYMS=n and CONFIG_KALLSYMS_ALL=n
If CONFIG_KALLSYMS_ALL=n, then /proc/kallsyms won't include lo_fops,
which is a data symbol. Use a function symbol, lo_open, instead. Also
check whether /proc/kallsyms exists in the first place.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-12-02 03:46:06 -08:00
Omar Sandoval
36f7e8b59b README: add libtool to build dependencies for Debian and Arch
Fixes: 1b7badad0a ("docs: expand and reorganize installation instructions")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-12-02 02:01:46 -08:00
Omar Sandoval
3914bb8e29 libdrgn: fix type names referring to anonymous types
A pointer, array, or function referring to an anonymous type currently
includes the full type definition in its type name. This creates very
badly formatted objects for, e.g., drgn's own hash table types. Instead,
use "struct <anonymous>" in the type name.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-23 00:57:42 -08:00
Omar Sandoval
d18be05b7a README: mention Meta
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-21 16:01:39 -08:00
Omar Sandoval
c0d8709b45 Update copyright headers to Meta
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-21 15:59:44 -08:00
Omar Sandoval
93dc02a271 setup.py: add 5.16 to vmtest kernels
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-21 14:52:46 -08:00
Omar Sandoval
cdee38af7a tests: use different symbol for kernel module debug info test
Linux kernel commit 47e9624616c8 ("block: remove support for cryptoloop
and the xor transfer") removed the loop_register_transfer function. We
only used that symbol because it and loop_unregister_transfer were the
only global symbols in the loop module. Now that we can get local
symbols by name, we can use the "lo_fops" symbol, which is unlikely to
be removed or renamed.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-21 14:40:06 -08:00
Omar Sandoval
ff40f65f0d libdrgn: allow symbol name lookup to get local symbols
Global symbols are preferred over weak symbols, and weak symbols are
preferred over other symbols.

dwfl_module_addrinfo() seems to have the same preference, so document
address lookups as having the same behavior. (This is actually incorrect
in the case of STB_GNU_UNIQUE, as dwfl_module_addrinfo() treats anything
other than STB_GLOBAL, STB_WEAK, and STB_LOCAL as having the lowest
precedence, but STB_GNU_UNIQUE is so obscure that it probably doesn't
matter.)

Based on work from Stephen Brennan. Closes #121.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-21 14:30:57 -08:00
Omar Sandoval
07d00b7b11 tests: add tests for ELF symbols
Add some scaffolding to generate ELF files with symbol tables and use it
to test symbol lookups and Elf_Sym -> drgn.Symbol translation.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-19 17:04:20 -08:00
Omar Sandoval
c84d7e8c15 tests: generate ELF constants from elf.h
Generalize generate_dwarf_constants.py for ELF and replace tests/elf.py
with the generated version.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-19 17:02:32 -08:00
Omar Sandoval
cb8bf339c8 tests: elfwriter: don't add sections if there aren't any
Only add SHT_NULL and .shstrtab sections if there are other sections to
be added. This allows us to create core dumps with no sections, like
core dumps on Linux.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-19 15:12:31 -08:00
Omar Sandoval
681d8453ce tests: elfwriter: set e_phoff to zero if there are no segments
readelf warns that a non-zero e_phoff with a zero e_phnum is invalid:

  Warning: possibly corrupt ELF header - it has a non-zero program header offset, but no program headers

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-19 15:11:54 -08:00
Omar Sandoval
4808ef72ee libdrgn: debug_info: get address range of reported ET_EXEC files
When explicitly reporting a debugging information file for a userspace
program, userspace_report_debug_info() currently always reports it with
a load address range of [0, 0) (i.e., not actually loaded into the
program). This is because for ET_DYN and ET_REL files, we have to
determine the address range by inspecting the core dump or program
state, which is a bit involved.

However, ET_EXEC is much easier: we can get the address range from the
segment headers. In fact, we already implemented this for vmlinux files,
so we can reuse that with a modification to make it more permissive.

ET_CORE debug info files don't make much sense, but libdwfl seems to
treat a reported ET_CORE file the same as ET_EXEC (see
dwfl_report_elf()), so we do, too.

Unfortunately, most executables on modern Linux distributions are
ET_DYN, but this will at least make testing easier.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-19 14:58:10 -08:00
Omar Sandoval
c3f31e28f9 libdrgn: reorganize and move DWARF index into dwarf_info.c
The upcoming introduction of a higher level data structure to represent
a namespace has implications on the organization of the DWARF index and
debug info management code. Basically, we're going to want to track what
is currently known as struct drgn_dwarf_index_namespace as part of the
new struct drgn_namespace. That only leaves the DWARF specification map
and list of CUs in struct drgn_dwarf_index, which doesn't make much
sense anymore. Instead, let's:

* Move the specification map and CUs into struct drgn_dwarf_info.
* Rename struct drgn_dwarf_index_namespace to struct
  drgn_namespace_dwarf_index to indicate that it is the "DWARF index for
  a namespace" rather than a "namespace of a DWARF index".
* Move the DWARF index implementation into dwarf_info.c. The DWARF index
  and debugging information management have always been coupled, so this
  makes it more explicit and is more convenient.
* Improve documentation and naming in the DWARF index implementation.

Now, the only DWARF-specific code outside of dwarf_info.c is for stack
tracing, but we'll leave that for another day.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-18 15:08:55 -08:00
Omar Sandoval
5591d199b1 libdrgn: debug_info: split DWARF support into its own file
Continuing the refactoring from the previous commit, move the DWARF code
from debug_info.c to its own file, leaving only the generic ELF file
management in debug_info.c

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-18 15:08:54 -08:00
Omar Sandoval
c6b2bc4181 libdrgn: debug_info: split ORC support into its own file
debug_info.c currently contains code for managing ELF files with
debugging information, for parsing DWARF, and for parsing ORC. Let's
split it up, starting by moving ORC support to its own file.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-18 15:08:04 -08:00
Jay Kamat
3700bb75b8 libdrgn: Follow typedefs in enum backing type lookup
In C++ enums can be a typedef to an int, not just an int itself.

Signed-off-by: Jay Kamat <jaygkamat@gmail.com>
2021-11-18 13:48:31 -08:00
Omar Sandoval
a90ffdfb67 libdrgn: dwarf_index: actually index namespaces in parallel
index_namespace() uses `#pragma omp for` instead of `#pragma omp
parallel for`, and it's not already in a parallel section. So, we're
indexing namespaces single-threaded, despite sharding the index. Oops.

Fixes: d1beb0184a ("libdrgn: add support for objects in C++ namespaces")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-17 18:11:08 -08:00
Omar Sandoval
2642f85a1a libdrgn: dwarf_index: avoid OpenMP when accessing indexed namespace
index_namespace() sets up an OpenMP loop everytime it is called.
However, if the namespace has no pending DIEs, this is unnecessary
overhead for every DWARF index lookup. Bail early if there are no
pending DIEs (i.e., because we already indexed the namespace). In a
microbenchmark, this was a 10x speed improvement for DWARF index
iterator initialization. For a Python prog.type() lookup benchmark, it
was a 10% speedup.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-17 18:10:33 -08:00
Omar Sandoval
12ddb87c26 libdrgn: dwarf_info: simplify DWARF index iterator code
We can save a pointer to the shard itself instead of the namespace and
shard index. We can also simplify drgn_dwarf_index_iterator_next()
further.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-17 18:08:58 -08:00
Omar Sandoval
40357b9d9e libdrgn: debug_info: don't use strlen() in drgn_debug_info_find_object()
The length of the name was passed, and the name may not be
null-terminated.

Fixes: 565e0343ef ("libdrgn: make symbol index pluggable with callbacks")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-17 18:06:43 -08:00
Omar Sandoval
64c4afa298 libdrgn: type: fix hash table insertion error check
table_insert_searched() returns -1 when insertion fails.

Fixes: a97f6c4fa2 ("Associate types with program")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-17 18:04:57 -08:00
Omar Sandoval
4b3eec40df libdrgn: dwarf_index: fix hash table insertion error check
table_insert_searched() returns -1 when insertion fails.

Fixes: d1beb0184a ("libdrgn: add support for objects in C++ namespaces")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-17 18:04:52 -08:00
Omar Sandoval
abc3ee4da0 libdrgn: dwarf_index: clean up index_die()
index_die() can only fail if it's out of memory, so return a bool
instead of a struct drgn_error. Also clean up the declarations.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-17 18:03:49 -08:00
Omar Sandoval
d1745755f1 Fix some include-what-you-use warnings
Also:

* Rename struct string to struct nstring and move it to its own header.
* Fix scripts/iwyu.py, which was broken by commit 5541fad063 ("Fix
  some flake8 errors").
* Add workarounds for a few outstanding include-what-you-use issues.

There is still a false positive for
include-what-you-use/include-what-you-use#970, but hopefully that is
fixed soon.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-10 15:09:29 -08:00
Omar Sandoval
794ffc22e8 libdrgn: kdump: fix leak in leak fix
The previous fix still leaks the vmcoreinfo buffer if parse_vmcoreinfo()
fails.

Fixes: bc85c2da08 ("libdrgn: kdump: fix kdump_vmcoreinfo_raw() memory leak")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-04 14:43:15 -07:00
Omar Sandoval
bc85c2da08 libdrgn: kdump: fix kdump_vmcoreinfo_raw() memory leak
Commit dd503c975ab3 ("Fix kdump_vmcoreinfo_raw()") in libkdumpfile
changed the buffer returned by kdump_vmcoreinfo_raw() to be dynamically
allocated. We need to free it on versions containing that change.

Closes #76.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-04 14:39:13 -07:00
Omar Sandoval
a5845e63d4 tests: fix race condition in stack trace tests
Stephen Brennan reported a flaky test while working on #121:

======================================================================
ERROR: test_by_task_struct (tests.helpers.linux.test_stack_trace.TestStackTrace)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/runner/work/drgn/drgn/tests/helpers/linux/test_stack_trace.py", line 22, in test_by_task_struct
    self.assertIn("pause", str(self.prog.stack_trace(find_task(self.prog, pid))))
ValueError: cannot unwind stack of running task

The problem is that the stack trace tests wait for the thread state to
change to "S". However, the state is updated while the thread is still
technically running. For example, the pause() system call is implemented
as:

SYSCALL_DEFINE0(pause)
{
	while (!signal_pending(current)) {
		__set_current_state(TASK_INTERRUPTIBLE);
		schedule();
	}
	return -ERESTARTNOHAND;
}

If Program.stack_trace() accesses the thread after the state is changed
but before the thread has actually been scheduled out (namely, before
task_struct::on_cpu is set to 0), it will fail.

Instead, let's check /proc/$pid/syscall, which contains "running" until
the thread is completely scheduled out.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-04 14:13:55 -07:00
Omar Sandoval
d36b12c682 CI: add Python 3.10
Python 3.10 was released in October. No changes to drgn are required.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-03 17:38:31 -07:00
Omar Sandoval
1b7badad0a docs: expand and reorganize installation instructions
* Mention installing drgn using a package manager on Fedora/EPEL.
  Closes #103.
* Mention that pip installs a binary wheel by default.
* Include instructions for installing from source in README.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-03 16:18:22 -07:00
Omar Sandoval
d9192b7245 docs: remove outdated comment about helper types
As of commit 0cf3320a89 ("Add type annotations to helpers"), helpers
have type annotations instead of C signatures.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-03 16:01:27 -07:00
Omar Sandoval
e5021952c8 docs: disable sphinx.ext.viewcode
viewcode works by importing modules. This doesn't actually work on Read
the Docs because we don't build and install the C extension. It looks
like there are workarounds (viewcode-find-source), but let's disable it
for now.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-03 15:58:11 -07:00
Omar Sandoval
bc2d5333c0 README: update link to crash
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-03 11:48:34 -07:00
Omar Sandoval
8358c31d26 docs: document how to get debugging symbols
I couldn't find any good summaries of how to get debugging symbols on
various distros, so I guess we'll have to maintain our own.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-02 17:48:36 -07:00
Omar Sandoval
9c54083830 libdrgn: pp: make PP_CAT not variadic
The overloaded version is slower to compile, and we don't actually need
it. We can add a variadic version if we need to in the future. Also add
the script used to generate the macros.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-10-29 18:38:49 -07:00
Omar Sandoval
568f4f9c2b libdrgn: debug_info: remove dies and length out parameters to drgn_dwarf_die_iterator_next()
These are already available in it->dies.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-10-29 18:38:49 -07:00
Omar Sandoval
198499e74b libdrgn: debug_info: optimize drgn_find_die_ancestors()
Jay pointed out that when finding the ancestors for a DIE, we should use
DW_AT_sibling to skip over subtrees that can't contain the target DIE.
So, let's check each DIE that we encounter for a DW_AT_sibling
attribute. dwarf_attr() also returns the end of the DIE if it doesn't
find the attribute, which we can use to avoid parsing DIEs redundantly.
This doesn't fit very well into drgn_dwarf_iterator, so let's just
hand-roll this special type of iteration. In my measurements, this made
drgn_find_die_ancestors() ~6x as fast on average.

Closes #124.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-10-29 18:38:40 -07:00
Omar Sandoval
6150935e96 Fix some cosmetic nits in Packit config and .gitignore
Fix .gitignore alphabetical order and indent YAML consistently.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-10-29 13:19:32 -07:00
Davide Cavalca
7e6082707d Add initial Packit config
Signed-off-by: Davide Cavalca <dcavalca@fb.com>
2021-10-28 15:13:05 -07:00
Omar Sandoval
3c52b18baa tests: skip PID memory read test if /proc/$pid/mem doesn't work
This works around a QEMU bug
(https://gitlab.com/qemu-project/qemu/-/issues/698) which causes Packit
build failures on 32-bit ARM. This should unblock #126.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-10-28 14:41:44 -07:00