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