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