File indexing completed on 2024-05-12 05:43:26
0001 /* 0002 Copyright (C) 2015 Volker Krause <vkrause@kde.org> 0003 0004 This program is free software; you can redistribute it and/or modify it 0005 under the terms of the GNU Library General Public License as published by 0006 the Free Software Foundation; either version 2 of the License, or (at your 0007 option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, but WITHOUT 0010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0011 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 0012 License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program. If not, see <https://www.gnu.org/licenses/>. 0016 */ 0017 0018 #include "config-elf-dissector.h" 0019 #include "virtualdtorcheck.h" 0020 0021 #include <elf/elffileset.h> 0022 #if HAVE_DWARF 0023 #include <dwarf/dwarfinfo.h> 0024 #include <dwarf/dwarfdie.h> 0025 #include <dwarf/dwarfcudie.h> 0026 #include <dwarf/dwarftypes.h> 0027 0028 #include <dwarf.h> 0029 #endif 0030 0031 #include <algorithm> 0032 #include <iostream> 0033 0034 void VirtualDtorCheck::findImplicitVirtualDtors(ElfFileSet* fileSet) 0035 { 0036 #if HAVE_DWARF 0037 for (int i = 0; i < fileSet->size(); ++i) { 0038 const auto file = fileSet->file(i); 0039 if (!file->dwarfInfo()) 0040 continue; 0041 foreach (const auto die, file->dwarfInfo()->compilationUnits()) 0042 findImplicitVirtualDtors(die); 0043 } 0044 0045 // implicit virtual dtors in implementation files are not a problem 0046 m_results.erase( 0047 std::remove_if(m_results.begin(), m_results.end(), [](const Result &res) { 0048 return res.sourceFilePath.endsWith(QLatin1String(".cpp")) 0049 || res.sourceFilePath.endsWith(QLatin1String(".c")) 0050 || res.sourceFilePath.endsWith(QLatin1String(".cxx")); 0051 }), m_results.end() 0052 ); 0053 #endif 0054 } 0055 0056 void VirtualDtorCheck::findImplicitVirtualDtors(DwarfDie* die) 0057 { 0058 #if HAVE_DWARF 0059 const bool isCandidate = 0060 die->tag() == DW_TAG_subprogram && 0061 die->attribute(DW_AT_external).toBool() && 0062 die->attribute(DW_AT_declaration).toBool() && 0063 die->attribute(DW_AT_artificial).toBool() && 0064 die->attribute(DW_AT_virtuality).value<DwarfVirtuality>() == DwarfVirtuality::Virtual && 0065 die->name().startsWith('~'); 0066 0067 if (isCandidate) { 0068 const auto fullName = die->fullyQualifiedName(); 0069 const auto it = std::find_if(m_results.begin(), m_results.end(), [&fullName](const Result& res) { 0070 return res.fullName == fullName; 0071 }); 0072 const auto *typeDie = die->attribute(DW_AT_containing_type).value<DwarfDie*>(); 0073 if (it == m_results.end()) { 0074 const Result res = { 0075 fullName, 0076 typeDie ? typeDie->sourceFilePath() : QString(), 0077 typeDie ? typeDie->attribute(DW_AT_decl_line).toInt() : 0 0078 }; 0079 m_results.push_back(res); 0080 } else if ((*it).sourceFilePath.isEmpty() && typeDie) { 0081 (*it).sourceFilePath = typeDie->sourceFilePath(); 0082 (*it).lineNumber = typeDie->attribute(DW_AT_decl_line).toInt(); 0083 } 0084 } 0085 0086 const auto children = die->children(); 0087 for (const auto child : children) { 0088 if (child->tag() != DW_TAG_subprogram && 0089 child->tag() != DW_TAG_class_type && 0090 child->tag() != DW_TAG_structure_type && 0091 child->tag() != DW_TAG_namespace) 0092 continue; 0093 findImplicitVirtualDtors(child); 0094 } 0095 #endif 0096 } 0097 0098 void VirtualDtorCheck::printResults() const 0099 { 0100 for (const auto &res : m_results) { 0101 std::cout << res.fullName.constData() << " at " << qPrintable(res.sourceFilePath); 0102 if (res.lineNumber) 0103 std::cout << ':' << res.lineNumber; 0104 std::cout << std::endl; 0105 } 0106 } 0107 0108 void VirtualDtorCheck::clear() 0109 { 0110 m_results.clear(); 0111 } 0112 0113 const QVector< VirtualDtorCheck::Result >& VirtualDtorCheck::results() const 0114 { 0115 return m_results; 0116 }