Commit Graph

519 Commits

Author SHA1 Message Date
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
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
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
c0d8709b45 Update copyright headers to Meta
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-11-21 15:59:44 -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
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
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
Jay Kamat
8bf26fafbb dwarf_index.c: lazily allocate shards to save memory on unused ns
Previously shards were allocated as soon as a namespace was
encountered, which means that we had a large array sitting around for
every ns we saw. By allocating them lazily, we can reduce this usage.

Signed-off-by: Jay Kamat <jaygkamat@gmail.com>
2021-10-26 02:07:26 -07:00
Omar Sandoval
1339dc6a2f libdrgn: hash_table: move entry_to_key to DEFINE_HASH_TABLE_FUNCTIONS()
DEFINE_HASH_TABLE_TYPE() doesn't actually need to know the key type.
Move that argument (and some of the derived constants) to
DEFINE_HASH_TABLE_FUNCTIONS(). This will allow recursive hash table
types. As a nice side effect, it also reduces the size of common header
files.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-10-23 00:52:23 -07:00
Omar Sandoval
802d6cc9ff libdrgn: rename drgn_program::_dbinfo to dbinfo
The underscore was meant to discourage direct access in favor of using
drgn_program_get_dbinfo(), but it turns out that it's more normal to
access it directly.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-10-23 00:52:23 -07:00
Omar Sandoval
c1e16ae3ec libdrgn: fold drgn_program_get_dbinfo() into only caller
The only time that we want to create the drgn_debug_info is when we're
loading debugging information. Everywhere else, we fail fast if there is
no debugging information.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-10-23 00:40:57 -07:00
Omar Sandoval
1d4dbc2b69 libdrgn: python: remove unused declaration
drgnpy_linux_helper_task_state_to_char() was removed by commit
ff96c75da0 ("helpers: translate task_state_to_char() to Python"), but
I left behind the declaration.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-10-12 18:01:42 -07:00
Omar Sandoval
734cbe5c7b libdrgn: dwarf_index: free pending DIEs after indexing namespace
Once we've cleared the pending DIEs vector, we won't use the vector
again (unless we load more debugging information), so we can free it.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-09-28 13:56:52 -07:00
Jake Hillion
b0ae2867d5 splay_tree.c: Rename splay_tree to avoid conflicts with splay-tree.h
When linking libdrgn as a static library, the name 'splay_tree' can
conflict with splay-tree.h in libiberty (namely splay_tree_splay).

Rename relevant functions to have a 'drgn_' prefix

Signed-off-by: Jake Hillion <jakehillion@fb.com>
2021-09-27 12:56:47 -07:00
Jay Kamat
2baee6fe16 dwarf_index.c: Shrink abbrev tables before saving them in CUs
In larger binaries, there can be a large number of CUs, and since we
store an abbrev table for each CU the extra space starts to add up.
The simplest way to mitigate this is to shrink the vectors before
saving them.

On a large binary, I noticed a memory reduction from 20.4G RES to
18.6G RES (on initial load-in).
2021-09-27 12:08:25 -07:00
Omar Sandoval
fba5947fec libdrgn: add array_for_each()
And use it in a few appropriate places. This should hopefully make it
harder to make iteration mistakes like the one fixed by commit
4755cfac7c ("libdrgn: dwarf_index: increment correct variable when
rolling back"). While we're doing this, move ARRAY_SIZE() into a new
header file with array_for_each() and make it lowercase.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-08-23 17:32:00 -07:00
Omar Sandoval
4755cfac7c libdrgn: dwarf_index: increment correct variable when rolling back
We need to increment to the next DIE, not the next shard here.

Fixes: 1c9ab2e7d1 ("libdrgn: dwarf_index: fix leak of DWARF index entries on failure")
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-08-23 17:06:24 -07:00
Omar Sandoval
84f6142879 libdrgn: dwarf_index: remove any_name functionality from dwarf_index_iterator
This hasn't been used since commit 06960f591c ("libdrgn: look up
primitive types on demand").

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-08-23 17:06:15 -07:00
Stephen Brennan
1744d8d93c libdrgn: python: Add binding, kind to drgn.Symbol
Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
2021-08-20 18:16:57 -07:00
Stephen Brennan
3d8db22c47 libdrgn: Add kind and binding fields to drgn_symbol
Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
2021-08-20 18:16:57 -07:00
Omar Sandoval
8d383fb89a libdrgn: fix alphabetization in gen_constants.py
PlatformFlags obviously comes before PrimitiveType.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-08-20 15:02:31 -07:00
Omar Sandoval
27906d0cf1 libdrgn: python: cast enums when wrapping with Python call
The "k" format expects an unsigned long, so make sure we cast C enums to
the proper type. This probably doesn't matter for x86 in practice, but
it's better to be safe.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-08-20 14:58:33 -07:00
Omar Sandoval
8b4532ca0a libdrgn: debug_info: improve handling of DW_AT_data_member_location
There are a couple of issues with how we interpret
DW_AT_data_member_location:

1. DW_AT_data_member_location can be a location list, and we shouldn't
   interpret the section offset as the member offset.
2. DW_AT_data_member_location can be location description block, and in
   DWARF 2, it cannot be a constant. We should handle constant offset
   expressions as generated by GCC and Clang.

Closes #13.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-08-16 11:57:42 -07:00
Omar Sandoval
611e4d90b2 libdrgn: debug_info: support DWARF 3 forms for loclistptr
DWARF 3 uses DW_FORM_data4 or DW_FORM_data8 for DW_AT_location
loclistptrs.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-08-13 17:52:24 -07:00
Omar Sandoval
ec3cb15bad drgn 0.0.14
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-08-12 11:57:07 -07:00
Omar Sandoval
5541fad063 Fix some flake8 errors
Mainly unused imports, unused variables, unnecessary f-strings, and
regex literals missing the r prefix. I'm not adding it to the CI linter
because it's too noisy, though.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-08-11 14:52:44 -07:00
Omar Sandoval
7335df114c libdrgn: python: add Object.to_bytes_()
And the libdrgn implementation, drgn_object_read_bytes().

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-07-26 17:12:34 -07:00
Omar Sandoval
9c00552007 libdrgn: python: add Object.from_bytes_()
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>
2021-07-26 17:06:58 -07:00
Omar Sandoval
a74716828d libdrgn: fix comment typo in serialize.h
s/grather/greater/g

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-07-21 20:32:53 -07:00
Omar Sandoval
a863f1e439 libdrgn: dwarf_index: print unknown forms in hexadecimal
The DWARF spec and dwarf.h list them in hexadecimal, so make it easier
to cross reference.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-07-09 01:52:08 -07:00
Omar Sandoval
26001733f6 libdrgn: debug_info: support DWARF 5 location lists
The DWARF 5 format is a little more complicated than DWARF 2-4 but
functionally very similar.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-07-09 01:52:08 -07:00
Omar Sandoval
215f7d79d7 libdrgn: debug_info: implement DW_OP_{addr,const}x
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>
2021-07-09 01:52:08 -07:00