diff options
| author | Pavel Labath <pavel@labath.sk> | 2019-12-05 16:21:23 +0100 |
|---|---|---|
| committer | Pavel Labath <pavel@labath.sk> | 2019-12-06 10:33:13 +0100 |
| commit | f69f92344adaada1f8f3cfcd711037227432b062 (patch) | |
| tree | 2e0381806a396e215749074aa33fb3a215b0f811 /lldb/source/Plugins/SymbolFile | |
| parent | b6e2cf3270dab43dbc6ffad4695c5c14789bc5e5 (diff) | |
| download | bcm5719-llvm-f69f92344adaada1f8f3cfcd711037227432b062.tar.gz bcm5719-llvm-f69f92344adaada1f8f3cfcd711037227432b062.zip | |
[lldb/DWARF] Fix DW_AT_addr_base & DW_AT_low_pc interaction
In DWARF5 DW_AT_low_pc (and DW_AT_entry_pc, and possibly others) can use
DW_FORM_addrx to refer to the address indirectly. This means we need to
have processed the DW_AT_addr_base attribute before we can do anything
with these.
Since we were processing the unit attributes serially, this created a
problem in cases where the DW_AT_addr_base comes after DW_AT_low_pc --
we would end up computing the wrong unit base address, which also
corrupted any values which later depended on that (for instance range
lists). Clang currently always emits DW_AT_addr_base last.
The fix is simple -- process DW_AT_addr_base first, regardless of its
position in the attribute list.
Diffstat (limited to 'lldb/source/Plugins/SymbolFile')
| -rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 35f5c30e177..072cbc2abc3 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -287,16 +287,25 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { DWARFAttributes attributes; size_t num_attributes = cu_die.GetAttributes(this, attributes); + + // Extract DW_AT_addr_base first, as other attributes may need it. + for (size_t i = 0; i < num_attributes; ++i) { + if (attributes.AttributeAtIndex(i) != DW_AT_addr_base) + continue; + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + addr_base = form_value.Unsigned(); + SetAddrBase(*addr_base); + break; + } + } + for (size_t i = 0; i < num_attributes; ++i) { dw_attr_t attr = attributes.AttributeAtIndex(i); DWARFFormValue form_value; if (!attributes.ExtractFormValueAtIndex(i, form_value)) continue; switch (attr) { - case DW_AT_addr_base: - addr_base = form_value.Unsigned(); - SetAddrBase(*addr_base); - break; case DW_AT_rnglists_base: ranges_base = form_value.Unsigned(); SetRangesBase(*ranges_base); |

