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.
p_paddr in /proc/kcore is always zero before Linux v4.11, so we can't
easily read from the physical address we get from /sys/kernel/vmcoreinfo
(we would need architecture-specific knowledge of the virtual address of
the direct mapping, as well as a way to defeat CONFIG_RANDOMIZE_MEMORY).
Instead, we can get the only two fields we currently use through other
means (OSRELEASE is trivial and KERNELOFFSET can be determined by
comparing /proc/kallsyms to the ELF symbols).
And replace the Python implementation in ProgramObject.string_(). The
CoreReader implementation is still naive in that it reads byte-by-byte,
but this could always be improved in the future.
CompoundType.members() currently returns a list of member names;
sometimes, we actually want the type and offset. So, rename members() to
member_names(), and make members() return the type and offset, using a
newly added version of functools.partial() that caches the return value.