[Lldb-commits] [lldb] r333437 - Fix DWARFUnit::GetUnitDIEPtrOnly stale pointer
Jan Kratochvil via lldb-commits
lldb-commits at lists.llvm.org
Tue May 29 10:17:46 PDT 2018
Author: jankratochvil
Date: Tue May 29 10:17:46 2018
New Revision: 333437
URL: http://llvm.org/viewvc/llvm-project?rev=333437&view=rev
Log:
Fix DWARFUnit::GetUnitDIEPtrOnly stale pointer
GetUnitDIEPtrOnly() needs to return pointer to the first DIE.
But the first element of m_die_array after ExtractDIEsIfNeeded(true)
may move in memory after later ExtractDIEsIfNeeded(false).
DWARFDebugInfoEntry::collection m_die_array is std::vector,
its data may move during its expansion.
Differential revision: https://reviews.llvm.org/D46810
Modified:
lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp?rev=333437&r1=333436&r2=333437&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp Tue May 29 10:17:46 2018
@@ -1825,3 +1825,15 @@ void DWARFDebugInfoEntry::DumpDIECollect
die_ref.HasChildren() ? " *" : "");
}
}
+
+bool DWARFDebugInfoEntry::operator==(const DWARFDebugInfoEntry &rhs) const {
+ return m_offset == rhs.m_offset && m_parent_idx == rhs.m_parent_idx &&
+ m_sibling_idx == rhs.m_sibling_idx &&
+ m_empty_children == rhs.m_empty_children &&
+ m_abbr_idx == rhs.m_abbr_idx && m_has_children == rhs.m_has_children &&
+ m_tag == rhs.m_tag;
+}
+
+bool DWARFDebugInfoEntry::operator!=(const DWARFDebugInfoEntry &rhs) const {
+ return !(*this == rhs);
+}
Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h?rev=333437&r1=333436&r2=333437&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h Tue May 29 10:17:46 2018
@@ -60,6 +60,10 @@ public:
m_empty_children(false), m_abbr_idx(0), m_has_children(false),
m_tag(0) {}
+ explicit operator bool() const { return m_offset != DW_INVALID_OFFSET; }
+ bool operator==(const DWARFDebugInfoEntry &rhs) const;
+ bool operator!=(const DWARFDebugInfoEntry &rhs) const;
+
void BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data,
const DWARFUnit *cu,
DWARFDebugAranges *debug_aranges) const;
Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp?rev=333437&r1=333436&r2=333437&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp Tue May 29 10:17:46 2018
@@ -14,6 +14,7 @@
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
@@ -35,19 +36,45 @@ DWARFUnit::DWARFUnit(SymbolFileDWARF *dw
DWARFUnit::~DWARFUnit() {}
//----------------------------------------------------------------------
-// ParseCompileUnitDIEsIfNeeded
-//
+// Parses first DIE of a compile unit.
+//----------------------------------------------------------------------
+void DWARFUnit::ExtractUnitDIEIfNeeded() {
+ if (m_first_die)
+ return; // Already parsed
+
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(
+ func_cat, "%8.8x: DWARFUnit::ExtractUnitDIEIfNeeded()", m_offset);
+
+ // Set the offset to that of the first DIE and calculate the start of the
+ // next compilation unit header.
+ lldb::offset_t offset = GetFirstDIEOffset();
+
+ // We are in our compile unit, parse starting at the offset we were told to
+ // parse
+ const DWARFDataExtractor &data = GetData();
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
+ IsDWARF64());
+ if (offset < GetNextCompileUnitOffset() &&
+ m_first_die.FastExtract(data, this, fixed_form_sizes, &offset)) {
+ AddUnitDIE(m_first_die);
+ return;
+ }
+
+ ExtractDIEsEndCheck(offset);
+}
+
+//----------------------------------------------------------------------
// Parses a compile unit and indexes its DIEs if it hasn't already been done.
//----------------------------------------------------------------------
-size_t DWARFUnit::ExtractDIEsIfNeeded(bool cu_die_only) {
- const size_t initial_die_array_size = m_die_array.size();
- if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1)
+bool DWARFUnit::ExtractDIEsIfNeeded() {
+ if (!m_die_array.empty())
return 0; // Already parsed
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(
- func_cat, "%8.8x: DWARFUnit::ExtractDIEsIfNeeded( cu_die_only = %i )",
- m_offset, cu_die_only);
+ func_cat, "%8.8x: DWARFUnit::ExtractDIEsIfNeeded()", m_offset);
// Set the offset to that of the first DIE and calculate the start of the
// next compilation unit header.
@@ -56,16 +83,14 @@ size_t DWARFUnit::ExtractDIEsIfNeeded(bo
DWARFDebugInfoEntry die;
// Keep a flat array of the DIE for binary lookup by DIE offset
- if (!cu_die_only) {
- Log *log(
- LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS));
- if (log) {
- m_dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
- log,
- "DWARFUnit::ExtractDIEsIfNeeded () for compile unit at "
- ".debug_info[0x%8.8x]",
- GetOffset());
- }
+ Log *log(
+ LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS));
+ if (log) {
+ m_dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
+ log,
+ "DWARFUnit::ExtractDIEsIfNeeded () for compile unit at "
+ ".debug_info[0x%8.8x]",
+ GetOffset());
}
uint32_t depth = 0;
@@ -90,16 +115,21 @@ size_t DWARFUnit::ExtractDIEsIfNeeded(bo
const bool null_die = die.IsNULL();
if (depth == 0) {
- if (initial_die_array_size == 0)
- AddUnitDIE(die);
- uint64_t base_addr = die.GetAttributeValueAsAddress(
- m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
- if (base_addr == LLDB_INVALID_ADDRESS)
- base_addr =
- die.GetAttributeValueAsAddress(m_dwarf, this, DW_AT_entry_pc, 0);
- SetBaseAddress(base_addr);
- if (cu_die_only)
- return 1;
+ assert(m_die_array.empty() && "Compile unit DIE already added");
+
+ // The average bytes per DIE entry has been seen to be around 14-20 so
+ // lets pre-reserve half of that since we are now stripping the NULL
+ // tags.
+
+ // Only reserve the memory if we are adding children of the main
+ // compile unit DIE. The compile unit DIE is always the first entry, so
+ // if our size is 1, then we are adding the first compile unit child
+ // DIE and should reserve the memory.
+ m_die_array.reserve(GetDebugInfoSize() / 24);
+ m_die_array.push_back(die);
+
+ if (!m_first_die)
+ AddUnitDIE(m_die_array.front());
} else {
if (null_die) {
if (prev_die_had_children) {
@@ -145,14 +175,9 @@ size_t DWARFUnit::ExtractDIEsIfNeeded(bo
}
}
- // Give a little bit of info if we encounter corrupt DWARF (our offset should
- // always terminate at or before the start of the next compilation unit
- // header).
- if (offset > next_cu_offset) {
- m_dwarf->GetObjectFile()->GetModule()->ReportWarning(
- "DWARF compile unit extends beyond its bounds cu 0x%8.8x at "
- "0x%8.8" PRIx64 "\n",
- GetOffset(), offset);
+ if (!m_die_array.empty()) {
+ lldbassert(!m_first_die || m_first_die == m_die_array.front());
+ m_first_die = m_die_array.front();
}
// Since std::vector objects will double their size, we really need to make a
@@ -164,6 +189,34 @@ size_t DWARFUnit::ExtractDIEsIfNeeded(bo
m_die_array.end());
exact_size_die_array.swap(m_die_array);
}
+
+ ExtractDIEsEndCheck(offset);
+
+ if (!m_dwo_symbol_file)
+ return m_die_array.size();
+
+ DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit();
+ size_t dwo_die_count = dwo_cu->ExtractDIEsIfNeeded();
+ return m_die_array.size() + dwo_die_count -
+ 1; // We have 2 CU die, but we want to count it only as one
+}
+
+//--------------------------------------------------------------------------
+// Final checks for both ExtractUnitDIEIfNeeded() and ExtractDIEsIfNeeded().
+//--------------------------------------------------------------------------
+void DWARFUnit::ExtractDIEsEndCheck(lldb::offset_t offset) const {
+ lldb::offset_t next_cu_offset = GetNextCompileUnitOffset();
+
+ // Give a little bit of info if we encounter corrupt DWARF (our offset should
+ // always terminate at or before the start of the next compilation unit
+ // header).
+ if (offset > GetNextCompileUnitOffset()) {
+ m_dwarf->GetObjectFile()->GetModule()->ReportWarning(
+ "DWARF compile unit extends beyond its bounds cu 0x%8.8x at "
+ "0x%8.8" PRIx64 "\n",
+ GetOffset(), offset);
+ }
+
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
if (log && log->GetVerbose()) {
StreamString strm;
@@ -174,30 +227,16 @@ size_t DWARFUnit::ExtractDIEsIfNeeded(bo
m_die_array[0].Dump(m_dwarf, this, strm, UINT32_MAX);
log->PutString(strm.GetString());
}
-
- if (!m_dwo_symbol_file)
- return m_die_array.size();
-
- DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit();
- size_t dwo_die_count = dwo_cu->ExtractDIEsIfNeeded(cu_die_only);
- return m_die_array.size() + dwo_die_count -
- 1; // We have 2 CU die, but we want to count it only as one
}
-void DWARFUnit::AddUnitDIE(DWARFDebugInfoEntry &die) {
- assert(m_die_array.empty() && "Compile unit DIE already added");
-
- // The average bytes per DIE entry has been seen to be around 14-20 so lets
- // pre-reserve half of that since we are now stripping the NULL tags.
-
- // Only reserve the memory if we are adding children of the main compile unit
- // DIE. The compile unit DIE is always the first entry, so if our size is 1,
- // then we are adding the first compile unit child DIE and should reserve the
- // memory.
- m_die_array.reserve(GetDebugInfoSize() / 24);
- m_die_array.push_back(die);
+void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
+ uint64_t base_addr = cu_die.GetAttributeValueAsAddress(
+ m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
+ if (base_addr == LLDB_INVALID_ADDRESS)
+ base_addr = cu_die.GetAttributeValueAsAddress(
+ m_dwarf, this, DW_AT_entry_pc, 0);
+ SetBaseAddress(base_addr);
- const DWARFDebugInfoEntry &cu_die = m_die_array.front();
std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
m_dwarf->GetDwoSymbolFileForCompileUnit(*this, cu_die);
if (!dwo_symbol_file)
@@ -289,19 +328,8 @@ void DWARFUnit::SetAddrBase(dw_addr_t ad
}
void DWARFUnit::ClearDIEs() {
- if (m_die_array.size() > 1) {
- // std::vectors never get any smaller when resized to a smaller size, or
- // when clear() or erase() are called, the size will report that it is
- // smaller, but the memory allocated remains intact (call capacity() to see
- // this). So we need to create a temporary vector and swap the contents
- // which will cause just the internal pointers to be swapped so that when
- // "tmp_array" goes out of scope, it will destroy the contents.
-
- // Save at least the compile unit DIE
- DWARFDebugInfoEntry::collection tmp_array;
- m_die_array.swap(tmp_array);
- m_die_array.push_back(tmp_array.front());
- }
+ m_die_array.clear();
+ m_die_array.shrink_to_fit();
if (m_dwo_symbol_file)
m_dwo_symbol_file->GetCompileUnit()->ClearDIEs();
@@ -342,7 +370,7 @@ void DWARFUnit::BuildAddressRangeTable(S
// If the DIEs weren't parsed, then we don't want all dies for all compile
// units to stay loaded when they weren't needed. So we can end up parsing
// the DWARF and then throwing them all away to keep memory usage down.
- const bool clear_dies = ExtractDIEsIfNeeded(false) > 1;
+ const bool clear_dies = ExtractDIEsIfNeeded();
die = DIEPtr();
if (die)
@@ -447,7 +475,7 @@ DWARFUnit::GetDIE(dw_offset_t die_offset
return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset);
if (ContainsDIEOffset(die_offset)) {
- ExtractDIEsIfNeeded(false);
+ ExtractDIEsIfNeeded();
DWARFDebugInfoEntry::const_iterator end = m_die_array.cend();
DWARFDebugInfoEntry::const_iterator pos =
lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset);
Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.h?rev=333437&r1=333436&r2=333437&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.h Tue May 29 10:17:46 2018
@@ -39,7 +39,8 @@ class DWARFUnit {
public:
virtual ~DWARFUnit();
- size_t ExtractDIEsIfNeeded(bool cu_die_only);
+ void ExtractUnitDIEIfNeeded();
+ bool ExtractDIEsIfNeeded();
DWARFDIE LookupAddress(const dw_addr_t address);
size_t AppendDIEsWithTag(const dw_tag_t tag,
DWARFDIECollection &matching_dies,
@@ -160,7 +161,7 @@ public:
dw_offset_t GetBaseObjOffset() const;
die_iterator_range dies() {
- ExtractDIEsIfNeeded(false);
+ ExtractDIEsIfNeeded();
return die_iterator_range(m_die_array.begin(), m_die_array.end());
}
@@ -173,6 +174,10 @@ protected:
void *m_user_data = nullptr;
// The compile unit debug information entry item
DWARFDebugInfoEntry::collection m_die_array;
+ // GetUnitDIEPtrOnly() needs to return pointer to the first DIE.
+ // But the first element of m_die_array after ExtractUnitDIEIfNeeded()
+ // would possibly move in memory after later ExtractDIEsIfNeeded().
+ DWARFDebugInfoEntry m_first_die;
// A table similar to the .debug_aranges table, but this one points to the
// exact DW_TAG_subprogram DIEs
std::unique_ptr<DWARFDebugAranges> m_func_aranges_ap;
@@ -202,21 +207,22 @@ private:
// Get the DWARF unit DWARF debug informration entry. Parse the single DIE
// if needed.
const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() {
- ExtractDIEsIfNeeded(true);
- if (m_die_array.empty())
+ ExtractUnitDIEIfNeeded();
+ if (!m_first_die)
return NULL;
- return &m_die_array[0];
+ return &m_first_die;
}
// Get all DWARF debug informration entries. Parse all DIEs if needed.
const DWARFDebugInfoEntry *DIEPtr() {
- ExtractDIEsIfNeeded(false);
+ ExtractDIEsIfNeeded();
if (m_die_array.empty())
return NULL;
return &m_die_array[0];
}
- void AddUnitDIE(DWARFDebugInfoEntry &die);
+ void AddUnitDIE(const DWARFDebugInfoEntry &cu_die);
+ void ExtractDIEsEndCheck(lldb::offset_t offset) const;
DISALLOW_COPY_AND_ASSIGN(DWARFUnit);
};
Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp?rev=333437&r1=333436&r2=333437&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp Tue May 29 10:17:46 2018
@@ -50,9 +50,9 @@ void ManualDWARFIndex::Index() {
auto extract_fn = [&debug_info, &clear_cu_dies](size_t cu_idx) {
DWARFUnit *dwarf_cu = debug_info.GetCompileUnitAtIndex(cu_idx);
if (dwarf_cu) {
- // dwarf_cu->ExtractDIEsIfNeeded(false) will return zero if the DIEs
+ // dwarf_cu->ExtractDIEsIfNeeded() will return false if the DIEs
// for a compile unit have already been parsed.
- if (dwarf_cu->ExtractDIEsIfNeeded(false) > 1)
+ if (dwarf_cu->ExtractDIEsIfNeeded())
clear_cu_dies[cu_idx] = true;
}
};
More information about the lldb-commits
mailing list