1 //===- ELFObjectFileTest.cpp - Tests for ELFObjectFile --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Object/ELFObjectFile.h" 10 #include "llvm/Support/MemoryBuffer.h" 11 #include "llvm/Testing/Support/Error.h" 12 #include "gtest/gtest.h" 13 14 using namespace llvm; 15 using namespace llvm::object; 16 17 namespace { 18 19 // A struct to initialize a buffer to represent an ELF object file. 20 struct DataForTest { 21 std::vector<uint8_t> Data; 22 23 template <typename T> 24 std::vector<uint8_t> makeElfData(uint8_t Class, uint8_t Encoding, 25 uint16_t Machine) { 26 T Ehdr{}; // Zero-initialise the header. 27 Ehdr.e_ident[ELF::EI_MAG0] = 0x7f; 28 Ehdr.e_ident[ELF::EI_MAG1] = 'E'; 29 Ehdr.e_ident[ELF::EI_MAG2] = 'L'; 30 Ehdr.e_ident[ELF::EI_MAG3] = 'F'; 31 Ehdr.e_ident[ELF::EI_CLASS] = Class; 32 Ehdr.e_ident[ELF::EI_DATA] = Encoding; 33 Ehdr.e_ident[ELF::EI_VERSION] = 1; 34 Ehdr.e_type = ELF::ET_REL; 35 Ehdr.e_machine = Machine; 36 Ehdr.e_version = 1; 37 Ehdr.e_ehsize = sizeof(T); 38 39 bool IsLittleEndian = Encoding == ELF::ELFDATA2LSB; 40 if (sys::IsLittleEndianHost != IsLittleEndian) { 41 sys::swapByteOrder(Ehdr.e_type); 42 sys::swapByteOrder(Ehdr.e_machine); 43 sys::swapByteOrder(Ehdr.e_version); 44 sys::swapByteOrder(Ehdr.e_ehsize); 45 } 46 47 uint8_t *EhdrBytes = reinterpret_cast<uint8_t *>(&Ehdr); 48 std::vector<uint8_t> Bytes; 49 std::copy(EhdrBytes, EhdrBytes + sizeof(Ehdr), std::back_inserter(Bytes)); 50 return Bytes; 51 } 52 53 DataForTest(uint8_t Class, uint8_t Encoding, uint16_t Machine) { 54 if (Class == ELF::ELFCLASS64) 55 Data = makeElfData<ELF::Elf64_Ehdr>(Class, Encoding, Machine); 56 else { 57 assert(Class == ELF::ELFCLASS32); 58 Data = makeElfData<ELF::Elf32_Ehdr>(Class, Encoding, Machine); 59 } 60 } 61 }; 62 63 void checkFormatAndArch(const DataForTest &D, StringRef Fmt, 64 Triple::ArchType Arch) { 65 Expected<std::unique_ptr<ObjectFile>> ELFObjOrErr = 66 object::ObjectFile::createELFObjectFile( 67 MemoryBufferRef(toStringRef(D.Data), "dummyELF")); 68 ASSERT_THAT_EXPECTED(ELFObjOrErr, Succeeded()); 69 70 const ObjectFile &File = *(*ELFObjOrErr).get(); 71 EXPECT_EQ(Fmt, File.getFileFormatName()); 72 EXPECT_EQ(Arch, File.getArch()); 73 } 74 75 std::array<DataForTest, 4> generateData(uint16_t Machine) { 76 return {DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2LSB, Machine), 77 DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2MSB, Machine), 78 DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2LSB, Machine), 79 DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2MSB, Machine)}; 80 } 81 82 } // namespace 83 84 TEST(ELFObjectFileTest, MachineTestForNoneOrUnused) { 85 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 86 "elf64-unknown", "elf64-unknown"}; 87 size_t I = 0; 88 for (const DataForTest &D : generateData(ELF::EM_NONE)) 89 checkFormatAndArch(D, Formats[I++], Triple::UnknownArch); 90 91 // Test an arbitrary unused EM_* value (255). 92 I = 0; 93 for (const DataForTest &D : generateData(255)) 94 checkFormatAndArch(D, Formats[I++], Triple::UnknownArch); 95 } 96 97 TEST(ELFObjectFileTest, MachineTestForVE) { 98 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 99 "elf64-ve", "elf64-ve"}; 100 size_t I = 0; 101 for (const DataForTest &D : generateData(ELF::EM_VE)) 102 checkFormatAndArch(D, Formats[I++], Triple::ve); 103 } 104 105 TEST(ELFObjectFileTest, MachineTestForX86_64) { 106 std::array<StringRef, 4> Formats = {"elf32-x86-64", "elf32-x86-64", 107 "elf64-x86-64", "elf64-x86-64"}; 108 size_t I = 0; 109 for (const DataForTest &D : generateData(ELF::EM_X86_64)) 110 checkFormatAndArch(D, Formats[I++], Triple::x86_64); 111 } 112 113 TEST(ELFObjectFileTest, MachineTestFor386) { 114 std::array<StringRef, 4> Formats = {"elf32-i386", "elf32-i386", "elf64-i386", 115 "elf64-i386"}; 116 size_t I = 0; 117 for (const DataForTest &D : generateData(ELF::EM_386)) 118 checkFormatAndArch(D, Formats[I++], Triple::x86); 119 } 120 121 TEST(ELFObjectFileTest, MachineTestForMIPS) { 122 std::array<StringRef, 4> Formats = {"elf32-mips", "elf32-mips", "elf64-mips", 123 "elf64-mips"}; 124 std::array<Triple::ArchType, 4> Archs = {Triple::mipsel, Triple::mips, 125 Triple::mips64el, Triple::mips64}; 126 size_t I = 0; 127 for (const DataForTest &D : generateData(ELF::EM_MIPS)) { 128 checkFormatAndArch(D, Formats[I], Archs[I]); 129 ++I; 130 } 131 } 132 133 TEST(ELFObjectFileTest, MachineTestForAMDGPU) { 134 std::array<StringRef, 4> Formats = {"elf32-amdgpu", "elf32-amdgpu", 135 "elf64-amdgpu", "elf64-amdgpu"}; 136 size_t I = 0; 137 for (const DataForTest &D : generateData(ELF::EM_AMDGPU)) 138 checkFormatAndArch(D, Formats[I++], Triple::UnknownArch); 139 } 140 141 TEST(ELFObjectFileTest, MachineTestForIAMCU) { 142 std::array<StringRef, 4> Formats = {"elf32-iamcu", "elf32-iamcu", 143 "elf64-unknown", "elf64-unknown"}; 144 size_t I = 0; 145 for (const DataForTest &D : generateData(ELF::EM_IAMCU)) 146 checkFormatAndArch(D, Formats[I++], Triple::x86); 147 } 148 149 TEST(ELFObjectFileTest, MachineTestForAARCH64) { 150 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 151 "elf64-littleaarch64", 152 "elf64-bigaarch64"}; 153 std::array<Triple::ArchType, 4> Archs = {Triple::aarch64, Triple::aarch64_be, 154 Triple::aarch64, Triple::aarch64_be}; 155 size_t I = 0; 156 for (const DataForTest &D : generateData(ELF::EM_AARCH64)) { 157 checkFormatAndArch(D, Formats[I], Archs[I]); 158 ++I; 159 } 160 } 161 162 TEST(ELFObjectFileTest, MachineTestForPPC64) { 163 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 164 "elf64-powerpcle", "elf64-powerpc"}; 165 std::array<Triple::ArchType, 4> Archs = {Triple::ppc64le, Triple::ppc64, 166 Triple::ppc64le, Triple::ppc64}; 167 size_t I = 0; 168 for (const DataForTest &D : generateData(ELF::EM_PPC64)) { 169 checkFormatAndArch(D, Formats[I], Archs[I]); 170 ++I; 171 } 172 } 173 174 TEST(ELFObjectFileTest, MachineTestForPPC) { 175 std::array<StringRef, 4> Formats = {"elf32-powerpc", "elf32-powerpc", 176 "elf64-unknown", "elf64-unknown"}; 177 size_t I = 0; 178 for (const DataForTest &D : generateData(ELF::EM_PPC)) 179 checkFormatAndArch(D, Formats[I++], Triple::ppc); 180 } 181 182 TEST(ELFObjectFileTest, MachineTestForRISCV) { 183 std::array<StringRef, 4> Formats = {"elf32-littleriscv", "elf32-littleriscv", 184 "elf64-littleriscv", "elf64-littleriscv"}; 185 std::array<Triple::ArchType, 4> Archs = {Triple::riscv32, Triple::riscv32, 186 Triple::riscv64, Triple::riscv64}; 187 size_t I = 0; 188 for (const DataForTest &D : generateData(ELF::EM_RISCV)) { 189 checkFormatAndArch(D, Formats[I], Archs[I]); 190 ++I; 191 } 192 } 193 194 TEST(ELFObjectFileTest, MachineTestForARM) { 195 std::array<StringRef, 4> Formats = {"elf32-littlearm", "elf32-bigarm", 196 "elf64-unknown", "elf64-unknown"}; 197 size_t I = 0; 198 for (const DataForTest &D : generateData(ELF::EM_ARM)) 199 checkFormatAndArch(D, Formats[I++], Triple::arm); 200 } 201 202 TEST(ELFObjectFileTest, MachineTestForS390) { 203 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 204 "elf64-s390", "elf64-s390"}; 205 size_t I = 0; 206 for (const DataForTest &D : generateData(ELF::EM_S390)) 207 checkFormatAndArch(D, Formats[I++], Triple::systemz); 208 } 209 210 TEST(ELFObjectFileTest, MachineTestForSPARCV9) { 211 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 212 "elf64-sparc", "elf64-sparc"}; 213 size_t I = 0; 214 for (const DataForTest &D : generateData(ELF::EM_SPARCV9)) 215 checkFormatAndArch(D, Formats[I++], Triple::sparcv9); 216 } 217 218 TEST(ELFObjectFileTest, MachineTestForSPARC) { 219 std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc", 220 "elf64-unknown", "elf64-unknown"}; 221 std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc, 222 Triple::sparcel, Triple::sparc}; 223 size_t I = 0; 224 for (const DataForTest &D : generateData(ELF::EM_SPARC)) { 225 checkFormatAndArch(D, Formats[I], Archs[I]); 226 ++I; 227 } 228 } 229 230 TEST(ELFObjectFileTest, MachineTestForSPARC32PLUS) { 231 std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc", 232 "elf64-unknown", "elf64-unknown"}; 233 std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc, 234 Triple::sparcel, Triple::sparc}; 235 size_t I = 0; 236 for (const DataForTest &D : generateData(ELF::EM_SPARC32PLUS)) { 237 checkFormatAndArch(D, Formats[I], Archs[I]); 238 ++I; 239 } 240 } 241 242 TEST(ELFObjectFileTest, MachineTestForBPF) { 243 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 244 "elf64-bpf", "elf64-bpf"}; 245 std::array<Triple::ArchType, 4> Archs = {Triple::bpfel, Triple::bpfeb, 246 Triple::bpfel, Triple::bpfeb}; 247 size_t I = 0; 248 for (const DataForTest &D : generateData(ELF::EM_BPF)) { 249 checkFormatAndArch(D, Formats[I], Archs[I]); 250 ++I; 251 } 252 } 253 254 TEST(ELFObjectFileTest, MachineTestForAVR) { 255 std::array<StringRef, 4> Formats = {"elf32-avr", "elf32-avr", "elf64-unknown", 256 "elf64-unknown"}; 257 size_t I = 0; 258 for (const DataForTest &D : generateData(ELF::EM_AVR)) 259 checkFormatAndArch(D, Formats[I++], Triple::avr); 260 } 261 262 TEST(ELFObjectFileTest, MachineTestForHEXAGON) { 263 std::array<StringRef, 4> Formats = {"elf32-hexagon", "elf32-hexagon", 264 "elf64-unknown", "elf64-unknown"}; 265 size_t I = 0; 266 for (const DataForTest &D : generateData(ELF::EM_HEXAGON)) 267 checkFormatAndArch(D, Formats[I++], Triple::hexagon); 268 } 269 270 TEST(ELFObjectFileTest, MachineTestForLANAI) { 271 std::array<StringRef, 4> Formats = {"elf32-lanai", "elf32-lanai", 272 "elf64-unknown", "elf64-unknown"}; 273 size_t I = 0; 274 for (const DataForTest &D : generateData(ELF::EM_LANAI)) 275 checkFormatAndArch(D, Formats[I++], Triple::lanai); 276 } 277 278 TEST(ELFObjectFileTest, MachineTestForMSP430) { 279 std::array<StringRef, 4> Formats = {"elf32-msp430", "elf32-msp430", 280 "elf64-unknown", "elf64-unknown"}; 281 size_t I = 0; 282 for (const DataForTest &D : generateData(ELF::EM_MSP430)) 283 checkFormatAndArch(D, Formats[I++], Triple::msp430); 284 } 285 286 TEST(ELFObjectFileTest, MachineTestForCSKY) { 287 std::array<StringRef, 4> Formats = {"elf32-csky", "elf32-csky", 288 "elf64-unknown", "elf64-unknown"}; 289 size_t I = 0; 290 for (const DataForTest &D : generateData(ELF::EM_CSKY)) 291 checkFormatAndArch(D, Formats[I++], Triple::csky); 292 } 293 294 295 296 // ELF relative relocation type test. 297 TEST(ELFObjectFileTest, RelativeRelocationTypeTest) { 298 EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY)); 299 } 300