11df42facSEugene Zelenko //===- ELFObjectFile.cpp - ELF object file implementation -----------------===// 2b60a18deSMichael J. Spencer // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6b60a18deSMichael J. Spencer // 7b60a18deSMichael J. Spencer //===----------------------------------------------------------------------===// 8b60a18deSMichael J. Spencer // 9c7d23ddbSEli Bendersky // Part of the ELFObjectFile class implementation. 10b60a18deSMichael J. Spencer // 11b60a18deSMichael J. Spencer //===----------------------------------------------------------------------===// 12b60a18deSMichael J. Spencer 136bda14b3SChandler Carruth #include "llvm/Object/ELFObjectFile.h" 141df42facSEugene Zelenko #include "llvm/ADT/Triple.h" 15264b5d9eSZachary Turner #include "llvm/BinaryFormat/ELF.h" 16d36fb48aSJoel Galenson #include "llvm/MC/MCInstrAnalysis.h" 171df42facSEugene Zelenko #include "llvm/MC/SubtargetFeature.h" 181df42facSEugene Zelenko #include "llvm/Object/ELF.h" 191df42facSEugene Zelenko #include "llvm/Object/ELFTypes.h" 201df42facSEugene Zelenko #include "llvm/Object/Error.h" 21b0de00d5SSam Parker #include "llvm/Support/ARMAttributeParser.h" 226bda14b3SChandler Carruth #include "llvm/Support/ARMBuildAttributes.h" 231df42facSEugene Zelenko #include "llvm/Support/Endian.h" 241df42facSEugene Zelenko #include "llvm/Support/ErrorHandling.h" 25bae14cefSMichael J. Spencer #include "llvm/Support/MathExtras.h" 26581ba352SKai Wang #include "llvm/Support/RISCVAttributeParser.h" 27581ba352SKai Wang #include "llvm/Support/RISCVAttributes.h" 28d36fb48aSJoel Galenson #include "llvm/Support/TargetRegistry.h" 291df42facSEugene Zelenko #include <algorithm> 301df42facSEugene Zelenko #include <cstddef> 311df42facSEugene Zelenko #include <cstdint> 321df42facSEugene Zelenko #include <memory> 331df42facSEugene Zelenko #include <string> 341df42facSEugene Zelenko #include <system_error> 351df42facSEugene Zelenko #include <utility> 36b60a18deSMichael J. Spencer 371df42facSEugene Zelenko using namespace llvm; 38b60a18deSMichael J. Spencer using namespace object; 39b60a18deSMichael J. Spencer 40ae8fe4e0SSunil Srivastava const EnumEntry<unsigned> llvm::object::ElfSymbolTypes[NumElfSymbolTypes] = { 41ae8fe4e0SSunil Srivastava {"None", "NOTYPE", ELF::STT_NOTYPE}, 42ae8fe4e0SSunil Srivastava {"Object", "OBJECT", ELF::STT_OBJECT}, 43ae8fe4e0SSunil Srivastava {"Function", "FUNC", ELF::STT_FUNC}, 44ae8fe4e0SSunil Srivastava {"Section", "SECTION", ELF::STT_SECTION}, 45ae8fe4e0SSunil Srivastava {"File", "FILE", ELF::STT_FILE}, 46ae8fe4e0SSunil Srivastava {"Common", "COMMON", ELF::STT_COMMON}, 47ae8fe4e0SSunil Srivastava {"TLS", "TLS", ELF::STT_TLS}, 4827f6f2f8SSunil Srivastava {"Unknown", "<unknown>: 7", 7}, 4927f6f2f8SSunil Srivastava {"Unknown", "<unknown>: 8", 8}, 5027f6f2f8SSunil Srivastava {"Unknown", "<unknown>: 9", 9}, 5127f6f2f8SSunil Srivastava {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC}, 5227f6f2f8SSunil Srivastava {"OS Specific", "<OS specific>: 11", 11}, 5327f6f2f8SSunil Srivastava {"OS Specific", "<OS specific>: 12", 12}, 5427f6f2f8SSunil Srivastava {"Proc Specific", "<processor specific>: 13", 13}, 5527f6f2f8SSunil Srivastava {"Proc Specific", "<processor specific>: 14", 14}, 5627f6f2f8SSunil Srivastava {"Proc Specific", "<processor specific>: 15", 15} 5727f6f2f8SSunil Srivastava }; 58ae8fe4e0SSunil Srivastava 5948af1c2aSRafael Espindola ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) 6048af1c2aSRafael Espindola : ObjectFile(Type, Source) {} 61ab73774cSRafael Espindola 62ef421f9cSRafael Espindola template <class ELFT> 63ef421f9cSRafael Espindola static Expected<std::unique_ptr<ELFObjectFile<ELFT>>> 6499a6401aSGeorgii Rymar createPtr(MemoryBufferRef Object, bool InitContent) { 6599a6401aSGeorgii Rymar auto Ret = ELFObjectFile<ELFT>::create(Object, InitContent); 66ef421f9cSRafael Espindola if (Error E = Ret.takeError()) 67c55cf4afSBill Wendling return std::move(E); 680eaee545SJonas Devlieghere return std::make_unique<ELFObjectFile<ELFT>>(std::move(*Ret)); 69ef421f9cSRafael Espindola } 70ef421f9cSRafael Espindola 7112db383eSRafael Espindola Expected<std::unique_ptr<ObjectFile>> 7299a6401aSGeorgii Rymar ObjectFile::createELFObjectFile(MemoryBufferRef Obj, bool InitContent) { 73d5a8efe7SRafael Espindola std::pair<unsigned char, unsigned char> Ident = 7448af1c2aSRafael Espindola getElfArchType(Obj.getBuffer()); 75bae14cefSMichael J. Spencer std::size_t MaxAlignment = 7622cf54a7SArthur O'Dwyer 1ULL << countTrailingZeros( 7722cf54a7SArthur O'Dwyer reinterpret_cast<uintptr_t>(Obj.getBufferStart())); 78bae14cefSMichael J. Spencer 79ac729b46SRafael Espindola if (MaxAlignment < 2) 8012db383eSRafael Espindola return createError("Insufficient alignment"); 81ac729b46SRafael Espindola 82ac729b46SRafael Espindola if (Ident.first == ELF::ELFCLASS32) { 83ac729b46SRafael Espindola if (Ident.second == ELF::ELFDATA2LSB) 8499a6401aSGeorgii Rymar return createPtr<ELF32LE>(Obj, InitContent); 85ac729b46SRafael Espindola else if (Ident.second == ELF::ELFDATA2MSB) 8699a6401aSGeorgii Rymar return createPtr<ELF32BE>(Obj, InitContent); 87692410efSRafael Espindola else 8812db383eSRafael Espindola return createError("Invalid ELF data"); 8949179ddbSAlexey Samsonov } else if (Ident.first == ELF::ELFCLASS64) { 90ac729b46SRafael Espindola if (Ident.second == ELF::ELFDATA2LSB) 9199a6401aSGeorgii Rymar return createPtr<ELF64LE>(Obj, InitContent); 92ac729b46SRafael Espindola else if (Ident.second == ELF::ELFDATA2MSB) 9399a6401aSGeorgii Rymar return createPtr<ELF64BE>(Obj, InitContent); 94ac729b46SRafael Espindola else 9512db383eSRafael Espindola return createError("Invalid ELF data"); 96ac729b46SRafael Espindola } 97ef421f9cSRafael Espindola return createError("Invalid ELF class"); 98b60a18deSMichael J. Spencer } 99b60a18deSMichael J. Spencer 100b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const { 1011d14864bSDaniel Sanders SubtargetFeatures Features; 102d5f76ad3SRafael Espindola unsigned PlatformFlags = getPlatformFlags(); 1031d14864bSDaniel Sanders 1041d14864bSDaniel Sanders switch (PlatformFlags & ELF::EF_MIPS_ARCH) { 1051d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_1: 1061d14864bSDaniel Sanders break; 1071d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_2: 1081d14864bSDaniel Sanders Features.AddFeature("mips2"); 1091d14864bSDaniel Sanders break; 1101d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_3: 1111d14864bSDaniel Sanders Features.AddFeature("mips3"); 1121d14864bSDaniel Sanders break; 1131d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_4: 1141d14864bSDaniel Sanders Features.AddFeature("mips4"); 1151d14864bSDaniel Sanders break; 1161d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_5: 1171d14864bSDaniel Sanders Features.AddFeature("mips5"); 1181d14864bSDaniel Sanders break; 1191d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_32: 1201d14864bSDaniel Sanders Features.AddFeature("mips32"); 1211d14864bSDaniel Sanders break; 1221d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_64: 1231d14864bSDaniel Sanders Features.AddFeature("mips64"); 1241d14864bSDaniel Sanders break; 1251d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_32R2: 1261d14864bSDaniel Sanders Features.AddFeature("mips32r2"); 1271d14864bSDaniel Sanders break; 1281d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_64R2: 1291d14864bSDaniel Sanders Features.AddFeature("mips64r2"); 1301d14864bSDaniel Sanders break; 1311d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_32R6: 1321d14864bSDaniel Sanders Features.AddFeature("mips32r6"); 1331d14864bSDaniel Sanders break; 1341d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_64R6: 1351d14864bSDaniel Sanders Features.AddFeature("mips64r6"); 1361d14864bSDaniel Sanders break; 1371d14864bSDaniel Sanders default: 1381d14864bSDaniel Sanders llvm_unreachable("Unknown EF_MIPS_ARCH value"); 1391d14864bSDaniel Sanders } 1401d14864bSDaniel Sanders 1411d14864bSDaniel Sanders switch (PlatformFlags & ELF::EF_MIPS_MACH) { 1421d14864bSDaniel Sanders case ELF::EF_MIPS_MACH_NONE: 1431d14864bSDaniel Sanders // No feature associated with this value. 1441d14864bSDaniel Sanders break; 1451d14864bSDaniel Sanders case ELF::EF_MIPS_MACH_OCTEON: 1461d14864bSDaniel Sanders Features.AddFeature("cnmips"); 1471d14864bSDaniel Sanders break; 1481d14864bSDaniel Sanders default: 1491d14864bSDaniel Sanders llvm_unreachable("Unknown EF_MIPS_ARCH value"); 1501d14864bSDaniel Sanders } 1511d14864bSDaniel Sanders 1521d14864bSDaniel Sanders if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16) 1531d14864bSDaniel Sanders Features.AddFeature("mips16"); 1541d14864bSDaniel Sanders if (PlatformFlags & ELF::EF_MIPS_MICROMIPS) 1551d14864bSDaniel Sanders Features.AddFeature("micromips"); 1561d14864bSDaniel Sanders 1571d14864bSDaniel Sanders return Features; 1581d14864bSDaniel Sanders } 159b0de00d5SSam Parker 160b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { 161b0de00d5SSam Parker SubtargetFeatures Features; 162b0de00d5SSam Parker ARMAttributeParser Attributes; 163791efb14SFangrui Song if (Error E = getBuildAttributes(Attributes)) { 164791efb14SFangrui Song consumeError(std::move(E)); 165b0de00d5SSam Parker return SubtargetFeatures(); 166791efb14SFangrui Song } 167b0de00d5SSam Parker 168b0de00d5SSam Parker // both ARMv7-M and R have to support thumb hardware div 169b0de00d5SSam Parker bool isV7 = false; 170581ba352SKai Wang Optional<unsigned> Attr = 171581ba352SKai Wang Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch); 172581ba352SKai Wang if (Attr.hasValue()) 173581ba352SKai Wang isV7 = Attr.getValue() == ARMBuildAttrs::v7; 174b0de00d5SSam Parker 175581ba352SKai Wang Attr = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile); 176581ba352SKai Wang if (Attr.hasValue()) { 177581ba352SKai Wang switch (Attr.getValue()) { 178b0de00d5SSam Parker case ARMBuildAttrs::ApplicationProfile: 179b0de00d5SSam Parker Features.AddFeature("aclass"); 180b0de00d5SSam Parker break; 181b0de00d5SSam Parker case ARMBuildAttrs::RealTimeProfile: 182b0de00d5SSam Parker Features.AddFeature("rclass"); 183b0de00d5SSam Parker if (isV7) 184b0de00d5SSam Parker Features.AddFeature("hwdiv"); 185b0de00d5SSam Parker break; 186b0de00d5SSam Parker case ARMBuildAttrs::MicroControllerProfile: 187b0de00d5SSam Parker Features.AddFeature("mclass"); 188b0de00d5SSam Parker if (isV7) 189b0de00d5SSam Parker Features.AddFeature("hwdiv"); 190b0de00d5SSam Parker break; 191b0de00d5SSam Parker } 192b0de00d5SSam Parker } 193b0de00d5SSam Parker 194581ba352SKai Wang Attr = Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use); 195581ba352SKai Wang if (Attr.hasValue()) { 196581ba352SKai Wang switch (Attr.getValue()) { 197b0de00d5SSam Parker default: 198b0de00d5SSam Parker break; 199b0de00d5SSam Parker case ARMBuildAttrs::Not_Allowed: 200b0de00d5SSam Parker Features.AddFeature("thumb", false); 201b0de00d5SSam Parker Features.AddFeature("thumb2", false); 202b0de00d5SSam Parker break; 203b0de00d5SSam Parker case ARMBuildAttrs::AllowThumb32: 204b0de00d5SSam Parker Features.AddFeature("thumb2"); 205b0de00d5SSam Parker break; 206b0de00d5SSam Parker } 207b0de00d5SSam Parker } 208b0de00d5SSam Parker 209581ba352SKai Wang Attr = Attributes.getAttributeValue(ARMBuildAttrs::FP_arch); 210581ba352SKai Wang if (Attr.hasValue()) { 211581ba352SKai Wang switch (Attr.getValue()) { 212b0de00d5SSam Parker default: 213b0de00d5SSam Parker break; 214b0de00d5SSam Parker case ARMBuildAttrs::Not_Allowed: 215ddf5e86cSEli Friedman Features.AddFeature("vfp2sp", false); 216760df47bSSimon Tatham Features.AddFeature("vfp3d16sp", false); 217760df47bSSimon Tatham Features.AddFeature("vfp4d16sp", false); 218b0de00d5SSam Parker break; 219b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv2: 220b0de00d5SSam Parker Features.AddFeature("vfp2"); 221b0de00d5SSam Parker break; 222b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv3A: 223b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv3B: 224b0de00d5SSam Parker Features.AddFeature("vfp3"); 225b0de00d5SSam Parker break; 226b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv4A: 227b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv4B: 228b0de00d5SSam Parker Features.AddFeature("vfp4"); 229b0de00d5SSam Parker break; 230b0de00d5SSam Parker } 231b0de00d5SSam Parker } 232b0de00d5SSam Parker 233581ba352SKai Wang Attr = Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch); 234581ba352SKai Wang if (Attr.hasValue()) { 235581ba352SKai Wang switch (Attr.getValue()) { 236b0de00d5SSam Parker default: 237b0de00d5SSam Parker break; 238b0de00d5SSam Parker case ARMBuildAttrs::Not_Allowed: 239b0de00d5SSam Parker Features.AddFeature("neon", false); 240b0de00d5SSam Parker Features.AddFeature("fp16", false); 241b0de00d5SSam Parker break; 242b0de00d5SSam Parker case ARMBuildAttrs::AllowNeon: 243b0de00d5SSam Parker Features.AddFeature("neon"); 244b0de00d5SSam Parker break; 245b0de00d5SSam Parker case ARMBuildAttrs::AllowNeon2: 246b0de00d5SSam Parker Features.AddFeature("neon"); 247b0de00d5SSam Parker Features.AddFeature("fp16"); 248b0de00d5SSam Parker break; 249b0de00d5SSam Parker } 250b0de00d5SSam Parker } 251b0de00d5SSam Parker 252581ba352SKai Wang Attr = Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch); 253581ba352SKai Wang if (Attr.hasValue()) { 254581ba352SKai Wang switch (Attr.getValue()) { 255930dee2cSSjoerd Meijer default: 256930dee2cSSjoerd Meijer break; 257930dee2cSSjoerd Meijer case ARMBuildAttrs::Not_Allowed: 258930dee2cSSjoerd Meijer Features.AddFeature("mve", false); 259930dee2cSSjoerd Meijer Features.AddFeature("mve.fp", false); 260930dee2cSSjoerd Meijer break; 261930dee2cSSjoerd Meijer case ARMBuildAttrs::AllowMVEInteger: 262930dee2cSSjoerd Meijer Features.AddFeature("mve.fp", false); 263930dee2cSSjoerd Meijer Features.AddFeature("mve"); 264930dee2cSSjoerd Meijer break; 265930dee2cSSjoerd Meijer case ARMBuildAttrs::AllowMVEIntegerAndFloat: 266930dee2cSSjoerd Meijer Features.AddFeature("mve.fp"); 267930dee2cSSjoerd Meijer break; 268930dee2cSSjoerd Meijer } 269930dee2cSSjoerd Meijer } 270930dee2cSSjoerd Meijer 271581ba352SKai Wang Attr = Attributes.getAttributeValue(ARMBuildAttrs::DIV_use); 272581ba352SKai Wang if (Attr.hasValue()) { 273581ba352SKai Wang switch (Attr.getValue()) { 274b0de00d5SSam Parker default: 275b0de00d5SSam Parker break; 276b0de00d5SSam Parker case ARMBuildAttrs::DisallowDIV: 277b0de00d5SSam Parker Features.AddFeature("hwdiv", false); 278b0de00d5SSam Parker Features.AddFeature("hwdiv-arm", false); 279b0de00d5SSam Parker break; 280b0de00d5SSam Parker case ARMBuildAttrs::AllowDIVExt: 281b0de00d5SSam Parker Features.AddFeature("hwdiv"); 282b0de00d5SSam Parker Features.AddFeature("hwdiv-arm"); 283b0de00d5SSam Parker break; 284b0de00d5SSam Parker } 285b0de00d5SSam Parker } 286b0de00d5SSam Parker 287b0de00d5SSam Parker return Features; 288b0de00d5SSam Parker } 289b0de00d5SSam Parker 29053489adaSShiva Chen SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const { 29153489adaSShiva Chen SubtargetFeatures Features; 29253489adaSShiva Chen unsigned PlatformFlags = getPlatformFlags(); 29353489adaSShiva Chen 29453489adaSShiva Chen if (PlatformFlags & ELF::EF_RISCV_RVC) { 29553489adaSShiva Chen Features.AddFeature("c"); 29653489adaSShiva Chen } 29753489adaSShiva Chen 298581ba352SKai Wang // Add features according to the ELF attribute section. 299581ba352SKai Wang // If there are any unrecognized features, ignore them. 300581ba352SKai Wang RISCVAttributeParser Attributes; 30149e20c4cSJessica Clarke if (Error E = getBuildAttributes(Attributes)) { 30249e20c4cSJessica Clarke // TODO Propagate Error. 30349e20c4cSJessica Clarke consumeError(std::move(E)); 304581ba352SKai Wang return Features; // Keep "c" feature if there is one in PlatformFlags. 30549e20c4cSJessica Clarke } 306581ba352SKai Wang 307581ba352SKai Wang Optional<StringRef> Attr = Attributes.getAttributeString(RISCVAttrs::ARCH); 308581ba352SKai Wang if (Attr.hasValue()) { 309581ba352SKai Wang // The Arch pattern is [rv32|rv64][i|e]version(_[m|a|f|d|c]version)* 310581ba352SKai Wang // Version string pattern is (major)p(minor). Major and minor are optional. 311581ba352SKai Wang // For example, a version number could be 2p0, 2, or p92. 312581ba352SKai Wang StringRef Arch = Attr.getValue(); 313581ba352SKai Wang if (Arch.consume_front("rv32")) 314581ba352SKai Wang Features.AddFeature("64bit", false); 315581ba352SKai Wang else if (Arch.consume_front("rv64")) 316581ba352SKai Wang Features.AddFeature("64bit"); 317581ba352SKai Wang 318581ba352SKai Wang while (!Arch.empty()) { 319581ba352SKai Wang switch (Arch[0]) { 320581ba352SKai Wang default: 321581ba352SKai Wang break; // Ignore unexpected features. 322581ba352SKai Wang case 'i': 323581ba352SKai Wang Features.AddFeature("e", false); 324581ba352SKai Wang break; 325581ba352SKai Wang case 'd': 326581ba352SKai Wang Features.AddFeature("f"); // D-ext will imply F-ext. 327581ba352SKai Wang LLVM_FALLTHROUGH; 328581ba352SKai Wang case 'e': 329581ba352SKai Wang case 'm': 330581ba352SKai Wang case 'a': 331581ba352SKai Wang case 'f': 332581ba352SKai Wang case 'c': 333581ba352SKai Wang Features.AddFeature(Arch.take_front()); 334581ba352SKai Wang break; 335581ba352SKai Wang } 336581ba352SKai Wang 337581ba352SKai Wang // FIXME: Handle version numbers. 338581ba352SKai Wang Arch = Arch.drop_until([](char c) { return c == '_' || c == '\0'; }); 339581ba352SKai Wang Arch = Arch.drop_while([](char c) { return c == '_'; }); 340581ba352SKai Wang } 341581ba352SKai Wang } 342581ba352SKai Wang 34353489adaSShiva Chen return Features; 34453489adaSShiva Chen } 34553489adaSShiva Chen 346b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getFeatures() const { 347b0de00d5SSam Parker switch (getEMachine()) { 348b0de00d5SSam Parker case ELF::EM_MIPS: 349b0de00d5SSam Parker return getMIPSFeatures(); 350b0de00d5SSam Parker case ELF::EM_ARM: 351b0de00d5SSam Parker return getARMFeatures(); 35253489adaSShiva Chen case ELF::EM_RISCV: 35353489adaSShiva Chen return getRISCVFeatures(); 3541d14864bSDaniel Sanders default: 3551d14864bSDaniel Sanders return SubtargetFeatures(); 3561d14864bSDaniel Sanders } 3571d14864bSDaniel Sanders } 3581d14864bSDaniel Sanders 359e760e856SRonak Chauhan Optional<StringRef> ELFObjectFileBase::tryGetCPUName() const { 360e760e856SRonak Chauhan switch (getEMachine()) { 361e760e856SRonak Chauhan case ELF::EM_AMDGPU: 362e760e856SRonak Chauhan return getAMDGPUCPUName(); 363e760e856SRonak Chauhan default: 364e760e856SRonak Chauhan return None; 365e760e856SRonak Chauhan } 366e760e856SRonak Chauhan } 367e760e856SRonak Chauhan 368e760e856SRonak Chauhan StringRef ELFObjectFileBase::getAMDGPUCPUName() const { 369e760e856SRonak Chauhan assert(getEMachine() == ELF::EM_AMDGPU); 370e760e856SRonak Chauhan unsigned CPU = getPlatformFlags() & ELF::EF_AMDGPU_MACH; 371e760e856SRonak Chauhan 372e760e856SRonak Chauhan switch (CPU) { 373e760e856SRonak Chauhan // Radeon HD 2000/3000 Series (R600). 374e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_R600: 375e760e856SRonak Chauhan return "r600"; 376e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_R630: 377e760e856SRonak Chauhan return "r630"; 378e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_RS880: 379e760e856SRonak Chauhan return "rs880"; 380e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_RV670: 381e760e856SRonak Chauhan return "rv670"; 382e760e856SRonak Chauhan 383e760e856SRonak Chauhan // Radeon HD 4000 Series (R700). 384e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_RV710: 385e760e856SRonak Chauhan return "rv710"; 386e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_RV730: 387e760e856SRonak Chauhan return "rv730"; 388e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_RV770: 389e760e856SRonak Chauhan return "rv770"; 390e760e856SRonak Chauhan 391e760e856SRonak Chauhan // Radeon HD 5000 Series (Evergreen). 392e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_CEDAR: 393e760e856SRonak Chauhan return "cedar"; 394e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_CYPRESS: 395e760e856SRonak Chauhan return "cypress"; 396e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_JUNIPER: 397e760e856SRonak Chauhan return "juniper"; 398e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_REDWOOD: 399e760e856SRonak Chauhan return "redwood"; 400e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_SUMO: 401e760e856SRonak Chauhan return "sumo"; 402e760e856SRonak Chauhan 403e760e856SRonak Chauhan // Radeon HD 6000 Series (Northern Islands). 404e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_BARTS: 405e760e856SRonak Chauhan return "barts"; 406e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_CAICOS: 407e760e856SRonak Chauhan return "caicos"; 408e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_CAYMAN: 409e760e856SRonak Chauhan return "cayman"; 410e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_R600_TURKS: 411e760e856SRonak Chauhan return "turks"; 412e760e856SRonak Chauhan 413e760e856SRonak Chauhan // AMDGCN GFX6. 414e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX600: 415e760e856SRonak Chauhan return "gfx600"; 416e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX601: 417e760e856SRonak Chauhan return "gfx601"; 418666ef0dbSTim Renouf case ELF::EF_AMDGPU_MACH_AMDGCN_GFX602: 419666ef0dbSTim Renouf return "gfx602"; 420e760e856SRonak Chauhan 421e760e856SRonak Chauhan // AMDGCN GFX7. 422e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX700: 423e760e856SRonak Chauhan return "gfx700"; 424e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX701: 425e760e856SRonak Chauhan return "gfx701"; 426e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX702: 427e760e856SRonak Chauhan return "gfx702"; 428e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX703: 429e760e856SRonak Chauhan return "gfx703"; 430e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX704: 431e760e856SRonak Chauhan return "gfx704"; 432666ef0dbSTim Renouf case ELF::EF_AMDGPU_MACH_AMDGCN_GFX705: 433666ef0dbSTim Renouf return "gfx705"; 434e760e856SRonak Chauhan 435e760e856SRonak Chauhan // AMDGCN GFX8. 436e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX801: 437e760e856SRonak Chauhan return "gfx801"; 438e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX802: 439e760e856SRonak Chauhan return "gfx802"; 440e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX803: 441e760e856SRonak Chauhan return "gfx803"; 442666ef0dbSTim Renouf case ELF::EF_AMDGPU_MACH_AMDGCN_GFX805: 443666ef0dbSTim Renouf return "gfx805"; 444e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX810: 445e760e856SRonak Chauhan return "gfx810"; 446e760e856SRonak Chauhan 447e760e856SRonak Chauhan // AMDGCN GFX9. 448e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX900: 449e760e856SRonak Chauhan return "gfx900"; 450e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX902: 451e760e856SRonak Chauhan return "gfx902"; 452e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX904: 453e760e856SRonak Chauhan return "gfx904"; 454e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX906: 455e760e856SRonak Chauhan return "gfx906"; 456e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX908: 457e760e856SRonak Chauhan return "gfx908"; 458e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX909: 459e760e856SRonak Chauhan return "gfx909"; 460a8d9d507SStanislav Mekhanoshin case ELF::EF_AMDGPU_MACH_AMDGCN_GFX90A: 461a8d9d507SStanislav Mekhanoshin return "gfx90a"; 462ee3e6426STim Renouf case ELF::EF_AMDGPU_MACH_AMDGCN_GFX90C: 463ee3e6426STim Renouf return "gfx90c"; 464e760e856SRonak Chauhan 465e760e856SRonak Chauhan // AMDGCN GFX10. 466e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1010: 467e760e856SRonak Chauhan return "gfx1010"; 468e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1011: 469e760e856SRonak Chauhan return "gfx1011"; 470e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1012: 471e760e856SRonak Chauhan return "gfx1012"; 472*294efbbdSBrendon Cahoon case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1013: 473*294efbbdSBrendon Cahoon return "gfx1013"; 474e760e856SRonak Chauhan case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1030: 475e760e856SRonak Chauhan return "gfx1030"; 47659840978STony case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1031: 47759840978STony return "gfx1031"; 47859840978STony case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1032: 47959840978STony return "gfx1032"; 48089d41f3aSTim Renouf case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1033: 48189d41f3aSTim Renouf return "gfx1033"; 482464e4dc5SAakanksha Patil case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1034: 483464e4dc5SAakanksha Patil return "gfx1034"; 484e760e856SRonak Chauhan default: 485e760e856SRonak Chauhan llvm_unreachable("Unknown EF_AMDGPU_MACH value"); 486e760e856SRonak Chauhan } 487e760e856SRonak Chauhan } 488e760e856SRonak Chauhan 489df7c6ef9SSam Parker // FIXME Encode from a tablegen description or target parser. 490df7c6ef9SSam Parker void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { 491df7c6ef9SSam Parker if (TheTriple.getSubArch() != Triple::NoSubArch) 492df7c6ef9SSam Parker return; 493df7c6ef9SSam Parker 494df7c6ef9SSam Parker ARMAttributeParser Attributes; 495791efb14SFangrui Song if (Error E = getBuildAttributes(Attributes)) { 496791efb14SFangrui Song // TODO Propagate Error. 497791efb14SFangrui Song consumeError(std::move(E)); 498df7c6ef9SSam Parker return; 499791efb14SFangrui Song } 500df7c6ef9SSam Parker 501df7c6ef9SSam Parker std::string Triple; 502df7c6ef9SSam Parker // Default to ARM, but use the triple if it's been set. 503a5ba4ee8SFlorian Hahn if (TheTriple.isThumb()) 504df7c6ef9SSam Parker Triple = "thumb"; 505df7c6ef9SSam Parker else 506df7c6ef9SSam Parker Triple = "arm"; 507df7c6ef9SSam Parker 508581ba352SKai Wang Optional<unsigned> Attr = 509581ba352SKai Wang Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch); 510581ba352SKai Wang if (Attr.hasValue()) { 511581ba352SKai Wang switch (Attr.getValue()) { 512df7c6ef9SSam Parker case ARMBuildAttrs::v4: 513df7c6ef9SSam Parker Triple += "v4"; 514df7c6ef9SSam Parker break; 515df7c6ef9SSam Parker case ARMBuildAttrs::v4T: 516df7c6ef9SSam Parker Triple += "v4t"; 517df7c6ef9SSam Parker break; 518df7c6ef9SSam Parker case ARMBuildAttrs::v5T: 519df7c6ef9SSam Parker Triple += "v5t"; 520df7c6ef9SSam Parker break; 521df7c6ef9SSam Parker case ARMBuildAttrs::v5TE: 522df7c6ef9SSam Parker Triple += "v5te"; 523df7c6ef9SSam Parker break; 524df7c6ef9SSam Parker case ARMBuildAttrs::v5TEJ: 525df7c6ef9SSam Parker Triple += "v5tej"; 526df7c6ef9SSam Parker break; 527df7c6ef9SSam Parker case ARMBuildAttrs::v6: 528df7c6ef9SSam Parker Triple += "v6"; 529df7c6ef9SSam Parker break; 530df7c6ef9SSam Parker case ARMBuildAttrs::v6KZ: 531df7c6ef9SSam Parker Triple += "v6kz"; 532df7c6ef9SSam Parker break; 533df7c6ef9SSam Parker case ARMBuildAttrs::v6T2: 534df7c6ef9SSam Parker Triple += "v6t2"; 535df7c6ef9SSam Parker break; 536df7c6ef9SSam Parker case ARMBuildAttrs::v6K: 537df7c6ef9SSam Parker Triple += "v6k"; 538df7c6ef9SSam Parker break; 539df7c6ef9SSam Parker case ARMBuildAttrs::v7: 540df7c6ef9SSam Parker Triple += "v7"; 541df7c6ef9SSam Parker break; 542df7c6ef9SSam Parker case ARMBuildAttrs::v6_M: 543df7c6ef9SSam Parker Triple += "v6m"; 544df7c6ef9SSam Parker break; 545df7c6ef9SSam Parker case ARMBuildAttrs::v6S_M: 546df7c6ef9SSam Parker Triple += "v6sm"; 547df7c6ef9SSam Parker break; 548df7c6ef9SSam Parker case ARMBuildAttrs::v7E_M: 549df7c6ef9SSam Parker Triple += "v7em"; 550df7c6ef9SSam Parker break; 551b9d87b95SYi Kong case ARMBuildAttrs::v8_A: 552b9d87b95SYi Kong Triple += "v8a"; 553b9d87b95SYi Kong break; 554b9d87b95SYi Kong case ARMBuildAttrs::v8_R: 555b9d87b95SYi Kong Triple += "v8r"; 556b9d87b95SYi Kong break; 557b9d87b95SYi Kong case ARMBuildAttrs::v8_M_Base: 558b9d87b95SYi Kong Triple += "v8m.base"; 559b9d87b95SYi Kong break; 560b9d87b95SYi Kong case ARMBuildAttrs::v8_M_Main: 561b9d87b95SYi Kong Triple += "v8m.main"; 562b9d87b95SYi Kong break; 563b9d87b95SYi Kong case ARMBuildAttrs::v8_1_M_Main: 564b9d87b95SYi Kong Triple += "v8.1m.main"; 565b9d87b95SYi Kong break; 566df7c6ef9SSam Parker } 567df7c6ef9SSam Parker } 568df7c6ef9SSam Parker if (!isLittleEndian()) 569df7c6ef9SSam Parker Triple += "eb"; 570df7c6ef9SSam Parker 571df7c6ef9SSam Parker TheTriple.setArchName(Triple); 572df7c6ef9SSam Parker } 573d36fb48aSJoel Galenson 5747f8c49b0SFangrui Song std::vector<std::pair<Optional<DataRefImpl>, uint64_t>> 575d36fb48aSJoel Galenson ELFObjectFileBase::getPltAddresses() const { 576d36fb48aSJoel Galenson std::string Err; 577d36fb48aSJoel Galenson const auto Triple = makeTriple(); 578d36fb48aSJoel Galenson const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err); 579d36fb48aSJoel Galenson if (!T) 580d36fb48aSJoel Galenson return {}; 581d36fb48aSJoel Galenson uint64_t JumpSlotReloc = 0; 582d36fb48aSJoel Galenson switch (Triple.getArch()) { 583d36fb48aSJoel Galenson case Triple::x86: 584d36fb48aSJoel Galenson JumpSlotReloc = ELF::R_386_JUMP_SLOT; 585d36fb48aSJoel Galenson break; 586d36fb48aSJoel Galenson case Triple::x86_64: 587d36fb48aSJoel Galenson JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT; 588d36fb48aSJoel Galenson break; 589d36fb48aSJoel Galenson case Triple::aarch64: 590157ac423SFangrui Song case Triple::aarch64_be: 591d36fb48aSJoel Galenson JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT; 592d36fb48aSJoel Galenson break; 593d36fb48aSJoel Galenson default: 594d36fb48aSJoel Galenson return {}; 595d36fb48aSJoel Galenson } 59696cbeffaSVitaly Buka std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo()); 59790f976a4SJoel Galenson std::unique_ptr<const MCInstrAnalysis> MIA( 59896cbeffaSVitaly Buka T->createMCInstrAnalysis(MII.get())); 599d36fb48aSJoel Galenson if (!MIA) 600d36fb48aSJoel Galenson return {}; 601d36fb48aSJoel Galenson Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None; 602d36fb48aSJoel Galenson for (const SectionRef &Section : sections()) { 603bcc00e1aSGeorge Rimar Expected<StringRef> NameOrErr = Section.getName(); 604bcc00e1aSGeorge Rimar if (!NameOrErr) { 605bcc00e1aSGeorge Rimar consumeError(NameOrErr.takeError()); 606d36fb48aSJoel Galenson continue; 607bcc00e1aSGeorge Rimar } 608bcc00e1aSGeorge Rimar StringRef Name = *NameOrErr; 609bcc00e1aSGeorge Rimar 610d36fb48aSJoel Galenson if (Name == ".plt") 611d36fb48aSJoel Galenson Plt = Section; 612d36fb48aSJoel Galenson else if (Name == ".rela.plt" || Name == ".rel.plt") 613d36fb48aSJoel Galenson RelaPlt = Section; 614d36fb48aSJoel Galenson else if (Name == ".got.plt") 615d36fb48aSJoel Galenson GotPlt = Section; 616d36fb48aSJoel Galenson } 617d36fb48aSJoel Galenson if (!Plt || !RelaPlt || !GotPlt) 618d36fb48aSJoel Galenson return {}; 619e183340cSFangrui Song Expected<StringRef> PltContents = Plt->getContents(); 620e183340cSFangrui Song if (!PltContents) { 621e183340cSFangrui Song consumeError(PltContents.takeError()); 622d36fb48aSJoel Galenson return {}; 623e183340cSFangrui Song } 624e183340cSFangrui Song auto PltEntries = MIA->findPltEntries(Plt->getAddress(), 625e183340cSFangrui Song arrayRefFromStringRef(*PltContents), 626d36fb48aSJoel Galenson GotPlt->getAddress(), Triple); 627d36fb48aSJoel Galenson // Build a map from GOT entry virtual address to PLT entry virtual address. 628d36fb48aSJoel Galenson DenseMap<uint64_t, uint64_t> GotToPlt; 629d36fb48aSJoel Galenson for (const auto &Entry : PltEntries) 630d36fb48aSJoel Galenson GotToPlt.insert(std::make_pair(Entry.second, Entry.first)); 631d36fb48aSJoel Galenson // Find the relocations in the dynamic relocation table that point to 632d36fb48aSJoel Galenson // locations in the GOT for which we know the corresponding PLT entry. 6337f8c49b0SFangrui Song std::vector<std::pair<Optional<DataRefImpl>, uint64_t>> Result; 634d36fb48aSJoel Galenson for (const auto &Relocation : RelaPlt->relocations()) { 635d36fb48aSJoel Galenson if (Relocation.getType() != JumpSlotReloc) 636d36fb48aSJoel Galenson continue; 637d36fb48aSJoel Galenson auto PltEntryIter = GotToPlt.find(Relocation.getOffset()); 6387f8c49b0SFangrui Song if (PltEntryIter != GotToPlt.end()) { 6397f8c49b0SFangrui Song symbol_iterator Sym = Relocation.getSymbol(); 6407f8c49b0SFangrui Song if (Sym == symbol_end()) 6417f8c49b0SFangrui Song Result.emplace_back(None, PltEntryIter->second); 6427f8c49b0SFangrui Song else 6437f8c49b0SFangrui Song Result.emplace_back(Sym->getRawDataRefImpl(), PltEntryIter->second); 6447f8c49b0SFangrui Song } 645d36fb48aSJoel Galenson } 646d36fb48aSJoel Galenson return Result; 647d36fb48aSJoel Galenson } 648