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 }