diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -29,7 +29,7 @@ eProducerClang, eProducerGCC, eProducerLLVMGCC, - eProcucerOther + eProducerOther }; /// Base class describing the header of any kind of "unit." Some information @@ -195,11 +195,7 @@ DWARFProducer GetProducer(); - uint32_t GetProducerVersionMajor(); - - uint32_t GetProducerVersionMinor(); - - uint32_t GetProducerVersionUpdate(); + llvm::VersionTuple GetProducerVersion(); uint64_t GetDWARFLanguageType(); @@ -311,9 +307,7 @@ std::unique_ptr m_func_aranges_up; dw_addr_t m_base_addr = 0; DWARFProducer m_producer = eProducerInvalid; - uint32_t m_producer_version_major = 0; - uint32_t m_producer_version_minor = 0; - uint32_t m_producer_version_update = 0; + llvm::VersionTuple m_producer_version; llvm::Optional m_language_type; lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate; llvm::Optional m_comp_dir; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -654,50 +654,38 @@ } bool DWARFUnit::Supports_unnamed_objc_bitfields() { - if (GetProducer() == eProducerClang) { - const uint32_t major_version = GetProducerVersionMajor(); - return major_version > 425 || - (major_version == 425 && GetProducerVersionUpdate() >= 13); - } - return true; // Assume all other compilers didn't have incorrect ObjC bitfield - // info + if (GetProducer() == eProducerClang) + return GetProducerVersion() >= llvm::VersionTuple(425, 0, 13); + // Assume all other compilers didn't have incorrect ObjC bitfield info. + return true; } void DWARFUnit::ParseProducerInfo() { - m_producer_version_major = UINT32_MAX; - m_producer_version_minor = UINT32_MAX; - m_producer_version_update = UINT32_MAX; - const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); if (die) { - const char *producer_cstr = die->GetAttributeValueAsString(this, DW_AT_producer, nullptr); - if (producer_cstr) { + llvm::StringRef producer(producer_cstr); + if (!producer.empty()) { RegularExpression llvm_gcc_regex( llvm::StringRef("^4\\.[012]\\.[01] \\(Based on Apple " "Inc\\. build [0-9]+\\) \\(LLVM build " "[\\.0-9]+\\)$")); - if (llvm_gcc_regex.Execute(llvm::StringRef(producer_cstr))) { + if (llvm_gcc_regex.Execute(producer)) { m_producer = eProducerLLVMGCC; - } else if (strstr(producer_cstr, "clang")) { + } else if (producer.contains("clang")) { static RegularExpression g_clang_version_regex( - llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)")); + llvm::StringRef(R"(clang-([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?))")); llvm::SmallVector matches; - if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr), - &matches)) { - // FIXME: improve error handling - llvm::to_integer(matches[1], m_producer_version_major); - llvm::to_integer(matches[2], m_producer_version_minor); - llvm::to_integer(matches[3], m_producer_version_update); - } + if (g_clang_version_regex.Execute(producer, &matches)) + m_producer_version.tryParse(matches[1]); m_producer = eProducerClang; - } else if (strstr(producer_cstr, "GNU")) + } else if (producer.contains("GNU")) m_producer = eProducerGCC; } } if (m_producer == eProducerInvalid) - m_producer = eProcucerOther; + m_producer = eProducerOther; } DWARFProducer DWARFUnit::GetProducer() { @@ -706,22 +694,10 @@ return m_producer; } -uint32_t DWARFUnit::GetProducerVersionMajor() { - if (m_producer_version_major == 0) - ParseProducerInfo(); - return m_producer_version_major; -} - -uint32_t DWARFUnit::GetProducerVersionMinor() { - if (m_producer_version_minor == 0) - ParseProducerInfo(); - return m_producer_version_minor; -} - -uint32_t DWARFUnit::GetProducerVersionUpdate() { - if (m_producer_version_update == 0) +llvm::VersionTuple DWARFUnit::GetProducerVersion() { + if (m_producer_version.empty()) ParseProducerInfo(); - return m_producer_version_update; + return m_producer_version; } uint64_t DWARFUnit::GetDWARFLanguageType() { diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFUnitTest.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFUnitTest.cpp --- a/lldb/unittests/SymbolFile/DWARF/DWARFUnitTest.cpp +++ b/lldb/unittests/SymbolFile/DWARF/DWARFUnitTest.cpp @@ -84,3 +84,42 @@ EXPECT_EQ(die_first->GetFirstChild(), nullptr); EXPECT_EQ(die_first->GetSibling(), nullptr); } + +TEST(DWARFUnitTest, Producer) { + const char *yamldata = R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_386 +DWARF: + debug_str: + - 'Apple clang version 13.0.0 (clang-1300.0.29.3)' + debug_abbrev: + - Table: + - Code: 0x00000001 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_producer + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_data2 + debug_info: + - Version: 4 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x0 + - Value: 0xC + - AbbrCode: 0x0 +)"; + + YAMLModuleTester t(yamldata); + DWARFUnit *unit = t.GetDwarfUnit(); + ASSERT_TRUE((bool)unit); + EXPECT_EQ(unit->GetProducer(), eProducerClang); + EXPECT_EQ(unit->GetProducerVersion(), llvm::VersionTuple(1300, 0, 29, 3)); +}