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