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