File indexing completed on 2024-05-12 05:43:25
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 "dependenciescheck.h" 0019 0020 #include <elf/elffileset.h> 0021 #include <elf/elffile.h> 0022 #include <elf/elfsectionheader.h> 0023 #include <elf/elfhashsection.h> 0024 #include <elf/elfsymboltablesection.h> 0025 #include <elf/elfsymboltableentry.h> 0026 0027 #include <QHash> 0028 0029 #include <cassert> 0030 #include <iostream> 0031 0032 DependenciesCheck::UnusedDependencies DependenciesCheck::unusedDependencies(ElfFileSet* fileSet, int fileToCheck) 0033 { 0034 QHash<QByteArray, int> fileIndex; 0035 for (int i = 0; i < fileSet->size(); ++i) { 0036 const auto file = fileSet->file(i); 0037 if (!file->dynamicSection()) 0038 continue; 0039 const auto soName = file->dynamicSection()->soName(); 0040 if (!soName.isEmpty()) 0041 fileIndex.insert(soName, i); 0042 else 0043 fileIndex.insert(file->fileName().toUtf8(), i); 0044 } 0045 0046 UnusedDependencies unusedDeps; 0047 for (int i = 0; i < fileSet->size(); ++i) { 0048 if (i != fileToCheck && fileToCheck >= 0) 0049 continue; 0050 const auto *dynamicSection = fileSet->file(i)->dynamicSection(); 0051 if (!dynamicSection) 0052 continue; 0053 foreach (const auto &needed, fileSet->file(i)->dynamicSection()->neededLibraries()) { 0054 const auto depIdx = fileIndex.value(needed); 0055 const auto depFile = fileSet->file(depIdx); 0056 const auto count = usedSymbolCount(fileSet->file(i), depFile); 0057 if (count == 0) 0058 unusedDeps.push_back(qMakePair(i, depIdx)); 0059 } 0060 } 0061 0062 return unusedDeps; 0063 } 0064 0065 void DependenciesCheck::printUnusedDependencies(ElfFileSet* fileSet, const UnusedDependencies& unusedDeps) 0066 { 0067 for (auto unusedDep : unusedDeps) { 0068 std::cout << qPrintable(fileSet->file(unusedDep.first)->displayName()) << " depends on " 0069 << qPrintable(fileSet->file(unusedDep.second)->displayName()) << " without using any of its symbols" 0070 << std::endl; 0071 } 0072 } 0073 0074 QVector<ElfSymbolTableEntry*> DependenciesCheck::usedSymbols(ElfFile* userFile, ElfFile* providerFile) 0075 { 0076 QVector<ElfSymbolTableEntry*> symbols; 0077 0078 const auto symtab = userFile->section<ElfSymbolTableSection>(userFile->indexOfSection(SHT_DYNSYM)); 0079 if (!symtab) 0080 return symbols; 0081 const auto symtabSize = symtab->header()->entryCount(); 0082 0083 const auto hashtab = providerFile->hash(); 0084 assert(hashtab); 0085 0086 for (uint i = 0; i < symtabSize; ++i) { 0087 const auto userEntry = symtab->entry(i); 0088 if (userEntry->value() != 0) 0089 continue; 0090 const auto providerEntry = hashtab->lookup(userEntry->name()); 0091 if (providerEntry && providerEntry->value() > 0) 0092 symbols.push_back(providerEntry); 0093 } 0094 0095 return symbols; 0096 } 0097 0098 int DependenciesCheck::usedSymbolCount(ElfFile* userFile, ElfFile* providerFile) 0099 { 0100 const auto symtab = userFile->section<ElfSymbolTableSection>(userFile->indexOfSection(SHT_DYNSYM)); 0101 if (!symtab) 0102 return 0; 0103 const auto symtabSize = symtab->header()->entryCount(); 0104 0105 const auto hashtab = providerFile->hash(); 0106 assert(hashtab); 0107 0108 int count = 0; 0109 for (uint i = 0; i < symtabSize; ++i) { 0110 const auto userEntry = symtab->entry(i); 0111 if (userEntry->value() != 0) 0112 continue; 0113 const auto providerEntry = hashtab->lookup(userEntry->name()); 0114 if (providerEntry && providerEntry->value() > 0) 0115 ++count; 0116 } 0117 return count; 0118 }