File indexing completed on 2024-05-19 05:44:08

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 #ifndef ELFFILE_H
0019 #define ELFFILE_H
0020 
0021 #include "elfsectionheader.h"
0022 #include "elfsection.h"
0023 #include "elfdynamicsection.h"
0024 #include "elfreverserelocator.h"
0025 
0026 #include <QFile>
0027 #include <QMetaType>
0028 #include <QVector>
0029 
0030 #include <memory>
0031 
0032 class DwarfInfo;
0033 class ElfHashSection;
0034 class ElfHeader;
0035 class ElfSymbolTableSection;
0036 class ElfSegmentHeader;
0037 
0038 /** Represents a ELF file. */
0039 class ElfFile
0040 {
0041 public:
0042     explicit ElfFile(const QString &fileName);
0043     ElfFile(const ElfFile &other) = delete;
0044     /** Closes the file. */
0045     ~ElfFile();
0046 
0047     ElfFile& operator=(const ElfFile &other) = delete;
0048 
0049     /** Open the file and parse its content. Must be called before the file can be used. */
0050     bool open(QIODevice::OpenMode openMode);
0051     void close();
0052 
0053 
0054     /** Returns @c true if the file could be loaded and is parsed correctly. */
0055     bool isValid() const;
0056 
0057     /** Returns a user readable label for this file. */
0058     QString displayName() const;
0059     /** Returns the full path of this file. */
0060     QString fileName() const;
0061     /** Returns the size of the entire file. */
0062     uint64_t size() const;
0063 
0064     /** Returns a pointer to the raw ELF data. */
0065     unsigned char* rawData() const;
0066 
0067     /** ELF class type (32/64 bit). */
0068     int type() const;
0069     /** Returns the numbers of bytes needed to store an address. */
0070     int addressSize() const;
0071     /** Endianess. */
0072     int byteOrder() const;
0073     /** OS ABI. */
0074     uint8_t osAbi() const;
0075 
0076     /** Returns the ELF header. */
0077     ElfHeader* header() const;
0078 
0079     /** Returns the number of sections.
0080      *  Use this rather than header()->sectionHeaderCount() to include sections merged
0081      *  from separate debug files.
0082      */
0083     int sectionCount() const;
0084     /** Returns a list of all available section headers. */
0085     QVector<ElfSectionHeader*> sectionHeaders() const;
0086     /** Returns the section at index @p index. */
0087     template <typename T>
0088     inline T* section(int index) const
0089     {
0090         return dynamic_cast<T*>(m_sections.at(index));
0091     }
0092     /** Finds a section by type. */
0093     int indexOfSection(uint32_t type) const;
0094     /** Finds a section by name. */
0095     int indexOfSection(const char* name) const;
0096     /** Finds the section containing @p virtAddr. */
0097     int indexOfSectionWithVirtualAddress(uint64_t virtAddr) const;
0098 
0099     /** Returns the dynamic section. */
0100     ElfDynamicSection* dynamicSection() const;
0101     /** Returns .symtab if present, .dynsym otherwise. */
0102     ElfSymbolTableSection* symbolTable() const;
0103     /** Returns a symbol table hash section for fast lookup. */
0104     ElfHashSection* hash() const;
0105     /** Reverse relocation lookup. */
0106     const ElfReverseRelocator* reverseRelocator() const;
0107 
0108     /** Returns the build-id, if present. */
0109     QByteArray buildId() const;
0110 
0111     /** Sets the path to a separate file containing the DWARF debug information. */
0112     void setSeparateDebugFile(const QString &fileName);
0113     /** Returns the separate debug file, if present. */
0114     ElfFile* separateDebugFile() const;
0115     /** Returns @c true if this is a separate debug file. */
0116     bool isSeparateDebugFile() const;
0117     /** Returns the file with the actual content if this is a separate debug file. */
0118     ElfFile* contentFile() const;
0119 
0120     /** DWARF debug information, if present. */
0121     DwarfInfo* dwarfInfo() const;
0122 
0123     /** Returns a lost of all available segment headers. */
0124     QVector<ElfSegmentHeader*> segmentHeaders() const;
0125 
0126 private:
0127     void parse();
0128     void parseHeader();
0129     void parseSections();
0130     void parseSection(uint16_t index);
0131     void parseSegments();
0132 
0133 private:
0134     QFile m_file;
0135     uchar *m_data;
0136     std::unique_ptr<ElfHeader> m_header;
0137     QVector<ElfSectionHeader*> m_sectionHeaders;
0138     QVector<ElfSection*> m_sections;
0139     ElfDynamicSection* m_dynamicSection = nullptr;
0140     ElfHashSection* m_hashSection = nullptr;
0141     ElfReverseRelocator m_reverseReloc;
0142     std::unique_ptr<ElfFile> m_separateDebugFile;
0143     ElfFile *m_contentFile = nullptr; // the counter part for a separate debug file
0144     DwarfInfo *m_dwarfInfo = nullptr;
0145     QVector<ElfSegmentHeader*> m_segmentHeaders;
0146 };
0147 
0148 Q_DECLARE_METATYPE(ElfFile*)
0149 
0150 #endif // ELFFILE_H