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 }