After thinking about this some more, I decided that although it makes
sense for scripts to convert a type to an IntEnum class, I'd prefer that
the helpers take and return drgn Objects rather than these classes.
We have a few use cases for converting a drgn.Type to a Python
enum.IntEnum (if I recall correctly, the original Python version of drgn
even did this automatically for enumerated types). Add an
enum_type_to_class() helper which does this conversion.
To make the previous reformatting commit less annoying, add a file
containing the commits to ignore in git blame. To use it, run `git blame
--ignore-revs-file .git-blame-ignore-revs` or `git config
blame.ignoreRevsFile .git-blame-ignore-revs`.
drgn.helpers has a couple of undocumented generic helpers. We might as
well document them. They're using type hints, so we need to use a sphinx
extension that strips the type hints out of the signature and adds them
to the documentation. We can also do the same for execscript().
Hopefully it can be used for the C extension documentation in the
future, too.
In order to make builds slightly more reproducible (and avoid leaking
details about the build machine's directory layout), let's remap the
compilation directory in DW_AT_comp_dir to be empty.
Currently the drgn version number is defined in drgn.h.in, and configure
and setup.py both parse it out of there. However, now that we're
generating drgn.h anyways, it's easier to make configure.ac the source
of truth.
Although it doesn't correspond to a Linux kernel function, it is more
convenient than open-coding it everywhere, especially since the leading
__ causes Python to mangle the name if it's inside of a class.
Add example script that goes over all TCP sockets and for every socket
prints:
- TCP state;
- IP:port pair;
- cgroup v2 path.
The script shows basic operations with sockets including getting `struct
sock`, `struct inet_sock`, socket fields and cgroup v2 of socket.
It provides output similar to `ss -nt` or `ss -lnt`:
% sudo python36 -m drgn examples/linux/tcp_sock.py | shuf -n 5
TIME_WAIT [::1]:2560 [::1]:44041
ESTABLISHED [::1]:54178 [::1]:11101 system.slice/async-distillery-server.service
LISTEN [::]:3201 [::]:0 system.slice/fbflow.service
ESTABLISHED [2401:db00:21:718a:face:0:31:0]:2406 [2401:db00:12:a106:face:0:1e:0]:46306 system.slice/configerator_proxy2.service
LISTEN 0.0.0.0:11150 0.0.0.0:0 system.slice/system-mcrouter.slice/mcrouter@tao.service
Signed-off-by: Andrey Ignatov <rdna@fb.com>
Add helpers for working with network sockets defined in
include/net/sock.h:
- sk_fullsock()
- sk_nulls_for_each()
sk_fullsock() is useful to filter out timewait and request sockets since
not all operations can be applied to such sockets.
sk_nulls_for_each() is useful to e.g. iterate over established sockets.
Signed-off-by: Andrey Ignatov <rdna@fb.com>
Add get_tcp_states() helper to get all TCP states enumerators and
construct enum.IntEnum from them.
The helper is useful in debugging TCP sockets.
Signed-off-by: Andrey Ignatov <rdna@fb.com>
These list helpers are useful to iterate over nulls hash lists of
sockets, specifically `ehash` member of `struct tcp_hashinfo`.
Corresponding functions and macros are defined in
`include/linux/list_nulls.h` kernel header.
Signed-off-by: Andrey Ignatov <rdna@fb.com>
When we're checking whether the element that we formatted on one line
would fit on the previous line, we check whether the previous line is
empty with remaining_columns == start_columns. This is never true, as
remaining_columns is always set to start_columns - 1 at most, and it
only decreases from there until we start a new line.
drgn_object_truthiness() is a misnomer, as truthiness is a
language-specific concept. Instead, invert the return value and rename
it to drgn_object_is_zero(), which more accurately conveys the meaning.
Instead of having two internal variants (drgn_find_symbol_internal() and
drgn_program_find_symbol_in_module()), combine them into the former and
add a separate drgn_error_symbol_not_found() for translating the static
error to the user-facing one. This makes things more flexible for the
next change.
We'd like to have more control over how objects are formatted. I
considered defining a custom string format specification syntax, but
that's not easily discoverable. Instead, let's get rid of the current
format specification support and replace it with a normal method.
In preparation for making drgn_pretty_print_object() more flexible
(i.e., not always "pretty"), rename it to drgn_format_object(). For
consistency, let's rename drgn_pretty_print_type_name(),
drgn_pretty_print_type(), and drgn_pretty_print_stack_trace(), too.
Commit f327552229 ("libdrgn: add strstartswith()") flipped the test
for a name entry in modinfo. This introduced a regression resulting in
kernel modules not loading at the right offset. This patch fixes the
regression.
The previous commit was the real fix for the failed symbol lookups. On
the bright side, the build fixes were merged, so we can rebase on master
and drop those.
Based on:
277c2c54f libcpu: Compile i386_lex.c with -Wno-implicit-fallthrough
With the following patches:
configure: Add --disable-programs
configure: Add --disable-shared
libdwfl: add interface for attaching to/detaching from threads
libdwfl: cache Dwfl_Module and Dwarf_Frame for Dwfl_Frame
libdwfl: add interface for evaluating DWARF expressions in a frame
It turns out this wasn't a problem with dwfl_addrmodule() at all; the
real problem is that .init sections are freed once the module is loaded
but we're still considering them for the address range we pass to
dwfl_report_module(). Ignore those sections entirely (by omitting them
from the section name to section index map). While we're here, let's not
bother inserting non-SHF_ALLOC sections in the map.
This fixes the issue that Program.symbol() sometimes fails for kernel
module symbols.
Based on:
2c7c4037 elfutils.spec.in: Sync with fedora spec, remove rhel/fedora specifics.
With the following patches:
configure: Add --disable-programs
configure: Add --disable-shared
configure: Fix -D_FORTIFY_SOURCE=2 check when CFLAGS contains -Wno-error
libcpu: compile i386_lex.c with -Wno-implicit-fallthrough
libdwfl: add interface for attaching to/detaching from threads
libdwfl: cache Dwfl_Module and Dwarf_Frame for Dwfl_Frame
libdwfl: add interface for evaluating DWARF expressions in a frame
libdwfl: return error from __libdwfl_relocate_value for unloaded sections
libdwfl: remove broken coalescing logic in dwfl_report_segment
libdwfl: store module lookup table separately from segments
libdwfl: use sections of relocatable files for dwfl_addrmodule
For live userspace processes, we add a single [0, UINT64_MAX) memory
file segment for /proc/$pid/mem. Of course, not every address in that
range is valid; reading from an invalid address returns EIO. We should
translate this to a DRGN_ERROR_FAULT instead of DRGN_ERROR_OS, but only
for /proc/$pid/mem.
execscript() is supposed to behave more or less like the script was
typed in at the console. However, if the script raises an exception,
then the variables or functions it defines are not added to the calling
context, which can be pretty confusing.
The problem is that runpy.run_code() returns the new globals, so if it
raises an exception, then we can't get them. Fix it by doing the exec()
ourselves; we just need to do the same setup that runpy does.
In commit 55a9700435 ("libdrgn: python: accept integer-like arguments
in more places"), I converted Program_symbol to use index_converter but
forgot to initialize the struct index_arg. Then, in commit c243daed59
("Translate find_task() helper (and dependencies) to C"), I added a
bunch more cases of uninitialized struct index_arg. If
index_arg.allow_none gets a non-zero garbage value, then this can end up
allowing None through when it shouldn't. Furthermore, since commit
2561226918 ("libdrgn: python: add signed integer support to
index_converter"), if index_arg.is_signed gets a non-zero garbage value,
then this will try to get a signed integer when we're expecting an
unsigned integer, which can blow up for values >= 2**63 (like kernel
symbols). Fix it by initializing struct index_arg everywhere.
Fixes#30.
Not all architectures name the bootable image bzImage, so to make
supporting other architectures easier in the future, let's use the more
generic name, vmlinuz.