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

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 "elfrelocationentry.h"
0019 #include "elfrelocationsection.h"
0020 #include "elffile.h"
0021 #include "elfsymboltablesection.h"
0022 
0023 #include <elf.h>
0024 
0025 ElfRelocationEntry::ElfRelocationEntry() :
0026     m_section(nullptr),
0027     m_index(0),
0028     m_withAddend(0)
0029 {
0030 }
0031 
0032 ElfRelocationEntry::ElfRelocationEntry(const ElfRelocationEntry&) = default;
0033 
0034 ElfRelocationEntry::ElfRelocationEntry(const ElfRelocationSection* section, uint64_t index, bool withAddend) :
0035     m_section(section),
0036     m_index(index),
0037     m_withAddend(withAddend)
0038 {
0039 }
0040 
0041 ElfRelocationEntry::~ElfRelocationEntry() = default;
0042 
0043 ElfRelocationEntry& ElfRelocationEntry::operator=(const ElfRelocationEntry&) = default;
0044 
0045 const ElfRelocationSection* ElfRelocationEntry::relocationTable() const
0046 {
0047     return m_section;
0048 }
0049 
0050 uint64_t ElfRelocationEntry::offset() const
0051 {
0052     if (is64()) {
0053         if (m_withAddend)
0054             return entry<Elf64_Rela>()->r_offset;
0055         else
0056             return entry<Elf64_Rel>()->r_offset;
0057     } else {
0058         if (m_withAddend)
0059             return entry<Elf32_Rela>()->r_offset;
0060         else
0061             return entry<Elf32_Rel>()->r_offset;
0062     }
0063     Q_UNREACHABLE();
0064 }
0065 
0066 uint32_t ElfRelocationEntry::symbolIndex() const
0067 {
0068     if (is64()) {
0069         if (m_withAddend)
0070             return ELF64_R_SYM(entry<Elf64_Rela>()->r_info);
0071         else
0072             return ELF64_R_SYM(entry<Elf64_Rel>()->r_info);
0073     } else {
0074         if (m_withAddend)
0075             return ELF32_R_SYM(entry<Elf32_Rela>()->r_info);
0076         else
0077             return ELF32_R_SYM(entry<Elf32_Rel>()->r_info);
0078     }
0079     Q_UNREACHABLE();
0080 }
0081 
0082 uint32_t ElfRelocationEntry::type() const
0083 {
0084     if (is64()) {
0085         if (m_withAddend)
0086             return ELF64_R_TYPE(entry<Elf64_Rela>()->r_info);
0087         else
0088             return ELF64_R_TYPE(entry<Elf64_Rel>()->r_info);
0089     } else {
0090         if (m_withAddend)
0091             return ELF32_R_TYPE(entry<Elf32_Rela>()->r_info);
0092         else
0093             return ELF32_R_TYPE(entry<Elf32_Rel>()->r_info);
0094     }
0095     Q_UNREACHABLE();
0096 }
0097 
0098 uint64_t ElfRelocationEntry::addend() const
0099 {
0100     if (m_withAddend) {
0101         if (is64()) {
0102             return entry<Elf64_Rela>()->r_addend;
0103         } else {
0104             return entry<Elf32_Rela>()->r_addend;
0105         }
0106     } else {
0107         // TODO
0108         Q_ASSERT_X(false, "", "not yet implemented!");
0109         return 0;
0110     }
0111     Q_UNREACHABLE();
0112 }
0113 
0114 template <typename T>
0115 const T* ElfRelocationEntry::entry() const
0116 {
0117     return reinterpret_cast<const T*>(m_section->rawData() + m_index * m_section->header()->entrySize());
0118 }
0119 
0120 bool ElfRelocationEntry::is64() const
0121 {
0122     return m_section->file()->type() == ELFCLASS64;
0123 }
0124 
0125 ElfSymbolTableEntry* ElfRelocationEntry::symbol() const
0126 {
0127     const auto symIdx = symbolIndex();
0128     if (symIdx > 0)
0129         return m_section->linkedSection<ElfSymbolTableSection>()->entry(symIdx);
0130     return nullptr;
0131 }
0132 
0133 uint64_t ElfRelocationEntry::relocationTarget() const
0134 {
0135     // ### TODO ### this is utterly incomplete and largely incorrect!!
0136     // this would need to implement the platform-specific relocation logic for all types
0137     // the below approximation just barely covers the current uses of this function
0138 
0139     if (symbolIndex() && addend()) {
0140         Q_ASSERT_X(false, "", "not yet implemented!");
0141         return 0;
0142     }
0143 
0144     if (symbolIndex()) {
0145         return symbol()->value();
0146     }
0147     return addend();
0148 }