jankratochvil updated this revision to Diff 172549.

Repository:
  rLLDB LLDB

https://reviews.llvm.org/D51578

Files:
  include/lldb/lldb-forward.h
  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/Plugins/SymbolFile/DWARF/CMakeLists.txt
  source/Plugins/SymbolFile/DWARF/DIERef.cpp
  source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
  source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
  source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
  source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
  source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
  source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
  source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp
  source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h
  source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
  source/Plugins/SymbolFile/DWARF/DWARFUnit.h
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h

Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -242,6 +242,7 @@
   const lldb_private::DWARFDataExtractor &get_debug_aranges_data();
   const lldb_private::DWARFDataExtractor &get_debug_frame_data();
   const lldb_private::DWARFDataExtractor &get_debug_info_data();
+  const lldb_private::DWARFDataExtractor &get_raw_debug_info_data();
   const lldb_private::DWARFDataExtractor &get_debug_line_data();
   const lldb_private::DWARFDataExtractor &get_debug_line_str_data();
   const lldb_private::DWARFDataExtractor &get_debug_macro_data();
@@ -251,7 +252,7 @@
   const lldb_private::DWARFDataExtractor &get_debug_rnglists_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_raw_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();
@@ -329,6 +330,10 @@
 
   void Dump(lldb_private::Stream &s) override;
 
+  uint64_t get_debug_types_offset() const {
+    return m_debug_info_concatenated_types_offset;
+  }
+
 protected:
   typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *>
       DIEToTypePtr;
@@ -475,7 +480,7 @@
   DWARFDataSegment m_data_debug_addr;
   DWARFDataSegment m_data_debug_aranges;
   DWARFDataSegment m_data_debug_frame;
-  DWARFDataSegment m_data_debug_info;
+  DWARFDataSegment m_data_raw_debug_info;
   DWARFDataSegment m_data_debug_line;
   DWARFDataSegment m_data_debug_line_str;
   DWARFDataSegment m_data_debug_macro;
@@ -485,13 +490,17 @@
   DWARFDataSegment m_data_debug_rnglists;
   DWARFDataSegment m_data_debug_str;
   DWARFDataSegment m_data_debug_str_offsets;
-  DWARFDataSegment m_data_debug_types;
+  DWARFDataSegment m_data_raw_debug_types;
   DWARFDataSegment m_data_apple_names;
   DWARFDataSegment m_data_apple_types;
   DWARFDataSegment m_data_apple_namespaces;
   DWARFDataSegment m_data_apple_objc;
   DWARFDataSegment m_data_gnu_debugaltlink;
 
+  llvm::once_flag m_concatenated_data_once;
+  lldb_private::DWARFDataExtractor m_data_debug_info_concatenated;
+  uint64_t m_debug_info_concatenated_types_offset;
+
   // The unique pointer items below are generated on demand if and when someone
   // accesses
   // them through a non const version of this class.
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -412,7 +412,7 @@
                                           // when this class parses .o files to
                                           // contain the .o file index/ID
       m_debug_map_module_wp(), m_debug_map_symfile(NULL), m_data_debug_abbrev(),
-      m_data_debug_aranges(), m_data_debug_frame(), m_data_debug_info(),
+      m_data_debug_aranges(), m_data_debug_frame(), m_data_raw_debug_info(),
       m_data_debug_line(), m_data_debug_macro(), m_data_debug_loc(),
       m_data_debug_ranges(), m_data_debug_rnglists(), m_data_debug_str(),
       m_data_apple_names(), m_data_apple_types(), m_data_apple_namespaces(),
@@ -506,20 +506,6 @@
     if (section_list == NULL)
       return 0;
 
-    // On non Apple platforms we might have .debug_types debug info that is
-    // created by using "-fdebug-types-section". LLDB currently will try to
-    // load this debug info, but it causes crashes during debugging when types
-    // are missing since it doesn't know how to parse the info in the
-    // .debug_types type units. This causes all complex debug info types to be
-    // unresolved. Because this causes LLDB to crash and since it really
-    // doesn't provide a solid debuggiung experience, we should disable trying
-    // to debug this kind of DWARF until support gets added or deprecated.
-    if (section_list->FindSectionByName(ConstString(".debug_types"))) {
-      m_obj_file->GetModule()->ReportWarning(
-        "lldb doesn’t support .debug_types debug info");
-      return 0;
-    }
-
     uint64_t debug_abbrev_file_size = 0;
     uint64_t debug_info_file_size = 0;
     uint64_t debug_line_file_size = 0;
@@ -638,8 +624,9 @@
   return GetCachedSectionData(eSectionTypeDWARFDebugFrame, m_data_debug_frame);
 }
 
-const DWARFDataExtractor &SymbolFileDWARF::get_debug_info_data() {
-  return GetCachedSectionData(eSectionTypeDWARFDebugInfo, m_data_debug_info);
+const DWARFDataExtractor &SymbolFileDWARF::get_raw_debug_info_data() {
+  return GetCachedSectionData(eSectionTypeDWARFDebugInfo,
+                              m_data_raw_debug_info);
 }
 
 const DWARFDataExtractor &SymbolFileDWARF::get_debug_line_data() {
@@ -689,8 +676,9 @@
                               m_data_debug_str_offsets);
 }
 
-const DWARFDataExtractor &SymbolFileDWARF::get_debug_types_data() {
-  return GetCachedSectionData(eSectionTypeDWARFDebugTypes, m_data_debug_types);
+const DWARFDataExtractor &SymbolFileDWARF::get_raw_debug_types_data() {
+  return GetCachedSectionData(eSectionTypeDWARFDebugTypes,
+                              m_data_raw_debug_types);
 }
 
 const DWARFDataExtractor &SymbolFileDWARF::get_apple_names_data() {
@@ -715,6 +703,71 @@
                               m_data_gnu_debugaltlink);
 }
 
+const DWARFDataExtractor &
+    SymbolFileDWARF::get_debug_info_data() {
+  llvm::call_once(m_concatenated_data_once, [&] {
+    const auto &debug_info_data = get_raw_debug_info_data();
+    const auto &debug_types_data = get_raw_debug_types_data();
+    if (!debug_info_data.GetByteSize() && !debug_types_data.GetByteSize())
+      return;
+    // For this optimization of mmapped sections we do not handle .debug_types
+    // present without .debug_info as that should not happen.
+    if (debug_info_data.GetByteSize()
+        && (!debug_types_data.GetByteSize()
+            || debug_info_data.GetDataStart() + debug_info_data.GetByteSize()
+                <= debug_types_data.GetDataStart())) {
+      uint64_t length;
+      if (debug_types_data.GetByteSize()) {
+        m_debug_info_concatenated_types_offset =
+            debug_types_data.GetDataStart() - debug_info_data.GetDataStart();
+        length = debug_types_data.GetDataStart()
+            + debug_types_data.GetByteSize() - debug_info_data.GetDataStart();
+      } else {
+        m_debug_info_concatenated_types_offset = debug_info_data.GetByteSize();
+        length = debug_info_data.GetByteSize();
+      }
+      if (m_dwarf_data.GetByteSize()) {
+//lldbassert(0 && "some OSX case");
+        m_data_debug_info_concatenated.SetData(m_dwarf_data,
+            debug_info_data.GetDataStart() - m_dwarf_data.GetDataStart(),
+            length);
+        return;
+      }
+      if (!m_obj_file->IsInMemory()) {
+        const SectionList *section_list =
+            m_obj_file->GetSectionList(false /* update_module_section_list */);
+        if (section_list) {
+          SectionSP section_sp(section_list->FindSectionByType(
+              eSectionTypeDWARFDebugInfo, true));
+          if (section_sp) {
+            lldbassert(section_sp->GetObjectFile() == m_obj_file);
+            m_obj_file->GetData(section_sp->GetFileOffset(), length,
+                m_data_debug_info_concatenated);
+            return;
+          }
+        }
+      }
+    }
+//lldbassert(0 && "fallback to data copy");
+    DataBufferHeap *databufferheap = new DataBufferHeap();
+    DataBufferSP databuffer = DataBufferSP(databufferheap);
+    databufferheap->AppendData(
+        debug_info_data.GetDataStart(),
+        debug_info_data.GetByteSize());
+    m_debug_info_concatenated_types_offset =
+        databufferheap->GetByteSize();
+    databufferheap->AppendData(
+        debug_types_data.GetDataStart(),
+        debug_types_data.GetByteSize());
+    m_data_debug_info_concatenated.SetData(databuffer);
+    m_data_debug_info_concatenated.SetByteOrder(
+        debug_info_data.GetByteOrder());
+    m_data_debug_info_concatenated.SetAddressByteSize(
+        debug_info_data.GetAddressByteSize());
+  });
+  return m_data_debug_info_concatenated;
+}
+
 DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() {
   if (m_abbr.get() == NULL) {
     const DWARFDataExtractor &debug_abbrev_data = get_debug_abbrev_data();
@@ -836,7 +889,7 @@
             cu_sp.reset(new CompileUnit(
                 module_sp, dwarf_cu, cu_file_spec, dwarf_cu->GetID(),
                 cu_language, is_optimized ? eLazyBoolYes : eLazyBoolNo));
-            if (cu_sp) {
+            if (dwarf_cu->GetAsCompileUnit() && cu_sp) {
               // If we just created a compile unit with an invalid file spec,
               // try and get the first entry in the supports files from the
               // line table as that should be the compile unit.
@@ -849,16 +902,16 @@
                   cu_sp->GetSupportFiles().Replace(0, cu_file_spec);
                 }
               }
+            }
 
-              dwarf_cu->SetUserData(cu_sp.get());
+            dwarf_cu->SetUserData(cu_sp.get());
 
-              // Figure out the compile unit index if we weren't given one
-              if (cu_idx == UINT32_MAX)
-                DebugInfo()->GetCompileUnit(dwarf_cu->GetOffset(), &cu_idx);
+            // Figure out the compile unit index if we weren't given one
+            if (cu_idx == UINT32_MAX)
+              DebugInfo()->GetCompileUnit(dwarf_cu->GetOffset(), &cu_idx);
 
-              m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(
-                  cu_idx, cu_sp);
-            }
+            m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(
+                cu_idx, cu_sp);
           }
         }
       }
Index: source/Plugins/SymbolFile/DWARF/DWARFUnit.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -17,12 +17,15 @@
 #include <atomic>
 
 class DWARFUnit;
+class DWARFTypeUnit;
 class DWARFCompileUnit;
 class NameToDIE;
 class SymbolFileDWARF;
 class SymbolFileDWARFDwo;
 
 typedef std::shared_ptr<DWARFUnit> DWARFUnitSP;
+typedef std::shared_ptr<DWARFTypeUnit> DWARFTypeUnitSP;
+typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP;
 
 enum DWARFProducer {
   eProducerInvalid = 0,
@@ -39,6 +42,12 @@
 public:
   virtual ~DWARFUnit();
 
+  bool ExtractHeader(SymbolFileDWARF *dwarf,
+                     const lldb_private::DWARFDataExtractor &data,
+                     lldb::offset_t *offset_ptr);
+
+  DWARFTypeUnit *GetAsTypeUnit();
+  DWARFCompileUnit *GetAsCompileUnit();
   void ExtractUnitDIEIfNeeded();
   void ExtractDIEsIfNeeded();
 
@@ -70,7 +79,7 @@
   /// @return
   ///   The correct data for the DIE information in this unit.
   //------------------------------------------------------------------
-  virtual const lldb_private::DWARFDataExtractor &GetData() const = 0;
+  const lldb_private::DWARFDataExtractor &GetData() const;
   //------------------------------------------------------------------
   /// Get the size in bytes of the compile unit header.
   ///
@@ -176,6 +185,10 @@
     return die_iterator_range(m_die_array.begin(), m_die_array.end());
   }
 
+  DWARFDIE FindTypeSignatureDIE(uint64_t type_sig) const;
+
+  dw_offset_t FindTypeSignatureDIEOffset(uint64_t type_sig) const;  
+
 protected:
   DWARFUnit(SymbolFileDWARF *dwarf);
 
Index: source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -18,9 +18,11 @@
 #include "lldb/Utility/StreamString.h"
 #include "lldb/Utility/Timer.h"
 
+#include "DWARFCompileUnit.h"
 #include "DWARFDIECollection.h"
 #include "DWARFDebugAranges.h"
 #include "DWARFDebugInfo.h"
+#include "DWARFTypeUnit.h"
 #include "LogChannelDWARF.h"
 #include "SymbolFileDWARFDebugMap.h"
 #include "SymbolFileDWARFDwo.h"
@@ -429,6 +431,10 @@
 
 void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf,
                                        DWARFDebugAranges *debug_aranges) {
+  // No addresses in a type unit
+  if (GetAsTypeUnit())
+    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.
@@ -768,3 +774,72 @@
   return *m_func_aranges_ap.get();
 }
 
+DWARFDIE DWARFUnit::FindTypeSignatureDIE(uint64_t type_sig) const {
+  if (auto cu = m_dwarf->DebugInfo()->GetTypeUnitForSignature(type_sig))
+    return cu->GetTypeUnitDIE();
+  return DWARFDIE();
+}
+
+dw_offset_t
+DWARFUnit::FindTypeSignatureDIEOffset(uint64_t type_sig) const {
+  if (auto cu = m_dwarf->DebugInfo()->GetTypeUnitForSignature(type_sig))
+    return cu->GetTypeUnitDIEOffset();
+  return DW_INVALID_OFFSET;
+}
+
+DWARFTypeUnit *DWARFUnit::GetAsTypeUnit() {
+  if (GetUnitDIEOnly().Tag() == DW_TAG_type_unit)
+    return static_cast<DWARFTypeUnit *>(this);
+  return nullptr;
+}
+
+DWARFCompileUnit *DWARFUnit::GetAsCompileUnit() {
+  if (GetUnitDIEOnly().Tag() == DW_TAG_compile_unit)
+    return static_cast<DWARFCompileUnit *>(this);
+  return nullptr;
+}
+
+bool
+DWARFUnit::ExtractHeader(SymbolFileDWARF *dwarf,
+                         const lldb_private::DWARFDataExtractor &data,
+                         lldb::offset_t *offset_ptr) {
+  m_offset = *offset_ptr;
+
+  if (data.ValidOffset(*offset_ptr)) {
+    dw_offset_t abbr_offset;
+    const DWARFDebugAbbrev *abbr = dwarf->DebugAbbrev();
+    m_length = data.GetDWARFInitialLength(offset_ptr);
+    m_is_dwarf64 = data.IsDWARF64();
+    m_version = data.GetU16(offset_ptr);
+    if (m_version == 5) {
+      m_unit_type = data.GetU8(offset_ptr);
+      m_addr_size = data.GetU8(offset_ptr);
+      abbr_offset = data.GetDWARFOffset(offset_ptr);
+
+      if (m_unit_type == llvm::dwarf::DW_UT_skeleton)
+        m_dwo_id = data.GetU64(offset_ptr);
+    } else {
+      abbr_offset = data.GetDWARFOffset(offset_ptr);
+      m_addr_size = data.GetU8(offset_ptr);
+    }
+
+    bool length_OK = data.ValidOffset(GetNextCompileUnitOffset() - 1);
+    bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
+    bool abbr_offset_OK =
+        dwarf->get_debug_abbrev_data().ValidOffset(abbr_offset);
+    bool addr_size_OK = (m_addr_size == 4) || (m_addr_size == 8);
+
+    if (length_OK && version_OK && addr_size_OK && abbr_offset_OK && abbr) {
+      m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset);
+      return m_abbrevs != nullptr;
+    }
+
+    // reset the offset to where we tried to parse from if anything went wrong
+    *offset_ptr = m_offset;
+  }
+  return false;
+}
+
+const lldb_private::DWARFDataExtractor &DWARFUnit::GetData() const {
+  return m_dwarf->get_debug_info_data();
+}
Index: source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h
===================================================================
--- /dev/null
+++ source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h
@@ -0,0 +1,85 @@
+//===-- DWARFTypeUnit.h --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFTypeUnit_h_
+#define SymbolFileDWARF_DWARFTypeUnit_h_
+
+#include "DWARFUnit.h"
+
+class DWARFTypeUnit : public DWARFUnit {
+  friend class DWARFUnit;
+
+public:
+  virtual ~DWARFTypeUnit();
+
+  static DWARFTypeUnitSP Extract(SymbolFileDWARF *dwarf2Data,
+                                 const lldb_private::DWARFDataExtractor &data,
+                                 lldb::offset_t *offset_ptr);
+
+  void Dump(lldb_private::Stream *s) const override;
+
+  //------------------------------------------------------------------
+  /// Get the size in bytes of the header.
+  ///
+  /// @return
+  ///     Byte size of the type unit header
+  //------------------------------------------------------------------
+  uint32_t GetHeaderByteSize() const override {
+    return m_is_dwarf64 ? 39 : 23;
+  }
+
+  //------------------------------------------------------------------
+  /// Get the type DIE offset if this is a type unit.
+  ///
+  /// If this unit is a type unit, return type DIE offset for the type
+  /// in this unit.
+  ///
+  /// @return
+  ///   The DIE offset that points to the type unit type if this is
+  ///   a type unit, otherwise return DW_INVALID_OFFSET.
+  //------------------------------------------------------------------
+  dw_offset_t GetTypeUnitDIEOffset() {
+    return m_offset + m_type_offset;
+  }
+  
+  //------------------------------------------------------------------
+  /// Get the type signature for the type contained in this unit.
+  ///
+  /// @return
+  ///   The 64 bit 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; }
+
+  //------------------------------------------------------------------
+  /// Get the type DIE if this is a type unit.
+  ///
+  /// If this unit is a type unit, return type contained within it as
+  /// a DWARFDIE object.
+  ///
+  /// @return
+  ///   The DIE representing the type if this is a type unit, or an
+  ///   invalid DWARFDIE if this is not a type unit.
+  //------------------------------------------------------------------
+  DWARFDIE GetTypeUnitDIE();
+
+protected:
+  // Type signature contained in a type unit which will be valid (non-zero)
+  // for type units only.
+  uint64_t m_type_signature = 0;
+  // Compile unit relative type offset for type units only.
+  dw_offset_t m_type_offset = DW_INVALID_OFFSET;
+
+private:
+  DWARFTypeUnit(SymbolFileDWARF *dwarf2Data);
+  DISALLOW_COPY_AND_ASSIGN(DWARFTypeUnit);
+};
+
+#endif // SymbolFileDWARF_DWARFTypeUnit_h_
Index: source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp
===================================================================
--- /dev/null
+++ source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp
@@ -0,0 +1,53 @@
+//===-- DWARFTypeUnit.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFTypeUnit.h"
+#include "DWARFDataExtractor.h"
+#include "SymbolFileDWARF.h"
+#include "lldb/Utility/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+DWARFTypeUnit::DWARFTypeUnit(SymbolFileDWARF *dwarf2Data)
+  : DWARFUnit(dwarf2Data) {}
+
+DWARFTypeUnit::~DWARFTypeUnit() {}
+
+void DWARFTypeUnit::Dump(Stream *s) const {
+  s->Printf("0x%8.8x: Type Unit: length = 0x%8.8x, version = 0x%4.4x, "
+            "abbr_offset = 0x%8.8x, addr_size = 0x%2.2x, "
+            "type_signature = 0x%16.16" PRIx64 ", type_offset = 0x%8.8x "
+            "(next CU at {0x%8.8x})\n",
+            m_offset, m_length, m_version, GetAbbrevOffset(), m_addr_size,
+            m_type_signature, m_type_offset, GetNextCompileUnitOffset());
+}
+
+DWARFTypeUnitSP DWARFTypeUnit::Extract(SymbolFileDWARF *dwarf,
+    const lldb_private::DWARFDataExtractor &data, lldb::offset_t *offset_ptr) {
+  // std::make_shared would require the ctor to be public.
+  std::shared_ptr<DWARFTypeUnit> cu_sp(new DWARFTypeUnit(dwarf));
+  // Out of memory?
+  if (!cu_sp)
+    return nullptr;
+  if (cu_sp->ExtractHeader(dwarf, data, offset_ptr)) {
+    cu_sp->m_type_signature = data.GetU64(offset_ptr);
+    cu_sp->m_type_offset = data.GetDWARFOffset(offset_ptr);
+    return cu_sp;
+  }
+  // reset the offset to where we tried to parse from if anything went wrong
+  *offset_ptr = cu_sp->m_offset;
+  return nullptr;
+}
+
+DWARFDIE DWARFTypeUnit::GetTypeUnitDIE() {
+  // 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());
+}
Index: source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -10,6 +10,7 @@
 #ifndef SymbolFileDWARF_DWARFFormValue_h_
 #define SymbolFileDWARF_DWARFFormValue_h_
 
+#include "DWARFDIE.h"
 #include "DWARFDataExtractor.h"
 #include <stddef.h> // for NULL
 
@@ -73,6 +74,7 @@
   const uint8_t *BlockData() const;
   uint64_t Reference() const;
   uint64_t Reference(dw_offset_t offset) const;
+  DWARFDIE GetTypeSignatureDIE() const;
   bool Boolean() const { return m_value.value.uval != 0; }
   uint64_t Unsigned() const { return m_value.value.uval; }
   void SetUnsigned(uint64_t uval) { m_value.value.uval = uval; }
Index: source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -629,6 +629,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;
   }
@@ -647,13 +654,32 @@
     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;
   }
 
   return die_offset;
 }
 
+DWARFDIE DWARFFormValue::GetTypeSignatureDIE() const {
+  if (m_form == 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);
+    return m_cu->FindTypeSignatureDIE(m_value.value.uval);
+  }
+
+  return DWARFDIE();
+}
+
 const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }
 
 bool DWARFFormValue::IsBlockForm(const dw_form_t form) {
Index: source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
+++ source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -11,14 +11,17 @@
 #define SymbolFileDWARF_DWARFDebugInfo_h_
 
 #include <map>
+#include <unordered_map>
 #include <vector>
 
 #include "DWARFUnit.h"
 #include "DWARFDIE.h"
 #include "SymbolFileDWARF.h"
 #include "lldb/Core/STLUtils.h"
 #include "lldb/lldb-private.h"
 
+class DWARFTypeUnit;
+
 typedef std::multimap<const char *, dw_offset_t, CStringCompareFunctionObject>
     CStringToDIEMap;
 typedef CStringToDIEMap::iterator CStringToDIEMapIter;
@@ -38,6 +41,7 @@
   size_t GetNumCompileUnits();
   bool ContainsCompileUnit(const DWARFUnit *cu) const;
   DWARFUnit *GetCompileUnitAtIndex(uint32_t idx);
+  DWARFTypeUnit *GetTypeUnitForSignature(uint64_t type_sig);
   DWARFUnit *GetCompileUnit(dw_offset_t cu_offset, uint32_t *idx_ptr = NULL);
   DWARFUnit *GetCompileUnitContainingDIEOffset(dw_offset_t die_offset);
   DWARFUnit *GetCompileUnit(const DIERef &die_ref);
@@ -58,12 +62,14 @@
                                               const DWARFUnitSP &cu_sp);
 
   typedef std::vector<DWARFUnitSP> CompileUnitColl;
+  typedef std::unordered_map<uint64_t, uint32_t> TypeSignatureMap;
 
   //----------------------------------------------------------------------
   // Member variables
   //----------------------------------------------------------------------
   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
@@ -23,6 +23,7 @@
 #include "DWARFDebugInfo.h"
 #include "DWARFDebugInfoEntry.h"
 #include "DWARFFormValue.h"
+#include "DWARFTypeUnit.h"
 #include "LogChannelDWARF.h"
 
 using namespace lldb;
@@ -94,18 +95,37 @@
 }
 
 void DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() {
-  if (m_compile_units.empty()) {
-    if (m_dwarf2Data != NULL) {
-      lldb::offset_t offset = 0;
-      DWARFUnitSP cu_sp;
-      const auto &debug_info_data = m_dwarf2Data->get_debug_info_data();
-      while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, debug_info_data,
-                                                &offset))) {
-        m_compile_units.push_back(cu_sp);
-
-        offset = cu_sp->GetNextCompileUnitOffset();
-      }
-    }
+  if (!m_compile_units.empty())
+    return;
+  
+  if (m_dwarf2Data == nullptr)
+    return;
+
+  lldb::offset_t offset = 0;
+  DWARFCompileUnitSP cu_sp;
+  const auto &raw_debug_info_data = m_dwarf2Data->get_raw_debug_info_data();
+  while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, raw_debug_info_data,
+                                            &offset))) {
+    m_compile_units.push_back(cu_sp);
+    offset = cu_sp->GetNextCompileUnitOffset();
+  }
+  
+  // If we have a separate .debug_types section, it means we are using DWARF4
+  // or earlier where type units are a separate section. All data in the
+  // .debug_types section doesn't refer directly to any other DIEs, all
+  // references are done via type signatures. With this in mind, we can support
+  // parsing .debug_types by pretending that the data in .debug_types
+  // follows all data in the .debug_info section. This allows all
+  // types in the .debug_types to have a unique DIE offset that is:
+  //    offset = sizeof(.debug_info) + (possible gap) + debug_type_offset
+  const auto &debug_info_data = m_dwarf2Data->get_debug_info_data();
+  offset = m_dwarf2Data->get_debug_types_offset();
+  DWARFTypeUnitSP tu_sp;
+  while ((tu_sp = DWARFTypeUnit::Extract(m_dwarf2Data, debug_info_data,
+                                         &offset))) {
+    m_type_sig_to_cu_index[tu_sp->GetTypeSignature()] = m_compile_units.size();
+    m_compile_units.push_back(tu_sp);
+    offset = tu_sp->GetNextCompileUnitOffset();
   }
 }
 
@@ -226,3 +246,9 @@
   return DWARFDIE(); // Not found
 }
 
+DWARFTypeUnit *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)->GetAsTypeUnit();
+  return nullptr;
+}
Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -14,21 +14,11 @@
 
 class DWARFCompileUnit : public DWARFUnit {
 public:
-  static DWARFUnitSP Extract(SymbolFileDWARF *dwarf2Data,
-                             const lldb_private::DWARFDataExtractor &debug_info,
-                             lldb::offset_t *offset_ptr);
+  static DWARFCompileUnitSP Extract(SymbolFileDWARF *dwarf2Data,
+      const lldb_private::DWARFDataExtractor &debug_info,
+      lldb::offset_t *offset_ptr);
   void Dump(lldb_private::Stream *s) const override;
 
-  //------------------------------------------------------------------
-  /// Get the data that contains the DIE information for this unit.
-  ///
-  /// @return
-  ///   The correct data (.debug_types for DWARF 4 and earlier, and
-  ///   .debug_info for DWARF 5 and later) for the DIE information in
-  ///   this unit.
-  //------------------------------------------------------------------
-  const lldb_private::DWARFDataExtractor &GetData() const override;
-
   //------------------------------------------------------------------
   /// Get the size in bytes of the header.
   ///
Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -15,56 +15,17 @@
 using namespace lldb;
 using namespace lldb_private;
 
-extern int g_verbose;
-
 DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF *dwarf2Data)
     : DWARFUnit(dwarf2Data) {}
 
-DWARFUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data,
+DWARFCompileUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data,
                                       const DWARFDataExtractor &debug_info,
                                       lldb::offset_t *offset_ptr) {
   // std::make_shared would require the ctor to be public.
-  std::shared_ptr<DWARFCompileUnit> cu_sp(new DWARFCompileUnit(dwarf2Data));
-
-  cu_sp->m_offset = *offset_ptr;
-
-  if (debug_info.ValidOffset(*offset_ptr)) {
-    dw_offset_t abbr_offset;
-    const DWARFDebugAbbrev *abbr = dwarf2Data->DebugAbbrev();
-    cu_sp->m_length = debug_info.GetDWARFInitialLength(offset_ptr);
-    cu_sp->m_is_dwarf64 = debug_info.IsDWARF64();
-    cu_sp->m_version = debug_info.GetU16(offset_ptr);
-
-    if (cu_sp->m_version == 5) {
-      cu_sp->m_unit_type = debug_info.GetU8(offset_ptr);
-      cu_sp->m_addr_size = debug_info.GetU8(offset_ptr);
-      abbr_offset = debug_info.GetDWARFOffset(offset_ptr);
-
-      if (cu_sp->m_unit_type == llvm::dwarf::DW_UT_skeleton)
-        cu_sp->m_dwo_id = debug_info.GetU64(offset_ptr);
-    } else {
-      abbr_offset = debug_info.GetDWARFOffset(offset_ptr);
-      cu_sp->m_addr_size = debug_info.GetU8(offset_ptr);
-    }
-
-    bool length_OK =
-        debug_info.ValidOffset(cu_sp->GetNextCompileUnitOffset() - 1);
-    bool version_OK = SymbolFileDWARF::SupportedVersion(cu_sp->m_version);
-    bool abbr_offset_OK =
-        dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset);
-    bool addr_size_OK = (cu_sp->m_addr_size == 4) || (cu_sp->m_addr_size == 8);
-
-    if (length_OK && version_OK && addr_size_OK && abbr_offset_OK &&
-        abbr != NULL) {
-      cu_sp->m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset);
-      return cu_sp;
-    }
-
-    // reset the offset to where we tried to parse from if anything went wrong
-    *offset_ptr = cu_sp->m_offset;
-  }
-
-  return nullptr;
+  DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(dwarf2Data));
+  if (cu_sp->ExtractHeader(dwarf2Data, debug_info, offset_ptr))
+    return cu_sp;
+  return DWARFCompileUnitSP();
 }
 
 void DWARFCompileUnit::Dump(Stream *s) const {
@@ -92,7 +53,3 @@
   }
   llvm_unreachable("invalid UnitType.");
 }
-
-const lldb_private::DWARFDataExtractor &DWARFCompileUnit::GetData() const {
-  return m_dwarf->get_debug_info_data();
-}
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -251,8 +251,21 @@
           context_die.GetOffset(), die.GetTagAsCString(), die.GetName());
     }
     Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE());
-    TypeList *type_list = dwarf->GetTypeList();
     if (type_ptr == NULL) {
+
+      // If we have .debug_types defer to the complete version in the
+      // .debug_types section, not the broken incomplete definition in real
+      // compile units that are only there so addresses can be assigned to
+      // static values.
+      auto signature_die = die.GetAttributeValueAsReferenceDIE(DW_AT_signature);
+      if (signature_die) {
+        type_sp = ParseTypeFromDWARF(sc, signature_die, log, type_is_new_ptr);
+        if (type_sp) {
+          dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+          return type_sp;
+        }
+      }
+
       if (type_is_new_ptr)
         *type_is_new_ptr = true;
 
@@ -1887,7 +1900,7 @@
 
         // We are ready to put this type into the uniqued list up at the module
         // level
-        type_list->Insert(type_sp);
+        dwarf->GetTypeList()->Insert(type_sp);
 
         dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
       }
Index: source/Plugins/SymbolFile/DWARF/DIERef.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DIERef.cpp
+++ source/Plugins/SymbolFile/DWARF/DIERef.cpp
@@ -9,6 +9,7 @@
 
 #include "DIERef.h"
 #include "DWARFUnit.h"
+#include "DWARFTypeUnit.h"
 #include "DWARFDebugInfo.h"
 #include "DWARFFormValue.h"
 #include "SymbolFileDWARF.h"
@@ -42,10 +43,24 @@
   if (form_value.IsValid()) {
     const DWARFUnit *dwarf_cu = form_value.GetCompileUnit();
     if (dwarf_cu) {
-      if (dwarf_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
-        cu_offset = dwarf_cu->GetBaseObjOffset();
-      else
-        cu_offset = dwarf_cu->GetOffset();
+      // Replace the compile unit with the type signature compile unit
+      // and DIE for the type signature. When a type is referred to by a
+      // DW_FORM_ref_sig8 form, the real information for the type in
+      // contained in a DW_TAG_type_unit.
+      if (form_value.Form() == DW_FORM_ref_sig8) {
+        uint64_t type_sig = form_value.Unsigned();
+        auto debug_info = dwarf_cu->GetSymbolFileDWARF()->DebugInfo();
+        auto tu = debug_info->GetTypeUnitForSignature(type_sig);
+        if (tu) {
+          cu_offset = tu->GetOffset();
+          die_offset = tu->GetTypeUnitDIEOffset();
+        }
+      } else {
+        if (dwarf_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
+          cu_offset = dwarf_cu->GetBaseObjOffset();
+        else
+          cu_offset = dwarf_cu->GetOffset();
+      }
     }
     die_offset = form_value.Reference();
   }
Index: source/Plugins/SymbolFile/DWARF/CMakeLists.txt
===================================================================
--- source/Plugins/SymbolFile/DWARF/CMakeLists.txt
+++ source/Plugins/SymbolFile/DWARF/CMakeLists.txt
@@ -28,6 +28,7 @@
   DWARFFormValue.cpp
   DWARFIndex.cpp
   DWARFUnit.cpp
+  DWARFTypeUnit.cpp
   HashedNameToDIE.cpp
   LogChannelDWARF.cpp
   ManualDWARFIndex.cpp
Index: packages/Python/lldbsuite/test/test_categories.py
===================================================================
--- packages/Python/lldbsuite/test/test_categories.py
+++ packages/Python/lldbsuite/test/test_categories.py
@@ -15,15 +15,16 @@
 
 
 debug_info_categories = [
-    'dwarf', 'dwo', 'dsym', 'gmodules'
+    'dwarf', 'dwo', 'dsym', 'gmodules', 'dwarf_type_units'
 ]
 
 all_categories = {
     'dataformatters': 'Tests related to the type command and the data formatters subsystem',
     'dwarf': 'Tests that can be run with DWARF debug information',
     '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 that can be run with DWARF type units',
     'expression': 'Tests related to the expression parser',
     'libc++': 'Test for libc++ data formatters',
     'libstdcxx': 'Test for libstdcxx data formatters',
@@ -62,6 +63,8 @@
         if platform not in ["freebsd", "darwin", "macosx", "ios", "watchos", "tvos", "bridgeos"]:
             return False
         return gmodules.is_compiler_clang_with_gmodules(compiler_path)
+    elif category == "dwarf_type_units":
+        return platform in ["linux"]
     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
@@ -212,6 +212,27 @@
     return True
 
 
+def buildDwarfTypeUnits(
+        sender=None,
+        architecture=None,
+        compiler=None,
+        dictionary=None,
+        testdir=None,
+        testname=None):
+    """Build the binaries with type units (type in  a .debug_types section)."""
+    commands = []
+    commands.append(getMake(testdir, testname) +
+                    ["MAKE_DSYM=NO",
+                     "DWARF_TYPE_UNITS=YES",
+                     getArchSpec(architecture),
+                     getCCSpec(compiler),
+                     getCmdLine(dictionary)])
+
+    lldbtest.system(commands, sender=sender)
+    # True signifies that we can handle building with type units.
+    return True
+
+
 def cleanup(sender=None, dictionary=None):
     """Perform a platform-specific cleanup after the test."""
     return True
Index: packages/Python/lldbsuite/test/make/Makefile.rules
===================================================================
--- packages/Python/lldbsuite/test/make/Makefile.rules
+++ packages/Python/lldbsuite/test/make/Makefile.rules
@@ -254,6 +254,12 @@
 	endif
 endif
 
+MANDATORY_DWARF_TYPE_UNITS_CFLAGS := -fdebug-types-section
+
+ifeq "$(DWARF_TYPE_UNITS)" "YES"
+	CFLAGS += $(MANDATORY_DWARF_TYPE_UNITS_CFLAGS)
+endif
+
 CXXFLAGS += -std=c++11 $(CFLAGS) $(ARCH_CXXFLAGS)
 LD = $(CC)
 LDFLAGS ?= $(CFLAGS)
Index: packages/Python/lldbsuite/test/lldbtest.py
===================================================================
--- packages/Python/lldbsuite/test/lldbtest.py
+++ packages/Python/lldbsuite/test/lldbtest.py
@@ -1587,6 +1587,23 @@
                                     dictionary, testdir, testname):
             raise Exception("Don't know how to build binary with gmodules")
 
+    def buildDwarfTypeUnits(
+            self,
+            architecture=None,
+            compiler=None,
+            dictionary=None):
+        """Platform specific way to build binaries with DWARF type units."""
+        testdir = self.mydir
+        testname = self.getBuildDirBasename()
+        if self.getDebugInfo() != "dwarf_type_units":
+            raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault")
+
+        module = builder_module()
+        dictionary = lldbplatformutil.finalize_build_dictionary(dictionary)
+        if not module.buildDwarfTypeUnits(self, architecture, compiler,
+                                          dictionary, testdir, testname):
+            raise Exception("Don't know how to build binary with DWARF type units")
+
     def buildGo(self):
         """Build the default go binary.
         """
@@ -2414,6 +2431,8 @@
             return self.buildDwo(architecture, compiler, dictionary)
         elif self.getDebugInfo() == "gmodules":
             return self.buildGModules(architecture, compiler, dictionary)
+        elif self.getDebugInfo() == "dwarf_type_units":
+            return self.buildDwarfTypeUnits(architecture, compiler, dictionary)
         else:
             self.fail("Can't build for debug info: %s" % self.getDebugInfo())
 
Index: include/lldb/lldb-forward.h
===================================================================
--- include/lldb/lldb-forward.h
+++ include/lldb/lldb-forward.h
@@ -86,6 +86,7 @@
 class DiagnosticManager;
 class Disassembler;
 class DumpValueObjectOptions;
+class DWARFDataExtractor;
 class DynamicCheckerFunctions;
 class DynamicLoader;
 class Editline;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to