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/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 <algorithm> 27 #include <cstddef> 28 #include <cstdint> 29 #include <memory> 30 #include <string> 31 #include <system_error> 32 #include <utility> 33 34 using namespace llvm; 35 using namespace object; 36 37 ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) 38 : ObjectFile(Type, Source) {} 39 40 template <class ELFT> 41 static Expected<std::unique_ptr<ELFObjectFile<ELFT>>> 42 createPtr(MemoryBufferRef Object) { 43 auto Ret = ELFObjectFile<ELFT>::create(Object); 44 if (Error E = Ret.takeError()) 45 return std::move(E); 46 return make_unique<ELFObjectFile<ELFT>>(std::move(*Ret)); 47 } 48 49 Expected<std::unique_ptr<ObjectFile>> 50 ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { 51 std::pair<unsigned char, unsigned char> Ident = 52 getElfArchType(Obj.getBuffer()); 53 std::size_t MaxAlignment = 54 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart())); 55 56 if (MaxAlignment < 2) 57 return createError("Insufficient alignment"); 58 59 if (Ident.first == ELF::ELFCLASS32) { 60 if (Ident.second == ELF::ELFDATA2LSB) 61 return createPtr<ELF32LE>(Obj); 62 else if (Ident.second == ELF::ELFDATA2MSB) 63 return createPtr<ELF32BE>(Obj); 64 else 65 return createError("Invalid ELF data"); 66 } else if (Ident.first == ELF::ELFCLASS64) { 67 if (Ident.second == ELF::ELFDATA2LSB) 68 return createPtr<ELF64LE>(Obj); 69 else if (Ident.second == ELF::ELFDATA2MSB) 70 return createPtr<ELF64BE>(Obj); 71 else 72 return createError("Invalid ELF data"); 73 } 74 return createError("Invalid ELF class"); 75 } 76 77 SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const { 78 SubtargetFeatures Features; 79 unsigned PlatformFlags = getPlatformFlags(); 80 81 switch (PlatformFlags & ELF::EF_MIPS_ARCH) { 82 case ELF::EF_MIPS_ARCH_1: 83 break; 84 case ELF::EF_MIPS_ARCH_2: 85 Features.AddFeature("mips2"); 86 break; 87 case ELF::EF_MIPS_ARCH_3: 88 Features.AddFeature("mips3"); 89 break; 90 case ELF::EF_MIPS_ARCH_4: 91 Features.AddFeature("mips4"); 92 break; 93 case ELF::EF_MIPS_ARCH_5: 94 Features.AddFeature("mips5"); 95 break; 96 case ELF::EF_MIPS_ARCH_32: 97 Features.AddFeature("mips32"); 98 break; 99 case ELF::EF_MIPS_ARCH_64: 100 Features.AddFeature("mips64"); 101 break; 102 case ELF::EF_MIPS_ARCH_32R2: 103 Features.AddFeature("mips32r2"); 104 break; 105 case ELF::EF_MIPS_ARCH_64R2: 106 Features.AddFeature("mips64r2"); 107 break; 108 case ELF::EF_MIPS_ARCH_32R6: 109 Features.AddFeature("mips32r6"); 110 break; 111 case ELF::EF_MIPS_ARCH_64R6: 112 Features.AddFeature("mips64r6"); 113 break; 114 default: 115 llvm_unreachable("Unknown EF_MIPS_ARCH value"); 116 } 117 118 switch (PlatformFlags & ELF::EF_MIPS_MACH) { 119 case ELF::EF_MIPS_MACH_NONE: 120 // No feature associated with this value. 121 break; 122 case ELF::EF_MIPS_MACH_OCTEON: 123 Features.AddFeature("cnmips"); 124 break; 125 default: 126 llvm_unreachable("Unknown EF_MIPS_ARCH value"); 127 } 128 129 if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16) 130 Features.AddFeature("mips16"); 131 if (PlatformFlags & ELF::EF_MIPS_MICROMIPS) 132 Features.AddFeature("micromips"); 133 134 return Features; 135 } 136 137 SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { 138 SubtargetFeatures Features; 139 ARMAttributeParser Attributes; 140 std::error_code EC = getBuildAttributes(Attributes); 141 if (EC) 142 return SubtargetFeatures(); 143 144 // both ARMv7-M and R have to support thumb hardware div 145 bool isV7 = false; 146 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) 147 isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch) 148 == ARMBuildAttrs::v7; 149 150 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) { 151 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) { 152 case ARMBuildAttrs::ApplicationProfile: 153 Features.AddFeature("aclass"); 154 break; 155 case ARMBuildAttrs::RealTimeProfile: 156 Features.AddFeature("rclass"); 157 if (isV7) 158 Features.AddFeature("hwdiv"); 159 break; 160 case ARMBuildAttrs::MicroControllerProfile: 161 Features.AddFeature("mclass"); 162 if (isV7) 163 Features.AddFeature("hwdiv"); 164 break; 165 } 166 } 167 168 if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) { 169 switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) { 170 default: 171 break; 172 case ARMBuildAttrs::Not_Allowed: 173 Features.AddFeature("thumb", false); 174 Features.AddFeature("thumb2", false); 175 break; 176 case ARMBuildAttrs::AllowThumb32: 177 Features.AddFeature("thumb2"); 178 break; 179 } 180 } 181 182 if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) { 183 switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) { 184 default: 185 break; 186 case ARMBuildAttrs::Not_Allowed: 187 Features.AddFeature("vfp2", false); 188 Features.AddFeature("vfp3", false); 189 Features.AddFeature("vfp4", false); 190 break; 191 case ARMBuildAttrs::AllowFPv2: 192 Features.AddFeature("vfp2"); 193 break; 194 case ARMBuildAttrs::AllowFPv3A: 195 case ARMBuildAttrs::AllowFPv3B: 196 Features.AddFeature("vfp3"); 197 break; 198 case ARMBuildAttrs::AllowFPv4A: 199 case ARMBuildAttrs::AllowFPv4B: 200 Features.AddFeature("vfp4"); 201 break; 202 } 203 } 204 205 if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) { 206 switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) { 207 default: 208 break; 209 case ARMBuildAttrs::Not_Allowed: 210 Features.AddFeature("neon", false); 211 Features.AddFeature("fp16", false); 212 break; 213 case ARMBuildAttrs::AllowNeon: 214 Features.AddFeature("neon"); 215 break; 216 case ARMBuildAttrs::AllowNeon2: 217 Features.AddFeature("neon"); 218 Features.AddFeature("fp16"); 219 break; 220 } 221 } 222 223 if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) { 224 switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) { 225 default: 226 break; 227 case ARMBuildAttrs::DisallowDIV: 228 Features.AddFeature("hwdiv", false); 229 Features.AddFeature("hwdiv-arm", false); 230 break; 231 case ARMBuildAttrs::AllowDIVExt: 232 Features.AddFeature("hwdiv"); 233 Features.AddFeature("hwdiv-arm"); 234 break; 235 } 236 } 237 238 return Features; 239 } 240 241 SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const { 242 SubtargetFeatures Features; 243 unsigned PlatformFlags = getPlatformFlags(); 244 245 if (PlatformFlags & ELF::EF_RISCV_RVC) { 246 Features.AddFeature("c"); 247 } 248 249 return Features; 250 } 251 252 SubtargetFeatures ELFObjectFileBase::getFeatures() const { 253 switch (getEMachine()) { 254 case ELF::EM_MIPS: 255 return getMIPSFeatures(); 256 case ELF::EM_ARM: 257 return getARMFeatures(); 258 case ELF::EM_RISCV: 259 return getRISCVFeatures(); 260 default: 261 return SubtargetFeatures(); 262 } 263 } 264 265 // FIXME Encode from a tablegen description or target parser. 266 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { 267 if (TheTriple.getSubArch() != Triple::NoSubArch) 268 return; 269 270 ARMAttributeParser Attributes; 271 std::error_code EC = getBuildAttributes(Attributes); 272 if (EC) 273 return; 274 275 std::string Triple; 276 // Default to ARM, but use the triple if it's been set. 277 if (TheTriple.isThumb()) 278 Triple = "thumb"; 279 else 280 Triple = "arm"; 281 282 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) { 283 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) { 284 case ARMBuildAttrs::v4: 285 Triple += "v4"; 286 break; 287 case ARMBuildAttrs::v4T: 288 Triple += "v4t"; 289 break; 290 case ARMBuildAttrs::v5T: 291 Triple += "v5t"; 292 break; 293 case ARMBuildAttrs::v5TE: 294 Triple += "v5te"; 295 break; 296 case ARMBuildAttrs::v5TEJ: 297 Triple += "v5tej"; 298 break; 299 case ARMBuildAttrs::v6: 300 Triple += "v6"; 301 break; 302 case ARMBuildAttrs::v6KZ: 303 Triple += "v6kz"; 304 break; 305 case ARMBuildAttrs::v6T2: 306 Triple += "v6t2"; 307 break; 308 case ARMBuildAttrs::v6K: 309 Triple += "v6k"; 310 break; 311 case ARMBuildAttrs::v7: 312 Triple += "v7"; 313 break; 314 case ARMBuildAttrs::v6_M: 315 Triple += "v6m"; 316 break; 317 case ARMBuildAttrs::v6S_M: 318 Triple += "v6sm"; 319 break; 320 case ARMBuildAttrs::v7E_M: 321 Triple += "v7em"; 322 break; 323 } 324 } 325 if (!isLittleEndian()) 326 Triple += "eb"; 327 328 TheTriple.setArchName(Triple); 329 } 330