This function returns the source position of a given address in the
program. If that address exists in an inline chain, then it also returns
the source positions that are in the chain.
This function returns the die object whose address range intersects
with the given address.
This function will also construct the DIE cache, if it hasn't been
constructed yet.
There is one cache that indexes DIE objects by the start address of
their range, and another cache that indexes by their offset in the
debug_info section.
Both caches are implemented with RedBlackTree, and are optional - they
will only be populated if 'build_cached_dies' is invoked.
In the current implementation, only DIE objects that are created via
DIE::for_each_child() will have parent offsets.
DIE objects that are created with CompilationUnit::get_die_at_offset()
do not currently store a parent offset.
We may improve this in the future, but this is enough for what we
currently need.
In some contexts, it's helpful to also know the "Attribute Form",
in addition to the "Attribute Type".
An example for such context is the interpretation of the
"DW_AT_high_pc" attribute, which has different meaning if the form
is an address or a constant.
Previously, the LineProgram objects were short-lived, and only created
inside DebugInfo::prepare_lines() to create a vector of sorted LineInfo
data.
However, Dwarf::LineProgram also contains other useful data, such as
index-to-string mapping of source directories and filenames.
This commit makes each Dwarf::CompilationUnit own its
Dwarf::LineProgram.
DebugInfo::prepare_lines() then iterates over the compilation units to
prepare its sorted vector of lines.
This fixes an issue were some LibDebug objects (for example,
Dwarf::CompilationUnit) held a reference to their parent
Dwarf::DwarfInfo object, which was constructed on the stack and later
moved to the heap.
Avoid promotion of static strings to AK::String, instead use
AK::StringView and operator ""sv, to force string view's instead
which avoids allocation of String. This code path isn't hot enough
that it makes a huge difference, but every bit counts.
When loading debug info, we encounter the same filename over and over
(since files usually have many lines!) and we were wasting a ton of
time re-checking if the filename was part of the Toolchain or libgcc,
along with some other checks.
This patch makes prepare_lines() significantly faster by memoizing
the result of these checks per filename.
This makes "bt 12" ~25% faster (from 850ms to 650ms on my machine.) :^)
Previously <AK/Function.h> also included <AK/OwnPtr.h>. That's about to
change though. This patch fixes a few build problems that will occur
when that change happens.
This code path is very hot, and since we're seeing a lot of the same
strings repeatedly (and they're heading into a FlyString for storage)
let's construct those using FlyString(StringView) to avoid temporary
String objects.
We were using ELF::Image::section(0) to indicate the "undefined"
section, when what we really wanted was just Optional<Section>.
So let's use Optional instead. :^)
While symbolicating a crash dump for UserspaceEmulator I came across
another data form we didn't support.
ImplicitConst encodes a LEB128 value in the abbreviation record
rather than - like all other values - in the .debug_info section.
SPDX License Identifiers are a more compact / standardized
way of representing file license information.
See: https://spdx.dev/resources/use/#identifiers
This was done with the `ambr` search and replace tool.
ambr --no-parent-ignore --key-from-file --rep-from-file key.txt rep.txt *
In LibDebug this required implementing the Kill debug action, and
in HackStudio this required making the toolbar's stop action stop
the debugger if active.
Previously, when trying to debug variables with more complex
types (such as String), we would crash the debugger simply because
it didn't know how to handle types that were irrelevant anyways.
Now we just skip data we don't yet know how to handle.
For one, viewing a variable who's type contained a subprogram will
no longer crash HackStudio. Additionally, the variable view will
handle invalid enum values gracefully now, fixing another crash.
Finally, deeply nested (nest count > 1) structures will have their
memory addresses properly set, fixing the final crash I found.
(...and ASSERT_NOT_REACHED => VERIFY_NOT_REACHED)
Since all of these checks are done in release builds as well,
let's rename them to VERIFY to prevent confusion, as everyone is
used to assertions being compiled out in release.
We can introduce a new ASSERT macro that is specifically for debug
checks, but I'm doing this wholesale conversion first since we've
accumulated thousands of these already, and it's not immediately
obvious which ones are suitable for ASSERT.