151690af2SDimitry Andric //===- ELFObjectFile.cpp - ELF object file implementation -----------------===//
22754fe60SDimitry Andric //
32754fe60SDimitry Andric // The LLVM Compiler Infrastructure
42754fe60SDimitry Andric //
52754fe60SDimitry Andric // This file is distributed under the University of Illinois Open Source
62754fe60SDimitry Andric // License. See LICENSE.TXT for details.
72754fe60SDimitry Andric //
82754fe60SDimitry Andric //===----------------------------------------------------------------------===//
92754fe60SDimitry Andric //
10dff0c46cSDimitry Andric // Part of the ELFObjectFile class implementation.
112754fe60SDimitry Andric //
122754fe60SDimitry Andric //===----------------------------------------------------------------------===//
132754fe60SDimitry Andric
14db17bf38SDimitry Andric #include "llvm/Object/ELFObjectFile.h"
1551690af2SDimitry Andric #include "llvm/ADT/Triple.h"
16db17bf38SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
17*b5893f02SDimitry Andric #include "llvm/MC/MCInstrAnalysis.h"
1851690af2SDimitry Andric #include "llvm/MC/SubtargetFeature.h"
1951690af2SDimitry Andric #include "llvm/Object/ELF.h"
2051690af2SDimitry Andric #include "llvm/Object/ELFTypes.h"
2151690af2SDimitry Andric #include "llvm/Object/Error.h"
227a7e6055SDimitry Andric #include "llvm/Support/ARMAttributeParser.h"
23db17bf38SDimitry Andric #include "llvm/Support/ARMBuildAttributes.h"
2451690af2SDimitry Andric #include "llvm/Support/Endian.h"
2551690af2SDimitry Andric #include "llvm/Support/ErrorHandling.h"
26139f7f9bSDimitry Andric #include "llvm/Support/MathExtras.h"
27*b5893f02SDimitry Andric #include "llvm/Support/TargetRegistry.h"
2851690af2SDimitry Andric #include <algorithm>
2951690af2SDimitry Andric #include <cstddef>
3051690af2SDimitry Andric #include <cstdint>
3151690af2SDimitry Andric #include <memory>
3251690af2SDimitry Andric #include <string>
3351690af2SDimitry Andric #include <system_error>
3451690af2SDimitry Andric #include <utility>
352754fe60SDimitry Andric
3651690af2SDimitry Andric using namespace llvm;
372754fe60SDimitry Andric using namespace object;
382754fe60SDimitry Andric
ELFObjectFileBase(unsigned int Type,MemoryBufferRef Source)3939d628a0SDimitry Andric ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
4039d628a0SDimitry Andric : ObjectFile(Type, Source) {}
4139d628a0SDimitry Andric
422cab237bSDimitry Andric template <class ELFT>
432cab237bSDimitry Andric static Expected<std::unique_ptr<ELFObjectFile<ELFT>>>
createPtr(MemoryBufferRef Object)442cab237bSDimitry Andric createPtr(MemoryBufferRef Object) {
452cab237bSDimitry Andric auto Ret = ELFObjectFile<ELFT>::create(Object);
462cab237bSDimitry Andric if (Error E = Ret.takeError())
472cab237bSDimitry Andric return std::move(E);
482cab237bSDimitry Andric return make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
492cab237bSDimitry Andric }
502cab237bSDimitry Andric
512cab237bSDimitry Andric Expected<std::unique_ptr<ObjectFile>>
createELFObjectFile(MemoryBufferRef Obj)5239d628a0SDimitry Andric ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
5391bc56edSDimitry Andric std::pair<unsigned char, unsigned char> Ident =
5439d628a0SDimitry Andric getElfArchType(Obj.getBuffer());
55139f7f9bSDimitry Andric std::size_t MaxAlignment =
5639d628a0SDimitry Andric 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
57139f7f9bSDimitry Andric
5897bc6c73SDimitry Andric if (MaxAlignment < 2)
592cab237bSDimitry Andric return createError("Insufficient alignment");
6097bc6c73SDimitry Andric
6197bc6c73SDimitry Andric if (Ident.first == ELF::ELFCLASS32) {
6297bc6c73SDimitry Andric if (Ident.second == ELF::ELFDATA2LSB)
632cab237bSDimitry Andric return createPtr<ELF32LE>(Obj);
6497bc6c73SDimitry Andric else if (Ident.second == ELF::ELFDATA2MSB)
652cab237bSDimitry Andric return createPtr<ELF32BE>(Obj);
66139f7f9bSDimitry Andric else
672cab237bSDimitry Andric return createError("Invalid ELF data");
6897bc6c73SDimitry Andric } else if (Ident.first == ELF::ELFCLASS64) {
6997bc6c73SDimitry Andric if (Ident.second == ELF::ELFDATA2LSB)
702cab237bSDimitry Andric return createPtr<ELF64LE>(Obj);
7197bc6c73SDimitry Andric else if (Ident.second == ELF::ELFDATA2MSB)
722cab237bSDimitry Andric return createPtr<ELF64BE>(Obj);
73139f7f9bSDimitry Andric else
742cab237bSDimitry Andric return createError("Invalid ELF data");
75dff0c46cSDimitry Andric }
762cab237bSDimitry Andric return createError("Invalid ELF class");
772754fe60SDimitry Andric }
782754fe60SDimitry Andric
getMIPSFeatures() const797a7e6055SDimitry Andric SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
803ca95b02SDimitry Andric SubtargetFeatures Features;
814ba319b5SDimitry Andric unsigned PlatformFlags = getPlatformFlags();
823ca95b02SDimitry Andric
833ca95b02SDimitry Andric switch (PlatformFlags & ELF::EF_MIPS_ARCH) {
843ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_1:
853ca95b02SDimitry Andric break;
863ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_2:
873ca95b02SDimitry Andric Features.AddFeature("mips2");
883ca95b02SDimitry Andric break;
893ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_3:
903ca95b02SDimitry Andric Features.AddFeature("mips3");
913ca95b02SDimitry Andric break;
923ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_4:
933ca95b02SDimitry Andric Features.AddFeature("mips4");
943ca95b02SDimitry Andric break;
953ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_5:
963ca95b02SDimitry Andric Features.AddFeature("mips5");
973ca95b02SDimitry Andric break;
983ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_32:
993ca95b02SDimitry Andric Features.AddFeature("mips32");
1003ca95b02SDimitry Andric break;
1013ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_64:
1023ca95b02SDimitry Andric Features.AddFeature("mips64");
1033ca95b02SDimitry Andric break;
1043ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_32R2:
1053ca95b02SDimitry Andric Features.AddFeature("mips32r2");
1063ca95b02SDimitry Andric break;
1073ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_64R2:
1083ca95b02SDimitry Andric Features.AddFeature("mips64r2");
1093ca95b02SDimitry Andric break;
1103ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_32R6:
1113ca95b02SDimitry Andric Features.AddFeature("mips32r6");
1123ca95b02SDimitry Andric break;
1133ca95b02SDimitry Andric case ELF::EF_MIPS_ARCH_64R6:
1143ca95b02SDimitry Andric Features.AddFeature("mips64r6");
1153ca95b02SDimitry Andric break;
1163ca95b02SDimitry Andric default:
1173ca95b02SDimitry Andric llvm_unreachable("Unknown EF_MIPS_ARCH value");
1183ca95b02SDimitry Andric }
1193ca95b02SDimitry Andric
1203ca95b02SDimitry Andric switch (PlatformFlags & ELF::EF_MIPS_MACH) {
1213ca95b02SDimitry Andric case ELF::EF_MIPS_MACH_NONE:
1223ca95b02SDimitry Andric // No feature associated with this value.
1233ca95b02SDimitry Andric break;
1243ca95b02SDimitry Andric case ELF::EF_MIPS_MACH_OCTEON:
1253ca95b02SDimitry Andric Features.AddFeature("cnmips");
1263ca95b02SDimitry Andric break;
1273ca95b02SDimitry Andric default:
1283ca95b02SDimitry Andric llvm_unreachable("Unknown EF_MIPS_ARCH value");
1293ca95b02SDimitry Andric }
1303ca95b02SDimitry Andric
1313ca95b02SDimitry Andric if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16)
1323ca95b02SDimitry Andric Features.AddFeature("mips16");
1333ca95b02SDimitry Andric if (PlatformFlags & ELF::EF_MIPS_MICROMIPS)
1343ca95b02SDimitry Andric Features.AddFeature("micromips");
1353ca95b02SDimitry Andric
1363ca95b02SDimitry Andric return Features;
1373ca95b02SDimitry Andric }
1387a7e6055SDimitry Andric
getARMFeatures() const1397a7e6055SDimitry Andric SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
1407a7e6055SDimitry Andric SubtargetFeatures Features;
1417a7e6055SDimitry Andric ARMAttributeParser Attributes;
1427a7e6055SDimitry Andric std::error_code EC = getBuildAttributes(Attributes);
1437a7e6055SDimitry Andric if (EC)
1447a7e6055SDimitry Andric return SubtargetFeatures();
1457a7e6055SDimitry Andric
1467a7e6055SDimitry Andric // both ARMv7-M and R have to support thumb hardware div
1477a7e6055SDimitry Andric bool isV7 = false;
1487a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch))
1497a7e6055SDimitry Andric isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)
1507a7e6055SDimitry Andric == ARMBuildAttrs::v7;
1517a7e6055SDimitry Andric
1527a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) {
1537a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) {
1547a7e6055SDimitry Andric case ARMBuildAttrs::ApplicationProfile:
1557a7e6055SDimitry Andric Features.AddFeature("aclass");
1567a7e6055SDimitry Andric break;
1577a7e6055SDimitry Andric case ARMBuildAttrs::RealTimeProfile:
1587a7e6055SDimitry Andric Features.AddFeature("rclass");
1597a7e6055SDimitry Andric if (isV7)
1607a7e6055SDimitry Andric Features.AddFeature("hwdiv");
1617a7e6055SDimitry Andric break;
1627a7e6055SDimitry Andric case ARMBuildAttrs::MicroControllerProfile:
1637a7e6055SDimitry Andric Features.AddFeature("mclass");
1647a7e6055SDimitry Andric if (isV7)
1657a7e6055SDimitry Andric Features.AddFeature("hwdiv");
1667a7e6055SDimitry Andric break;
1677a7e6055SDimitry Andric }
1687a7e6055SDimitry Andric }
1697a7e6055SDimitry Andric
1707a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
1717a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
1727a7e6055SDimitry Andric default:
1737a7e6055SDimitry Andric break;
1747a7e6055SDimitry Andric case ARMBuildAttrs::Not_Allowed:
1757a7e6055SDimitry Andric Features.AddFeature("thumb", false);
1767a7e6055SDimitry Andric Features.AddFeature("thumb2", false);
1777a7e6055SDimitry Andric break;
1787a7e6055SDimitry Andric case ARMBuildAttrs::AllowThumb32:
1797a7e6055SDimitry Andric Features.AddFeature("thumb2");
1807a7e6055SDimitry Andric break;
1817a7e6055SDimitry Andric }
1827a7e6055SDimitry Andric }
1837a7e6055SDimitry Andric
1847a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
1857a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
1867a7e6055SDimitry Andric default:
1877a7e6055SDimitry Andric break;
1887a7e6055SDimitry Andric case ARMBuildAttrs::Not_Allowed:
1897a7e6055SDimitry Andric Features.AddFeature("vfp2", false);
1907a7e6055SDimitry Andric Features.AddFeature("vfp3", false);
1917a7e6055SDimitry Andric Features.AddFeature("vfp4", false);
1927a7e6055SDimitry Andric break;
1937a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv2:
1947a7e6055SDimitry Andric Features.AddFeature("vfp2");
1957a7e6055SDimitry Andric break;
1967a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv3A:
1977a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv3B:
1987a7e6055SDimitry Andric Features.AddFeature("vfp3");
1997a7e6055SDimitry Andric break;
2007a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv4A:
2017a7e6055SDimitry Andric case ARMBuildAttrs::AllowFPv4B:
2027a7e6055SDimitry Andric Features.AddFeature("vfp4");
2037a7e6055SDimitry Andric break;
2047a7e6055SDimitry Andric }
2057a7e6055SDimitry Andric }
2067a7e6055SDimitry Andric
2077a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) {
2087a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) {
2097a7e6055SDimitry Andric default:
2107a7e6055SDimitry Andric break;
2117a7e6055SDimitry Andric case ARMBuildAttrs::Not_Allowed:
2127a7e6055SDimitry Andric Features.AddFeature("neon", false);
2137a7e6055SDimitry Andric Features.AddFeature("fp16", false);
2147a7e6055SDimitry Andric break;
2157a7e6055SDimitry Andric case ARMBuildAttrs::AllowNeon:
2167a7e6055SDimitry Andric Features.AddFeature("neon");
2177a7e6055SDimitry Andric break;
2187a7e6055SDimitry Andric case ARMBuildAttrs::AllowNeon2:
2197a7e6055SDimitry Andric Features.AddFeature("neon");
2207a7e6055SDimitry Andric Features.AddFeature("fp16");
2217a7e6055SDimitry Andric break;
2227a7e6055SDimitry Andric }
2237a7e6055SDimitry Andric }
2247a7e6055SDimitry Andric
2257a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
2267a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
2277a7e6055SDimitry Andric default:
2287a7e6055SDimitry Andric break;
2297a7e6055SDimitry Andric case ARMBuildAttrs::DisallowDIV:
2307a7e6055SDimitry Andric Features.AddFeature("hwdiv", false);
2317a7e6055SDimitry Andric Features.AddFeature("hwdiv-arm", false);
2327a7e6055SDimitry Andric break;
2337a7e6055SDimitry Andric case ARMBuildAttrs::AllowDIVExt:
2347a7e6055SDimitry Andric Features.AddFeature("hwdiv");
2357a7e6055SDimitry Andric Features.AddFeature("hwdiv-arm");
2367a7e6055SDimitry Andric break;
2377a7e6055SDimitry Andric }
2387a7e6055SDimitry Andric }
2397a7e6055SDimitry Andric
2407a7e6055SDimitry Andric return Features;
2417a7e6055SDimitry Andric }
2427a7e6055SDimitry Andric
getRISCVFeatures() const2434ba319b5SDimitry Andric SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const {
2444ba319b5SDimitry Andric SubtargetFeatures Features;
2454ba319b5SDimitry Andric unsigned PlatformFlags = getPlatformFlags();
2464ba319b5SDimitry Andric
2474ba319b5SDimitry Andric if (PlatformFlags & ELF::EF_RISCV_RVC) {
2484ba319b5SDimitry Andric Features.AddFeature("c");
2494ba319b5SDimitry Andric }
2504ba319b5SDimitry Andric
2514ba319b5SDimitry Andric return Features;
2524ba319b5SDimitry Andric }
2534ba319b5SDimitry Andric
getFeatures() const2547a7e6055SDimitry Andric SubtargetFeatures ELFObjectFileBase::getFeatures() const {
2557a7e6055SDimitry Andric switch (getEMachine()) {
2567a7e6055SDimitry Andric case ELF::EM_MIPS:
2577a7e6055SDimitry Andric return getMIPSFeatures();
2587a7e6055SDimitry Andric case ELF::EM_ARM:
2597a7e6055SDimitry Andric return getARMFeatures();
2604ba319b5SDimitry Andric case ELF::EM_RISCV:
2614ba319b5SDimitry Andric return getRISCVFeatures();
2623ca95b02SDimitry Andric default:
2633ca95b02SDimitry Andric return SubtargetFeatures();
2643ca95b02SDimitry Andric }
2653ca95b02SDimitry Andric }
2663ca95b02SDimitry Andric
2677a7e6055SDimitry Andric // FIXME Encode from a tablegen description or target parser.
setARMSubArch(Triple & TheTriple) const2687a7e6055SDimitry Andric void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
2697a7e6055SDimitry Andric if (TheTriple.getSubArch() != Triple::NoSubArch)
2707a7e6055SDimitry Andric return;
2717a7e6055SDimitry Andric
2727a7e6055SDimitry Andric ARMAttributeParser Attributes;
2737a7e6055SDimitry Andric std::error_code EC = getBuildAttributes(Attributes);
2747a7e6055SDimitry Andric if (EC)
2757a7e6055SDimitry Andric return;
2767a7e6055SDimitry Andric
2777a7e6055SDimitry Andric std::string Triple;
2787a7e6055SDimitry Andric // Default to ARM, but use the triple if it's been set.
2792cab237bSDimitry Andric if (TheTriple.isThumb())
2807a7e6055SDimitry Andric Triple = "thumb";
2817a7e6055SDimitry Andric else
2827a7e6055SDimitry Andric Triple = "arm";
2837a7e6055SDimitry Andric
2847a7e6055SDimitry Andric if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
2857a7e6055SDimitry Andric switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
2867a7e6055SDimitry Andric case ARMBuildAttrs::v4:
2877a7e6055SDimitry Andric Triple += "v4";
2887a7e6055SDimitry Andric break;
2897a7e6055SDimitry Andric case ARMBuildAttrs::v4T:
2907a7e6055SDimitry Andric Triple += "v4t";
2917a7e6055SDimitry Andric break;
2927a7e6055SDimitry Andric case ARMBuildAttrs::v5T:
2937a7e6055SDimitry Andric Triple += "v5t";
2947a7e6055SDimitry Andric break;
2957a7e6055SDimitry Andric case ARMBuildAttrs::v5TE:
2967a7e6055SDimitry Andric Triple += "v5te";
2977a7e6055SDimitry Andric break;
2987a7e6055SDimitry Andric case ARMBuildAttrs::v5TEJ:
2997a7e6055SDimitry Andric Triple += "v5tej";
3007a7e6055SDimitry Andric break;
3017a7e6055SDimitry Andric case ARMBuildAttrs::v6:
3027a7e6055SDimitry Andric Triple += "v6";
3037a7e6055SDimitry Andric break;
3047a7e6055SDimitry Andric case ARMBuildAttrs::v6KZ:
3057a7e6055SDimitry Andric Triple += "v6kz";
3067a7e6055SDimitry Andric break;
3077a7e6055SDimitry Andric case ARMBuildAttrs::v6T2:
3087a7e6055SDimitry Andric Triple += "v6t2";
3097a7e6055SDimitry Andric break;
3107a7e6055SDimitry Andric case ARMBuildAttrs::v6K:
3117a7e6055SDimitry Andric Triple += "v6k";
3127a7e6055SDimitry Andric break;
3137a7e6055SDimitry Andric case ARMBuildAttrs::v7:
3147a7e6055SDimitry Andric Triple += "v7";
3157a7e6055SDimitry Andric break;
3167a7e6055SDimitry Andric case ARMBuildAttrs::v6_M:
3177a7e6055SDimitry Andric Triple += "v6m";
3187a7e6055SDimitry Andric break;
3197a7e6055SDimitry Andric case ARMBuildAttrs::v6S_M:
3207a7e6055SDimitry Andric Triple += "v6sm";
3217a7e6055SDimitry Andric break;
3227a7e6055SDimitry Andric case ARMBuildAttrs::v7E_M:
3237a7e6055SDimitry Andric Triple += "v7em";
3247a7e6055SDimitry Andric break;
3257a7e6055SDimitry Andric }
3267a7e6055SDimitry Andric }
3277a7e6055SDimitry Andric if (!isLittleEndian())
3287a7e6055SDimitry Andric Triple += "eb";
3297a7e6055SDimitry Andric
3307a7e6055SDimitry Andric TheTriple.setArchName(Triple);
3317a7e6055SDimitry Andric }
332*b5893f02SDimitry Andric
333*b5893f02SDimitry Andric std::vector<std::pair<DataRefImpl, uint64_t>>
getPltAddresses() const334*b5893f02SDimitry Andric ELFObjectFileBase::getPltAddresses() const {
335*b5893f02SDimitry Andric std::string Err;
336*b5893f02SDimitry Andric const auto Triple = makeTriple();
337*b5893f02SDimitry Andric const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err);
338*b5893f02SDimitry Andric if (!T)
339*b5893f02SDimitry Andric return {};
340*b5893f02SDimitry Andric uint64_t JumpSlotReloc = 0;
341*b5893f02SDimitry Andric switch (Triple.getArch()) {
342*b5893f02SDimitry Andric case Triple::x86:
343*b5893f02SDimitry Andric JumpSlotReloc = ELF::R_386_JUMP_SLOT;
344*b5893f02SDimitry Andric break;
345*b5893f02SDimitry Andric case Triple::x86_64:
346*b5893f02SDimitry Andric JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT;
347*b5893f02SDimitry Andric break;
348*b5893f02SDimitry Andric case Triple::aarch64:
349*b5893f02SDimitry Andric JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT;
350*b5893f02SDimitry Andric break;
351*b5893f02SDimitry Andric default:
352*b5893f02SDimitry Andric return {};
353*b5893f02SDimitry Andric }
354*b5893f02SDimitry Andric std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
355*b5893f02SDimitry Andric std::unique_ptr<const MCInstrAnalysis> MIA(
356*b5893f02SDimitry Andric T->createMCInstrAnalysis(MII.get()));
357*b5893f02SDimitry Andric if (!MIA)
358*b5893f02SDimitry Andric return {};
359*b5893f02SDimitry Andric Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
360*b5893f02SDimitry Andric for (const SectionRef &Section : sections()) {
361*b5893f02SDimitry Andric StringRef Name;
362*b5893f02SDimitry Andric if (Section.getName(Name))
363*b5893f02SDimitry Andric continue;
364*b5893f02SDimitry Andric if (Name == ".plt")
365*b5893f02SDimitry Andric Plt = Section;
366*b5893f02SDimitry Andric else if (Name == ".rela.plt" || Name == ".rel.plt")
367*b5893f02SDimitry Andric RelaPlt = Section;
368*b5893f02SDimitry Andric else if (Name == ".got.plt")
369*b5893f02SDimitry Andric GotPlt = Section;
370*b5893f02SDimitry Andric }
371*b5893f02SDimitry Andric if (!Plt || !RelaPlt || !GotPlt)
372*b5893f02SDimitry Andric return {};
373*b5893f02SDimitry Andric StringRef PltContents;
374*b5893f02SDimitry Andric if (Plt->getContents(PltContents))
375*b5893f02SDimitry Andric return {};
376*b5893f02SDimitry Andric ArrayRef<uint8_t> PltBytes((const uint8_t *)PltContents.data(),
377*b5893f02SDimitry Andric Plt->getSize());
378*b5893f02SDimitry Andric auto PltEntries = MIA->findPltEntries(Plt->getAddress(), PltBytes,
379*b5893f02SDimitry Andric GotPlt->getAddress(), Triple);
380*b5893f02SDimitry Andric // Build a map from GOT entry virtual address to PLT entry virtual address.
381*b5893f02SDimitry Andric DenseMap<uint64_t, uint64_t> GotToPlt;
382*b5893f02SDimitry Andric for (const auto &Entry : PltEntries)
383*b5893f02SDimitry Andric GotToPlt.insert(std::make_pair(Entry.second, Entry.first));
384*b5893f02SDimitry Andric // Find the relocations in the dynamic relocation table that point to
385*b5893f02SDimitry Andric // locations in the GOT for which we know the corresponding PLT entry.
386*b5893f02SDimitry Andric std::vector<std::pair<DataRefImpl, uint64_t>> Result;
387*b5893f02SDimitry Andric for (const auto &Relocation : RelaPlt->relocations()) {
388*b5893f02SDimitry Andric if (Relocation.getType() != JumpSlotReloc)
389*b5893f02SDimitry Andric continue;
390*b5893f02SDimitry Andric auto PltEntryIter = GotToPlt.find(Relocation.getOffset());
391*b5893f02SDimitry Andric if (PltEntryIter != GotToPlt.end())
392*b5893f02SDimitry Andric Result.push_back(std::make_pair(
393*b5893f02SDimitry Andric Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second));
394*b5893f02SDimitry Andric }
395*b5893f02SDimitry Andric return Result;
396*b5893f02SDimitry Andric }
397