Additionally this reduces some GHashTable lookup costs by doing it once
for the process-info per-traceable rather than one per instruction pointer
per traceable.
This does a simple binary search across the parsed kallsyms using the
addresses we've parsed. We need to be sure we've created the array properly
so that our bounds checking will prevent infinite loops in the tight
binary search loop.
Compressed, this adds about 2.5mb to the capture file for the contents of
the kallsyms. However, that is useful so that we can decode kernel symbols
after the fact without relying on __symbols__ to be tacked on by the
recording machine.
This adds an O(1) check at the head of the lookup to avoid looking at
every RB_RIGHT() in the tree when address falls beyond the upper bound of
the interval tree.
This instead moves to a public API on the document to symbolize now
that we've gotten much of the necessary bits private in loading the
document. This commit ensures that we only do loading via the loader
now (and removes the incorrect use from the tests so they too go
through the loader).
We check for NoSymbolizer in document symbols so that we can skip any
decoding. That keeps various use cases fast where you don't want to
waste time on symbolizing if you don't need to look at symbols.
There is plenty more we can do to batch decode symbols with some more
API changes, but that will come after we have kernel/userland decoding
integrated from this library.
We may still want to get all symbols into a single symbol cache, but
given that we have address ranges associated with them, that may not
be very useful beyond the hashtable to pid-specific cache we have now.
If symbols were shared between processes, that'd make more sense, but
we aren't doing that (albeit strings are shared between symbol
instances to reduce that overhead).
We will want to start embedding this content in the capture file (but
after gzipping it as it's otherwise quite large). This will get things in
place so that we can parse that .gz file into the address ranges and
decode symbols found within the capture file.
and thereby make a bunch of the exposed API on SysprofDocument private.
Instead we'll push some of that to the loader but for now the tests can
keep doing what their doing using the private API.
The goal here is to not expose a SysprofDocument pointer until the document
has been loaded and symbolized via the loader API. Then we can lookup
symbols directly from the document w/o intermediary objects.
This uses an augmented red-black tree to create an interval tree with
non-interval lookups. That amounts to storing address ranges within the
red-black tree, but looking up by single address.
And expose it via sysprof_document_process_list_mounts() so that when
inspecting processes we can see what binaries were mapped as well as what
the filesystem looked like to locate those mapped paths.
This internal type is used to collect things about a process like the
memory maps, address layout, and symbol cache. This can persist once
parsed at startup, then applied to objects created on demand such as the
SysprofDocumentProcess or used by symbolizers internally rather than
complicated function arguments.
This relies on begin/end range for the symbols to create something akin to
an interval tree, albeit with GSequence. If performance needs to be
addressed, can probably augment SysprofSymbol for an interval rbtree.
I want to do this differently than we did in libsysprof, which is going
to require a bit of thinking on how we should represent something like
a SysprofMount within the mount namespace.