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