Index: lit/SymbolFile/DWARF/Inputs/debug-types-basic.cpp =================================================================== --- /dev/null +++ lit/SymbolFile/DWARF/Inputs/debug-types-basic.cpp @@ -0,0 +1,13 @@ +struct A { + int i; + long l; + float f; + double d; +}; + +enum E { e1, e2, e3 }; +enum class EC { e1, e2, e3 }; + +extern constexpr A a{42, 47l, 4.2f, 4.7}; +extern constexpr E e(e2); +extern constexpr EC ec(EC::e2); Index: lit/SymbolFile/DWARF/Inputs/debug-types-expressions.cpp =================================================================== --- /dev/null +++ lit/SymbolFile/DWARF/Inputs/debug-types-expressions.cpp @@ -0,0 +1,25 @@ +struct A { + int i = 47; + int f() { return i; } + virtual ~A() = default; +}; + +struct B: public A { + int j = 42; +}; + +namespace ns { +struct A { + int i = 147; + A(); +}; +A::A() = default; +} + +int foo(A *a) { + return a->f(); +} + +int main() { + return foo(new B); +} Index: lit/SymbolFile/DWARF/debug-types-basic.test =================================================================== --- /dev/null +++ lit/SymbolFile/DWARF/debug-types-basic.test @@ -0,0 +1,46 @@ +# REQUIRES: lld + +# Make sure DWARF v4 type units work. +# RUN: %clangxx -target x86_64-pc-linux %S/Inputs/debug-types-basic.cpp \ +# RUN: -g -gdwarf-4 -fdebug-types-section -c -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: %lldb %t -s %s -o exit | FileCheck %s + +# Now do the same for DWARF v5. +# RUN: %clangxx -target x86_64-pc-linux %S/Inputs/debug-types-basic.cpp \ +# RUN: -g -gdwarf-5 -fdebug-types-section -c -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: %lldb %t -s %s -o exit | FileCheck %s + +type lookup A +# CHECK-LABEL: type lookup A +# CHECK: struct A { +# CHECK-NEXT: int i; +# CHECK-NEXT: long l; +# CHECK-NEXT: float f; +# CHECK-NEXT: double d; +# CHECK-NEXT: } + +type lookup E +# CHECK-LABEL: type lookup E +# CHECK: enum E { +# CHECK-NEXT: e1, +# CHECK-NEXT: e2, +# CHECK-NEXT: e3 +# CHECK-NEXT: } + +type lookup EC +# CHECK-LABEL: type lookup EC +# CHECK: enum class EC { +# CHECK-NEXT: e1, +# CHECK-NEXT: e2, +# CHECK-NEXT: e3 +# CHECK-NEXT: } + +print (E) 1 +# CHECK-LABEL: print (E) 1 +# CHECK: (E) $0 = e2 + +print (EC) 1 +# CHECK-LABEL: print (EC) 1 +# CHECK: (EC) $1 = e2 Index: lit/SymbolFile/DWARF/debug-types-expressions.test =================================================================== --- /dev/null +++ lit/SymbolFile/DWARF/debug-types-expressions.test @@ -0,0 +1,28 @@ +# UNSUPPORTED: system-darwin, system-windows + +# Make sure DWARF v4 type units work. +# RUN: %clangxx %S/Inputs/debug-types-expressions.cpp \ +# RUN: -g -fdebug-types-section -o %t +# RUN: %lldb %t -s %s -o exit | FileCheck %s + +# Now do the same for DWARF v5. +# RUN: %clangxx %S/Inputs/debug-types-expressions.cpp \ +# RUN: -g -gdwarf-5 -fdebug-types-section -o %t +# RUN: %lldb %t -s %s -o exit | FileCheck %s + +breakpoint set -n foo +process launch + +# CHECK: Process {{.*}} stopped + +frame variable a +# CHECK-LABEL: frame variable a +# CHECK: (B *) a = + +print a->f() +# CHECK-LABEL: print a->f() +# CHECK: (int) $0 = 47 + +print ns::A() +# CHECK-LABEL: print ns::A() +# CHECK: (ns::A) $1 = (i = 147) Index: lit/SymbolFile/DWARF/lit.local.cfg =================================================================== --- lit/SymbolFile/DWARF/lit.local.cfg +++ lit/SymbolFile/DWARF/lit.local.cfg @@ -1 +1 @@ -config.suffixes = ['.cpp', '.s'] +config.suffixes = ['.cpp', '.s', '.test'] Index: source/Plugins/SymbolFile/DWARF/CMakeLists.txt =================================================================== --- source/Plugins/SymbolFile/DWARF/CMakeLists.txt +++ source/Plugins/SymbolFile/DWARF/CMakeLists.txt @@ -22,6 +22,7 @@ DWARFDIE.cpp DWARFFormValue.cpp DWARFIndex.cpp + DWARFTypeUnit.cpp DWARFUnit.cpp HashedNameToDIE.cpp LogChannelDWARF.cpp Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -16,15 +16,12 @@ public: void Dump(lldb_private::Stream *s) const override; - DIERef::Section GetDebugSection() const override { - return DIERef::Section::DebugInfo; - } - private: DWARFCompileUnit(SymbolFileDWARF *dwarf, lldb::user_id_t uid, const DWARFUnitHeader &header, - const DWARFAbbreviationDeclarationSet &abbrevs) - : DWARFUnit(dwarf, uid, header, abbrevs) {} + const DWARFAbbreviationDeclarationSet &abbrevs, + DIERef::Section section) + : DWARFUnit(dwarf, uid, header, abbrevs, section) {} DISALLOW_COPY_AND_ASSIGN(DWARFCompileUnit); Index: source/Plugins/SymbolFile/DWARF/DWARFContext.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFContext.h +++ source/Plugins/SymbolFile/DWARF/DWARFContext.h @@ -28,6 +28,7 @@ llvm::Optional m_data_debug_macro; llvm::Optional m_data_debug_str; llvm::Optional m_data_debug_str_offsets; + llvm::Optional m_data_debug_types; bool isDwo() { return m_dwo_section_list != nullptr; } @@ -45,6 +46,7 @@ const DWARFDataExtractor &getOrLoadMacroData(); const DWARFDataExtractor &getOrLoadStrData(); const DWARFDataExtractor &getOrLoadStrOffsetsData(); + const DWARFDataExtractor &getOrLoadDebugTypesData(); }; } // namespace lldb_private Index: source/Plugins/SymbolFile/DWARF/DWARFContext.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFContext.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFContext.cpp @@ -86,3 +86,8 @@ return LoadOrGetSection(m_main_section_list, eSectionTypeDWARFDebugStrOffsets, m_data_debug_str_offsets); } + +const DWARFDataExtractor &DWARFContext::getOrLoadDebugTypesData() { + return LoadOrGetSection(m_main_section_list, eSectionTypeDWARFDebugTypes, + m_data_debug_types); +} Index: source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -22,6 +22,7 @@ #include "DWARFDebugInfo.h" #include "DWARFDebugInfoEntry.h" #include "DWARFFormValue.h" +#include "DWARFTypeUnit.h" using namespace lldb; using namespace lldb_private; @@ -73,17 +74,12 @@ return *m_cu_aranges_up; } -void DWARFDebugInfo::ParseUnitHeadersIfNeeded() { - if (!m_units.empty()) - return; - if (!m_dwarf2Data) - return; - +void Parse(SymbolFileDWARF *dwarf, const DWARFDataExtractor &data, + DIERef::Section section, std::vector &units) { lldb::offset_t offset = 0; - const auto &debug_info_data = m_context.getOrLoadDebugInfoData(); - while (debug_info_data.ValidOffset(offset)) { - llvm::Expected unit_sp = DWARFUnit::extract( - m_dwarf2Data, m_units.size(), debug_info_data, &offset); + while (data.ValidOffset(offset)) { + llvm::Expected unit_sp = + DWARFUnit::extract(dwarf, units.size(), data, section, &offset); if (!unit_sp) { // FIXME: Propagate this error up. @@ -94,12 +90,24 @@ // If it didn't return an error, then it should be returning a valid Unit. assert(*unit_sp); - m_units.push_back(*unit_sp); + units.push_back(*unit_sp); offset = (*unit_sp)->GetNextUnitOffset(); } } +void DWARFDebugInfo::ParseUnitHeadersIfNeeded() { + if (!m_units.empty()) + return; + if (!m_dwarf2Data) + return; + + Parse(m_dwarf2Data, m_context.getOrLoadDebugInfoData(), + DIERef::Section::DebugInfo, m_units); + Parse(m_dwarf2Data, m_context.getOrLoadDebugTypesData(), + DIERef::Section::DebugTypes, m_units); +} + size_t DWARFDebugInfo::GetNumUnits() { ParseUnitHeadersIfNeeded(); return m_units.size(); Index: source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h =================================================================== --- /dev/null +++ source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h @@ -0,0 +1,29 @@ +//===-- DWARFTypeUnit.h -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DWARFTypeUnit_h_ +#define SymbolFileDWARF_DWARFTypeUnit_h_ + +#include "DWARFUnit.h" +#include "llvm/Support/Error.h" + +class DWARFTypeUnit : public DWARFUnit { +public: + void Dump(lldb_private::Stream *s) const override; + +private: + DWARFTypeUnit(SymbolFileDWARF *dwarf, lldb::user_id_t uid, + const DWARFUnitHeader &header, + const DWARFAbbreviationDeclarationSet &abbrevs, + DIERef::Section section) + : DWARFUnit(dwarf, uid, header, abbrevs, section) {} + + friend class DWARFUnit; +}; + +#endif // SymbolFileDWARF_DWARFTypeUnit_h_ Index: source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp =================================================================== --- /dev/null +++ source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp @@ -0,0 +1,24 @@ +//===-- DWARFTypeUnit.cpp ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "DWARFTypeUnit.h" + +#include "SymbolFileDWARF.h" +#include "lldb/Utility/Stream.h" + +using namespace lldb; +using namespace lldb_private; + + +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 (next CU at " + "{0x%8.8x})\n", + GetOffset(), GetLength(), GetVersion(), GetAbbrevOffset(), + GetAddressByteSize(), GetNextUnitOffset()); +} Index: source/Plugins/SymbolFile/DWARF/DWARFUnit.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -58,7 +58,7 @@ uint32_t GetNextUnitOffset() const { return m_offset + m_length + 4; } static llvm::Expected - extract(const lldb_private::DWARFDataExtractor &data, + extract(const lldb_private::DWARFDataExtractor &data, DIERef::Section section, lldb::offset_t *offset_ptr); }; @@ -70,7 +70,7 @@ static llvm::Expected extract(SymbolFileDWARF *dwarf2Data, lldb::user_id_t uid, const lldb_private::DWARFDataExtractor &debug_info, - lldb::offset_t *offset_ptr); + DIERef::Section section, lldb::offset_t *offset_ptr); virtual ~DWARFUnit(); void ExtractUnitDIEIfNeeded(); @@ -204,12 +204,17 @@ return die_iterator_range(m_die_array.begin(), m_die_array.end()); } - virtual DIERef::Section GetDebugSection() const = 0; + DIERef::Section GetDebugSection() const { return m_section; } protected: DWARFUnit(SymbolFileDWARF *dwarf, lldb::user_id_t uid, const DWARFUnitHeader &header, - const DWARFAbbreviationDeclarationSet &abbrevs); + const DWARFAbbreviationDeclarationSet &abbrevs, + DIERef::Section section); + + llvm::Error ExtractHeader(SymbolFileDWARF *dwarf, + const lldb_private::DWARFDataExtractor &data, + lldb::offset_t *offset_ptr); SymbolFileDWARF *m_dwarf = nullptr; std::unique_ptr m_dwo_symbol_file; @@ -246,6 +251,7 @@ // in the main object file dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET; dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base. + const DIERef::Section m_section; private: void ParseProducerInfo(); Index: source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -21,6 +21,7 @@ #include "DWARFCompileUnit.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" +#include "DWARFTypeUnit.h" #include "LogChannelDWARF.h" #include "SymbolFileDWARFDebugMap.h" #include "SymbolFileDWARFDwo.h" @@ -33,9 +34,10 @@ DWARFUnit::DWARFUnit(SymbolFileDWARF *dwarf, lldb::user_id_t uid, const DWARFUnitHeader &header, - const DWARFAbbreviationDeclarationSet &abbrevs) + const DWARFAbbreviationDeclarationSet &abbrevs, + DIERef::Section section) : UserID(uid), m_dwarf(dwarf), m_header(header), m_abbrevs(&abbrevs), - m_cancel_scopes(false) {} + m_cancel_scopes(false), m_section(section) {} DWARFUnit::~DWARFUnit() = default; @@ -792,7 +794,7 @@ } llvm::Expected -DWARFUnitHeader::extract(const DWARFDataExtractor &data, +DWARFUnitHeader::extract(const DWARFDataExtractor &data, DIERef::Section section, lldb::offset_t *offset_ptr) { DWARFUnitHeader header; header.m_offset = *offset_ptr; @@ -807,8 +809,8 @@ } else { header.m_abbr_offset = data.GetDWARFOffset(offset_ptr); header.m_addr_size = data.GetU8(offset_ptr); - // Only compile units supported so far. - header.m_unit_type = DW_UT_compile; + header.m_unit_type = + section == DIERef::Section::DebugTypes ? DW_UT_type : DW_UT_compile; } bool length_OK = data.ValidOffset(header.GetNextUnitOffset() - 1); @@ -830,11 +832,12 @@ llvm::Expected DWARFUnit::extract(SymbolFileDWARF *dwarf, user_id_t uid, - const DWARFDataExtractor &debug_info, + const DWARFDataExtractor &debug_info, DIERef::Section section, lldb::offset_t *offset_ptr) { assert(debug_info.ValidOffset(*offset_ptr)); - auto expected_header = DWARFUnitHeader::extract(debug_info, offset_ptr); + auto expected_header = + DWARFUnitHeader::extract(debug_info, section, offset_ptr); if (!expected_header) return expected_header.takeError(); @@ -856,14 +859,17 @@ return llvm::make_error( "No abbrev exists at the specified offset."); - DWARFUnitSP unit_sp( - new DWARFCompileUnit(dwarf, uid, *expected_header, *abbrevs)); - - return unit_sp; + if (expected_header->IsTypeUnit()) + return DWARFUnitSP( + new DWARFTypeUnit(dwarf, uid, *expected_header, *abbrevs, section)); + return DWARFUnitSP( + new DWARFCompileUnit(dwarf, uid, *expected_header, *abbrevs, section)); } const lldb_private::DWARFDataExtractor &DWARFUnit::GetData() const { - return m_dwarf->GetDWARFContext().getOrLoadDebugInfoData(); + return m_section == DIERef::Section::DebugTypes + ? m_dwarf->GetDWARFContext().getOrLoadDebugTypesData() + : m_dwarf->GetDWARFContext().getOrLoadDebugInfoData(); } uint32_t DWARFUnit::GetHeaderByteSize() const { Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -439,20 +439,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;