aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp')
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp296
1 files changed, 296 insertions, 0 deletions
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
new file mode 100644
index 000000000000..3e511007a1ec
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
@@ -0,0 +1,296 @@
+//===-- DWARFDebugPubnames.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugPubnames.h"
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Timer.h"
+
+#include "DWARFDebugInfo.h"
+#include "DWARFDIECollection.h"
+#include "DWARFFormValue.h"
+#include "DWARFCompileUnit.h"
+#include "LogChannelDWARF.h"
+#include "SymbolFileDWARF.h"
+
+
+using namespace lldb;
+using namespace lldb_private;
+
+DWARFDebugPubnames::DWARFDebugPubnames() :
+ m_sets()
+{
+}
+
+bool
+DWARFDebugPubnames::Extract(const DataExtractor& data)
+{
+ Timer scoped_timer (__PRETTY_FUNCTION__,
+ "DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
+ (uint64_t)data.GetByteSize());
+ Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
+ if (log)
+ log->Printf("DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")", (uint64_t)data.GetByteSize());
+
+ if (data.ValidOffset(0))
+ {
+ lldb::offset_t offset = 0;
+
+ DWARFDebugPubnamesSet set;
+ while (data.ValidOffset(offset))
+ {
+ if (set.Extract(data, &offset))
+ {
+ m_sets.push_back(set);
+ offset = set.GetOffsetOfNextEntry();
+ }
+ else
+ break;
+ }
+ if (log)
+ Dump (log);
+ return true;
+ }
+ return false;
+}
+
+
+bool
+DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
+{
+ Timer scoped_timer (__PRETTY_FUNCTION__,
+ "DWARFDebugPubnames::GeneratePubnames (data = %p)",
+ dwarf2Data);
+
+ Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
+ if (log)
+ log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)", dwarf2Data);
+
+ m_sets.clear();
+ DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
+ if (debug_info)
+ {
+
+ const DataExtractor* debug_str = &dwarf2Data->get_debug_str_data();
+
+ uint32_t cu_idx = 0;
+ const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
+ for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+ {
+
+ DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+
+ const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize());
+
+ bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1;
+
+ DWARFDIECollection dies;
+ const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_subprogram, dies) +
+ cu->AppendDIEsWithTag (DW_TAG_variable, dies);
+
+ dw_offset_t cu_offset = cu->GetOffset();
+ DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset);
+
+ size_t die_idx;
+ for (die_idx = 0; die_idx < die_count; ++die_idx)
+ {
+ const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx);
+ DWARFDebugInfoEntry::Attributes attributes;
+ const char *name = NULL;
+ const char *mangled = NULL;
+ bool add_die = false;
+ const size_t num_attributes = die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes);
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+
+ dw_tag_t tag = die->Tag();
+
+ for (i=0; i<num_attributes; ++i)
+ {
+ dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ switch (attr)
+ {
+ case DW_AT_name:
+ if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
+ name = form_value.AsCString(debug_str);
+ break;
+
+ case DW_AT_MIPS_linkage_name:
+ case DW_AT_linkage_name:
+ if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
+ mangled = form_value.AsCString(debug_str);
+ break;
+
+ case DW_AT_low_pc:
+ case DW_AT_ranges:
+ case DW_AT_entry_pc:
+ if (tag == DW_TAG_subprogram)
+ add_die = true;
+ break;
+
+ case DW_AT_location:
+ if (tag == DW_TAG_variable)
+ {
+ const DWARFDebugInfoEntry* parent_die = die->GetParent();
+ while ( parent_die != NULL )
+ {
+ switch (parent_die->Tag())
+ {
+ case DW_TAG_subprogram:
+ case DW_TAG_lexical_block:
+ case DW_TAG_inlined_subroutine:
+ // Even if this is a function level static, we don't add it. We could theoretically
+ // add these if we wanted to by introspecting into the DW_AT_location and seeing
+ // if the location describes a hard coded address, but we don't want the performance
+ // penalty of that right now.
+ add_die = false;
+// if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
+// {
+// // If we have valid block data, then we have location expression bytes
+// // that are fixed (not a location list).
+// const uint8_t *block_data = form_value.BlockData();
+// if (block_data)
+// {
+// uint32_t block_length = form_value.Unsigned();
+// if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
+// {
+// if (block_data[0] == DW_OP_addr)
+// add_die = true;
+// }
+// }
+// }
+ parent_die = NULL; // Terminate the while loop.
+ break;
+
+ case DW_TAG_compile_unit:
+ add_die = true;
+ parent_die = NULL; // Terminate the while loop.
+ break;
+
+ default:
+ parent_die = parent_die->GetParent(); // Keep going in the while loop.
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ if (add_die && (name || mangled))
+ {
+ pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, mangled ? mangled : name);
+ }
+ }
+
+ if (pubnames_set.NumDescriptors() > 0)
+ {
+ m_sets.push_back(pubnames_set);
+ }
+
+ // Keep memory down by clearing DIEs if this generate function
+ // caused them to be parsed
+ if (clear_dies)
+ cu->ClearDIEs (true);
+ }
+ }
+ if (m_sets.empty())
+ return false;
+ if (log)
+ Dump (log);
+ return true;
+}
+
+bool
+DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data)
+{
+ m_sets.clear();
+ DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
+ if (debug_info)
+ {
+ uint32_t cu_idx = 0;
+ const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
+ for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+ {
+ DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+ DWARFDIECollection dies;
+ const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_base_type, dies);
+ dw_offset_t cu_offset = cu->GetOffset();
+ DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset);
+
+ size_t die_idx;
+ for (die_idx = 0; die_idx < die_count; ++die_idx)
+ {
+ const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx);
+ const char *name = die->GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, NULL);
+
+ if (name)
+ {
+ pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, name);
+ }
+ }
+
+ if (pubnames_set.NumDescriptors() > 0)
+ {
+ m_sets.push_back(pubnames_set);
+ }
+ }
+ }
+ return !m_sets.empty();
+}
+
+void
+DWARFDebugPubnames::Dump(Log *s) const
+{
+ if (m_sets.empty())
+ s->PutCString("< EMPTY >\n");
+ else
+ {
+ const_iterator pos;
+ const_iterator end = m_sets.end();
+
+ for (pos = m_sets.begin(); pos != end; ++pos)
+ (*pos).Dump(s);
+ }
+}
+
+bool
+DWARFDebugPubnames::Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offsets) const
+{
+ const_iterator pos;
+ const_iterator end = m_sets.end();
+
+ die_offsets.clear();
+
+ for (pos = m_sets.begin(); pos != end; ++pos)
+ {
+ (*pos).Find(name, ignore_case, die_offsets);
+ }
+
+ return !die_offsets.empty();
+}
+
+bool
+DWARFDebugPubnames::Find(const RegularExpression& regex, std::vector<dw_offset_t>& die_offsets) const
+{
+ const_iterator pos;
+ const_iterator end = m_sets.end();
+
+ die_offsets.clear();
+
+ for (pos = m_sets.begin(); pos != end; ++pos)
+ {
+ (*pos).Find(regex, die_offsets);
+ }
+
+ return !die_offsets.empty();
+}