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; 80 getPlatformFlags(PlatformFlags); 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::getFeatures() const { 243 switch (getEMachine()) { 244 case ELF::EM_MIPS: 245 return getMIPSFeatures(); 246 case ELF::EM_ARM: 247 return getARMFeatures(); 248 default: 249 return SubtargetFeatures(); 250 } 251 } 252 253 // FIXME Encode from a tablegen description or target parser. 254 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { 255 if (TheTriple.getSubArch() != Triple::NoSubArch) 256 return; 257 258 ARMAttributeParser Attributes; 259 std::error_code EC = getBuildAttributes(Attributes); 260 if (EC) 261 return; 262 263 std::string Triple; 264 // Default to ARM, but use the triple if it's been set. 265 if (TheTriple.isThumb()) 266 Triple = "thumb"; 267 else 268 Triple = "arm"; 269 270 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) { 271 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) { 272 case ARMBuildAttrs::v4: 273 Triple += "v4"; 274 break; 275 case ARMBuildAttrs::v4T: 276 Triple += "v4t"; 277 break; 278 case ARMBuildAttrs::v5T: 279 Triple += "v5t"; 280 break; 281 case ARMBuildAttrs::v5TE: 282 Triple += "v5te"; 283 break; 284 case ARMBuildAttrs::v5TEJ: 285 Triple += "v5tej"; 286 break; 287 case ARMBuildAttrs::v6: 288 Triple += "v6"; 289 break; 290 case ARMBuildAttrs::v6KZ: 291 Triple += "v6kz"; 292 break; 293 case ARMBuildAttrs::v6T2: 294 Triple += "v6t2"; 295 break; 296 case ARMBuildAttrs::v6K: 297 Triple += "v6k"; 298 break; 299 case ARMBuildAttrs::v7: 300 Triple += "v7"; 301 break; 302 case ARMBuildAttrs::v6_M: 303 Triple += "v6m"; 304 break; 305 case ARMBuildAttrs::v6S_M: 306 Triple += "v6sm"; 307 break; 308 case ARMBuildAttrs::v7E_M: 309 Triple += "v7em"; 310 break; 311 } 312 } 313 if (!isLittleEndian()) 314 Triple += "eb"; 315 316 TheTriple.setArchName(Triple); 317 } 318