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" 26*581ba352SKai Wang #include "llvm/Support/RISCVAttributeParser.h" 27*581ba352SKai 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>>> 64ef421f9cSRafael Espindola createPtr(MemoryBufferRef Object) { 65ef421f9cSRafael Espindola auto Ret = ELFObjectFile<ELFT>::create(Object); 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>> 7248af1c2aSRafael Espindola ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { 73d5a8efe7SRafael Espindola std::pair<unsigned char, unsigned char> Ident = 7448af1c2aSRafael Espindola getElfArchType(Obj.getBuffer()); 75bae14cefSMichael J. Spencer std::size_t MaxAlignment = 7648af1c2aSRafael Espindola 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart())); 77bae14cefSMichael J. Spencer 78ac729b46SRafael Espindola if (MaxAlignment < 2) 7912db383eSRafael Espindola return createError("Insufficient alignment"); 80ac729b46SRafael Espindola 81ac729b46SRafael Espindola if (Ident.first == ELF::ELFCLASS32) { 82ac729b46SRafael Espindola if (Ident.second == ELF::ELFDATA2LSB) 83ef421f9cSRafael Espindola return createPtr<ELF32LE>(Obj); 84ac729b46SRafael Espindola else if (Ident.second == ELF::ELFDATA2MSB) 85ef421f9cSRafael Espindola return createPtr<ELF32BE>(Obj); 86692410efSRafael Espindola else 8712db383eSRafael Espindola return createError("Invalid ELF data"); 8849179ddbSAlexey Samsonov } else if (Ident.first == ELF::ELFCLASS64) { 89ac729b46SRafael Espindola if (Ident.second == ELF::ELFDATA2LSB) 90ef421f9cSRafael Espindola return createPtr<ELF64LE>(Obj); 91ac729b46SRafael Espindola else if (Ident.second == ELF::ELFDATA2MSB) 92ef421f9cSRafael Espindola return createPtr<ELF64BE>(Obj); 93ac729b46SRafael Espindola else 9412db383eSRafael Espindola return createError("Invalid ELF data"); 95ac729b46SRafael Espindola } 96ef421f9cSRafael Espindola return createError("Invalid ELF class"); 97b60a18deSMichael J. Spencer } 98b60a18deSMichael J. Spencer 99b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const { 1001d14864bSDaniel Sanders SubtargetFeatures Features; 101d5f76ad3SRafael Espindola unsigned PlatformFlags = getPlatformFlags(); 1021d14864bSDaniel Sanders 1031d14864bSDaniel Sanders switch (PlatformFlags & ELF::EF_MIPS_ARCH) { 1041d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_1: 1051d14864bSDaniel Sanders break; 1061d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_2: 1071d14864bSDaniel Sanders Features.AddFeature("mips2"); 1081d14864bSDaniel Sanders break; 1091d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_3: 1101d14864bSDaniel Sanders Features.AddFeature("mips3"); 1111d14864bSDaniel Sanders break; 1121d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_4: 1131d14864bSDaniel Sanders Features.AddFeature("mips4"); 1141d14864bSDaniel Sanders break; 1151d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_5: 1161d14864bSDaniel Sanders Features.AddFeature("mips5"); 1171d14864bSDaniel Sanders break; 1181d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_32: 1191d14864bSDaniel Sanders Features.AddFeature("mips32"); 1201d14864bSDaniel Sanders break; 1211d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_64: 1221d14864bSDaniel Sanders Features.AddFeature("mips64"); 1231d14864bSDaniel Sanders break; 1241d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_32R2: 1251d14864bSDaniel Sanders Features.AddFeature("mips32r2"); 1261d14864bSDaniel Sanders break; 1271d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_64R2: 1281d14864bSDaniel Sanders Features.AddFeature("mips64r2"); 1291d14864bSDaniel Sanders break; 1301d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_32R6: 1311d14864bSDaniel Sanders Features.AddFeature("mips32r6"); 1321d14864bSDaniel Sanders break; 1331d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_64R6: 1341d14864bSDaniel Sanders Features.AddFeature("mips64r6"); 1351d14864bSDaniel Sanders break; 1361d14864bSDaniel Sanders default: 1371d14864bSDaniel Sanders llvm_unreachable("Unknown EF_MIPS_ARCH value"); 1381d14864bSDaniel Sanders } 1391d14864bSDaniel Sanders 1401d14864bSDaniel Sanders switch (PlatformFlags & ELF::EF_MIPS_MACH) { 1411d14864bSDaniel Sanders case ELF::EF_MIPS_MACH_NONE: 1421d14864bSDaniel Sanders // No feature associated with this value. 1431d14864bSDaniel Sanders break; 1441d14864bSDaniel Sanders case ELF::EF_MIPS_MACH_OCTEON: 1451d14864bSDaniel Sanders Features.AddFeature("cnmips"); 1461d14864bSDaniel Sanders break; 1471d14864bSDaniel Sanders default: 1481d14864bSDaniel Sanders llvm_unreachable("Unknown EF_MIPS_ARCH value"); 1491d14864bSDaniel Sanders } 1501d14864bSDaniel Sanders 1511d14864bSDaniel Sanders if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16) 1521d14864bSDaniel Sanders Features.AddFeature("mips16"); 1531d14864bSDaniel Sanders if (PlatformFlags & ELF::EF_MIPS_MICROMIPS) 1541d14864bSDaniel Sanders Features.AddFeature("micromips"); 1551d14864bSDaniel Sanders 1561d14864bSDaniel Sanders return Features; 1571d14864bSDaniel Sanders } 158b0de00d5SSam Parker 159b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { 160b0de00d5SSam Parker SubtargetFeatures Features; 161b0de00d5SSam Parker ARMAttributeParser Attributes; 162791efb14SFangrui Song if (Error E = getBuildAttributes(Attributes)) { 163791efb14SFangrui Song consumeError(std::move(E)); 164b0de00d5SSam Parker return SubtargetFeatures(); 165791efb14SFangrui Song } 166b0de00d5SSam Parker 167b0de00d5SSam Parker // both ARMv7-M and R have to support thumb hardware div 168b0de00d5SSam Parker bool isV7 = false; 169*581ba352SKai Wang Optional<unsigned> Attr = 170*581ba352SKai Wang Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch); 171*581ba352SKai Wang if (Attr.hasValue()) 172*581ba352SKai Wang isV7 = Attr.getValue() == ARMBuildAttrs::v7; 173b0de00d5SSam Parker 174*581ba352SKai Wang Attr = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile); 175*581ba352SKai Wang if (Attr.hasValue()) { 176*581ba352SKai Wang switch (Attr.getValue()) { 177b0de00d5SSam Parker case ARMBuildAttrs::ApplicationProfile: 178b0de00d5SSam Parker Features.AddFeature("aclass"); 179b0de00d5SSam Parker break; 180b0de00d5SSam Parker case ARMBuildAttrs::RealTimeProfile: 181b0de00d5SSam Parker Features.AddFeature("rclass"); 182b0de00d5SSam Parker if (isV7) 183b0de00d5SSam Parker Features.AddFeature("hwdiv"); 184b0de00d5SSam Parker break; 185b0de00d5SSam Parker case ARMBuildAttrs::MicroControllerProfile: 186b0de00d5SSam Parker Features.AddFeature("mclass"); 187b0de00d5SSam Parker if (isV7) 188b0de00d5SSam Parker Features.AddFeature("hwdiv"); 189b0de00d5SSam Parker break; 190b0de00d5SSam Parker } 191b0de00d5SSam Parker } 192b0de00d5SSam Parker 193*581ba352SKai Wang Attr = Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use); 194*581ba352SKai Wang if (Attr.hasValue()) { 195*581ba352SKai Wang switch (Attr.getValue()) { 196b0de00d5SSam Parker default: 197b0de00d5SSam Parker break; 198b0de00d5SSam Parker case ARMBuildAttrs::Not_Allowed: 199b0de00d5SSam Parker Features.AddFeature("thumb", false); 200b0de00d5SSam Parker Features.AddFeature("thumb2", false); 201b0de00d5SSam Parker break; 202b0de00d5SSam Parker case ARMBuildAttrs::AllowThumb32: 203b0de00d5SSam Parker Features.AddFeature("thumb2"); 204b0de00d5SSam Parker break; 205b0de00d5SSam Parker } 206b0de00d5SSam Parker } 207b0de00d5SSam Parker 208*581ba352SKai Wang Attr = Attributes.getAttributeValue(ARMBuildAttrs::FP_arch); 209*581ba352SKai Wang if (Attr.hasValue()) { 210*581ba352SKai Wang switch (Attr.getValue()) { 211b0de00d5SSam Parker default: 212b0de00d5SSam Parker break; 213b0de00d5SSam Parker case ARMBuildAttrs::Not_Allowed: 214ddf5e86cSEli Friedman Features.AddFeature("vfp2sp", false); 215760df47bSSimon Tatham Features.AddFeature("vfp3d16sp", false); 216760df47bSSimon Tatham Features.AddFeature("vfp4d16sp", false); 217b0de00d5SSam Parker break; 218b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv2: 219b0de00d5SSam Parker Features.AddFeature("vfp2"); 220b0de00d5SSam Parker break; 221b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv3A: 222b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv3B: 223b0de00d5SSam Parker Features.AddFeature("vfp3"); 224b0de00d5SSam Parker break; 225b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv4A: 226b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv4B: 227b0de00d5SSam Parker Features.AddFeature("vfp4"); 228b0de00d5SSam Parker break; 229b0de00d5SSam Parker } 230b0de00d5SSam Parker } 231b0de00d5SSam Parker 232*581ba352SKai Wang Attr = Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch); 233*581ba352SKai Wang if (Attr.hasValue()) { 234*581ba352SKai Wang switch (Attr.getValue()) { 235b0de00d5SSam Parker default: 236b0de00d5SSam Parker break; 237b0de00d5SSam Parker case ARMBuildAttrs::Not_Allowed: 238b0de00d5SSam Parker Features.AddFeature("neon", false); 239b0de00d5SSam Parker Features.AddFeature("fp16", false); 240b0de00d5SSam Parker break; 241b0de00d5SSam Parker case ARMBuildAttrs::AllowNeon: 242b0de00d5SSam Parker Features.AddFeature("neon"); 243b0de00d5SSam Parker break; 244b0de00d5SSam Parker case ARMBuildAttrs::AllowNeon2: 245b0de00d5SSam Parker Features.AddFeature("neon"); 246b0de00d5SSam Parker Features.AddFeature("fp16"); 247b0de00d5SSam Parker break; 248b0de00d5SSam Parker } 249b0de00d5SSam Parker } 250b0de00d5SSam Parker 251*581ba352SKai Wang Attr = Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch); 252*581ba352SKai Wang if (Attr.hasValue()) { 253*581ba352SKai Wang switch (Attr.getValue()) { 254930dee2cSSjoerd Meijer default: 255930dee2cSSjoerd Meijer break; 256930dee2cSSjoerd Meijer case ARMBuildAttrs::Not_Allowed: 257930dee2cSSjoerd Meijer Features.AddFeature("mve", false); 258930dee2cSSjoerd Meijer Features.AddFeature("mve.fp", false); 259930dee2cSSjoerd Meijer break; 260930dee2cSSjoerd Meijer case ARMBuildAttrs::AllowMVEInteger: 261930dee2cSSjoerd Meijer Features.AddFeature("mve.fp", false); 262930dee2cSSjoerd Meijer Features.AddFeature("mve"); 263930dee2cSSjoerd Meijer break; 264930dee2cSSjoerd Meijer case ARMBuildAttrs::AllowMVEIntegerAndFloat: 265930dee2cSSjoerd Meijer Features.AddFeature("mve.fp"); 266930dee2cSSjoerd Meijer break; 267930dee2cSSjoerd Meijer } 268930dee2cSSjoerd Meijer } 269930dee2cSSjoerd Meijer 270*581ba352SKai Wang Attr = Attributes.getAttributeValue(ARMBuildAttrs::DIV_use); 271*581ba352SKai Wang if (Attr.hasValue()) { 272*581ba352SKai Wang switch (Attr.getValue()) { 273b0de00d5SSam Parker default: 274b0de00d5SSam Parker break; 275b0de00d5SSam Parker case ARMBuildAttrs::DisallowDIV: 276b0de00d5SSam Parker Features.AddFeature("hwdiv", false); 277b0de00d5SSam Parker Features.AddFeature("hwdiv-arm", false); 278b0de00d5SSam Parker break; 279b0de00d5SSam Parker case ARMBuildAttrs::AllowDIVExt: 280b0de00d5SSam Parker Features.AddFeature("hwdiv"); 281b0de00d5SSam Parker Features.AddFeature("hwdiv-arm"); 282b0de00d5SSam Parker break; 283b0de00d5SSam Parker } 284b0de00d5SSam Parker } 285b0de00d5SSam Parker 286b0de00d5SSam Parker return Features; 287b0de00d5SSam Parker } 288b0de00d5SSam Parker 28953489adaSShiva Chen SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const { 29053489adaSShiva Chen SubtargetFeatures Features; 29153489adaSShiva Chen unsigned PlatformFlags = getPlatformFlags(); 29253489adaSShiva Chen 29353489adaSShiva Chen if (PlatformFlags & ELF::EF_RISCV_RVC) { 29453489adaSShiva Chen Features.AddFeature("c"); 29553489adaSShiva Chen } 29653489adaSShiva Chen 297*581ba352SKai Wang // Add features according to the ELF attribute section. 298*581ba352SKai Wang // If there are any unrecognized features, ignore them. 299*581ba352SKai Wang RISCVAttributeParser Attributes; 300*581ba352SKai Wang if (Error E = getBuildAttributes(Attributes)) 301*581ba352SKai Wang return Features; // Keep "c" feature if there is one in PlatformFlags. 302*581ba352SKai Wang 303*581ba352SKai Wang Optional<StringRef> Attr = Attributes.getAttributeString(RISCVAttrs::ARCH); 304*581ba352SKai Wang if (Attr.hasValue()) { 305*581ba352SKai Wang // The Arch pattern is [rv32|rv64][i|e]version(_[m|a|f|d|c]version)* 306*581ba352SKai Wang // Version string pattern is (major)p(minor). Major and minor are optional. 307*581ba352SKai Wang // For example, a version number could be 2p0, 2, or p92. 308*581ba352SKai Wang StringRef Arch = Attr.getValue(); 309*581ba352SKai Wang if (Arch.consume_front("rv32")) 310*581ba352SKai Wang Features.AddFeature("64bit", false); 311*581ba352SKai Wang else if (Arch.consume_front("rv64")) 312*581ba352SKai Wang Features.AddFeature("64bit"); 313*581ba352SKai Wang 314*581ba352SKai Wang while (!Arch.empty()) { 315*581ba352SKai Wang switch (Arch[0]) { 316*581ba352SKai Wang default: 317*581ba352SKai Wang break; // Ignore unexpected features. 318*581ba352SKai Wang case 'i': 319*581ba352SKai Wang Features.AddFeature("e", false); 320*581ba352SKai Wang break; 321*581ba352SKai Wang case 'd': 322*581ba352SKai Wang Features.AddFeature("f"); // D-ext will imply F-ext. 323*581ba352SKai Wang LLVM_FALLTHROUGH; 324*581ba352SKai Wang case 'e': 325*581ba352SKai Wang case 'm': 326*581ba352SKai Wang case 'a': 327*581ba352SKai Wang case 'f': 328*581ba352SKai Wang case 'c': 329*581ba352SKai Wang Features.AddFeature(Arch.take_front()); 330*581ba352SKai Wang break; 331*581ba352SKai Wang } 332*581ba352SKai Wang 333*581ba352SKai Wang // FIXME: Handle version numbers. 334*581ba352SKai Wang Arch = Arch.drop_until([](char c) { return c == '_' || c == '\0'; }); 335*581ba352SKai Wang Arch = Arch.drop_while([](char c) { return c == '_'; }); 336*581ba352SKai Wang } 337*581ba352SKai Wang } 338*581ba352SKai Wang 33953489adaSShiva Chen return Features; 34053489adaSShiva Chen } 34153489adaSShiva Chen 342b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getFeatures() const { 343b0de00d5SSam Parker switch (getEMachine()) { 344b0de00d5SSam Parker case ELF::EM_MIPS: 345b0de00d5SSam Parker return getMIPSFeatures(); 346b0de00d5SSam Parker case ELF::EM_ARM: 347b0de00d5SSam Parker return getARMFeatures(); 34853489adaSShiva Chen case ELF::EM_RISCV: 34953489adaSShiva Chen return getRISCVFeatures(); 3501d14864bSDaniel Sanders default: 3511d14864bSDaniel Sanders return SubtargetFeatures(); 3521d14864bSDaniel Sanders } 3531d14864bSDaniel Sanders } 3541d14864bSDaniel Sanders 355df7c6ef9SSam Parker // FIXME Encode from a tablegen description or target parser. 356df7c6ef9SSam Parker void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { 357df7c6ef9SSam Parker if (TheTriple.getSubArch() != Triple::NoSubArch) 358df7c6ef9SSam Parker return; 359df7c6ef9SSam Parker 360df7c6ef9SSam Parker ARMAttributeParser Attributes; 361791efb14SFangrui Song if (Error E = getBuildAttributes(Attributes)) { 362791efb14SFangrui Song // TODO Propagate Error. 363791efb14SFangrui Song consumeError(std::move(E)); 364df7c6ef9SSam Parker return; 365791efb14SFangrui Song } 366df7c6ef9SSam Parker 367df7c6ef9SSam Parker std::string Triple; 368df7c6ef9SSam Parker // Default to ARM, but use the triple if it's been set. 369a5ba4ee8SFlorian Hahn if (TheTriple.isThumb()) 370df7c6ef9SSam Parker Triple = "thumb"; 371df7c6ef9SSam Parker else 372df7c6ef9SSam Parker Triple = "arm"; 373df7c6ef9SSam Parker 374*581ba352SKai Wang Optional<unsigned> Attr = 375*581ba352SKai Wang Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch); 376*581ba352SKai Wang if (Attr.hasValue()) { 377*581ba352SKai Wang switch (Attr.getValue()) { 378df7c6ef9SSam Parker case ARMBuildAttrs::v4: 379df7c6ef9SSam Parker Triple += "v4"; 380df7c6ef9SSam Parker break; 381df7c6ef9SSam Parker case ARMBuildAttrs::v4T: 382df7c6ef9SSam Parker Triple += "v4t"; 383df7c6ef9SSam Parker break; 384df7c6ef9SSam Parker case ARMBuildAttrs::v5T: 385df7c6ef9SSam Parker Triple += "v5t"; 386df7c6ef9SSam Parker break; 387df7c6ef9SSam Parker case ARMBuildAttrs::v5TE: 388df7c6ef9SSam Parker Triple += "v5te"; 389df7c6ef9SSam Parker break; 390df7c6ef9SSam Parker case ARMBuildAttrs::v5TEJ: 391df7c6ef9SSam Parker Triple += "v5tej"; 392df7c6ef9SSam Parker break; 393df7c6ef9SSam Parker case ARMBuildAttrs::v6: 394df7c6ef9SSam Parker Triple += "v6"; 395df7c6ef9SSam Parker break; 396df7c6ef9SSam Parker case ARMBuildAttrs::v6KZ: 397df7c6ef9SSam Parker Triple += "v6kz"; 398df7c6ef9SSam Parker break; 399df7c6ef9SSam Parker case ARMBuildAttrs::v6T2: 400df7c6ef9SSam Parker Triple += "v6t2"; 401df7c6ef9SSam Parker break; 402df7c6ef9SSam Parker case ARMBuildAttrs::v6K: 403df7c6ef9SSam Parker Triple += "v6k"; 404df7c6ef9SSam Parker break; 405df7c6ef9SSam Parker case ARMBuildAttrs::v7: 406df7c6ef9SSam Parker Triple += "v7"; 407df7c6ef9SSam Parker break; 408df7c6ef9SSam Parker case ARMBuildAttrs::v6_M: 409df7c6ef9SSam Parker Triple += "v6m"; 410df7c6ef9SSam Parker break; 411df7c6ef9SSam Parker case ARMBuildAttrs::v6S_M: 412df7c6ef9SSam Parker Triple += "v6sm"; 413df7c6ef9SSam Parker break; 414df7c6ef9SSam Parker case ARMBuildAttrs::v7E_M: 415df7c6ef9SSam Parker Triple += "v7em"; 416df7c6ef9SSam Parker break; 417b9d87b95SYi Kong case ARMBuildAttrs::v8_A: 418b9d87b95SYi Kong Triple += "v8a"; 419b9d87b95SYi Kong break; 420b9d87b95SYi Kong case ARMBuildAttrs::v8_R: 421b9d87b95SYi Kong Triple += "v8r"; 422b9d87b95SYi Kong break; 423b9d87b95SYi Kong case ARMBuildAttrs::v8_M_Base: 424b9d87b95SYi Kong Triple += "v8m.base"; 425b9d87b95SYi Kong break; 426b9d87b95SYi Kong case ARMBuildAttrs::v8_M_Main: 427b9d87b95SYi Kong Triple += "v8m.main"; 428b9d87b95SYi Kong break; 429b9d87b95SYi Kong case ARMBuildAttrs::v8_1_M_Main: 430b9d87b95SYi Kong Triple += "v8.1m.main"; 431b9d87b95SYi Kong break; 432df7c6ef9SSam Parker } 433df7c6ef9SSam Parker } 434df7c6ef9SSam Parker if (!isLittleEndian()) 435df7c6ef9SSam Parker Triple += "eb"; 436df7c6ef9SSam Parker 437df7c6ef9SSam Parker TheTriple.setArchName(Triple); 438df7c6ef9SSam Parker } 439d36fb48aSJoel Galenson 440d36fb48aSJoel Galenson std::vector<std::pair<DataRefImpl, uint64_t>> 441d36fb48aSJoel Galenson ELFObjectFileBase::getPltAddresses() const { 442d36fb48aSJoel Galenson std::string Err; 443d36fb48aSJoel Galenson const auto Triple = makeTriple(); 444d36fb48aSJoel Galenson const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err); 445d36fb48aSJoel Galenson if (!T) 446d36fb48aSJoel Galenson return {}; 447d36fb48aSJoel Galenson uint64_t JumpSlotReloc = 0; 448d36fb48aSJoel Galenson switch (Triple.getArch()) { 449d36fb48aSJoel Galenson case Triple::x86: 450d36fb48aSJoel Galenson JumpSlotReloc = ELF::R_386_JUMP_SLOT; 451d36fb48aSJoel Galenson break; 452d36fb48aSJoel Galenson case Triple::x86_64: 453d36fb48aSJoel Galenson JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT; 454d36fb48aSJoel Galenson break; 455d36fb48aSJoel Galenson case Triple::aarch64: 456d36fb48aSJoel Galenson JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT; 457d36fb48aSJoel Galenson break; 458d36fb48aSJoel Galenson default: 459d36fb48aSJoel Galenson return {}; 460d36fb48aSJoel Galenson } 46196cbeffaSVitaly Buka std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo()); 46290f976a4SJoel Galenson std::unique_ptr<const MCInstrAnalysis> MIA( 46396cbeffaSVitaly Buka T->createMCInstrAnalysis(MII.get())); 464d36fb48aSJoel Galenson if (!MIA) 465d36fb48aSJoel Galenson return {}; 466d36fb48aSJoel Galenson Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None; 467d36fb48aSJoel Galenson for (const SectionRef &Section : sections()) { 468bcc00e1aSGeorge Rimar Expected<StringRef> NameOrErr = Section.getName(); 469bcc00e1aSGeorge Rimar if (!NameOrErr) { 470bcc00e1aSGeorge Rimar consumeError(NameOrErr.takeError()); 471d36fb48aSJoel Galenson continue; 472bcc00e1aSGeorge Rimar } 473bcc00e1aSGeorge Rimar StringRef Name = *NameOrErr; 474bcc00e1aSGeorge Rimar 475d36fb48aSJoel Galenson if (Name == ".plt") 476d36fb48aSJoel Galenson Plt = Section; 477d36fb48aSJoel Galenson else if (Name == ".rela.plt" || Name == ".rel.plt") 478d36fb48aSJoel Galenson RelaPlt = Section; 479d36fb48aSJoel Galenson else if (Name == ".got.plt") 480d36fb48aSJoel Galenson GotPlt = Section; 481d36fb48aSJoel Galenson } 482d36fb48aSJoel Galenson if (!Plt || !RelaPlt || !GotPlt) 483d36fb48aSJoel Galenson return {}; 484e183340cSFangrui Song Expected<StringRef> PltContents = Plt->getContents(); 485e183340cSFangrui Song if (!PltContents) { 486e183340cSFangrui Song consumeError(PltContents.takeError()); 487d36fb48aSJoel Galenson return {}; 488e183340cSFangrui Song } 489e183340cSFangrui Song auto PltEntries = MIA->findPltEntries(Plt->getAddress(), 490e183340cSFangrui Song arrayRefFromStringRef(*PltContents), 491d36fb48aSJoel Galenson GotPlt->getAddress(), Triple); 492d36fb48aSJoel Galenson // Build a map from GOT entry virtual address to PLT entry virtual address. 493d36fb48aSJoel Galenson DenseMap<uint64_t, uint64_t> GotToPlt; 494d36fb48aSJoel Galenson for (const auto &Entry : PltEntries) 495d36fb48aSJoel Galenson GotToPlt.insert(std::make_pair(Entry.second, Entry.first)); 496d36fb48aSJoel Galenson // Find the relocations in the dynamic relocation table that point to 497d36fb48aSJoel Galenson // locations in the GOT for which we know the corresponding PLT entry. 498d36fb48aSJoel Galenson std::vector<std::pair<DataRefImpl, uint64_t>> Result; 499d36fb48aSJoel Galenson for (const auto &Relocation : RelaPlt->relocations()) { 500d36fb48aSJoel Galenson if (Relocation.getType() != JumpSlotReloc) 501d36fb48aSJoel Galenson continue; 502d36fb48aSJoel Galenson auto PltEntryIter = GotToPlt.find(Relocation.getOffset()); 503d36fb48aSJoel Galenson if (PltEntryIter != GotToPlt.end()) 504d36fb48aSJoel Galenson Result.push_back(std::make_pair( 505d36fb48aSJoel Galenson Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second)); 506d36fb48aSJoel Galenson } 507d36fb48aSJoel Galenson return Result; 508d36fb48aSJoel Galenson } 509