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 return SubtargetFeatures(); 162 163 // both ARMv7-M and R have to support thumb hardware div 164 bool isV7 = false; 165 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) 166 isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch) 167 == ARMBuildAttrs::v7; 168 169 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) { 170 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) { 171 case ARMBuildAttrs::ApplicationProfile: 172 Features.AddFeature("aclass"); 173 break; 174 case ARMBuildAttrs::RealTimeProfile: 175 Features.AddFeature("rclass"); 176 if (isV7) 177 Features.AddFeature("hwdiv"); 178 break; 179 case ARMBuildAttrs::MicroControllerProfile: 180 Features.AddFeature("mclass"); 181 if (isV7) 182 Features.AddFeature("hwdiv"); 183 break; 184 } 185 } 186 187 if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) { 188 switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) { 189 default: 190 break; 191 case ARMBuildAttrs::Not_Allowed: 192 Features.AddFeature("thumb", false); 193 Features.AddFeature("thumb2", false); 194 break; 195 case ARMBuildAttrs::AllowThumb32: 196 Features.AddFeature("thumb2"); 197 break; 198 } 199 } 200 201 if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) { 202 switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) { 203 default: 204 break; 205 case ARMBuildAttrs::Not_Allowed: 206 Features.AddFeature("vfp2sp", false); 207 Features.AddFeature("vfp3d16sp", false); 208 Features.AddFeature("vfp4d16sp", false); 209 break; 210 case ARMBuildAttrs::AllowFPv2: 211 Features.AddFeature("vfp2"); 212 break; 213 case ARMBuildAttrs::AllowFPv3A: 214 case ARMBuildAttrs::AllowFPv3B: 215 Features.AddFeature("vfp3"); 216 break; 217 case ARMBuildAttrs::AllowFPv4A: 218 case ARMBuildAttrs::AllowFPv4B: 219 Features.AddFeature("vfp4"); 220 break; 221 } 222 } 223 224 if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) { 225 switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) { 226 default: 227 break; 228 case ARMBuildAttrs::Not_Allowed: 229 Features.AddFeature("neon", false); 230 Features.AddFeature("fp16", false); 231 break; 232 case ARMBuildAttrs::AllowNeon: 233 Features.AddFeature("neon"); 234 break; 235 case ARMBuildAttrs::AllowNeon2: 236 Features.AddFeature("neon"); 237 Features.AddFeature("fp16"); 238 break; 239 } 240 } 241 242 if (Attributes.hasAttribute(ARMBuildAttrs::MVE_arch)) { 243 switch(Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch)) { 244 default: 245 break; 246 case ARMBuildAttrs::Not_Allowed: 247 Features.AddFeature("mve", false); 248 Features.AddFeature("mve.fp", false); 249 break; 250 case ARMBuildAttrs::AllowMVEInteger: 251 Features.AddFeature("mve.fp", false); 252 Features.AddFeature("mve"); 253 break; 254 case ARMBuildAttrs::AllowMVEIntegerAndFloat: 255 Features.AddFeature("mve.fp"); 256 break; 257 } 258 } 259 260 if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) { 261 switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) { 262 default: 263 break; 264 case ARMBuildAttrs::DisallowDIV: 265 Features.AddFeature("hwdiv", false); 266 Features.AddFeature("hwdiv-arm", false); 267 break; 268 case ARMBuildAttrs::AllowDIVExt: 269 Features.AddFeature("hwdiv"); 270 Features.AddFeature("hwdiv-arm"); 271 break; 272 } 273 } 274 275 return Features; 276 } 277 278 SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const { 279 SubtargetFeatures Features; 280 unsigned PlatformFlags = getPlatformFlags(); 281 282 if (PlatformFlags & ELF::EF_RISCV_RVC) { 283 Features.AddFeature("c"); 284 } 285 286 return Features; 287 } 288 289 SubtargetFeatures ELFObjectFileBase::getFeatures() const { 290 switch (getEMachine()) { 291 case ELF::EM_MIPS: 292 return getMIPSFeatures(); 293 case ELF::EM_ARM: 294 return getARMFeatures(); 295 case ELF::EM_RISCV: 296 return getRISCVFeatures(); 297 default: 298 return SubtargetFeatures(); 299 } 300 } 301 302 // FIXME Encode from a tablegen description or target parser. 303 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { 304 if (TheTriple.getSubArch() != Triple::NoSubArch) 305 return; 306 307 ARMAttributeParser Attributes; 308 if (Error E = getBuildAttributes(Attributes)) 309 return; 310 311 std::string Triple; 312 // Default to ARM, but use the triple if it's been set. 313 if (TheTriple.isThumb()) 314 Triple = "thumb"; 315 else 316 Triple = "arm"; 317 318 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) { 319 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) { 320 case ARMBuildAttrs::v4: 321 Triple += "v4"; 322 break; 323 case ARMBuildAttrs::v4T: 324 Triple += "v4t"; 325 break; 326 case ARMBuildAttrs::v5T: 327 Triple += "v5t"; 328 break; 329 case ARMBuildAttrs::v5TE: 330 Triple += "v5te"; 331 break; 332 case ARMBuildAttrs::v5TEJ: 333 Triple += "v5tej"; 334 break; 335 case ARMBuildAttrs::v6: 336 Triple += "v6"; 337 break; 338 case ARMBuildAttrs::v6KZ: 339 Triple += "v6kz"; 340 break; 341 case ARMBuildAttrs::v6T2: 342 Triple += "v6t2"; 343 break; 344 case ARMBuildAttrs::v6K: 345 Triple += "v6k"; 346 break; 347 case ARMBuildAttrs::v7: 348 Triple += "v7"; 349 break; 350 case ARMBuildAttrs::v6_M: 351 Triple += "v6m"; 352 break; 353 case ARMBuildAttrs::v6S_M: 354 Triple += "v6sm"; 355 break; 356 case ARMBuildAttrs::v7E_M: 357 Triple += "v7em"; 358 break; 359 case ARMBuildAttrs::v8_A: 360 Triple += "v8a"; 361 break; 362 case ARMBuildAttrs::v8_R: 363 Triple += "v8r"; 364 break; 365 case ARMBuildAttrs::v8_M_Base: 366 Triple += "v8m.base"; 367 break; 368 case ARMBuildAttrs::v8_M_Main: 369 Triple += "v8m.main"; 370 break; 371 case ARMBuildAttrs::v8_1_M_Main: 372 Triple += "v8.1m.main"; 373 break; 374 } 375 } 376 if (!isLittleEndian()) 377 Triple += "eb"; 378 379 TheTriple.setArchName(Triple); 380 } 381 382 std::vector<std::pair<DataRefImpl, uint64_t>> 383 ELFObjectFileBase::getPltAddresses() const { 384 std::string Err; 385 const auto Triple = makeTriple(); 386 const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err); 387 if (!T) 388 return {}; 389 uint64_t JumpSlotReloc = 0; 390 switch (Triple.getArch()) { 391 case Triple::x86: 392 JumpSlotReloc = ELF::R_386_JUMP_SLOT; 393 break; 394 case Triple::x86_64: 395 JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT; 396 break; 397 case Triple::aarch64: 398 JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT; 399 break; 400 default: 401 return {}; 402 } 403 std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo()); 404 std::unique_ptr<const MCInstrAnalysis> MIA( 405 T->createMCInstrAnalysis(MII.get())); 406 if (!MIA) 407 return {}; 408 Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None; 409 for (const SectionRef &Section : sections()) { 410 Expected<StringRef> NameOrErr = Section.getName(); 411 if (!NameOrErr) { 412 consumeError(NameOrErr.takeError()); 413 continue; 414 } 415 StringRef Name = *NameOrErr; 416 417 if (Name == ".plt") 418 Plt = Section; 419 else if (Name == ".rela.plt" || Name == ".rel.plt") 420 RelaPlt = Section; 421 else if (Name == ".got.plt") 422 GotPlt = Section; 423 } 424 if (!Plt || !RelaPlt || !GotPlt) 425 return {}; 426 Expected<StringRef> PltContents = Plt->getContents(); 427 if (!PltContents) { 428 consumeError(PltContents.takeError()); 429 return {}; 430 } 431 auto PltEntries = MIA->findPltEntries(Plt->getAddress(), 432 arrayRefFromStringRef(*PltContents), 433 GotPlt->getAddress(), Triple); 434 // Build a map from GOT entry virtual address to PLT entry virtual address. 435 DenseMap<uint64_t, uint64_t> GotToPlt; 436 for (const auto &Entry : PltEntries) 437 GotToPlt.insert(std::make_pair(Entry.second, Entry.first)); 438 // Find the relocations in the dynamic relocation table that point to 439 // locations in the GOT for which we know the corresponding PLT entry. 440 std::vector<std::pair<DataRefImpl, uint64_t>> Result; 441 for (const auto &Relocation : RelaPlt->relocations()) { 442 if (Relocation.getType() != JumpSlotReloc) 443 continue; 444 auto PltEntryIter = GotToPlt.find(Relocation.getOffset()); 445 if (PltEntryIter != GotToPlt.end()) 446 Result.push_back(std::make_pair( 447 Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second)); 448 } 449 return Result; 450 } 451