The main difference is that the llvm class (just a std::vector in
disguise) is not sorted. It turns out this isn't an issue because the
callers either:
- ignore the range list;
- convert it to a different format (which is then sorted);
- or query the minimum value (which is faster than sorting)
The last case is something I want to get rid of in a followup as a part
of removing the assumption that function's entry point is also its
lowest address.
The class is only used from one place, which is trivial to implement
using the llvm class.
The main difference is that in the new implementation, the ranges are
parsed each time anew (instead of being parsed at startup and cached). I
believe this is fine because:
- this is already how things work with DWARF v5 debug_rnglists
- parsing debug_ranges is fairly fast (definitely faster than rnglists)
- generally, this result will be cached at a higher level anyway.
Browsing the code I did find one instance where that is not the case --
SymbolFileDWARF::ResolveFunctionAndBlock -- which is called each time we
resolve an address (to the block level). However, this function is
already pretty suboptimal: it first traverses the DIE tree (which
involves parsing all the DIE attributes) to find the correct block, then
it parses them again to construct the `lldb_private::Block`
representation, and *then* it uses the ID of the block DIE it found in
the first step to look up the `Block` object. If this turns out to be a
bottleneck, I think there are better ways to optimize it than caching
the debug_ranges parse.
The motiviation for this is that DWARFDebugRanges sorts the block
ranges, even though the order of the ranges is load-bearing (in the
absence of DW_AT_low_pc, the "base address" of a scope is determined by
the first range entry). Delaying the parsing (and sorting) step makes it
easier to access the first entry.
In DWARF 4 and earlier `static const` members of structs, classes and
unions have an entry tag `DW_TAG_member`, and are also tagged as
`DW_AT_declaration`, but otherwise follow the same rules as
`DW_TAG_variable`.
This patch allows offsets to the DW_AT_frame_base to exceed 4GB. Prior
to this, for any .debug_info.dwo offset that exceeded 4GB, we would
truncate the offset to the DW_AT_frame_base expression bytes to be 32
bit only. Changing the offset to 64 bits restores correct functionality.
No test for this as we don't want to create a .dwp file that has a
.debug_info.dwo size that is over 4GB.
This allows e.g. DWARFDIE::GetName() to return the name of the type when
looking at its declaration (which contains only
DW_AT_declaration+DW_AT_signature). This is similar to how we recurse
through DW_AT_specification when looking for a function name. Llvm dwarf
parser has obtained the same functionality through #99495.
This fixes a bug where we would confuse a type like NS::Outer::Struct
with NS::Struct (because NS::Outer (and its name) was in a type unit).
…ARFDIE
This puts them closer to the other two functions doing something very
similar. I've tried to stick to the original logic of the functions as
much as possible, though I did apply some easy simplifications.
The changes in DWARFDeclContext.h are there to make the unit tests
produce more useful error messages.
We currently cannot represent abbreviation codes with more than 16 bits,
and we were lldb-asserting if we ever ran into one. While I haven't seen
any real DWARF with these kinds of abbreviations, it is possible to hit
this with handcrafted evil dwarf, due some sort of corruptions, or just
bugs (the addition of PeekDIEName makes these bugs more likely, as the
function blindly dereferences offsets within the debug info section) .
Missing abbreviations were already reporting an error. This patch turns
sure that large abbreviations into an error as well, and adds a test for
both cases.
The method DWARFDebugInfoEntry::Extract needs to skip over all the data
in the debug_info / debug_types section for each DIE. It had the logic
to do so hardcoded inside a loop, when it already exists in a neatly
isolated function.
As a followup of https://github.com/llvm/llvm-project/pull/67851, I'm
defining a new namespace `lldb_plugin::dwarf` for the classes in this
Plugins/SymbolFile/DWARF folder. This change is very NFC and helped me
with exporting the necessary symbols for my out-of-tree language plugin.
The only class that I didn't change is ClangDWARFASTParser, because that
shouldn't be in the same namespace as the generic language-agnostic
dwarf parser.
It would be a good idea if other plugins follow the same namespace
scheme.
lldb's and llvm's implementations of DWARFAbbreviationDeclarationSet are
now close enough (almost the same, actually) to replace lldb's with
llvm's wholesale. llvm's is also tested against the same kinds of
scenarios that lldb's is tested against so we can remove lldb's tests
here. (see: llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp).
Differential Revision: https://reviews.llvm.org/D152476
Currently, the method `GetAttributeAddressRanges` takes a DWARFRangeList as a
parameter, just to immediately clear it. The method also returns the size of
this list. Such an API was obfuscating the intent of the call sites (it's not
clear from the method name what it returns) and it was obfuscating redundant
checks on the size of the list.
This commit refactors the method to return the list and to also make the call
sites use the more explicit `IsEmpty` method.
Differential Revision: https://reviews.llvm.org/D151451
Both LLVM and LLDB implement DWARFAbbreviationDeclaration. As of
631ff46cbf51, llvm's implementation of
DWARFAbbreviationDeclaration::extract behaves the same as LLDB's
implementation, making it easier to merge the implementations.
The only major difference between LLDB's implementation and LLVM's
implementation is that LLVM's DWARFAbbreviationDeclaration is slightly
larger. Specifically, it has some metadata that keeps track of the size
of a declaration (if it has a fixed size) so that it can potentially
optimize extraction in some scenarios. I think this increase in size
should be acceptable and possibly useful on the LLDB side.
Differential Revision: https://reviews.llvm.org/D150716
The purpose of this method is to get the list of attributes of a
DebugInfoEntry. Prior to this change we were passing in a mutable
reference to a DWARFAttributes object and having the method fill it in
for us while returning the size of the filled out list. But
instead of doing that, we can just return a `DWARFAttributes` object
ourselves since every caller creates a new list before calling
GetAttributes.
Differential Revision: https://reviews.llvm.org/D150402
LLDB currently defines `dw_form_t` as a `uint16_t` which makes sense.
However, LLVM also defines a similar type `llvm::dwarf::Form` which is
an enum backed by a `uint16_t`. Switching to the llvm implementation
means that we can more easily interoperate with the LLVM DWARF code.
Additionally, we get some type checking out of this: I found that
DWARFAttribute had a method called `FormAtIndex` that returned a
`dw_attr_t`. Although `dw_attr_t` is also a `uint16_t` under the hood,
the type checking benefits here are undeniable: If this had returned a
something of different signedness/width, we could have had some bad
bugs.
Differential Revision: https://reviews.llvm.org/D150228
In an upcoming patch, D142556, Clang is proposed to be changed to emit
line locations that are inlined at line 0. This clashed with the behavior of
GetDIENamesAndRanges() which used 0 as a default value to determine if
file, line or column numbers had been set. Users of that function then
checked for any non-0 values when setting up the call site:
if (call_file != 0 || call_line != 0 || call_column != 0)
[...]
which did not work with the Clang change since all three values then
could be 0.
This changes the function to use std::optional to catch non-set values
instead.
Reviewed By: clayborg
Differential Revision: https://reviews.llvm.org/D142552
This came out of from https://discourse.llvm.org/t/dwarf-dwp-4gb-limit/63902
With big binaries we can have .dwp files where .debug_info.dwo section can grow
beyond 4GB. We would like to support this in LLVM and in LLDB.
The plan is to enable manual parsing of cu/tu index in DWARF library
(https://reviews.llvm.org/D137882), and then
switch internal index data structure to 64 bit.
For the second part is to enable 64bit offset support in LLDB with
this patch.
Reviewed By: labath
Differential Revision: https://reviews.llvm.org/D138618
This came out of from https://discourse.llvm.org/t/dwarf-dwp-4gb-limit/63902
With big binaries we can have .dwp files where .debug_info.dwo section can grow
beyond 4GB. We would like to support this in LLVM and in LLDB.
The plan is to enable manual parsing of cu/tu index in DWARF library
(https://reviews.llvm.org/D137882), and then
switch internal index data structure to 64 bit.
For the second part is to enable 64bit offset support in LLDB with
this patch.
Depends on D139955
Reviewed By: labath
Differential Revision: https://reviews.llvm.org/D138618
This came out of from https://discourse.llvm.org/t/dwarf-dwp-4gb-limit/63902
With big binaries we can have .dwp files where .debug_info.dwo section can grow
beyond 4GB. We would like to support this in LLVM and in LLDB.
The plan is to enable manual parsing of cu/tu index in DWARF library
(https://reviews.llvm.org/D137882), and then
switch internal index data structure to 64 bit.
For the second part is to enable 64bit offset support in LLDB with
this patch.
Depends on D139955
Reviewed By: labath
Differential Revision: https://reviews.llvm.org/D138618
In preparation for eanbling 64bit support in LLDB switching to use llvm::formatv
instead of format MACROs.
Reviewed By: labath, JDevlieghere
Differential Revision: https://reviews.llvm.org/D139955
This patch mechanically replaces None with std::nullopt where the
compiler would warn if None were deprecated. The intent is to reduce
the amount of manual work required in migrating from Optional to
std::optional.
This is part of an effort to migrate from llvm::Optional to
std::optional:
https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
In D134378, we'll need the clang AST to be able to construct the qualified in some cases.
This makes logging in one place slightly less informative.
Reviewed By: dblaikie, Michael137
Differential Revision: https://reviews.llvm.org/D135979
When fission is enabled, we were indexing the skeleton CU _and_ the .dwo CU. Issues arise when users enable compiler options that add extra data to the skeleton CU (like -fsplit-dwarf-inlining) and there can end up being types in the skeleton CU due to template parameters. We never want to index this information since the .dwo file has the real definition, and we really don't want function prototypes from this info since all parameters are removed. The index doesn't work correctly if it does index the skeleton CU as the DIE offset will assume it is from the .dwo file, so even if we do index the skeleton CU, the index entries will try and grab information from the .dwo file using the wrong DIE offset which can cause errors to be displayed or even worse, if the DIE offsets is valid in the .dwo CU, the wrong DIE will be used.
We also fix DWO ID detection to use llvm::Optional<uint64_t> to make sure we can load a .dwo file with a DWO ID of zero.
Differential Revision: https://reviews.llvm.org/D131437
This reverts commit 967df65a3610f98a3bc0ec0f2303641d7bad176c.
This fixes test/Shell/SymbolFile/NativePDB/find-functions.cpp. When
looking up functions with the PDB plugins, if we are looking for a
full function name, we should use `GetName` to populate the `name`
field instead of `GetLookupName` since `GetName` has the more
complete information.
This reverts commit befa77e59a7760d8c4fdd177b234e4a59500f61c.
Looks like this broke a SymbolFileNativePDB test. I'll investigate and
resubmit with a fix soon.
Context:
When setting a breakpoint by name, we invoke Module::FindFunctions to
find the function(s) in question. However, we use a Module::LookupInfo
to first process the user-provided name and figure out exactly what
we're looking for. When we actually perform the function lookup, we
search for the basename. After performing the search, we then filter out
the results using Module::LookupInfo::Prune. For example, given
a:🅱️:foo we would first search for all instances of foo and then filter
out the results to just names that have a:🅱️:foo in them. As one can
imagine, this involves a lot of debug info processing that we do not
necessarily need to be doing. Instead of doing one large post-processing
step after finding each instance of `foo`, we can filter them as we go
to save time.
Some numbers:
Debugging LLDB and placing a breakpoint on
llvm::itanium_demangle::StringView::begin without this change takes
approximately 70 seconds and resolves 31,920 DIEs. With this change,
placing the breakpoint takes around 30 seconds and resolves 8 DIEs.
Differential Revision: https://reviews.llvm.org/D129682
This reland 227dffd0b6d78154516ace45f6ed28259c7baa48 and
562c3467a6738aa89203f72fc1d1343e5baadf3c with failed api tests fixed by keeping
function base file addres in DWARFExpressionList.
We have using namespace llvm::dwarf in dwarf.h header globally. Replacing that
with a using namespace within lldb_private::dwarf and moving to a
using namespace lldb_private::dwarf in .cpp files and fully qualified names
in the few header files.
Differential Revision: https://reviews.llvm.org/D120836
The C headers are deprecated so as requested in D102845, this is replacing them
all with their (not deprecated) C++ equivalent.
Reviewed By: shafik
Differential Revision: https://reviews.llvm.org/D103084
In D98289#inline-939112 @dblaikie said:
Perhaps this could be more informative about what makes the range list
index of 0 invalid? "index 0 out of range of range list table (with
range list base 0xXXX) with offset entry count of XX (valid indexes
0-(XX-1))" Maybe that's too verbose/not worth worrying about since
this'll only be relevant to DWARF producers trying to debug their
DWARFv5, maybe no one will ever see this message in practice. Just
a thought.
Reviewed By: dblaikie
Differential Revision: https://reviews.llvm.org/D102851
gcc already produces debug info with this form
-freorder-block-and-partition
clang produces this sort of thing with -fbasic-block-sections and with a
coming-soon tweak to use ranges in DWARFv5 where they can allow greater
reuse of debug_addr than the low/high_pc forms.
This fixes the case of breaking on a function name, but leaves broken
printing a variable - a follow-up commit will add that and improve the
test case to match.
Differential Revision: https://reviews.llvm.org/D94063
This would be reproducible in future DWZ category of the testsuite as:
Failed Tests (1):
lldb-api :: python_api/symbol-context/two-files/TestSymbolContextTwoFiles.py
Differential Revision: https://reviews.llvm.org/D91014
D80519 <https://reviews.llvm.org/D80519>
added support for `DW_TAG_GNU_call_site` but
Bug 45886 <https://bugs.llvm.org/show_bug.cgi?id=45886>
found one case did not work.
There is:
0x000000b1: DW_TAG_GNU_call_site
DW_AT_low_pc (0x000000000040111e)
DW_AT_abstract_origin (0x000000cc "a")
...
0x000000cc: DW_TAG_subprogram
DW_AT_name ("a")
DW_AT_prototyped (true)
DW_AT_low_pc (0x0000000000401109)
^^^^^^^^^^^^ - here it did overwrite the 'low_pc' variable containing value 0x40111e we wanted
DW_AT_high_pc (0x0000000000401114)
DW_AT_frame_base (DW_OP_call_frame_cfa)
DW_AT_GNU_all_call_sites (true)
DW_TAG_GNU_call_site attributes order as produced by GCC:
0x000000b1: DW_TAG_GNU_call_site
DW_AT_low_pc (0x000000000040111e)
DW_AT_abstract_origin (0x000000cc "a")
clang produces the attributes in opposite order:
0x00000064: DW_TAG_GNU_call_site
DW_AT_abstract_origin (0x0000002a "a")
DW_AT_low_pc (0x0000000000401146)
Differential Revision: https://reviews.llvm.org/D81334
The dumping code is not used by anyone, and is a source of
inconsistencies with the llvm dwarf parser, as dumping is implemented at
a different level (DWARFDie) there.
Summary:
The code in DWARFCompileUnit::BuildAddressRangeTable tries hard to avoid
relying on DW_AT_low/high_pc for compile unit range information, and
this logic is a big cause of llvm/lldb divergence in the lowest layers
of dwarf parsing code.
The implicit assumption in that code is that this information (as opposed to
DW_AT_ranges) is unreliable. However, I have not been able to verify
that assumption. It is definitely not true for all present-day
compilers (gcc, clang, icc), and it was also not the case for the
historic compilers that I have been able to get a hold of (thanks Matt
Godbolt).
All compiler included in my research either produced correct
DW_AT_ranges or .debug_aranges entries, or they produced no DW_AT_hi/lo
pc at all. The detailed findings are:
- gcc >= 4.4: produces DW_AT_ranges and .debug_aranges
- 4.1 <= gcc < 4.4: no DW_AT_ranges, no DW_AT_high_pc, .debug_aranges
present. The upper version range here is uncertain as godbolt.org does
not have intermediate versions.
- gcc < 4.1: no versions on godbolt.org
- clang >= 3.5: produces DW_AT_ranges, and (optionally) .debug_aranges
- 3.4 <= clang < 3.5: no DW_AT_ranges, no DW_AT_high_pc, .debug_aranges
present.
- clang <= 3.3: no DW_AT_ranges, no DW_AT_high_pc, no .debug_aranges
- icc >= 16.0.1: produces DW_AT_ranges
- icc < 16.0.1: no functional versions on godbolt.org (some are present
but fail to compile)
Based on this analysis, I believe it is safe to start trusting
DW_AT_low/high_pc information in dwarf as well as remove the code for
manually reconstructing range information by traversing the DIE
structure, and just keep the line table fallback. The only compilers
where this will change behavior are pre-3.4 clangs, which are almost 7
years old now. However, the functionality should remain unchanged
because we will be able to reconstruct this information from the line
table, which seems to be needed for some line-tables-only scenarios
anyway (haven't researched this too much, but at least some compilers
seem to emit DW_AT_ranges even in these situations).
In addition, benchmarks showed that for these compilers computing the
ranges via line tables is noticably faster than doing so via the DIE
tree.
Other advantages include simplifying the code base, removing some
untested code (the only test changes are recent tests with overly
reduced synthetic dwarf), and increasing llvm convergence.
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D78489