clayborg created this revision.

This patch adds support for type units and parsing the .debug_types section 
which allows LLDB to debug binaries that were built with "-gdwarf-4 
-fdebug-types-section". This patch takes into account how DWARF 5 will 
represent type units: all compile units will contain extra fields and all type 
units are in the .debug_info section.

Normally this change would be very invasive because we would need to make a way 
for DIEs in the .debug_types section to have unique IDs (lldb::user_id_t). This 
patch takes advantage of the fact that debug info in the .debug_types section 
can't point to any other DWARF directly. There are only CU relative references 
and type signatures that might point to other debug info, but indirected 
through the type signature. This means the offset of the DIEs in the 
,.debug_types section are not important. Given all of this, there are the 
important takes from this patch:

- Modify DWARFCompileUnit to contain extra fields: type signature and type 
offset. This is the way DWARF5 is doing it, so we will need to do that anyway 
in the near future.
- Slide the offset of all DIEs in .debug_types by the size of the .debug_info 
section. This allows every DIE to have unique offset and allows this patch to 
"just work" with the existing DWARF parser
- Anyone extracting attribute values must use the DWARFDIE::GetData() or 
DWARFCompileUnit::GetData() to make sure they are getting the right info 
(.debug_info or .debug_types) to extract from
- LLDB testing adds a new "_dwarf_debug_types" variant (like we add the _dwarf, 
_dwarf_dsym, _dwo) on platforms that support the .debug_types

I would love to get this in. Anything is better that what LLDB does now when it 
debugs binaries with .debug_types: crash a lot. So we should get this in and 
iterate on it.


https://reviews.llvm.org/D32167

Files:
  include/lldb/lldb-enumerations.h
  include/lldb/lldb-forward.h
  packages/Python/lldbsuite/test/lldbinline.py
  packages/Python/lldbsuite/test/lldbtest.py
  packages/Python/lldbsuite/test/make/Makefile.rules
  packages/Python/lldbsuite/test/plugins/builder_base.py
  packages/Python/lldbsuite/test/test_categories.py
  source/Core/Section.cpp
  source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
  source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
  source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
  source/Plugins/SymbolFile/DWARF/DIERef.cpp
  source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
  source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
  source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
  source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
  source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
  source/Plugins/SymbolFile/DWARF/DWARFDIE.h
  source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp
  source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
  source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
  source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
  source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
  source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
  source/Symbol/ObjectFile.cpp

Index: source/Symbol/ObjectFile.cpp
===================================================================
--- source/Symbol/ObjectFile.cpp
+++ source/Symbol/ObjectFile.cpp
@@ -356,6 +356,7 @@
           case eSectionTypeDWARFDebugRanges:
           case eSectionTypeDWARFDebugStr:
           case eSectionTypeDWARFDebugStrOffsets:
+          case eSectionTypeDWARFDebugTypes:
           case eSectionTypeDWARFAppleNames:
           case eSectionTypeDWARFAppleTypes:
           case eSectionTypeDWARFAppleNamespaces:
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -244,6 +244,7 @@
   const lldb_private::DWARFDataExtractor &get_debug_ranges_data();
   const lldb_private::DWARFDataExtractor &get_debug_str_data();
   const lldb_private::DWARFDataExtractor &get_debug_str_offsets_data();
+  const lldb_private::DWARFDataExtractor &get_debug_types_data();
   const lldb_private::DWARFDataExtractor &get_apple_names_data();
   const lldb_private::DWARFDataExtractor &get_apple_types_data();
   const lldb_private::DWARFDataExtractor &get_apple_namespaces_data();
@@ -477,6 +478,7 @@
   DWARFDataSegment m_data_debug_ranges;
   DWARFDataSegment m_data_debug_str;
   DWARFDataSegment m_data_debug_str_offsets;
+  DWARFDataSegment m_data_debug_types;
   DWARFDataSegment m_data_apple_names;
   DWARFDataSegment m_data_apple_types;
   DWARFDataSegment m_data_apple_namespaces;
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -558,8 +558,23 @@
 const DWARFDataExtractor &
 SymbolFileDWARF::GetCachedSectionData(lldb::SectionType sect_type,
                                       DWARFDataSegment &data_segment) {
-  llvm::call_once(data_segment.m_flag, [this, sect_type, &data_segment] {
+  llvm::call_once(data_segment.m_flag, [&] {
     this->LoadSectionData(sect_type, std::ref(data_segment.m_data));
+    if (sect_type == eSectionTypeDWARFDebugTypes) {
+      // To add .debug_types support with minimally invasive changes, we pretend
+      // that any DIEs in .debug_types start at the end of the .debug_info
+      // section. All info in .debug_types is relative and has no external DIE
+      // references unless thay are DW_AT_signature references, so the DIE
+      // offset for things in the .debug_types. If we do this, then we can
+      // just add the type units to the compile units collection and treat all
+      // information just as we do for all other information in the DWARF and
+      // everything just works. If we were to try to split this out, we would
+      // end up having to change a TON of code. Also DWARF 5 will have compile
+      // and type units in the .debug_info, so coding it this way will prepare
+      // use for an easy transition to DWARF 5.
+      uint64_t debug_info_size = get_debug_info_data().GetByteSize();
+      data_segment.m_data.OffsetData(debug_info_size);
+    }
   });
   return data_segment.m_data;
 }
@@ -631,6 +646,10 @@
                               m_data_debug_str_offsets);
 }
 
+const DWARFDataExtractor &SymbolFileDWARF::get_debug_types_data() {
+  return GetCachedSectionData(eSectionTypeDWARFDebugTypes, m_data_debug_types);
+}
+
 const DWARFDataExtractor &SymbolFileDWARF::get_apple_names_data() {
   return GetCachedSectionData(eSectionTypeDWARFAppleNames, m_data_apple_names);
 }
@@ -3729,7 +3748,7 @@
               location_is_const_value_data = true;
               // The constant value will be either a block, a data value or a
               // string.
-              const DWARFDataExtractor &debug_info_data = get_debug_info_data();
+              auto debug_info_data = die.GetData();
               if (DWARFFormValue::IsBlockForm(form_value.Form())) {
                 // Retrieve the value as a block expression.
                 uint32_t block_offset =
@@ -3786,7 +3805,7 @@
             location_is_const_value_data = false;
             has_explicit_location = true;
             if (DWARFFormValue::IsBlockForm(form_value.Form())) {
-              const DWARFDataExtractor &debug_info_data = get_debug_info_data();
+              const DWARFDataExtractor &debug_info_data = die.GetData();
 
               uint32_t block_offset =
                   form_value.BlockData() - debug_info_data.GetDataStart();
Index: source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -580,6 +580,13 @@
     die_offset += m_cu->GetOffset();
     break;
 
+  case DW_FORM_ref_sig8:
+    // CU must be valid since we will need to back up into the debug info and
+    // find the DIE offset of the type in the type unit.
+    assert(m_cu);
+      die_offset = m_cu->FindTypeSignatureDIEOffset(m_value.value.uval);
+      break;
+
   default:
     break;
   }
@@ -598,6 +605,14 @@
     die_offset += base_offset;
     break;
 
+  case DW_FORM_ref_sig8:
+    // CU must be valid since we will need to back up into the debug info and
+    // find the DIE offset of the type in the type unit.
+    assert(m_cu);
+    die_offset = m_cu->FindTypeSignatureDIEOffset(m_value.value.uval) +
+        base_offset;
+    break;
+      
   default:
     break;
   }
Index: source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -196,7 +196,7 @@
 bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
                                   const DWARFCompileUnit *cu,
                                   lldb::offset_t *offset_ptr) {
-  const DWARFDataExtractor &debug_info_data = dwarf2Data->get_debug_info_data();
+  const DWARFDataExtractor &debug_info_data = cu->GetData();
   //    const DWARFDataExtractor& debug_str_data =
   //    dwarf2Data->get_debug_str_data();
   const uint32_t cu_end_offset = cu->GetNextCompileUnitOffset();
@@ -404,8 +404,7 @@
   lldb::ModuleSP module = dwarf2Data->GetObjectFile()->GetModule();
 
   if (abbrevDecl) {
-    const DWARFDataExtractor &debug_info_data =
-        dwarf2Data->get_debug_info_data();
+    const DWARFDataExtractor &debug_info_data = cu->GetData();
 
     if (!debug_info_data.ValidOffset(offset))
       return false;
@@ -588,7 +587,7 @@
 void DWARFDebugInfoEntry::Dump(SymbolFileDWARF *dwarf2Data,
                                const DWARFCompileUnit *cu, Stream &s,
                                uint32_t recurse_depth) const {
-  const DWARFDataExtractor &debug_info_data = dwarf2Data->get_debug_info_data();
+  const DWARFDataExtractor &debug_info_data = cu->GetData();
   lldb::offset_t offset = m_offset;
 
   if (debug_info_data.ValidOffset(offset)) {
@@ -782,8 +781,7 @@
   }
 
   if (abbrevDecl) {
-    const DWARFDataExtractor &debug_info_data =
-        dwarf2Data->get_debug_info_data();
+    const DWARFDataExtractor &debug_info_data = cu->GetData();
 
     if (fixed_form_sizes.Empty())
       fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(
@@ -864,8 +862,7 @@
     uint32_t attr_idx = abbrevDecl->FindAttributeIndex(attr);
 
     if (attr_idx != DW_INVALID_INDEX) {
-      const DWARFDataExtractor &debug_info_data =
-          dwarf2Data->get_debug_info_data();
+      const DWARFDataExtractor &debug_info_data = cu->GetData();
 
       uint32_t idx = 0;
       while (idx < attr_idx)
@@ -1797,7 +1794,7 @@
         // the DWARF data was mmap'ed, the backing file might have been modified
         // which is bad news.
         const uint64_t abbrev_code =
-            dwarf2Data->get_debug_info_data().GetULEB128(&offset);
+            cu->GetData().GetULEB128(&offset);
 
         if (abbrev_decl->Code() == abbrev_code)
           return abbrev_decl;
Index: source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
+++ source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -12,6 +12,7 @@
 
 #include <map>
 #include <vector>
+#include <unordered_map>
 
 #include "DWARFDIE.h"
 #include "SymbolFileDWARF.h"
@@ -37,6 +38,7 @@
   size_t GetNumCompileUnits();
   bool ContainsCompileUnit(const DWARFCompileUnit *cu) const;
   DWARFCompileUnit *GetCompileUnitAtIndex(uint32_t idx);
+  DWARFCompileUnit *GetTypeUnitForSignature(uint64_t type_sig);
   DWARFCompileUnit *GetCompileUnit(dw_offset_t cu_offset,
                                    uint32_t *idx_ptr = NULL);
   DWARFCompileUnit *GetCompileUnitContainingDIEOffset(dw_offset_t die_offset);
@@ -44,17 +46,6 @@
   DWARFDIE GetDIEForDIEOffset(dw_offset_t die_offset);
   DWARFDIE GetDIE(const DIERef &die_ref);
 
-  void Dump(lldb_private::Stream *s, const uint32_t die_offset,
-            const uint32_t recurse_depth);
-  static void Parse(SymbolFileDWARF *parser, Callback callback, void *userData);
-  static void Verify(lldb_private::Stream *s, SymbolFileDWARF *dwarf2Data);
-  static void Dump(lldb_private::Stream *s, SymbolFileDWARF *dwarf2Data,
-                   const uint32_t die_offset, const uint32_t recurse_depth);
-  bool Find(const char *name, bool ignore_case,
-            std::vector<dw_offset_t> &die_offsets) const;
-  bool Find(lldb_private::RegularExpression &re,
-            std::vector<dw_offset_t> &die_offsets) const;
-
   enum {
     eDumpFlag_Verbose = (1 << 0),  // Verbose dumping
     eDumpFlag_ShowForm = (1 << 1), // Show the DW_form type
@@ -66,6 +57,7 @@
 
 protected:
   typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP;
+  typedef std::unordered_map<uint64_t, uint32_t> TypeSignatureMap;
 
   static bool OffsetLessThanCompileUnitOffset(dw_offset_t offset,
                                               const DWARFCompileUnitSP &cu_sp);
@@ -77,6 +69,7 @@
   //----------------------------------------------------------------------
   SymbolFileDWARF *m_dwarf2Data;
   CompileUnitColl m_compile_units;
+  TypeSignatureMap m_type_sig_to_cu_index;
   std::unique_ptr<DWARFDebugAranges>
       m_cu_aranges_ap; // A quick address to compile unit table
 
Index: source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -97,8 +97,7 @@
   if (m_compile_units.empty()) {
     if (m_dwarf2Data != NULL) {
       lldb::offset_t offset = 0;
-      const DWARFDataExtractor &debug_info_data =
-          m_dwarf2Data->get_debug_info_data();
+      auto debug_info_data = m_dwarf2Data->get_debug_info_data();
       while (debug_info_data.ValidOffset(offset)) {
         DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data));
         // Out of memory?
@@ -105,7 +104,7 @@
         if (cu_sp.get() == NULL)
           break;
 
-        if (cu_sp->Extract(debug_info_data, &offset) == false)
+        if (cu_sp->Extract(debug_info_data, &offset, false) == false)
           break;
 
         m_compile_units.push_back(cu_sp);
@@ -112,6 +111,24 @@
 
         offset = cu_sp->GetNextCompileUnitOffset();
       }
+      
+      auto debug_types_data = m_dwarf2Data->get_debug_types_data();
+      offset = debug_info_data.GetByteSize();
+      while (debug_types_data.ValidOffset(offset)) {
+        DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data));
+        // Out of memory?
+        if (!cu_sp)
+          break;
+        
+        if (cu_sp->Extract(debug_types_data, &offset, true) == false)
+          break;
+        
+        m_type_sig_to_cu_index[cu_sp->GetTypeSignature()] = m_compile_units.size();
+
+        m_compile_units.push_back(cu_sp);
+        
+        offset = cu_sp->GetNextCompileUnitOffset();
+      }
     }
   }
 }
@@ -128,6 +145,13 @@
   return cu;
 }
 
+DWARFCompileUnit *DWARFDebugInfo::GetTypeUnitForSignature(uint64_t type_sig) {
+  auto pos = m_type_sig_to_cu_index.find(type_sig);
+  if (pos != m_type_sig_to_cu_index.end())
+    return GetCompileUnitAtIndex(pos->second);
+  return nullptr;
+}
+
 bool DWARFDebugInfo::ContainsCompileUnit(const DWARFCompileUnit *cu) const {
   // Not a verify efficient function, but it is handy for use in assertions
   // to make sure that a compile unit comes from a debug information file.
@@ -232,355 +256,3 @@
     return cu->GetDIE(die_ref.die_offset);
   return DWARFDIE(); // Not found
 }
-
-//----------------------------------------------------------------------
-// Parse
-//
-// Parses the .debug_info section and uses the .debug_abbrev section
-// and various other sections in the SymbolFileDWARF class and calls the
-// supplied callback function each time a compile unit header, or debug
-// information entry is successfully parsed. This function can be used
-// for different tasks such as parsing the file contents into a
-// structured data, dumping, verifying and much more.
-//----------------------------------------------------------------------
-void DWARFDebugInfo::Parse(SymbolFileDWARF *dwarf2Data, Callback callback,
-                           void *userData) {
-  if (dwarf2Data) {
-    lldb::offset_t offset = 0;
-    uint32_t depth = 0;
-    DWARFCompileUnitSP cu(new DWARFCompileUnit(dwarf2Data));
-    if (cu.get() == NULL)
-      return;
-    DWARFDebugInfoEntry die;
-
-    while (cu->Extract(dwarf2Data->get_debug_info_data(), &offset)) {
-      const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset();
-
-      depth = 0;
-      // Call the callback function with no DIE pointer for the compile unit
-      // and get the offset that we are to continue to parse from
-      offset = callback(dwarf2Data, cu.get(), NULL, offset, depth, userData);
-
-      // Make sure we are within our compile unit
-      if (offset < next_cu_offset) {
-        // We are in our compile unit, parse starting at the offset
-        // we were told to parse
-        bool done = false;
-        while (!done && die.Extract(dwarf2Data, cu.get(), &offset)) {
-          // Call the callback function with DIE pointer that falls within the
-          // compile unit
-          offset =
-              callback(dwarf2Data, cu.get(), &die, offset, depth, userData);
-
-          if (die.IsNULL()) {
-            if (depth)
-              --depth;
-            else
-              done = true; // We are done with this compile unit!
-          } else if (die.HasChildren())
-            ++depth;
-        }
-      }
-
-      // Make sure the offset returned is valid, and if not stop parsing.
-      // Returning DW_INVALID_OFFSET from this callback is a good way to end
-      // all parsing
-      if (!dwarf2Data->get_debug_info_data().ValidOffset(offset))
-        break;
-
-      // See if during the callback anyone retained a copy of the compile
-      // unit other than ourselves and if so, let whomever did own the object
-      // and create a new one for our own use!
-      if (!cu.unique())
-        cu.reset(new DWARFCompileUnit(dwarf2Data));
-
-      // Make sure we start on a proper
-      offset = next_cu_offset;
-    }
-  }
-}
-
-typedef struct DumpInfo {
-  DumpInfo(Stream *init_strm, uint32_t off, uint32_t depth)
-      : strm(init_strm), die_offset(off), recurse_depth(depth),
-        found_depth(UINT32_MAX), found_die(false), ancestors() {}
-  Stream *strm;
-  const uint32_t die_offset;
-  const uint32_t recurse_depth;
-  uint32_t found_depth;
-  bool found_die;
-  std::vector<DWARFDebugInfoEntry> ancestors;
-
-  DISALLOW_COPY_AND_ASSIGN(DumpInfo);
-} DumpInfo;
-
-//----------------------------------------------------------------------
-// DumpCallback
-//
-// A callback function for the static DWARFDebugInfo::Parse() function
-// that gets called each time a compile unit header or debug information
-// entry is successfully parsed.
-//
-// This function dump DWARF information and obey recurse depth and
-// whether a single DIE is to be dumped (or all of the data).
-//----------------------------------------------------------------------
-static dw_offset_t DumpCallback(SymbolFileDWARF *dwarf2Data,
-                                DWARFCompileUnit *cu, DWARFDebugInfoEntry *die,
-                                const dw_offset_t next_offset,
-                                const uint32_t curr_depth, void *userData) {
-  DumpInfo *dumpInfo = (DumpInfo *)userData;
-  Stream *s = dumpInfo->strm;
-  bool show_parents =
-      s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors);
-
-  if (die) {
-    // Are we dumping everything?
-    if (dumpInfo->die_offset == DW_INVALID_OFFSET) {
-      // Yes we are dumping everything. Obey our recurse level though
-      if (curr_depth < dumpInfo->recurse_depth)
-        die->Dump(dwarf2Data, cu, *s, 0);
-    } else {
-      // We are dumping a specific DIE entry by offset
-      if (dumpInfo->die_offset == die->GetOffset()) {
-        // We found the DIE we were looking for, dump it!
-        if (show_parents) {
-          s->SetIndentLevel(0);
-          const uint32_t num_ancestors = dumpInfo->ancestors.size();
-          if (num_ancestors > 0) {
-            for (uint32_t i = 0; i < num_ancestors - 1; ++i) {
-              dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0);
-              s->IndentMore();
-            }
-          }
-        }
-
-        dumpInfo->found_depth = curr_depth;
-
-        die->Dump(dwarf2Data, cu, *s, 0);
-
-        // Note that we found the DIE we were looking for
-        dumpInfo->found_die = true;
-
-        // Since we are dumping a single DIE, if there are no children we are
-        // done!
-        if (!die->HasChildren() || dumpInfo->recurse_depth == 0)
-          return DW_INVALID_OFFSET; // Return an invalid address to end parsing
-      } else if (dumpInfo->found_die) {
-        // Are we done with all the children?
-        if (curr_depth <= dumpInfo->found_depth)
-          return DW_INVALID_OFFSET;
-
-        // We have already found our DIE and are printing it's children. Obey
-        // our recurse depth and return an invalid offset if we get done
-        // dumping all of the children
-        if (dumpInfo->recurse_depth == UINT32_MAX ||
-            curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth)
-          die->Dump(dwarf2Data, cu, *s, 0);
-      } else if (dumpInfo->die_offset > die->GetOffset()) {
-        if (show_parents)
-          dumpInfo->ancestors.back() = *die;
-      }
-    }
-
-    // Keep up with our indent level
-    if (die->IsNULL()) {
-      if (show_parents)
-        dumpInfo->ancestors.pop_back();
-
-      if (curr_depth <= 1)
-        return cu->GetNextCompileUnitOffset();
-      else
-        s->IndentLess();
-    } else if (die->HasChildren()) {
-      if (show_parents) {
-        DWARFDebugInfoEntry null_die;
-        dumpInfo->ancestors.push_back(null_die);
-      }
-      s->IndentMore();
-    }
-  } else {
-    if (cu == NULL)
-      s->PutCString("NULL - cu");
-    // We have a compile unit, reset our indent level to zero just in case
-    s->SetIndentLevel(0);
-
-    // See if we are dumping everything?
-    if (dumpInfo->die_offset == DW_INVALID_OFFSET) {
-      // We are dumping everything
-      if (cu) {
-        cu->Dump(s);
-        return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this
-                                        // Compile Unit
-      } else {
-        return DW_INVALID_OFFSET;
-      }
-    } else {
-      if (show_parents) {
-        dumpInfo->ancestors.clear();
-        dumpInfo->ancestors.resize(1);
-      }
-
-      // We are dumping only a single DIE possibly with it's children and
-      // we must find it's compile unit before we can dump it properly
-      if (cu && dumpInfo->die_offset < cu->GetFirstDIEOffset()) {
-        // Not found, maybe the DIE offset provided wasn't correct?
-        //  *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << "
-        //  was not found." << endl;
-        return DW_INVALID_OFFSET;
-      } else {
-        // See if the DIE is in this compile unit?
-        if (cu && dumpInfo->die_offset < cu->GetNextCompileUnitOffset()) {
-          return next_offset;
-          //  // We found our compile unit that contains our DIE, just skip to
-          //  dumping the requested DIE...
-          //  return dumpInfo->die_offset;
-        } else {
-          // Skip to the next compile unit as the DIE isn't in the current one!
-          if (cu) {
-            return cu->GetNextCompileUnitOffset();
-          } else {
-            return DW_INVALID_OFFSET;
-          }
-        }
-      }
-    }
-  }
-
-  // Just return the current offset to parse the next CU or DIE entry
-  return next_offset;
-}
-
-//----------------------------------------------------------------------
-// Dump
-//
-// Dump the information in the .debug_info section to the specified
-// ostream. If die_offset is valid, a single DIE will be dumped. If the
-// die_offset is invalid, all the DWARF information will be dumped. Both
-// cases will obey a "recurse_depth" or how deep to traverse into the
-// children of each DIE entry. A recurse_depth of zero will dump all
-// compile unit headers. A recurse_depth of 1 will dump all compile unit
-// headers and the DW_TAG_compile unit tags. A depth of 2 will also
-// dump all types and functions.
-//----------------------------------------------------------------------
-void DWARFDebugInfo::Dump(Stream *s, SymbolFileDWARF *dwarf2Data,
-                          const uint32_t die_offset,
-                          const uint32_t recurse_depth) {
-  DumpInfo dumpInfo(s, die_offset, recurse_depth);
-  s->PutCString(".debug_info contents");
-  if (dwarf2Data->get_debug_info_data().GetByteSize() > 0) {
-    if (die_offset == DW_INVALID_OFFSET)
-      s->PutCString(":\n");
-    else {
-      s->Printf(" for DIE entry at .debug_info[0x%8.8x]", die_offset);
-      if (recurse_depth != UINT32_MAX)
-        s->Printf(" recursing %u levels deep.", recurse_depth);
-      s->EOL();
-    }
-  } else {
-    s->PutCString(": < EMPTY >\n");
-    return;
-  }
-  DWARFDebugInfo::Parse(dwarf2Data, DumpCallback, &dumpInfo);
-}
-
-//----------------------------------------------------------------------
-// Dump
-//
-// Dump the contents of this DWARFDebugInfo object as has been parsed
-// and/or modified after it has been parsed.
-//----------------------------------------------------------------------
-void DWARFDebugInfo::Dump(Stream *s, const uint32_t die_offset,
-                          const uint32_t recurse_depth) {
-  DumpInfo dumpInfo(s, die_offset, recurse_depth);
-
-  s->PutCString("Dumping .debug_info section from internal representation\n");
-
-  CompileUnitColl::const_iterator pos;
-  uint32_t curr_depth = 0;
-  ParseCompileUnitHeadersIfNeeded();
-  for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos) {
-    DWARFCompileUnit *cu = pos->get();
-    DumpCallback(m_dwarf2Data, cu, NULL, 0, curr_depth, &dumpInfo);
-
-    const DWARFDIE die = cu->DIE();
-    if (die)
-      die.Dump(s, recurse_depth);
-  }
-}
-
-//----------------------------------------------------------------------
-// FindCallbackString
-//
-// A callback function for the static DWARFDebugInfo::Parse() function
-// that gets called each time a compile unit header or debug information
-// entry is successfully parsed.
-//
-// This function will find the die_offset of any items whose DW_AT_name
-// matches the given string
-//----------------------------------------------------------------------
-typedef struct FindCallbackStringInfoTag {
-  const char *name;
-  bool ignore_case;
-  RegularExpression *regex;
-  vector<dw_offset_t> &die_offsets;
-} FindCallbackStringInfo;
-
-static dw_offset_t
-FindCallbackString(SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu,
-                   DWARFDebugInfoEntry *die, const dw_offset_t next_offset,
-                   const uint32_t curr_depth, void *userData) {
-  FindCallbackStringInfo *info = (FindCallbackStringInfo *)userData;
-
-  if (!die)
-    return next_offset;
-
-  const char *die_name = die->GetName(dwarf2Data, cu);
-  if (!die_name)
-    return next_offset;
-
-  if (info->regex) {
-    if (info->regex->Execute(llvm::StringRef(die_name)))
-      info->die_offsets.push_back(die->GetOffset());
-  } else {
-    if ((info->ignore_case ? strcasecmp(die_name, info->name)
-                           : strcmp(die_name, info->name)) == 0)
-      info->die_offsets.push_back(die->GetOffset());
-  }
-
-  // Just return the current offset to parse the next CU or DIE entry
-  return next_offset;
-}
-
-//----------------------------------------------------------------------
-// Find
-//
-// Finds all DIE that have a specific DW_AT_name attribute by manually
-// searching through the debug information (not using the
-// .debug_pubnames section). The string must match the entire name
-// and case sensitive searches are an option.
-//----------------------------------------------------------------------
-bool DWARFDebugInfo::Find(const char *name, bool ignore_case,
-                          vector<dw_offset_t> &die_offsets) const {
-  die_offsets.clear();
-  if (name && name[0]) {
-    FindCallbackStringInfo info = {name, ignore_case, NULL, die_offsets};
-    DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info);
-  }
-  return !die_offsets.empty();
-}
-
-//----------------------------------------------------------------------
-// Find
-//
-// Finds all DIE that have a specific DW_AT_name attribute by manually
-// searching through the debug information (not using the
-// .debug_pubnames section). The string must match the supplied regular
-// expression.
-//----------------------------------------------------------------------
-bool DWARFDebugInfo::Find(RegularExpression &re,
-                          vector<dw_offset_t> &die_offsets) const {
-  die_offsets.clear();
-  FindCallbackStringInfo info = {NULL, false, &re, die_offsets};
-  DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info);
-  return !die_offsets.empty();
-}
Index: source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
+++ source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
@@ -29,9 +29,32 @@
   dw_offset_t GetDWARFOffset(lldb::offset_t *offset_ptr) const;
 
   size_t GetDWARFSizeofInitialLength() const { return m_is_dwarf64 ? 12 : 4; }
+  size_t GetDWARFSizeOfOffset() const { return m_is_dwarf64 ? 8 : 4; }
 
   bool IsDWARF64() const { return m_is_dwarf64; }
 
+  //------------------------------------------------------------------
+  /// Slide the data in the buffer so that access to the data will
+  /// start at offset \a offset.
+  ///
+  /// This is currently used to provide access to the .debug_types
+  /// section and pretend it starts at at offset of the size of the
+  /// .debug_info section. This allows a minimally invasive change to
+  /// add support for .debug_types by allowing all DIEs to have unique
+  /// offsets and thus allowing no code to change in the DWARF parser.
+  /// Modifying the offsets in the .debug_types doesn't affect
+  /// anything because since all info in the .debug_types is type unit
+  /// relative and no types within a type unit can refer to any DIEs
+  /// outside of the type unit without using DW_AT_signature. It also
+  /// sets us up to move to DWARF5 where there is no .debug_types
+  /// section as compile units and type units are in the .debug_info.
+  //------------------------------------------------------------------
+  void OffsetData(lldb::offset_t offset)
+  {
+    if (GetByteSize())
+      m_start -= offset;
+  }
+
 protected:
   mutable bool m_is_dwarf64;
 };
Index: source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp
@@ -22,6 +22,6 @@
 
 dw_offset_t
 DWARFDataExtractor::GetDWARFOffset(lldb::offset_t *offset_ptr) const {
-  return GetMaxU64(offset_ptr, m_is_dwarf64 ? 8 : 4);
+  return GetMaxU64(offset_ptr, GetDWARFSizeOfOffset());
 }
 }
Index: source/Plugins/SymbolFile/DWARF/DWARFDIE.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -86,6 +86,14 @@
   DWARFDIE
   GetContainingDWOModuleDIE() const;
 
+  // Get the data that contains the attribute values for this DIE. Support
+  // for .debug_types means that any DIE can have its data either in the
+  // .debug_info or the .debug_types section so anyone extracting data from
+  // a DIE must use the correct data.
+  //
+  // Clients must validate that this object is valid before calling this.
+  const lldb_private::DWARFDataExtractor &GetData() const;
+
   //----------------------------------------------------------------------
   // Accessing information about a DIE
   //----------------------------------------------------------------------
Index: source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -466,3 +466,9 @@
 bool operator!=(const DWARFDIE &lhs, const DWARFDIE &rhs) {
   return lhs.GetDIE() != rhs.GetDIE() || lhs.GetCU() != rhs.GetCU();
 }
+
+const DWARFDataExtractor &DWARFDIE::GetData() const {
+  // Clients must check if this DIE is valid before calling this function.
+  assert(IsValid());
+  return m_cu->GetData();
+}
Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -32,7 +32,8 @@
   ~DWARFCompileUnit();
 
   bool Extract(const lldb_private::DWARFDataExtractor &debug_info,
-               lldb::offset_t *offset_ptr);
+               lldb::offset_t *offset_ptr, bool is_type_unit);
+  const lldb_private::DWARFDataExtractor &GetData() const;
   size_t ExtractDIEsIfNeeded(bool cu_die_only);
   DWARFDIE LookupAddress(const dw_addr_t address);
   size_t AppendDIEsWithTag(const dw_tag_t tag,
@@ -39,13 +40,18 @@
                            DWARFDIECollection &matching_dies,
                            uint32_t depth = UINT32_MAX) const;
   void Clear();
-  bool Verify(lldb_private::Stream *s) const;
   void Dump(lldb_private::Stream *s) const;
   dw_offset_t GetOffset() const { return m_offset; }
+  size_t GetLengthByteSize() const { return m_is_dwarf64 ? 12 : 4; }
   lldb::user_id_t GetID() const;
   uint32_t Size() const {
-    return m_is_dwarf64 ? 23
-                        : 11; /* Size in bytes of the compile unit header */
+    // Size in bytes of the compile or type unit header
+    // Start with the common size between compile and type units
+    uint32_t header_size = m_is_dwarf64 ? 23 : 11;
+    // Add the extra type unit size if needed
+    if (IsTypeUnit())
+      header_size += m_is_dwarf64 ? 16 : 12;
+    return header_size;
   }
   bool ContainsDIEOffset(dw_offset_t die_offset) const {
     return die_offset >= GetFirstDIEOffset() &&
@@ -53,13 +59,12 @@
   }
   dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); }
   dw_offset_t GetNextCompileUnitOffset() const {
-    return m_offset + m_length + (m_is_dwarf64 ? 12 : 4);
+    return m_offset + m_length + GetLengthByteSize();
   }
   size_t GetDebugInfoSize() const {
-    return m_length + (m_is_dwarf64 ? 12 : 4) - Size(); /* Size in bytes of the
-                                                           .debug_info data
-                                                           associated with this
-                                                           compile unit. */
+    // Size in bytes of the .debug_info or .debug_types data associated with
+    // this compile or type unit.
+    return m_length + GetLengthByteSize() - Size();
   }
   uint32_t GetLength() const { return m_length; }
   uint16_t GetVersion() const { return m_version; }
@@ -161,6 +166,42 @@
 
   dw_offset_t GetBaseObjOffset() const { return m_base_obj_offset; }
 
+  // Return true if this compile unit is a type unit.
+  bool IsTypeUnit() const { return m_type_offset != DW_INVALID_OFFSET; }
+  // Return the type signature for the type contained in this type unit. This
+  // value will not be valid if this compile unit is not a type unit.
+  uint64_t GetTypeSignature() const { return m_type_signature; }
+  // If this compile unit is a type unit, then return the DWARFDIE that
+  // respresents the type contained in the type unit, else return an invalid
+  // DIE.
+  DWARFDIE GetTypeUnitDIE();
+  // If this compile unit is a type unit, then return the DIE offset for the
+  // type contained in the type unit, else return an invalid DIE offset.
+  dw_offset_t GetTypeUnitDIEOffset() {
+    if (IsTypeUnit())
+      return m_offset + m_type_offset;
+    return DW_INVALID_OFFSET;
+  }
+  
+  // Find the DIE for any given type signature.
+  //
+  // This is a convenience function that allows anyone to use the current
+  // compile unit to access the DWARF and use its debug info to retrieve a DIE
+  // that represents a type given a type signature. This function will cause all
+  // DIEs in the type unit to be parsed, only call if you need the actual DIE
+  // object.
+  DWARFDIE FindTypeSignatureDIE(uint64_t type_sig) const;
+  
+  // Find the DIE offset for any given type signature.
+  //
+  // This is a convenience function that allows anyone to use the current
+  // compile unit to access the DWARF and use its debug info to retrieve a DIE
+  // offset that represents a type given a type signature. This function doesn't
+  // cause any debug information to be parsed, so if clients only need the
+  // DIE offset of a type signature, this function is more efficient than
+  // DWARFDIE FindTypeSignatureDIE(...) above.
+  dw_offset_t FindTypeSignatureDIEOffset(uint64_t type_sig) const;
+  
 protected:
   SymbolFileDWARF *m_dwarf2Data;
   std::unique_ptr<SymbolFileDWARFDwo> m_dwo_symbol_file;
@@ -191,6 +232,11 @@
   dw_offset_t m_base_obj_offset; // If this is a dwo compile unit this is the
                                  // offset of the base compile unit in the main
                                  // object file
+  uint64_t m_type_signature;     // Type signature contained in a type unit
+                                 // which will be valid (non-zero) for type
+                                 // units only.
+  dw_offset_t m_type_offset;     // Compile unit relative type offset for type
+                                 // units only.
 
   void ParseProducerInfo();
 
Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -47,7 +47,9 @@
       m_producer_version_minor(0), m_producer_version_update(0),
       m_language_type(eLanguageTypeUnknown), m_is_dwarf64(false),
       m_is_optimized(eLazyBoolCalculate), m_addr_base(0),
-      m_ranges_base(0), m_base_obj_offset(DW_INVALID_OFFSET) {}
+      m_ranges_base(0), m_base_obj_offset(DW_INVALID_OFFSET),
+      m_type_signature(0), m_type_offset(DW_INVALID_OFFSET)
+{}
 
 DWARFCompileUnit::~DWARFCompileUnit() {}
 
@@ -70,7 +72,7 @@
 }
 
 bool DWARFCompileUnit::Extract(const DWARFDataExtractor &debug_info,
-                               lldb::offset_t *offset_ptr) {
+                               lldb::offset_t *offset_ptr, bool is_type_unit) {
   Clear();
 
   m_offset = *offset_ptr;
@@ -90,8 +92,12 @@
         m_dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset);
     bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));
 
+    if (is_type_unit) {
+      m_type_signature = debug_info.GetU64(offset_ptr);
+      m_type_offset = debug_info.GetDWARFOffset(offset_ptr);
+    }
     if (length_OK && version_OK && addr_size_OK && abbr_offset_OK &&
-        abbr != NULL) {
+        abbr != NULL && (!is_type_unit || m_type_offset != DW_INVALID_OFFSET)) {
       m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset);
       return true;
     }
@@ -161,8 +167,7 @@
   uint32_t depth = 0;
   // We are in our compile unit, parse starting at the offset
   // we were told to parse
-  const DWARFDataExtractor &debug_info_data =
-      m_dwarf2Data->get_debug_info_data();
+  const DWARFDataExtractor &debug_info_data = GetData();
   std::vector<uint32_t> die_index_stack;
   die_index_stack.reserve(32);
   die_index_stack.push_back(0);
@@ -316,45 +321,6 @@
   return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET;
 }
 
-bool DWARFCompileUnit::Verify(Stream *s) const {
-  const DWARFDataExtractor &debug_info = m_dwarf2Data->get_debug_info_data();
-  bool valid_offset = debug_info.ValidOffset(m_offset);
-  bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset() - 1);
-  bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
-  bool abbr_offset_OK =
-      m_dwarf2Data->get_debug_abbrev_data().ValidOffset(GetAbbrevOffset());
-  bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));
-  if (valid_offset && length_OK && version_OK && addr_size_OK &&
-      abbr_offset_OK) {
-    return true;
-  } else {
-    s->Printf("    0x%8.8x: ", m_offset);
-    DumpDataExtractor(m_dwarf2Data->get_debug_info_data(), s, m_offset,
-                      lldb::eFormatHex, 1, Size(), 32, LLDB_INVALID_ADDRESS, 0,
-                      0);
-    s->EOL();
-    if (valid_offset) {
-      if (!length_OK)
-        s->Printf("        The length (0x%8.8x) for this compile unit is too "
-                  "large for the .debug_info provided.\n",
-                  m_length);
-      if (!version_OK)
-        s->Printf("        The 16 bit compile unit header version is not "
-                  "supported.\n");
-      if (!abbr_offset_OK)
-        s->Printf("        The offset into the .debug_abbrev section (0x%8.8x) "
-                  "is not valid.\n",
-                  GetAbbrevOffset());
-      if (!addr_size_OK)
-        s->Printf("        The address size is unsupported: 0x%2.2x\n",
-                  m_addr_size);
-    } else
-      s->Printf("        The start offset of the compile unit header in the "
-                ".debug_info is invalid.\n");
-  }
-  return false;
-}
-
 void DWARFCompileUnit::Dump(Stream *s) const {
   s->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, "
             "abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at "
@@ -396,6 +362,11 @@
 
 void DWARFCompileUnit::BuildAddressRangeTable(
     SymbolFileDWARF *dwarf2Data, DWARFDebugAranges *debug_aranges) {
+
+  // No addresses are found in a type unit.
+  if (IsTypeUnit())
+    return;
+
   // This function is usually called if there in no .debug_aranges section
   // in order to produce a compile unit level set of address ranges that
   // is accurate.
@@ -1124,3 +1095,36 @@
 lldb::ByteOrder DWARFCompileUnit::GetByteOrder() const {
   return m_dwarf2Data->GetObjectFile()->GetByteOrder();
 }
+
+DWARFDIE DWARFCompileUnit::GetTypeUnitDIE() {
+  if (IsTypeUnit()) {
+    // The type offset is compile unit relative, so we need to add the compile
+    // unit offset to ensure we get the correct DIE.
+    return GetDIE(GetTypeUnitDIEOffset());
+  }
+  return DWARFDIE();
+}
+
+DWARFDIE DWARFCompileUnit::FindTypeSignatureDIE(uint64_t type_sig) const {
+  auto cu = m_dwarf2Data->DebugInfo()->GetTypeUnitForSignature(type_sig);
+  if (cu)
+    return cu->GetTypeUnitDIE();
+  return DWARFDIE();
+}
+
+dw_offset_t DWARFCompileUnit::FindTypeSignatureDIEOffset(uint64_t type_sig) const {
+  auto cu = m_dwarf2Data->DebugInfo()->GetTypeUnitForSignature(type_sig);
+  if (cu)
+    return cu->GetTypeUnitDIEOffset();
+  return DW_INVALID_OFFSET;
+}
+
+const lldb_private::DWARFDataExtractor &DWARFCompileUnit::GetData() const {
+  // In DWARF 5, type units are in the .debug_info section. Prior to DWARF 5
+  // type units are in the .debug_types section.
+  if (IsTypeUnit() && GetVersion() < 5)
+    return m_dwarf2Data->get_debug_types_data();
+  else
+    return m_dwarf2Data->get_debug_info_data();
+}
+
Index: source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
@@ -52,8 +52,7 @@
   form_value.SetCompileUnit(cu);
   form_value.SetForm(FormAtIndex(i));
   lldb::offset_t offset = DIEOffsetAtIndex(i);
-  return form_value.ExtractValue(
-      cu->GetSymbolFileDWARF()->get_debug_info_data(), &offset);
+  return form_value.ExtractValue(cu->GetData(), &offset);
 }
 
 uint64_t DWARFAttributes::FormValueAsUnsigned(dw_attr_t attr,
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
@@ -655,8 +655,7 @@
               if (form_value.BlockData()) {
                 Value initialValue(0);
                 Value memberOffset(0);
-                const DWARFDataExtractor &debug_info_data =
-                    die.GetDWARF()->get_debug_info_data();
+                const DWARFDataExtractor &debug_info_data = die.GetData();
                 uint32_t block_length = form_value.Unsigned();
                 uint32_t block_offset =
                     form_value.BlockData() - debug_info_data.GetDataStart();
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2727,7 +2727,7 @@
               if (form_value.BlockData()) {
                 Value initialValue(0);
                 Value memberOffset(0);
-                const DWARFDataExtractor &debug_info_data =
+                const DWARFDataExtractor &debug_info_data = die.GetData();
                     die.GetDWARF()->get_debug_info_data();
                 uint32_t block_length = form_value.Unsigned();
                 uint32_t block_offset =
@@ -3202,8 +3202,7 @@
               if (form_value.BlockData()) {
                 Value initialValue(0);
                 Value memberOffset(0);
-                const DWARFDataExtractor &debug_info_data =
-                    die.GetDWARF()->get_debug_info_data();
+                const DWARFDataExtractor &debug_info_data = die.GetData();
                 uint32_t block_length = form_value.Unsigned();
                 uint32_t block_offset =
                     form_value.BlockData() - debug_info_data.GetDataStart();
Index: source/Plugins/SymbolFile/DWARF/DIERef.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DIERef.cpp
+++ source/Plugins/SymbolFile/DWARF/DIERef.cpp
@@ -47,6 +47,18 @@
   if (form_value.IsValid()) {
     const DWARFCompileUnit *dwarf_cu = form_value.GetCompileUnit();
     if (dwarf_cu) {
+      // Replace the compile unit with the type signature compile unit for
+      // type signature attributes.
+      if (form_value.Form() == DW_FORM_ref_sig8) {
+        uint64_t type_sig = form_value.Unsigned();
+        auto debug_info = dwarf_cu->GetSymbolFileDWARF()->DebugInfo();
+        auto type_cu = debug_info->GetTypeUnitForSignature(type_sig);
+        if (type_cu) {
+          cu_offset = type_cu->GetOffset();
+          die_offset = type_cu->GetTypeUnitDIEOffset();
+        }
+        return;
+      }
       if (dwarf_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
         cu_offset = dwarf_cu->GetBaseObjOffset();
       else
Index: source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
===================================================================
--- source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -695,6 +695,7 @@
         static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes");
         static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges");
         static ConstString g_sect_name_dwarf_debug_str(".debug_str");
+        static ConstString g_sect_name_dwarf_debug_types(".debug_types");
         static ConstString g_sect_name_eh_frame(".eh_frame");
         static ConstString g_sect_name_go_symtab(".gosymtab");
         SectionType section_type = eSectionTypeOther;
@@ -743,6 +744,8 @@
           section_type = eSectionTypeDWARFDebugRanges;
         else if (const_sect_name == g_sect_name_dwarf_debug_str)
           section_type = eSectionTypeDWARFDebugStr;
+        else if (const_sect_name == g_sect_name_dwarf_debug_types)
+          section_type = eSectionTypeDWARFDebugTypes;
         else if (const_sect_name == g_sect_name_eh_frame)
           section_type = eSectionTypeEHFrame;
         else if (const_sect_name == g_sect_name_go_symtab)
Index: source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
===================================================================
--- source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -1211,6 +1211,7 @@
           case eSectionTypeDWARFDebugRanges:
           case eSectionTypeDWARFDebugStr:
           case eSectionTypeDWARFDebugStrOffsets:
+          case eSectionTypeDWARFDebugTypes:
           case eSectionTypeDWARFAppleNames:
           case eSectionTypeDWARFAppleTypes:
           case eSectionTypeDWARFAppleNamespaces:
@@ -1722,6 +1723,8 @@
                   static ConstString g_sect_name_dwarf_debug_ranges(
                       "__debug_ranges");
                   static ConstString g_sect_name_dwarf_debug_str("__debug_str");
+                  static ConstString g_sect_name_dwarf_debug_types(
+                      "__debug_types");
                   static ConstString g_sect_name_dwarf_apple_names(
                       "__apple_names");
                   static ConstString g_sect_name_dwarf_apple_types(
@@ -1759,6 +1762,8 @@
                     sect_type = eSectionTypeDWARFDebugRanges;
                   else if (section_name == g_sect_name_dwarf_debug_str)
                     sect_type = eSectionTypeDWARFDebugStr;
+                  else if (section_name == g_sect_name_dwarf_debug_types)
+                    sect_type = eSectionTypeDWARFDebugTypes;
                   else if (section_name == g_sect_name_dwarf_apple_names)
                     sect_type = eSectionTypeDWARFAppleNames;
                   else if (section_name == g_sect_name_dwarf_apple_types)
Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
===================================================================
--- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -1907,6 +1907,7 @@
       static ConstString g_sect_name_dwarf_debug_str(".debug_str");
       static ConstString g_sect_name_dwarf_debug_str_offsets(
           ".debug_str_offsets");
+      static ConstString g_sect_name_dwarf_debug_types(".debug_types");
       static ConstString g_sect_name_dwarf_debug_abbrev_dwo(
           ".debug_abbrev.dwo");
       static ConstString g_sect_name_dwarf_debug_info_dwo(".debug_info.dwo");
@@ -1984,6 +1985,8 @@
         sect_type = eSectionTypeDWARFDebugRanges;
       else if (name == g_sect_name_dwarf_debug_str)
         sect_type = eSectionTypeDWARFDebugStr;
+      else if (name == g_sect_name_dwarf_debug_types)
+        sect_type = eSectionTypeDWARFDebugTypes;
       else if (name == g_sect_name_dwarf_debug_str_offsets)
         sect_type = eSectionTypeDWARFDebugStrOffsets;
       else if (name == g_sect_name_dwarf_debug_abbrev_dwo)
Index: source/Core/Section.cpp
===================================================================
--- source/Core/Section.cpp
+++ source/Core/Section.cpp
@@ -87,6 +87,8 @@
     return "dwarf-str";
   case eSectionTypeDWARFDebugStrOffsets:
     return "dwarf-str-offsets";
+  case eSectionTypeDWARFDebugTypes:
+      return "dwarf-types";
   case eSectionTypeELFSymbolTable:
     return "elf-symbol-table";
   case eSectionTypeELFDynamicSymbols:
Index: packages/Python/lldbsuite/test/test_categories.py
===================================================================
--- packages/Python/lldbsuite/test/test_categories.py
+++ packages/Python/lldbsuite/test/test_categories.py
@@ -15,7 +15,7 @@
 
 
 debug_info_categories = [
-    'dwarf', 'dwo', 'dsym', 'gmodules'
+    'dwarf', 'dwo', 'dsym', 'gmodules', 'dwarf_type_units'
 ]
 
 all_categories = {
@@ -24,6 +24,7 @@
     'dwo': 'Tests that can be run with DWO debug information',
     'dsym': 'Tests that can be run with DSYM debug information',
     'gmodules': 'Tests that can be run with -gmodules debug information',
+    'dwarf_type_units' : 'Tests using the DWARF type units (-fdebug-types-section)',
     'expression': 'Tests related to the expression parser',
     'libc++': 'Test for libc++ data formatters',
     'objc': 'Tests related to the Objective-C programming language support',
@@ -59,6 +60,8 @@
         if platform not in ["linux", "freebsd", "darwin", "macosx", "ios"]:
             return False
         return gmodules.is_compiler_clang_with_gmodules(compiler_path)
+    elif category == "dwarf_type_units":
+        return platform in ["linux", "freebsd"]
     return True
 
 
Index: packages/Python/lldbsuite/test/plugins/builder_base.py
===================================================================
--- packages/Python/lldbsuite/test/plugins/builder_base.py
+++ packages/Python/lldbsuite/test/plugins/builder_base.py
@@ -170,7 +170,6 @@
     # True signifies that we can handle building dwo.
     return True
 
-
 def buildGModules(
         sender=None,
         architecture=None,
@@ -192,7 +191,24 @@
     # True signifies that we can handle building with gmodules.
     return True
 
+def buildDwarfTypeUnits(
+        sender=None,
+        architecture=None,
+        compiler=None,
+        dictionary=None,
+        clean=True):
+    """Build the binaries with type units (type in  a .debug_types section)."""
+    commands = []
+    if clean:
+        commands.append([getMake(), "clean", getCmdLine(dictionary)])
+    commands.append([getMake(), "MAKE_DSYM=NO", "DWARF_TYPE_UNITS=YES",
+                    getArchSpec( architecture), getCCSpec(compiler),
+                    getCmdLine(dictionary)])
 
+    runBuildCommands(commands, sender=sender)
+    # True signifies that we can handle building dwo.
+    return True
+
 def cleanup(sender=None, dictionary=None):
     """Perform a platform-specific cleanup after the test."""
     #import traceback
Index: packages/Python/lldbsuite/test/make/Makefile.rules
===================================================================
--- packages/Python/lldbsuite/test/make/Makefile.rules
+++ packages/Python/lldbsuite/test/make/Makefile.rules
@@ -193,7 +193,11 @@
    MODULE_DEBUG_INFO_FLAGS += -gmodules
 endif
 
-DEBUG_INFO_FLAG ?= -g
+ifeq "$(DWARF_TYPE_UNITS)" "YES"
+	DEBUG_INFO_FLAG ?= -gdwarf-4
+else
+	DEBUG_INFO_FLAG ?= -g
+endif
 
 CFLAGS ?= $(DEBUG_INFO_FLAG) -O0 -fno-builtin
 ifeq "$(OS)" "Darwin"
@@ -215,6 +219,10 @@
 	CFLAGS += -gsplit-dwarf
 endif
 
+ifeq "$(DWARF_TYPE_UNITS)" "YES"
+	CFLAGS += -fdebug-types-section
+endif
+
 ifeq "$(MAKE_GMODULES)" "YES"
 	CFLAGS += -fmodules -gmodules
 endif
@@ -638,7 +646,7 @@
 
 #----------------------------------------------------------------------
 # From http://blog.melski.net/tag/debugging-makefiles/
-# 
+#
 # Usage: make print-CC print-CXX print-LD
 #----------------------------------------------------------------------
 print-%:
Index: packages/Python/lldbsuite/test/lldbtest.py
===================================================================
--- packages/Python/lldbsuite/test/lldbtest.py
+++ packages/Python/lldbsuite/test/lldbtest.py
@@ -1569,6 +1569,22 @@
                 clean):
             raise Exception("Don't know how to build binary with gmodules")
 
+    def buildDwarfTypeUnits(
+            self,
+            architecture=None,
+            compiler=None,
+            dictionary=None,
+            clean=True):
+        """Platform specific way to build binaries with gmodules info."""
+        module = builder_module()
+        if not module.buildDwarfTypeUnits(
+                self,
+                architecture,
+                compiler,
+                dictionary,
+                clean):
+            raise Exception("Don't know how to build binary with DWARF type units")
+
     def buildGo(self):
         """Build the default go binary.
         """
@@ -1754,6 +1770,16 @@
                     gmodules_test_method.__name__ = gmodules_method_name
                     newattrs[gmodules_method_name] = gmodules_test_method
 
+                if "dwarf_type_units" in supported_categories:
+                    @decorators.add_test_categories(["dwarf_type_units"])
+                    @wraps(attrvalue)
+                    def gmodules_test_method(self, attrvalue=attrvalue):
+                        self.debug_info = "dwarf_type_units"
+                        return attrvalue(self)
+                    gmodules_method_name = attrname + "_dwarf_type_units"
+                    gmodules_test_method.__name__ = gmodules_method_name
+                    newattrs[gmodules_method_name] = gmodules_test_method
+
             else:
                 newattrs[attrname] = attrvalue
         return super(
@@ -1862,7 +1888,7 @@
         temp = os.path.join(os.getcwd(), template)
         with open(temp, 'r') as f:
             content = f.read()
-            
+
         public_api_dir = os.path.join(
             os.environ["LLDB_SRC"], "include", "lldb", "API")
 
@@ -2288,6 +2314,9 @@
         elif self.debug_info == "gmodules":
             return self.buildGModules(
                 architecture, compiler, dictionary, clean)
+        elif self.debug_info == "dwarf_type_units":
+            return self.buildDwarfTypeUnits(
+                architecture, compiler, dictionary, clean)
         else:
             self.fail("Can't build for debug info: %s" % self.debug_info)
 
Index: packages/Python/lldbsuite/test/lldbinline.py
===================================================================
--- packages/Python/lldbsuite/test/lldbinline.py
+++ packages/Python/lldbsuite/test/lldbinline.py
@@ -159,6 +159,12 @@
         self.buildGModules()
         self.do_test()
 
+    def __test_with_dwarf_type_units(self):
+        self.using_dsym = False
+        self.BuildMakefile()
+        self.buildDwarfTypeUnits()
+        self.do_test()
+
     def execute_user_command(self, __command):
         exec(__command, globals(), locals())
 
@@ -241,6 +247,10 @@
             "gmodules", target_platform, configuration.compiler):
         test.test_with_gmodules = ApplyDecoratorsToFunction(
             test._InlineTest__test_with_gmodules, decorators)
+    if test_categories.is_supported_on_platform(
+            "dwarf_type_units", target_platform, configuration.compiler):
+        test.test_with_gmodules = ApplyDecoratorsToFunction(
+            test._InlineTest__test_with_dwarf_type_units, decorators)
 
     # Add the test case to the globals, and hide InlineTest
     __globals.update({test_name: test})
Index: include/lldb/lldb-forward.h
===================================================================
--- include/lldb/lldb-forward.h
+++ include/lldb/lldb-forward.h
@@ -83,6 +83,7 @@
 class DiagnosticManager;
 class Disassembler;
 class DumpValueObjectOptions;
+class DWARFDataExtractor;
 class DynamicCheckerFunctions;
 class DynamicLoader;
 class Editline;
Index: include/lldb/lldb-enumerations.h
===================================================================
--- include/lldb/lldb-enumerations.h
+++ include/lldb/lldb-enumerations.h
@@ -650,6 +650,7 @@
   eSectionTypeGoSymtab,
   eSectionTypeAbsoluteAddress, // Dummy section for symbols with absolute
                                // address
+  eSectionTypeDWARFDebugTypes,
   eSectionTypeOther
 };
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to