File indexing completed on 2024-05-12 05:43:28

0001 /*
0002     Copyright (C) 2013-2014 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 "elffile.h"
0020 #include "elfheader.h"
0021 #include "elfsectionheader_impl.h"
0022 #include "elfstringtablesection.h"
0023 #include "elfsymboltablesection.h"
0024 #include "elfdynamicsection_impl.h"
0025 #include "elfgnudebuglinksection.h"
0026 #include "elfgnuhashsection.h"
0027 #include "elfgnusymbolversiontable.h"
0028 #include "elfgnusymbolversiondefinitionssection.h"
0029 #include "elfgnusymbolversionrequirementssection.h"
0030 #include "elfgotsection.h"
0031 #include "elfnotesection.h"
0032 #include "elfpltsection.h"
0033 #include "elfrelocationsection.h"
0034 #include "elfsysvhashsection.h"
0035 #include "elfsegmentheader_impl.h"
0036 #include "elfnoteentry.h"
0037 
0038 #if HAVE_DWARF
0039 #include <dwarf/dwarfinfo.h>
0040 #endif
0041 
0042 #include <QDebug>
0043 #include <QFileInfo>
0044 
0045 #include <cassert>
0046 #include <elf.h>
0047 
0048 struct ElfFileException {};
0049 
0050 ElfFile::ElfFile(const QString& fileName) : m_data(nullptr)
0051 {
0052     m_file.setFileName(fileName);
0053 }
0054 
0055 ElfFile::~ElfFile()
0056 {
0057     close();
0058 }
0059 
0060 bool ElfFile::isValid() const
0061 {
0062     return m_data;
0063 }
0064 
0065 QString ElfFile::displayName() const
0066 {
0067     if (dynamicSection() && !dynamicSection()->soName().isEmpty())
0068         return dynamicSection()->soName();
0069     return QFileInfo(m_file.fileName()).fileName();
0070 }
0071 
0072 QString ElfFile::fileName() const
0073 {
0074     return m_file.fileName();
0075 }
0076 
0077 uint64_t ElfFile::size() const
0078 {
0079     return m_file.size();
0080 }
0081 
0082 unsigned char* ElfFile::rawData() const
0083 {
0084     return m_data;
0085 }
0086 
0087 int ElfFile::type() const
0088 {
0089     assert(isValid());
0090     return m_data[EI_CLASS];
0091 }
0092 
0093 int ElfFile::addressSize() const
0094 {
0095     assert(isValid());
0096     return type() == ELFCLASS32 ? 4 : 8;
0097 }
0098 
0099 int ElfFile::byteOrder() const
0100 {
0101     assert(isValid());
0102     return m_data[EI_DATA];
0103 }
0104 
0105 uint8_t ElfFile::osAbi() const
0106 {
0107     return m_data[EI_OSABI];
0108 }
0109 
0110 ElfHeader* ElfFile::header() const
0111 {
0112     return m_header.get();
0113 }
0114 
0115 int ElfFile::sectionCount() const
0116 {
0117     assert(m_sectionHeaders.size() == m_sections.size());
0118     return m_sectionHeaders.size();
0119 }
0120 
0121 QVector<ElfSectionHeader*> ElfFile::sectionHeaders() const
0122 {
0123     return m_sectionHeaders;
0124 }
0125 
0126 bool ElfFile::open(QIODevice::OpenMode openMode)
0127 {
0128     if (!m_file.open(openMode)) {
0129         qCritical() << m_file.errorString() << m_file.fileName();
0130         return false;
0131     }
0132     m_data = m_file.map(0, m_file.size());
0133     if (!m_data) {
0134         close();
0135         return false;
0136     }
0137 
0138     try {
0139         parse();
0140     } catch (const ElfFileException&) {
0141         qCritical() << m_file.fileName() << "is not a valid ELF file.";
0142         close();
0143         return false;
0144     }
0145 
0146     return true;
0147 }
0148 
0149 void ElfFile::close()
0150 {
0151     delete m_dwarfInfo;
0152     assert(m_sectionHeaders.size() == m_sections.size());
0153     for (int i = 0; header() && i < header()->sectionHeaderCount(); ++i) { // don't delete sections merged from separate debug files
0154         delete m_sectionHeaders.at(i);
0155         delete m_sections.at(i);
0156     }
0157     m_file.close();
0158     m_data = nullptr;
0159 }
0160 
0161 void ElfFile::parse()
0162 {
0163     static_assert(EV_CURRENT == 1, "ELF version changed");
0164     if (m_file.size() <= EI_NIDENT || strncmp(reinterpret_cast<const char*>(m_data), ELFMAG, SELFMAG) != 0 || m_data[EI_VERSION] != EV_CURRENT)
0165         throw ElfFileException();
0166 
0167     parseHeader();
0168     parseSections();
0169     parseSegments();
0170 
0171 #if HAVE_DWARF
0172     if (indexOfSection(".debug_info") >= 0)
0173         m_dwarfInfo = new DwarfInfo(this);
0174 #endif
0175 }
0176 
0177 void ElfFile::parseHeader()
0178 {
0179     switch (type()) {
0180         case ELFCLASS32:
0181             m_header.reset(new ElfHeaderImpl<Elf32_Ehdr>(m_data));
0182             break;
0183         case ELFCLASS64:
0184             m_header.reset(new ElfHeaderImpl<Elf64_Ehdr>(m_data));
0185             break;
0186         default:
0187             throw ElfFileException();
0188     }
0189 }
0190 
0191 void ElfFile::parseSections()
0192 {
0193     assert(m_header.get());
0194 
0195     m_sectionHeaders.reserve(m_header->sectionHeaderCount());
0196     m_sections.resize(m_header->sectionHeaderCount());
0197 
0198     // pass 1: create section headers
0199     for (int i = 0; i < m_header->sectionHeaderCount(); ++i) {
0200         ElfSectionHeader* shdr = nullptr;
0201         switch(type()) {
0202             case ELFCLASS32:
0203                 shdr = new ElfSectionHeaderImpl<Elf32_Shdr>(this, i);
0204                 break;
0205             case ELFCLASS64:
0206                 shdr = new ElfSectionHeaderImpl<Elf64_Shdr>(this, i);
0207                 break;
0208             default:
0209                 throw ElfFileException();
0210         }
0211         m_sectionHeaders.push_back(shdr);
0212     }
0213 
0214     // pass 2: create sections, if any
0215     // make sure the string table section needed for section names is created first
0216     if (m_header->sectionHeaderCount() > 0) {
0217         parseSection(m_header->stringTableSectionHeader());
0218         for (int i = 0; i < m_header->sectionHeaderCount(); ++i) {
0219             if (i == m_header->stringTableSectionHeader())
0220                 continue;
0221             parseSection(i);
0222         }
0223     }
0224 
0225     // pass 3: set section links
0226     foreach (const auto shdr, m_sectionHeaders) {
0227         if (shdr->link()) {
0228             m_sections.at(shdr->sectionIndex())->setLinkedSection(m_sections.at(shdr->link()));
0229         }
0230     }
0231 
0232     // pass 4: stuff that requires the full setup for parsing
0233     // TODO can probably be done more efficient with on-demand parsing in those places
0234     foreach (auto section, m_sections) {
0235         switch (section->header()->type()) {
0236             case SHT_GNU_verdef:
0237                 dynamic_cast<ElfGNUSymbolVersionDefinitionsSection*>(section)->parse();
0238                 continue;
0239             case SHT_GNU_verneed:
0240                 dynamic_cast<ElfGNUSymbolVersionRequirementsSection*>(section)->parse();
0241                 continue;
0242         }
0243     }
0244 }
0245 
0246 void ElfFile::parseSection(uint16_t index)
0247 {
0248     const auto shdr = m_sectionHeaders.at(index);
0249     ElfSection* section = nullptr;
0250     switch (shdr->type()) {
0251         case SHT_STRTAB:
0252             section = new ElfStringTableSection(this, shdr);
0253             break;
0254         case SHT_SYMTAB:
0255         case SHT_DYNSYM:
0256             section = new ElfSymbolTableSection(this, shdr);
0257             break;
0258         case SHT_DYNAMIC:
0259             if (type() == ELFCLASS32)
0260                 m_dynamicSection = new ElfDynamicSectionImpl<Elf32_Dyn>(this, shdr);
0261             else if (type() == ELFCLASS64)
0262                 m_dynamicSection = new ElfDynamicSectionImpl<Elf64_Dyn>(this, shdr);
0263             section = m_dynamicSection;
0264             break;
0265         case SHT_REL:
0266         case SHT_RELA:
0267         {
0268             auto relocSec = new ElfRelocationSection(this, shdr);
0269             m_reverseReloc.addRelocationSection(relocSec);
0270             section = relocSec;
0271             break;
0272         }
0273         case SHT_NOTE:
0274             section = new ElfNoteSection(this, shdr);
0275             break;
0276         case SHT_GNU_versym:
0277             section = new ElfGNUSymbolVersionTable(this, shdr);
0278             break;
0279         case SHT_GNU_verdef:
0280             section = new ElfGNUSymbolVersionDefinitionsSection(this, shdr);
0281             break;
0282         case SHT_GNU_verneed:
0283             section = new ElfGNUSymbolVersionRequirementsSection(this, shdr);
0284             break;
0285         case SHT_HASH:
0286             section = new ElfSysvHashSection(this, shdr);
0287             if (!m_hashSection)
0288                 m_hashSection = static_cast<ElfHashSection*>(section);
0289             break;
0290         case SHT_GNU_HASH:
0291             section = m_hashSection = new ElfGnuHashSection(this, shdr);
0292             break;
0293         case SHT_PROGBITS:
0294             if (shdr->name() && strcmp(shdr->name(), ".plt") == 0) {
0295                 section = new ElfPltSection(this, shdr);
0296                 break;
0297             } else if ((shdr->flags() & SHF_WRITE) && strncmp(shdr->name(), ".got", 4) == 0) {
0298                 section = new ElfGotSection(this, shdr);
0299                 break;
0300             } else if (strcmp(shdr->name(), ".gnu_debuglink") == 0) {
0301                 section = new ElfGnuDebugLinkSection(this, shdr);
0302                 break;
0303             }
0304             // fall-through
0305         default:
0306             section = new ElfSection(this, shdr);
0307             break;
0308     }
0309     m_sections[index] = section;
0310 }
0311 
0312 void ElfFile::parseSegments()
0313 {
0314     m_segmentHeaders.reserve(m_header->programHeaderCount());
0315     for (int i = 0; i < m_header->programHeaderCount(); ++i) {
0316         ElfSegmentHeader* phdr = nullptr;
0317         switch(type()) {
0318             case ELFCLASS32:
0319                 phdr = new ElfSegmentHeaderImpl<Elf32_Phdr>(this, i);
0320                 break;
0321             case ELFCLASS64:
0322                 phdr = new ElfSegmentHeaderImpl<Elf64_Phdr>(this, i);
0323                 break;
0324             default:
0325                 throw ElfFileException();
0326         }
0327         m_segmentHeaders.push_back(phdr);
0328     }
0329 }
0330 
0331 int ElfFile::indexOfSection(uint32_t type) const
0332 {
0333     for (int i = 0; i < m_sectionHeaders.size(); ++i) {
0334         if (m_sectionHeaders.at(i)->type() == type)
0335             return i;
0336     }
0337     return -1;
0338 }
0339 
0340 int ElfFile::indexOfSection(const char* name) const
0341 {
0342     for (int i = 0; i < m_sectionHeaders.size(); ++i) {
0343         const auto hdr = m_sectionHeaders.at(i);
0344         if (qstrcmp(name, hdr->name()) == 0)
0345             return i;
0346     }
0347     return -1;
0348 }
0349 
0350 int ElfFile::indexOfSectionWithVirtualAddress(uint64_t virtAddr) const
0351 {
0352     for (int i = 0; i < m_sectionHeaders.size(); ++i) {
0353         const auto hdr = m_sectionHeaders.at(i);
0354         if (hdr->virtualAddress() <= virtAddr && virtAddr < hdr->virtualAddress() + hdr->size())
0355             return i;
0356     }
0357     return -1;
0358 }
0359 
0360 ElfDynamicSection* ElfFile::dynamicSection() const
0361 {
0362     return m_dynamicSection;
0363 }
0364 
0365 ElfSymbolTableSection* ElfFile::symbolTable() const
0366 {
0367     auto index = indexOfSection(SHT_SYMTAB);
0368     if (index < 0)
0369         index = indexOfSection(SHT_DYNSYM);
0370     if (index < 0)
0371         return nullptr;
0372     return section<ElfSymbolTableSection>(index);
0373 }
0374 
0375 ElfHashSection* ElfFile::hash() const
0376 {
0377     return m_hashSection;
0378 }
0379 
0380 const ElfReverseRelocator* ElfFile::reverseRelocator() const
0381 {
0382     return &m_reverseReloc;
0383 }
0384 
0385 QByteArray ElfFile::buildId() const
0386 {
0387     auto buildIdIndex = indexOfSection(".note.gnu.build-id");
0388     if (buildIdIndex < 0)
0389         return {};
0390     auto buildIdSection = section<ElfNoteSection>(buildIdIndex);
0391     assert(buildIdSection);
0392     assert(buildIdSection->entryCount() == 1);
0393 
0394     auto buildIdEntry = buildIdSection->entry(0);
0395     assert(buildIdEntry);
0396     assert(buildIdEntry->isGNUVendorNote());
0397     assert(buildIdEntry->type() == NT_GNU_BUILD_ID);
0398 
0399     return QByteArray::fromRawData(buildIdEntry->descriptionData(), buildIdEntry->descriptionSize());
0400 }
0401 
0402 void ElfFile::setSeparateDebugFile(const QString& fileName)
0403 {
0404     m_separateDebugFile.reset(new ElfFile(fileName));
0405     if (!m_separateDebugFile->open(QIODevice::ReadOnly) || !m_separateDebugFile->isValid()) {
0406         qWarning() << "Invalid separate debug file for" << m_file.fileName() << ":" << fileName;
0407         m_separateDebugFile.reset();
0408         return;
0409     }
0410 
0411     m_separateDebugFile->m_contentFile = this;
0412     // merge sections from separate debug file
0413     for (int i = 0; i < m_separateDebugFile->sectionHeaders().size(); ++i) {
0414         auto debugHdr = m_separateDebugFile->sectionHeaders().at(i);
0415         if (indexOfSection(debugHdr->name()) >= 0)
0416             continue;
0417         m_sectionHeaders.push_back(debugHdr);
0418         m_sections.push_back(m_separateDebugFile->section<ElfSection>(i));
0419     }
0420 }
0421 
0422 ElfFile* ElfFile::separateDebugFile() const
0423 {
0424     return m_separateDebugFile.get();
0425 }
0426 
0427 bool ElfFile::isSeparateDebugFile() const
0428 {
0429     return m_contentFile;
0430 }
0431 
0432 ElfFile* ElfFile::contentFile() const
0433 {
0434     return m_contentFile;
0435 }
0436 
0437 DwarfInfo* ElfFile::dwarfInfo() const
0438 {
0439     if (m_separateDebugFile)
0440         return m_separateDebugFile->dwarfInfo();
0441     return m_dwarfInfo;
0442 }
0443 
0444 QVector< ElfSegmentHeader* > ElfFile::segmentHeaders() const
0445 {
0446     return m_segmentHeaders;
0447 }