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" 26d36fb48aSJoel Galenson #include "llvm/Support/TargetRegistry.h" 271df42facSEugene Zelenko #include <algorithm> 281df42facSEugene Zelenko #include <cstddef> 291df42facSEugene Zelenko #include <cstdint> 301df42facSEugene Zelenko #include <memory> 311df42facSEugene Zelenko #include <string> 321df42facSEugene Zelenko #include <system_error> 331df42facSEugene Zelenko #include <utility> 34b60a18deSMichael J. Spencer 351df42facSEugene Zelenko using namespace llvm; 36b60a18deSMichael J. Spencer using namespace object; 37b60a18deSMichael J. Spencer 38ae8fe4e0SSunil Srivastava const EnumEntry<unsigned> llvm::object::ElfSymbolTypes[NumElfSymbolTypes] = { 39ae8fe4e0SSunil Srivastava {"None", "NOTYPE", ELF::STT_NOTYPE}, 40ae8fe4e0SSunil Srivastava {"Object", "OBJECT", ELF::STT_OBJECT}, 41ae8fe4e0SSunil Srivastava {"Function", "FUNC", ELF::STT_FUNC}, 42ae8fe4e0SSunil Srivastava {"Section", "SECTION", ELF::STT_SECTION}, 43ae8fe4e0SSunil Srivastava {"File", "FILE", ELF::STT_FILE}, 44ae8fe4e0SSunil Srivastava {"Common", "COMMON", ELF::STT_COMMON}, 45ae8fe4e0SSunil Srivastava {"TLS", "TLS", ELF::STT_TLS}, 4627f6f2f8SSunil Srivastava {"Unknown", "<unknown>: 7", 7}, 4727f6f2f8SSunil Srivastava {"Unknown", "<unknown>: 8", 8}, 4827f6f2f8SSunil Srivastava {"Unknown", "<unknown>: 9", 9}, 4927f6f2f8SSunil Srivastava {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC}, 5027f6f2f8SSunil Srivastava {"OS Specific", "<OS specific>: 11", 11}, 5127f6f2f8SSunil Srivastava {"OS Specific", "<OS specific>: 12", 12}, 5227f6f2f8SSunil Srivastava {"Proc Specific", "<processor specific>: 13", 13}, 5327f6f2f8SSunil Srivastava {"Proc Specific", "<processor specific>: 14", 14}, 5427f6f2f8SSunil Srivastava {"Proc Specific", "<processor specific>: 15", 15} 5527f6f2f8SSunil Srivastava }; 56ae8fe4e0SSunil Srivastava 5748af1c2aSRafael Espindola ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) 5848af1c2aSRafael Espindola : ObjectFile(Type, Source) {} 59ab73774cSRafael Espindola 60ef421f9cSRafael Espindola template <class ELFT> 61ef421f9cSRafael Espindola static Expected<std::unique_ptr<ELFObjectFile<ELFT>>> 62ef421f9cSRafael Espindola createPtr(MemoryBufferRef Object) { 63ef421f9cSRafael Espindola auto Ret = ELFObjectFile<ELFT>::create(Object); 64ef421f9cSRafael Espindola if (Error E = Ret.takeError()) 65c55cf4afSBill Wendling return std::move(E); 660eaee545SJonas Devlieghere return std::make_unique<ELFObjectFile<ELFT>>(std::move(*Ret)); 67ef421f9cSRafael Espindola } 68ef421f9cSRafael Espindola 6912db383eSRafael Espindola Expected<std::unique_ptr<ObjectFile>> 7048af1c2aSRafael Espindola ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { 71d5a8efe7SRafael Espindola std::pair<unsigned char, unsigned char> Ident = 7248af1c2aSRafael Espindola getElfArchType(Obj.getBuffer()); 73bae14cefSMichael J. Spencer std::size_t MaxAlignment = 7448af1c2aSRafael Espindola 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart())); 75bae14cefSMichael J. Spencer 76ac729b46SRafael Espindola if (MaxAlignment < 2) 7712db383eSRafael Espindola return createError("Insufficient alignment"); 78ac729b46SRafael Espindola 79ac729b46SRafael Espindola if (Ident.first == ELF::ELFCLASS32) { 80ac729b46SRafael Espindola if (Ident.second == ELF::ELFDATA2LSB) 81ef421f9cSRafael Espindola return createPtr<ELF32LE>(Obj); 82ac729b46SRafael Espindola else if (Ident.second == ELF::ELFDATA2MSB) 83ef421f9cSRafael Espindola return createPtr<ELF32BE>(Obj); 84692410efSRafael Espindola else 8512db383eSRafael Espindola return createError("Invalid ELF data"); 8649179ddbSAlexey Samsonov } else if (Ident.first == ELF::ELFCLASS64) { 87ac729b46SRafael Espindola if (Ident.second == ELF::ELFDATA2LSB) 88ef421f9cSRafael Espindola return createPtr<ELF64LE>(Obj); 89ac729b46SRafael Espindola else if (Ident.second == ELF::ELFDATA2MSB) 90ef421f9cSRafael Espindola return createPtr<ELF64BE>(Obj); 91ac729b46SRafael Espindola else 9212db383eSRafael Espindola return createError("Invalid ELF data"); 93ac729b46SRafael Espindola } 94ef421f9cSRafael Espindola return createError("Invalid ELF class"); 95b60a18deSMichael J. Spencer } 96b60a18deSMichael J. Spencer 97b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const { 981d14864bSDaniel Sanders SubtargetFeatures Features; 99d5f76ad3SRafael Espindola unsigned PlatformFlags = getPlatformFlags(); 1001d14864bSDaniel Sanders 1011d14864bSDaniel Sanders switch (PlatformFlags & ELF::EF_MIPS_ARCH) { 1021d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_1: 1031d14864bSDaniel Sanders break; 1041d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_2: 1051d14864bSDaniel Sanders Features.AddFeature("mips2"); 1061d14864bSDaniel Sanders break; 1071d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_3: 1081d14864bSDaniel Sanders Features.AddFeature("mips3"); 1091d14864bSDaniel Sanders break; 1101d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_4: 1111d14864bSDaniel Sanders Features.AddFeature("mips4"); 1121d14864bSDaniel Sanders break; 1131d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_5: 1141d14864bSDaniel Sanders Features.AddFeature("mips5"); 1151d14864bSDaniel Sanders break; 1161d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_32: 1171d14864bSDaniel Sanders Features.AddFeature("mips32"); 1181d14864bSDaniel Sanders break; 1191d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_64: 1201d14864bSDaniel Sanders Features.AddFeature("mips64"); 1211d14864bSDaniel Sanders break; 1221d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_32R2: 1231d14864bSDaniel Sanders Features.AddFeature("mips32r2"); 1241d14864bSDaniel Sanders break; 1251d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_64R2: 1261d14864bSDaniel Sanders Features.AddFeature("mips64r2"); 1271d14864bSDaniel Sanders break; 1281d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_32R6: 1291d14864bSDaniel Sanders Features.AddFeature("mips32r6"); 1301d14864bSDaniel Sanders break; 1311d14864bSDaniel Sanders case ELF::EF_MIPS_ARCH_64R6: 1321d14864bSDaniel Sanders Features.AddFeature("mips64r6"); 1331d14864bSDaniel Sanders break; 1341d14864bSDaniel Sanders default: 1351d14864bSDaniel Sanders llvm_unreachable("Unknown EF_MIPS_ARCH value"); 1361d14864bSDaniel Sanders } 1371d14864bSDaniel Sanders 1381d14864bSDaniel Sanders switch (PlatformFlags & ELF::EF_MIPS_MACH) { 1391d14864bSDaniel Sanders case ELF::EF_MIPS_MACH_NONE: 1401d14864bSDaniel Sanders // No feature associated with this value. 1411d14864bSDaniel Sanders break; 1421d14864bSDaniel Sanders case ELF::EF_MIPS_MACH_OCTEON: 1431d14864bSDaniel Sanders Features.AddFeature("cnmips"); 1441d14864bSDaniel Sanders break; 1451d14864bSDaniel Sanders default: 1461d14864bSDaniel Sanders llvm_unreachable("Unknown EF_MIPS_ARCH value"); 1471d14864bSDaniel Sanders } 1481d14864bSDaniel Sanders 1491d14864bSDaniel Sanders if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16) 1501d14864bSDaniel Sanders Features.AddFeature("mips16"); 1511d14864bSDaniel Sanders if (PlatformFlags & ELF::EF_MIPS_MICROMIPS) 1521d14864bSDaniel Sanders Features.AddFeature("micromips"); 1531d14864bSDaniel Sanders 1541d14864bSDaniel Sanders return Features; 1551d14864bSDaniel Sanders } 156b0de00d5SSam Parker 157b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { 158b0de00d5SSam Parker SubtargetFeatures Features; 159b0de00d5SSam Parker ARMAttributeParser Attributes; 160*791efb14SFangrui Song if (Error E = getBuildAttributes(Attributes)) { 161*791efb14SFangrui Song consumeError(std::move(E)); 162b0de00d5SSam Parker return SubtargetFeatures(); 163*791efb14SFangrui Song } 164b0de00d5SSam Parker 165b0de00d5SSam Parker // both ARMv7-M and R have to support thumb hardware div 166b0de00d5SSam Parker bool isV7 = false; 167b0de00d5SSam Parker if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) 168b0de00d5SSam Parker isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch) 169b0de00d5SSam Parker == ARMBuildAttrs::v7; 170b0de00d5SSam Parker 171b0de00d5SSam Parker if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) { 172b0de00d5SSam Parker switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) { 173b0de00d5SSam Parker case ARMBuildAttrs::ApplicationProfile: 174b0de00d5SSam Parker Features.AddFeature("aclass"); 175b0de00d5SSam Parker break; 176b0de00d5SSam Parker case ARMBuildAttrs::RealTimeProfile: 177b0de00d5SSam Parker Features.AddFeature("rclass"); 178b0de00d5SSam Parker if (isV7) 179b0de00d5SSam Parker Features.AddFeature("hwdiv"); 180b0de00d5SSam Parker break; 181b0de00d5SSam Parker case ARMBuildAttrs::MicroControllerProfile: 182b0de00d5SSam Parker Features.AddFeature("mclass"); 183b0de00d5SSam Parker if (isV7) 184b0de00d5SSam Parker Features.AddFeature("hwdiv"); 185b0de00d5SSam Parker break; 186b0de00d5SSam Parker } 187b0de00d5SSam Parker } 188b0de00d5SSam Parker 189b0de00d5SSam Parker if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) { 190b0de00d5SSam Parker switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) { 191b0de00d5SSam Parker default: 192b0de00d5SSam Parker break; 193b0de00d5SSam Parker case ARMBuildAttrs::Not_Allowed: 194b0de00d5SSam Parker Features.AddFeature("thumb", false); 195b0de00d5SSam Parker Features.AddFeature("thumb2", false); 196b0de00d5SSam Parker break; 197b0de00d5SSam Parker case ARMBuildAttrs::AllowThumb32: 198b0de00d5SSam Parker Features.AddFeature("thumb2"); 199b0de00d5SSam Parker break; 200b0de00d5SSam Parker } 201b0de00d5SSam Parker } 202b0de00d5SSam Parker 203b0de00d5SSam Parker if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) { 204b0de00d5SSam Parker switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) { 205b0de00d5SSam Parker default: 206b0de00d5SSam Parker break; 207b0de00d5SSam Parker case ARMBuildAttrs::Not_Allowed: 208ddf5e86cSEli Friedman Features.AddFeature("vfp2sp", false); 209760df47bSSimon Tatham Features.AddFeature("vfp3d16sp", false); 210760df47bSSimon Tatham Features.AddFeature("vfp4d16sp", false); 211b0de00d5SSam Parker break; 212b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv2: 213b0de00d5SSam Parker Features.AddFeature("vfp2"); 214b0de00d5SSam Parker break; 215b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv3A: 216b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv3B: 217b0de00d5SSam Parker Features.AddFeature("vfp3"); 218b0de00d5SSam Parker break; 219b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv4A: 220b0de00d5SSam Parker case ARMBuildAttrs::AllowFPv4B: 221b0de00d5SSam Parker Features.AddFeature("vfp4"); 222b0de00d5SSam Parker break; 223b0de00d5SSam Parker } 224b0de00d5SSam Parker } 225b0de00d5SSam Parker 226b0de00d5SSam Parker if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) { 227b0de00d5SSam Parker switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) { 228b0de00d5SSam Parker default: 229b0de00d5SSam Parker break; 230b0de00d5SSam Parker case ARMBuildAttrs::Not_Allowed: 231b0de00d5SSam Parker Features.AddFeature("neon", false); 232b0de00d5SSam Parker Features.AddFeature("fp16", false); 233b0de00d5SSam Parker break; 234b0de00d5SSam Parker case ARMBuildAttrs::AllowNeon: 235b0de00d5SSam Parker Features.AddFeature("neon"); 236b0de00d5SSam Parker break; 237b0de00d5SSam Parker case ARMBuildAttrs::AllowNeon2: 238b0de00d5SSam Parker Features.AddFeature("neon"); 239b0de00d5SSam Parker Features.AddFeature("fp16"); 240b0de00d5SSam Parker break; 241b0de00d5SSam Parker } 242b0de00d5SSam Parker } 243b0de00d5SSam Parker 244930dee2cSSjoerd Meijer if (Attributes.hasAttribute(ARMBuildAttrs::MVE_arch)) { 245930dee2cSSjoerd Meijer switch(Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch)) { 246930dee2cSSjoerd Meijer default: 247930dee2cSSjoerd Meijer break; 248930dee2cSSjoerd Meijer case ARMBuildAttrs::Not_Allowed: 249930dee2cSSjoerd Meijer Features.AddFeature("mve", false); 250930dee2cSSjoerd Meijer Features.AddFeature("mve.fp", false); 251930dee2cSSjoerd Meijer break; 252930dee2cSSjoerd Meijer case ARMBuildAttrs::AllowMVEInteger: 253930dee2cSSjoerd Meijer Features.AddFeature("mve.fp", false); 254930dee2cSSjoerd Meijer Features.AddFeature("mve"); 255930dee2cSSjoerd Meijer break; 256930dee2cSSjoerd Meijer case ARMBuildAttrs::AllowMVEIntegerAndFloat: 257930dee2cSSjoerd Meijer Features.AddFeature("mve.fp"); 258930dee2cSSjoerd Meijer break; 259930dee2cSSjoerd Meijer } 260930dee2cSSjoerd Meijer } 261930dee2cSSjoerd Meijer 262b0de00d5SSam Parker if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) { 263b0de00d5SSam Parker switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) { 264b0de00d5SSam Parker default: 265b0de00d5SSam Parker break; 266b0de00d5SSam Parker case ARMBuildAttrs::DisallowDIV: 267b0de00d5SSam Parker Features.AddFeature("hwdiv", false); 268b0de00d5SSam Parker Features.AddFeature("hwdiv-arm", false); 269b0de00d5SSam Parker break; 270b0de00d5SSam Parker case ARMBuildAttrs::AllowDIVExt: 271b0de00d5SSam Parker Features.AddFeature("hwdiv"); 272b0de00d5SSam Parker Features.AddFeature("hwdiv-arm"); 273b0de00d5SSam Parker break; 274b0de00d5SSam Parker } 275b0de00d5SSam Parker } 276b0de00d5SSam Parker 277b0de00d5SSam Parker return Features; 278b0de00d5SSam Parker } 279b0de00d5SSam Parker 28053489adaSShiva Chen SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const { 28153489adaSShiva Chen SubtargetFeatures Features; 28253489adaSShiva Chen unsigned PlatformFlags = getPlatformFlags(); 28353489adaSShiva Chen 28453489adaSShiva Chen if (PlatformFlags & ELF::EF_RISCV_RVC) { 28553489adaSShiva Chen Features.AddFeature("c"); 28653489adaSShiva Chen } 28753489adaSShiva Chen 28853489adaSShiva Chen return Features; 28953489adaSShiva Chen } 29053489adaSShiva Chen 291b0de00d5SSam Parker SubtargetFeatures ELFObjectFileBase::getFeatures() const { 292b0de00d5SSam Parker switch (getEMachine()) { 293b0de00d5SSam Parker case ELF::EM_MIPS: 294b0de00d5SSam Parker return getMIPSFeatures(); 295b0de00d5SSam Parker case ELF::EM_ARM: 296b0de00d5SSam Parker return getARMFeatures(); 29753489adaSShiva Chen case ELF::EM_RISCV: 29853489adaSShiva Chen return getRISCVFeatures(); 2991d14864bSDaniel Sanders default: 3001d14864bSDaniel Sanders return SubtargetFeatures(); 3011d14864bSDaniel Sanders } 3021d14864bSDaniel Sanders } 3031d14864bSDaniel Sanders 304df7c6ef9SSam Parker // FIXME Encode from a tablegen description or target parser. 305df7c6ef9SSam Parker void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { 306df7c6ef9SSam Parker if (TheTriple.getSubArch() != Triple::NoSubArch) 307df7c6ef9SSam Parker return; 308df7c6ef9SSam Parker 309df7c6ef9SSam Parker ARMAttributeParser Attributes; 310*791efb14SFangrui Song if (Error E = getBuildAttributes(Attributes)) { 311*791efb14SFangrui Song // TODO Propagate Error. 312*791efb14SFangrui Song consumeError(std::move(E)); 313df7c6ef9SSam Parker return; 314*791efb14SFangrui Song } 315df7c6ef9SSam Parker 316df7c6ef9SSam Parker std::string Triple; 317df7c6ef9SSam Parker // Default to ARM, but use the triple if it's been set. 318a5ba4ee8SFlorian Hahn if (TheTriple.isThumb()) 319df7c6ef9SSam Parker Triple = "thumb"; 320df7c6ef9SSam Parker else 321df7c6ef9SSam Parker Triple = "arm"; 322df7c6ef9SSam Parker 323df7c6ef9SSam Parker if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) { 324df7c6ef9SSam Parker switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) { 325df7c6ef9SSam Parker case ARMBuildAttrs::v4: 326df7c6ef9SSam Parker Triple += "v4"; 327df7c6ef9SSam Parker break; 328df7c6ef9SSam Parker case ARMBuildAttrs::v4T: 329df7c6ef9SSam Parker Triple += "v4t"; 330df7c6ef9SSam Parker break; 331df7c6ef9SSam Parker case ARMBuildAttrs::v5T: 332df7c6ef9SSam Parker Triple += "v5t"; 333df7c6ef9SSam Parker break; 334df7c6ef9SSam Parker case ARMBuildAttrs::v5TE: 335df7c6ef9SSam Parker Triple += "v5te"; 336df7c6ef9SSam Parker break; 337df7c6ef9SSam Parker case ARMBuildAttrs::v5TEJ: 338df7c6ef9SSam Parker Triple += "v5tej"; 339df7c6ef9SSam Parker break; 340df7c6ef9SSam Parker case ARMBuildAttrs::v6: 341df7c6ef9SSam Parker Triple += "v6"; 342df7c6ef9SSam Parker break; 343df7c6ef9SSam Parker case ARMBuildAttrs::v6KZ: 344df7c6ef9SSam Parker Triple += "v6kz"; 345df7c6ef9SSam Parker break; 346df7c6ef9SSam Parker case ARMBuildAttrs::v6T2: 347df7c6ef9SSam Parker Triple += "v6t2"; 348df7c6ef9SSam Parker break; 349df7c6ef9SSam Parker case ARMBuildAttrs::v6K: 350df7c6ef9SSam Parker Triple += "v6k"; 351df7c6ef9SSam Parker break; 352df7c6ef9SSam Parker case ARMBuildAttrs::v7: 353df7c6ef9SSam Parker Triple += "v7"; 354df7c6ef9SSam Parker break; 355df7c6ef9SSam Parker case ARMBuildAttrs::v6_M: 356df7c6ef9SSam Parker Triple += "v6m"; 357df7c6ef9SSam Parker break; 358df7c6ef9SSam Parker case ARMBuildAttrs::v6S_M: 359df7c6ef9SSam Parker Triple += "v6sm"; 360df7c6ef9SSam Parker break; 361df7c6ef9SSam Parker case ARMBuildAttrs::v7E_M: 362df7c6ef9SSam Parker Triple += "v7em"; 363df7c6ef9SSam Parker break; 364b9d87b95SYi Kong case ARMBuildAttrs::v8_A: 365b9d87b95SYi Kong Triple += "v8a"; 366b9d87b95SYi Kong break; 367b9d87b95SYi Kong case ARMBuildAttrs::v8_R: 368b9d87b95SYi Kong Triple += "v8r"; 369b9d87b95SYi Kong break; 370b9d87b95SYi Kong case ARMBuildAttrs::v8_M_Base: 371b9d87b95SYi Kong Triple += "v8m.base"; 372b9d87b95SYi Kong break; 373b9d87b95SYi Kong case ARMBuildAttrs::v8_M_Main: 374b9d87b95SYi Kong Triple += "v8m.main"; 375b9d87b95SYi Kong break; 376b9d87b95SYi Kong case ARMBuildAttrs::v8_1_M_Main: 377b9d87b95SYi Kong Triple += "v8.1m.main"; 378b9d87b95SYi Kong break; 379df7c6ef9SSam Parker } 380df7c6ef9SSam Parker } 381df7c6ef9SSam Parker if (!isLittleEndian()) 382df7c6ef9SSam Parker Triple += "eb"; 383df7c6ef9SSam Parker 384df7c6ef9SSam Parker TheTriple.setArchName(Triple); 385df7c6ef9SSam Parker } 386d36fb48aSJoel Galenson 387d36fb48aSJoel Galenson std::vector<std::pair<DataRefImpl, uint64_t>> 388d36fb48aSJoel Galenson ELFObjectFileBase::getPltAddresses() const { 389d36fb48aSJoel Galenson std::string Err; 390d36fb48aSJoel Galenson const auto Triple = makeTriple(); 391d36fb48aSJoel Galenson const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err); 392d36fb48aSJoel Galenson if (!T) 393d36fb48aSJoel Galenson return {}; 394d36fb48aSJoel Galenson uint64_t JumpSlotReloc = 0; 395d36fb48aSJoel Galenson switch (Triple.getArch()) { 396d36fb48aSJoel Galenson case Triple::x86: 397d36fb48aSJoel Galenson JumpSlotReloc = ELF::R_386_JUMP_SLOT; 398d36fb48aSJoel Galenson break; 399d36fb48aSJoel Galenson case Triple::x86_64: 400d36fb48aSJoel Galenson JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT; 401d36fb48aSJoel Galenson break; 402d36fb48aSJoel Galenson case Triple::aarch64: 403d36fb48aSJoel Galenson JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT; 404d36fb48aSJoel Galenson break; 405d36fb48aSJoel Galenson default: 406d36fb48aSJoel Galenson return {}; 407d36fb48aSJoel Galenson } 40896cbeffaSVitaly Buka std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo()); 40990f976a4SJoel Galenson std::unique_ptr<const MCInstrAnalysis> MIA( 41096cbeffaSVitaly Buka T->createMCInstrAnalysis(MII.get())); 411d36fb48aSJoel Galenson if (!MIA) 412d36fb48aSJoel Galenson return {}; 413d36fb48aSJoel Galenson Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None; 414d36fb48aSJoel Galenson for (const SectionRef &Section : sections()) { 415bcc00e1aSGeorge Rimar Expected<StringRef> NameOrErr = Section.getName(); 416bcc00e1aSGeorge Rimar if (!NameOrErr) { 417bcc00e1aSGeorge Rimar consumeError(NameOrErr.takeError()); 418d36fb48aSJoel Galenson continue; 419bcc00e1aSGeorge Rimar } 420bcc00e1aSGeorge Rimar StringRef Name = *NameOrErr; 421bcc00e1aSGeorge Rimar 422d36fb48aSJoel Galenson if (Name == ".plt") 423d36fb48aSJoel Galenson Plt = Section; 424d36fb48aSJoel Galenson else if (Name == ".rela.plt" || Name == ".rel.plt") 425d36fb48aSJoel Galenson RelaPlt = Section; 426d36fb48aSJoel Galenson else if (Name == ".got.plt") 427d36fb48aSJoel Galenson GotPlt = Section; 428d36fb48aSJoel Galenson } 429d36fb48aSJoel Galenson if (!Plt || !RelaPlt || !GotPlt) 430d36fb48aSJoel Galenson return {}; 431e183340cSFangrui Song Expected<StringRef> PltContents = Plt->getContents(); 432e183340cSFangrui Song if (!PltContents) { 433e183340cSFangrui Song consumeError(PltContents.takeError()); 434d36fb48aSJoel Galenson return {}; 435e183340cSFangrui Song } 436e183340cSFangrui Song auto PltEntries = MIA->findPltEntries(Plt->getAddress(), 437e183340cSFangrui Song arrayRefFromStringRef(*PltContents), 438d36fb48aSJoel Galenson GotPlt->getAddress(), Triple); 439d36fb48aSJoel Galenson // Build a map from GOT entry virtual address to PLT entry virtual address. 440d36fb48aSJoel Galenson DenseMap<uint64_t, uint64_t> GotToPlt; 441d36fb48aSJoel Galenson for (const auto &Entry : PltEntries) 442d36fb48aSJoel Galenson GotToPlt.insert(std::make_pair(Entry.second, Entry.first)); 443d36fb48aSJoel Galenson // Find the relocations in the dynamic relocation table that point to 444d36fb48aSJoel Galenson // locations in the GOT for which we know the corresponding PLT entry. 445d36fb48aSJoel Galenson std::vector<std::pair<DataRefImpl, uint64_t>> Result; 446d36fb48aSJoel Galenson for (const auto &Relocation : RelaPlt->relocations()) { 447d36fb48aSJoel Galenson if (Relocation.getType() != JumpSlotReloc) 448d36fb48aSJoel Galenson continue; 449d36fb48aSJoel Galenson auto PltEntryIter = GotToPlt.find(Relocation.getOffset()); 450d36fb48aSJoel Galenson if (PltEntryIter != GotToPlt.end()) 451d36fb48aSJoel Galenson Result.push_back(std::make_pair( 452d36fb48aSJoel Galenson Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second)); 453d36fb48aSJoel Galenson } 454d36fb48aSJoel Galenson return Result; 455d36fb48aSJoel Galenson } 456