1 //===- ELFObjectFile.cpp - ELF object file implementation -----------------===// 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 // Part of the ELFObjectFile class implementation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/Object/ELFObjectFile.h" 14 #include "llvm/ADT/Triple.h" 15 #include "llvm/BinaryFormat/ELF.h" 16 #include "llvm/MC/MCInstrAnalysis.h" 17 #include "llvm/MC/SubtargetFeature.h" 18 #include "llvm/Object/ELF.h" 19 #include "llvm/Object/ELFTypes.h" 20 #include "llvm/Object/Error.h" 21 #include "llvm/Support/ARMAttributeParser.h" 22 #include "llvm/Support/ARMBuildAttributes.h" 23 #include "llvm/Support/Endian.h" 24 #include "llvm/Support/ErrorHandling.h" 25 #include "llvm/Support/MathExtras.h" 26 #include "llvm/Support/TargetRegistry.h" 27 #include <algorithm> 28 #include <cstddef> 29 #include <cstdint> 30 #include <memory> 31 #include <string> 32 #include <system_error> 33 #include <utility> 34 35 using namespace llvm; 36 using namespace object; 37 38 const EnumEntry<unsigned> llvm::object::ElfSymbolTypes[NumElfSymbolTypes] = { 39 {"None", "NOTYPE", ELF::STT_NOTYPE}, 40 {"Object", "OBJECT", ELF::STT_OBJECT}, 41 {"Function", "FUNC", ELF::STT_FUNC}, 42 {"Section", "SECTION", ELF::STT_SECTION}, 43 {"File", "FILE", ELF::STT_FILE}, 44 {"Common", "COMMON", ELF::STT_COMMON}, 45 {"TLS", "TLS", ELF::STT_TLS}, 46 {"Unknown", "<unknown>: 7", 7}, 47 {"Unknown", "<unknown>: 8", 8}, 48 {"Unknown", "<unknown>: 9", 9}, 49 {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC}, 50 {"OS Specific", "<OS specific>: 11", 11}, 51 {"OS Specific", "<OS specific>: 12", 12}, 52 {"Proc Specific", "<processor specific>: 13", 13}, 53 {"Proc Specific", "<processor specific>: 14", 14}, 54 {"Proc Specific", "<processor specific>: 15", 15} 55 }; 56 57 ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) 58 : ObjectFile(Type, Source) {} 59 60 template <class ELFT> 61 static Expected<std::unique_ptr<ELFObjectFile<ELFT>>> 62 createPtr(MemoryBufferRef Object) { 63 auto Ret = ELFObjectFile<ELFT>::create(Object); 64 if (Error E = Ret.takeError()) 65 return std::move(E); 66 return std::make_unique<ELFObjectFile<ELFT>>(std::move(*Ret)); 67 } 68 69 Expected<std::unique_ptr<ObjectFile>> 70 ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { 71 std::pair<unsigned char, unsigned char> Ident = 72 getElfArchType(Obj.getBuffer()); 73 std::size_t MaxAlignment = 74 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart())); 75 76 if (MaxAlignment < 2) 77 return createError("Insufficient alignment"); 78 79 if (Ident.first == ELF::ELFCLASS32) { 80 if (Ident.second == ELF::ELFDATA2LSB) 81 return createPtr<ELF32LE>(Obj); 82 else if (Ident.second == ELF::ELFDATA2MSB) 83 return createPtr<ELF32BE>(Obj); 84 else 85 return createError("Invalid ELF data"); 86 } else if (Ident.first == ELF::ELFCLASS64) { 87 if (Ident.second == ELF::ELFDATA2LSB) 88 return createPtr<ELF64LE>(Obj); 89 else if (Ident.second == ELF::ELFDATA2MSB) 90 return createPtr<ELF64BE>(Obj); 91 else 92 return createError("Invalid ELF data"); 93 } 94 return createError("Invalid ELF class"); 95 } 96 97 SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const { 98 SubtargetFeatures Features; 99 unsigned PlatformFlags = getPlatformFlags(); 100 101 switch (PlatformFlags & ELF::EF_MIPS_ARCH) { 102 case ELF::EF_MIPS_ARCH_1: 103 break; 104 case ELF::EF_MIPS_ARCH_2: 105 Features.AddFeature("mips2"); 106 break; 107 case ELF::EF_MIPS_ARCH_3: 108 Features.AddFeature("mips3"); 109 break; 110 case ELF::EF_MIPS_ARCH_4: 111 Features.AddFeature("mips4"); 112 break; 113 case ELF::EF_MIPS_ARCH_5: 114 Features.AddFeature("mips5"); 115 break; 116 case ELF::EF_MIPS_ARCH_32: 117 Features.AddFeature("mips32"); 118 break; 119 case ELF::EF_MIPS_ARCH_64: 120 Features.AddFeature("mips64"); 121 break; 122 case ELF::EF_MIPS_ARCH_32R2: 123 Features.AddFeature("mips32r2"); 124 break; 125 case ELF::EF_MIPS_ARCH_64R2: 126 Features.AddFeature("mips64r2"); 127 break; 128 case ELF::EF_MIPS_ARCH_32R6: 129 Features.AddFeature("mips32r6"); 130 break; 131 case ELF::EF_MIPS_ARCH_64R6: 132 Features.AddFeature("mips64r6"); 133 break; 134 default: 135 llvm_unreachable("Unknown EF_MIPS_ARCH value"); 136 } 137 138 switch (PlatformFlags & ELF::EF_MIPS_MACH) { 139 case ELF::EF_MIPS_MACH_NONE: 140 // No feature associated with this value. 141 break; 142 case ELF::EF_MIPS_MACH_OCTEON: 143 Features.AddFeature("cnmips"); 144 break; 145 default: 146 llvm_unreachable("Unknown EF_MIPS_ARCH value"); 147 } 148 149 if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16) 150 Features.AddFeature("mips16"); 151 if (PlatformFlags & ELF::EF_MIPS_MICROMIPS) 152 Features.AddFeature("micromips"); 153 154 return Features; 155 } 156 157 SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { 158 SubtargetFeatures Features; 159 ARMAttributeParser Attributes; 160 if (Error E = getBuildAttributes(Attributes)) { 161 consumeError(std::move(E)); 162 return SubtargetFeatures(); 163 } 164 165 // both ARMv7-M and R have to support thumb hardware div 166 bool isV7 = false; 167 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) 168 isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch) 169 == ARMBuildAttrs::v7; 170 171 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) { 172 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) { 173 case ARMBuildAttrs::ApplicationProfile: 174 Features.AddFeature("aclass"); 175 break; 176 case ARMBuildAttrs::RealTimeProfile: 177 Features.AddFeature("rclass"); 178 if (isV7) 179 Features.AddFeature("hwdiv"); 180 break; 181 case ARMBuildAttrs::MicroControllerProfile: 182 Features.AddFeature("mclass"); 183 if (isV7) 184 Features.AddFeature("hwdiv"); 185 break; 186 } 187 } 188 189 if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) { 190 switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) { 191 default: 192 break; 193 case ARMBuildAttrs::Not_Allowed: 194 Features.AddFeature("thumb", false); 195 Features.AddFeature("thumb2", false); 196 break; 197 case ARMBuildAttrs::AllowThumb32: 198 Features.AddFeature("thumb2"); 199 break; 200 } 201 } 202 203 if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) { 204 switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) { 205 default: 206 break; 207 case ARMBuildAttrs::Not_Allowed: 208 Features.AddFeature("vfp2sp", false); 209 Features.AddFeature("vfp3d16sp", false); 210 Features.AddFeature("vfp4d16sp", false); 211 break; 212 case ARMBuildAttrs::AllowFPv2: 213 Features.AddFeature("vfp2"); 214 break; 215 case ARMBuildAttrs::AllowFPv3A: 216 case ARMBuildAttrs::AllowFPv3B: 217 Features.AddFeature("vfp3"); 218 break; 219 case ARMBuildAttrs::AllowFPv4A: 220 case ARMBuildAttrs::AllowFPv4B: 221 Features.AddFeature("vfp4"); 222 break; 223 } 224 } 225 226 if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) { 227 switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) { 228 default: 229 break; 230 case ARMBuildAttrs::Not_Allowed: 231 Features.AddFeature("neon", false); 232 Features.AddFeature("fp16", false); 233 break; 234 case ARMBuildAttrs::AllowNeon: 235 Features.AddFeature("neon"); 236 break; 237 case ARMBuildAttrs::AllowNeon2: 238 Features.AddFeature("neon"); 239 Features.AddFeature("fp16"); 240 break; 241 } 242 } 243 244 if (Attributes.hasAttribute(ARMBuildAttrs::MVE_arch)) { 245 switch(Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch)) { 246 default: 247 break; 248 case ARMBuildAttrs::Not_Allowed: 249 Features.AddFeature("mve", false); 250 Features.AddFeature("mve.fp", false); 251 break; 252 case ARMBuildAttrs::AllowMVEInteger: 253 Features.AddFeature("mve.fp", false); 254 Features.AddFeature("mve"); 255 break; 256 case ARMBuildAttrs::AllowMVEIntegerAndFloat: 257 Features.AddFeature("mve.fp"); 258 break; 259 } 260 } 261 262 if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) { 263 switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) { 264 default: 265 break; 266 case ARMBuildAttrs::DisallowDIV: 267 Features.AddFeature("hwdiv", false); 268 Features.AddFeature("hwdiv-arm", false); 269 break; 270 case ARMBuildAttrs::AllowDIVExt: 271 Features.AddFeature("hwdiv"); 272 Features.AddFeature("hwdiv-arm"); 273 break; 274 } 275 } 276 277 return Features; 278 } 279 280 SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const { 281 SubtargetFeatures Features; 282 unsigned PlatformFlags = getPlatformFlags(); 283 284 if (PlatformFlags & ELF::EF_RISCV_RVC) { 285 Features.AddFeature("c"); 286 } 287 288 return Features; 289 } 290 291 SubtargetFeatures ELFObjectFileBase::getFeatures() const { 292 switch (getEMachine()) { 293 case ELF::EM_MIPS: 294 return getMIPSFeatures(); 295 case ELF::EM_ARM: 296 return getARMFeatures(); 297 case ELF::EM_RISCV: 298 return getRISCVFeatures(); 299 default: 300 return SubtargetFeatures(); 301 } 302 } 303 304 // FIXME Encode from a tablegen description or target parser. 305 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { 306 if (TheTriple.getSubArch() != Triple::NoSubArch) 307 return; 308 309 ARMAttributeParser Attributes; 310 if (Error E = getBuildAttributes(Attributes)) { 311 // TODO Propagate Error. 312 consumeError(std::move(E)); 313 return; 314 } 315 316 std::string Triple; 317 // Default to ARM, but use the triple if it's been set. 318 if (TheTriple.isThumb()) 319 Triple = "thumb"; 320 else 321 Triple = "arm"; 322 323 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) { 324 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) { 325 case ARMBuildAttrs::v4: 326 Triple += "v4"; 327 break; 328 case ARMBuildAttrs::v4T: 329 Triple += "v4t"; 330 break; 331 case ARMBuildAttrs::v5T: 332 Triple += "v5t"; 333 break; 334 case ARMBuildAttrs::v5TE: 335 Triple += "v5te"; 336 break; 337 case ARMBuildAttrs::v5TEJ: 338 Triple += "v5tej"; 339 break; 340 case ARMBuildAttrs::v6: 341 Triple += "v6"; 342 break; 343 case ARMBuildAttrs::v6KZ: 344 Triple += "v6kz"; 345 break; 346 case ARMBuildAttrs::v6T2: 347 Triple += "v6t2"; 348 break; 349 case ARMBuildAttrs::v6K: 350 Triple += "v6k"; 351 break; 352 case ARMBuildAttrs::v7: 353 Triple += "v7"; 354 break; 355 case ARMBuildAttrs::v6_M: 356 Triple += "v6m"; 357 break; 358 case ARMBuildAttrs::v6S_M: 359 Triple += "v6sm"; 360 break; 361 case ARMBuildAttrs::v7E_M: 362 Triple += "v7em"; 363 break; 364 case ARMBuildAttrs::v8_A: 365 Triple += "v8a"; 366 break; 367 case ARMBuildAttrs::v8_R: 368 Triple += "v8r"; 369 break; 370 case ARMBuildAttrs::v8_M_Base: 371 Triple += "v8m.base"; 372 break; 373 case ARMBuildAttrs::v8_M_Main: 374 Triple += "v8m.main"; 375 break; 376 case ARMBuildAttrs::v8_1_M_Main: 377 Triple += "v8.1m.main"; 378 break; 379 } 380 } 381 if (!isLittleEndian()) 382 Triple += "eb"; 383 384 TheTriple.setArchName(Triple); 385 } 386 387 std::vector<std::pair<DataRefImpl, uint64_t>> 388 ELFObjectFileBase::getPltAddresses() const { 389 std::string Err; 390 const auto Triple = makeTriple(); 391 const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err); 392 if (!T) 393 return {}; 394 uint64_t JumpSlotReloc = 0; 395 switch (Triple.getArch()) { 396 case Triple::x86: 397 JumpSlotReloc = ELF::R_386_JUMP_SLOT; 398 break; 399 case Triple::x86_64: 400 JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT; 401 break; 402 case Triple::aarch64: 403 JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT; 404 break; 405 default: 406 return {}; 407 } 408 std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo()); 409 std::unique_ptr<const MCInstrAnalysis> MIA( 410 T->createMCInstrAnalysis(MII.get())); 411 if (!MIA) 412 return {}; 413 Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None; 414 for (const SectionRef &Section : sections()) { 415 Expected<StringRef> NameOrErr = Section.getName(); 416 if (!NameOrErr) { 417 consumeError(NameOrErr.takeError()); 418 continue; 419 } 420 StringRef Name = *NameOrErr; 421 422 if (Name == ".plt") 423 Plt = Section; 424 else if (Name == ".rela.plt" || Name == ".rel.plt") 425 RelaPlt = Section; 426 else if (Name == ".got.plt") 427 GotPlt = Section; 428 } 429 if (!Plt || !RelaPlt || !GotPlt) 430 return {}; 431 Expected<StringRef> PltContents = Plt->getContents(); 432 if (!PltContents) { 433 consumeError(PltContents.takeError()); 434 return {}; 435 } 436 auto PltEntries = MIA->findPltEntries(Plt->getAddress(), 437 arrayRefFromStringRef(*PltContents), 438 GotPlt->getAddress(), Triple); 439 // Build a map from GOT entry virtual address to PLT entry virtual address. 440 DenseMap<uint64_t, uint64_t> GotToPlt; 441 for (const auto &Entry : PltEntries) 442 GotToPlt.insert(std::make_pair(Entry.second, Entry.first)); 443 // Find the relocations in the dynamic relocation table that point to 444 // locations in the GOT for which we know the corresponding PLT entry. 445 std::vector<std::pair<DataRefImpl, uint64_t>> Result; 446 for (const auto &Relocation : RelaPlt->relocations()) { 447 if (Relocation.getType() != JumpSlotReloc) 448 continue; 449 auto PltEntryIter = GotToPlt.find(Relocation.getOffset()); 450 if (PltEntryIter != GotToPlt.end()) 451 Result.push_back(std::make_pair( 452 Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second)); 453 } 454 return Result; 455 } 456