xref: /freebsd/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp (revision aa7208254996a66fb0b363bb696fe65d81335d81)
1  //===- ELFObjectFile.cpp - ELF object file implementation -----------------===//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  // Part of the ELFObjectFile class implementation.
10  //
11  //===----------------------------------------------------------------------===//
12  
13  #include "llvm/Object/ELFObjectFile.h"
14  #include "llvm/ADT/Triple.h"
15  #include "llvm/BinaryFormat/ELF.h"
16  #include "llvm/MC/MCInstrAnalysis.h"
17  #include "llvm/MC/SubtargetFeature.h"
18  #include "llvm/Object/ELF.h"
19  #include "llvm/Object/ELFTypes.h"
20  #include "llvm/Object/Error.h"
21  #include "llvm/Support/ARMAttributeParser.h"
22  #include "llvm/Support/ARMBuildAttributes.h"
23  #include "llvm/Support/Endian.h"
24  #include "llvm/Support/ErrorHandling.h"
25  #include "llvm/Support/MathExtras.h"
26  #include "llvm/Support/RISCVAttributeParser.h"
27  #include "llvm/Support/RISCVAttributes.h"
28  #include "llvm/Support/TargetRegistry.h"
29  #include <algorithm>
30  #include <cstddef>
31  #include <cstdint>
32  #include <memory>
33  #include <string>
34  #include <system_error>
35  #include <utility>
36  
37  using namespace llvm;
38  using namespace object;
39  
40  const EnumEntry<unsigned> llvm::object::ElfSymbolTypes[NumElfSymbolTypes] = {
41      {"None", "NOTYPE", ELF::STT_NOTYPE},
42      {"Object", "OBJECT", ELF::STT_OBJECT},
43      {"Function", "FUNC", ELF::STT_FUNC},
44      {"Section", "SECTION", ELF::STT_SECTION},
45      {"File", "FILE", ELF::STT_FILE},
46      {"Common", "COMMON", ELF::STT_COMMON},
47      {"TLS", "TLS", ELF::STT_TLS},
48      {"Unknown", "<unknown>: 7", 7},
49      {"Unknown", "<unknown>: 8", 8},
50      {"Unknown", "<unknown>: 9", 9},
51      {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC},
52      {"OS Specific", "<OS specific>: 11", 11},
53      {"OS Specific", "<OS specific>: 12", 12},
54      {"Proc Specific", "<processor specific>: 13", 13},
55      {"Proc Specific", "<processor specific>: 14", 14},
56      {"Proc Specific", "<processor specific>: 15", 15}
57  };
58  
59  ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
60      : ObjectFile(Type, Source) {}
61  
62  template <class ELFT>
63  static Expected<std::unique_ptr<ELFObjectFile<ELFT>>>
64  createPtr(MemoryBufferRef Object, bool InitContent) {
65    auto Ret = ELFObjectFile<ELFT>::create(Object, InitContent);
66    if (Error E = Ret.takeError())
67      return std::move(E);
68    return std::make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
69  }
70  
71  Expected<std::unique_ptr<ObjectFile>>
72  ObjectFile::createELFObjectFile(MemoryBufferRef Obj, bool InitContent) {
73    std::pair<unsigned char, unsigned char> Ident =
74        getElfArchType(Obj.getBuffer());
75    std::size_t MaxAlignment =
76        1ULL << countTrailingZeros(
77            reinterpret_cast<uintptr_t>(Obj.getBufferStart()));
78  
79    if (MaxAlignment < 2)
80      return createError("Insufficient alignment");
81  
82    if (Ident.first == ELF::ELFCLASS32) {
83      if (Ident.second == ELF::ELFDATA2LSB)
84        return createPtr<ELF32LE>(Obj, InitContent);
85      else if (Ident.second == ELF::ELFDATA2MSB)
86        return createPtr<ELF32BE>(Obj, InitContent);
87      else
88        return createError("Invalid ELF data");
89    } else if (Ident.first == ELF::ELFCLASS64) {
90      if (Ident.second == ELF::ELFDATA2LSB)
91        return createPtr<ELF64LE>(Obj, InitContent);
92      else if (Ident.second == ELF::ELFDATA2MSB)
93        return createPtr<ELF64BE>(Obj, InitContent);
94      else
95        return createError("Invalid ELF data");
96    }
97    return createError("Invalid ELF class");
98  }
99  
100  SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
101    SubtargetFeatures Features;
102    unsigned PlatformFlags = getPlatformFlags();
103  
104    switch (PlatformFlags & ELF::EF_MIPS_ARCH) {
105    case ELF::EF_MIPS_ARCH_1:
106      break;
107    case ELF::EF_MIPS_ARCH_2:
108      Features.AddFeature("mips2");
109      break;
110    case ELF::EF_MIPS_ARCH_3:
111      Features.AddFeature("mips3");
112      break;
113    case ELF::EF_MIPS_ARCH_4:
114      Features.AddFeature("mips4");
115      break;
116    case ELF::EF_MIPS_ARCH_5:
117      Features.AddFeature("mips5");
118      break;
119    case ELF::EF_MIPS_ARCH_32:
120      Features.AddFeature("mips32");
121      break;
122    case ELF::EF_MIPS_ARCH_64:
123      Features.AddFeature("mips64");
124      break;
125    case ELF::EF_MIPS_ARCH_32R2:
126      Features.AddFeature("mips32r2");
127      break;
128    case ELF::EF_MIPS_ARCH_64R2:
129      Features.AddFeature("mips64r2");
130      break;
131    case ELF::EF_MIPS_ARCH_32R6:
132      Features.AddFeature("mips32r6");
133      break;
134    case ELF::EF_MIPS_ARCH_64R6:
135      Features.AddFeature("mips64r6");
136      break;
137    default:
138      llvm_unreachable("Unknown EF_MIPS_ARCH value");
139    }
140  
141    switch (PlatformFlags & ELF::EF_MIPS_MACH) {
142    case ELF::EF_MIPS_MACH_NONE:
143      // No feature associated with this value.
144      break;
145    case ELF::EF_MIPS_MACH_OCTEON:
146      Features.AddFeature("cnmips");
147      break;
148    default:
149      llvm_unreachable("Unknown EF_MIPS_ARCH value");
150    }
151  
152    if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16)
153      Features.AddFeature("mips16");
154    if (PlatformFlags & ELF::EF_MIPS_MICROMIPS)
155      Features.AddFeature("micromips");
156  
157    return Features;
158  }
159  
160  SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
161    SubtargetFeatures Features;
162    ARMAttributeParser Attributes;
163    if (Error E = getBuildAttributes(Attributes)) {
164      consumeError(std::move(E));
165      return SubtargetFeatures();
166    }
167  
168    // both ARMv7-M and R have to support thumb hardware div
169    bool isV7 = false;
170    Optional<unsigned> Attr =
171        Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch);
172    if (Attr.hasValue())
173      isV7 = Attr.getValue() == ARMBuildAttrs::v7;
174  
175    Attr = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile);
176    if (Attr.hasValue()) {
177      switch (Attr.getValue()) {
178      case ARMBuildAttrs::ApplicationProfile:
179        Features.AddFeature("aclass");
180        break;
181      case ARMBuildAttrs::RealTimeProfile:
182        Features.AddFeature("rclass");
183        if (isV7)
184          Features.AddFeature("hwdiv");
185        break;
186      case ARMBuildAttrs::MicroControllerProfile:
187        Features.AddFeature("mclass");
188        if (isV7)
189          Features.AddFeature("hwdiv");
190        break;
191      }
192    }
193  
194    Attr = Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use);
195    if (Attr.hasValue()) {
196      switch (Attr.getValue()) {
197      default:
198        break;
199      case ARMBuildAttrs::Not_Allowed:
200        Features.AddFeature("thumb", false);
201        Features.AddFeature("thumb2", false);
202        break;
203      case ARMBuildAttrs::AllowThumb32:
204        Features.AddFeature("thumb2");
205        break;
206      }
207    }
208  
209    Attr = Attributes.getAttributeValue(ARMBuildAttrs::FP_arch);
210    if (Attr.hasValue()) {
211      switch (Attr.getValue()) {
212      default:
213        break;
214      case ARMBuildAttrs::Not_Allowed:
215        Features.AddFeature("vfp2sp", false);
216        Features.AddFeature("vfp3d16sp", false);
217        Features.AddFeature("vfp4d16sp", false);
218        break;
219      case ARMBuildAttrs::AllowFPv2:
220        Features.AddFeature("vfp2");
221        break;
222      case ARMBuildAttrs::AllowFPv3A:
223      case ARMBuildAttrs::AllowFPv3B:
224        Features.AddFeature("vfp3");
225        break;
226      case ARMBuildAttrs::AllowFPv4A:
227      case ARMBuildAttrs::AllowFPv4B:
228        Features.AddFeature("vfp4");
229        break;
230      }
231    }
232  
233    Attr = Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch);
234    if (Attr.hasValue()) {
235      switch (Attr.getValue()) {
236      default:
237        break;
238      case ARMBuildAttrs::Not_Allowed:
239        Features.AddFeature("neon", false);
240        Features.AddFeature("fp16", false);
241        break;
242      case ARMBuildAttrs::AllowNeon:
243        Features.AddFeature("neon");
244        break;
245      case ARMBuildAttrs::AllowNeon2:
246        Features.AddFeature("neon");
247        Features.AddFeature("fp16");
248        break;
249      }
250    }
251  
252    Attr = Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch);
253    if (Attr.hasValue()) {
254      switch (Attr.getValue()) {
255      default:
256        break;
257      case ARMBuildAttrs::Not_Allowed:
258        Features.AddFeature("mve", false);
259        Features.AddFeature("mve.fp", false);
260        break;
261      case ARMBuildAttrs::AllowMVEInteger:
262        Features.AddFeature("mve.fp", false);
263        Features.AddFeature("mve");
264        break;
265      case ARMBuildAttrs::AllowMVEIntegerAndFloat:
266        Features.AddFeature("mve.fp");
267        break;
268      }
269    }
270  
271    Attr = Attributes.getAttributeValue(ARMBuildAttrs::DIV_use);
272    if (Attr.hasValue()) {
273      switch (Attr.getValue()) {
274      default:
275        break;
276      case ARMBuildAttrs::DisallowDIV:
277        Features.AddFeature("hwdiv", false);
278        Features.AddFeature("hwdiv-arm", false);
279        break;
280      case ARMBuildAttrs::AllowDIVExt:
281        Features.AddFeature("hwdiv");
282        Features.AddFeature("hwdiv-arm");
283        break;
284      }
285    }
286  
287    return Features;
288  }
289  
290  SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const {
291    SubtargetFeatures Features;
292    unsigned PlatformFlags = getPlatformFlags();
293  
294    if (PlatformFlags & ELF::EF_RISCV_RVC) {
295      Features.AddFeature("c");
296    }
297  
298    // Add features according to the ELF attribute section.
299    // If there are any unrecognized features, ignore them.
300    RISCVAttributeParser Attributes;
301    if (Error E = getBuildAttributes(Attributes)) {
302      // TODO Propagate Error.
303      consumeError(std::move(E));
304      return Features; // Keep "c" feature if there is one in PlatformFlags.
305    }
306  
307    Optional<StringRef> Attr = Attributes.getAttributeString(RISCVAttrs::ARCH);
308    if (Attr.hasValue()) {
309      // The Arch pattern is [rv32|rv64][i|e]version(_[m|a|f|d|c]version)*
310      // Version string pattern is (major)p(minor). Major and minor are optional.
311      // For example, a version number could be 2p0, 2, or p92.
312      StringRef Arch = Attr.getValue();
313      if (Arch.consume_front("rv32"))
314        Features.AddFeature("64bit", false);
315      else if (Arch.consume_front("rv64"))
316        Features.AddFeature("64bit");
317  
318      while (!Arch.empty()) {
319        switch (Arch[0]) {
320        default:
321          break; // Ignore unexpected features.
322        case 'i':
323          Features.AddFeature("e", false);
324          break;
325        case 'd':
326          Features.AddFeature("f"); // D-ext will imply F-ext.
327          LLVM_FALLTHROUGH;
328        case 'e':
329        case 'm':
330        case 'a':
331        case 'f':
332        case 'c':
333          Features.AddFeature(Arch.take_front());
334          break;
335        }
336  
337        // FIXME: Handle version numbers.
338        Arch = Arch.drop_until([](char c) { return c == '_' || c == '\0'; });
339        Arch = Arch.drop_while([](char c) { return c == '_'; });
340      }
341    }
342  
343    return Features;
344  }
345  
346  SubtargetFeatures ELFObjectFileBase::getFeatures() const {
347    switch (getEMachine()) {
348    case ELF::EM_MIPS:
349      return getMIPSFeatures();
350    case ELF::EM_ARM:
351      return getARMFeatures();
352    case ELF::EM_RISCV:
353      return getRISCVFeatures();
354    default:
355      return SubtargetFeatures();
356    }
357  }
358  
359  Optional<StringRef> ELFObjectFileBase::tryGetCPUName() const {
360    switch (getEMachine()) {
361    case ELF::EM_AMDGPU:
362      return getAMDGPUCPUName();
363    default:
364      return None;
365    }
366  }
367  
368  StringRef ELFObjectFileBase::getAMDGPUCPUName() const {
369    assert(getEMachine() == ELF::EM_AMDGPU);
370    unsigned CPU = getPlatformFlags() & ELF::EF_AMDGPU_MACH;
371  
372    switch (CPU) {
373    // Radeon HD 2000/3000 Series (R600).
374    case ELF::EF_AMDGPU_MACH_R600_R600:
375      return "r600";
376    case ELF::EF_AMDGPU_MACH_R600_R630:
377      return "r630";
378    case ELF::EF_AMDGPU_MACH_R600_RS880:
379      return "rs880";
380    case ELF::EF_AMDGPU_MACH_R600_RV670:
381      return "rv670";
382  
383    // Radeon HD 4000 Series (R700).
384    case ELF::EF_AMDGPU_MACH_R600_RV710:
385      return "rv710";
386    case ELF::EF_AMDGPU_MACH_R600_RV730:
387      return "rv730";
388    case ELF::EF_AMDGPU_MACH_R600_RV770:
389      return "rv770";
390  
391    // Radeon HD 5000 Series (Evergreen).
392    case ELF::EF_AMDGPU_MACH_R600_CEDAR:
393      return "cedar";
394    case ELF::EF_AMDGPU_MACH_R600_CYPRESS:
395      return "cypress";
396    case ELF::EF_AMDGPU_MACH_R600_JUNIPER:
397      return "juniper";
398    case ELF::EF_AMDGPU_MACH_R600_REDWOOD:
399      return "redwood";
400    case ELF::EF_AMDGPU_MACH_R600_SUMO:
401      return "sumo";
402  
403    // Radeon HD 6000 Series (Northern Islands).
404    case ELF::EF_AMDGPU_MACH_R600_BARTS:
405      return "barts";
406    case ELF::EF_AMDGPU_MACH_R600_CAICOS:
407      return "caicos";
408    case ELF::EF_AMDGPU_MACH_R600_CAYMAN:
409      return "cayman";
410    case ELF::EF_AMDGPU_MACH_R600_TURKS:
411      return "turks";
412  
413    // AMDGCN GFX6.
414    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX600:
415      return "gfx600";
416    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX601:
417      return "gfx601";
418    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX602:
419      return "gfx602";
420  
421    // AMDGCN GFX7.
422    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX700:
423      return "gfx700";
424    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX701:
425      return "gfx701";
426    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX702:
427      return "gfx702";
428    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX703:
429      return "gfx703";
430    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX704:
431      return "gfx704";
432    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX705:
433      return "gfx705";
434  
435    // AMDGCN GFX8.
436    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX801:
437      return "gfx801";
438    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX802:
439      return "gfx802";
440    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX803:
441      return "gfx803";
442    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX805:
443      return "gfx805";
444    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX810:
445      return "gfx810";
446  
447    // AMDGCN GFX9.
448    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX900:
449      return "gfx900";
450    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX902:
451      return "gfx902";
452    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX904:
453      return "gfx904";
454    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX906:
455      return "gfx906";
456    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX908:
457      return "gfx908";
458    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX909:
459      return "gfx909";
460    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX90A:
461      return "gfx90a";
462    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX90C:
463      return "gfx90c";
464  
465    // AMDGCN GFX10.
466    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1010:
467      return "gfx1010";
468    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1011:
469      return "gfx1011";
470    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1012:
471      return "gfx1012";
472    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1013:
473      return "gfx1013";
474    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1030:
475      return "gfx1030";
476    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1031:
477      return "gfx1031";
478    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1032:
479      return "gfx1032";
480    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1033:
481      return "gfx1033";
482    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1034:
483      return "gfx1034";
484    case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1035:
485      return "gfx1035";
486    default:
487      llvm_unreachable("Unknown EF_AMDGPU_MACH value");
488    }
489  }
490  
491  // FIXME Encode from a tablegen description or target parser.
492  void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
493    if (TheTriple.getSubArch() != Triple::NoSubArch)
494      return;
495  
496    ARMAttributeParser Attributes;
497    if (Error E = getBuildAttributes(Attributes)) {
498      // TODO Propagate Error.
499      consumeError(std::move(E));
500      return;
501    }
502  
503    std::string Triple;
504    // Default to ARM, but use the triple if it's been set.
505    if (TheTriple.isThumb())
506      Triple = "thumb";
507    else
508      Triple = "arm";
509  
510    Optional<unsigned> Attr =
511        Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch);
512    if (Attr.hasValue()) {
513      switch (Attr.getValue()) {
514      case ARMBuildAttrs::v4:
515        Triple += "v4";
516        break;
517      case ARMBuildAttrs::v4T:
518        Triple += "v4t";
519        break;
520      case ARMBuildAttrs::v5T:
521        Triple += "v5t";
522        break;
523      case ARMBuildAttrs::v5TE:
524        Triple += "v5te";
525        break;
526      case ARMBuildAttrs::v5TEJ:
527        Triple += "v5tej";
528        break;
529      case ARMBuildAttrs::v6:
530        Triple += "v6";
531        break;
532      case ARMBuildAttrs::v6KZ:
533        Triple += "v6kz";
534        break;
535      case ARMBuildAttrs::v6T2:
536        Triple += "v6t2";
537        break;
538      case ARMBuildAttrs::v6K:
539        Triple += "v6k";
540        break;
541      case ARMBuildAttrs::v7:
542        Triple += "v7";
543        break;
544      case ARMBuildAttrs::v6_M:
545        Triple += "v6m";
546        break;
547      case ARMBuildAttrs::v6S_M:
548        Triple += "v6sm";
549        break;
550      case ARMBuildAttrs::v7E_M:
551        Triple += "v7em";
552        break;
553      case ARMBuildAttrs::v8_A:
554        Triple += "v8a";
555        break;
556      case ARMBuildAttrs::v8_R:
557        Triple += "v8r";
558        break;
559      case ARMBuildAttrs::v8_M_Base:
560        Triple += "v8m.base";
561        break;
562      case ARMBuildAttrs::v8_M_Main:
563        Triple += "v8m.main";
564        break;
565      case ARMBuildAttrs::v8_1_M_Main:
566        Triple += "v8.1m.main";
567        break;
568      }
569    }
570    if (!isLittleEndian())
571      Triple += "eb";
572  
573    TheTriple.setArchName(Triple);
574  }
575  
576  std::vector<std::pair<Optional<DataRefImpl>, uint64_t>>
577  ELFObjectFileBase::getPltAddresses() const {
578    std::string Err;
579    const auto Triple = makeTriple();
580    const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err);
581    if (!T)
582      return {};
583    uint64_t JumpSlotReloc = 0;
584    switch (Triple.getArch()) {
585      case Triple::x86:
586        JumpSlotReloc = ELF::R_386_JUMP_SLOT;
587        break;
588      case Triple::x86_64:
589        JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT;
590        break;
591      case Triple::aarch64:
592      case Triple::aarch64_be:
593        JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT;
594        break;
595      default:
596        return {};
597    }
598    std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
599    std::unique_ptr<const MCInstrAnalysis> MIA(
600        T->createMCInstrAnalysis(MII.get()));
601    if (!MIA)
602      return {};
603    Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
604    for (const SectionRef &Section : sections()) {
605      Expected<StringRef> NameOrErr = Section.getName();
606      if (!NameOrErr) {
607        consumeError(NameOrErr.takeError());
608        continue;
609      }
610      StringRef Name = *NameOrErr;
611  
612      if (Name == ".plt")
613        Plt = Section;
614      else if (Name == ".rela.plt" || Name == ".rel.plt")
615        RelaPlt = Section;
616      else if (Name == ".got.plt")
617        GotPlt = Section;
618    }
619    if (!Plt || !RelaPlt || !GotPlt)
620      return {};
621    Expected<StringRef> PltContents = Plt->getContents();
622    if (!PltContents) {
623      consumeError(PltContents.takeError());
624      return {};
625    }
626    auto PltEntries = MIA->findPltEntries(Plt->getAddress(),
627                                          arrayRefFromStringRef(*PltContents),
628                                          GotPlt->getAddress(), Triple);
629    // Build a map from GOT entry virtual address to PLT entry virtual address.
630    DenseMap<uint64_t, uint64_t> GotToPlt;
631    for (const auto &Entry : PltEntries)
632      GotToPlt.insert(std::make_pair(Entry.second, Entry.first));
633    // Find the relocations in the dynamic relocation table that point to
634    // locations in the GOT for which we know the corresponding PLT entry.
635    std::vector<std::pair<Optional<DataRefImpl>, uint64_t>> Result;
636    for (const auto &Relocation : RelaPlt->relocations()) {
637      if (Relocation.getType() != JumpSlotReloc)
638        continue;
639      auto PltEntryIter = GotToPlt.find(Relocation.getOffset());
640      if (PltEntryIter != GotToPlt.end()) {
641        symbol_iterator Sym = Relocation.getSymbol();
642        if (Sym == symbol_end())
643          Result.emplace_back(None, PltEntryIter->second);
644        else
645          Result.emplace_back(Sym->getRawDataRefImpl(), PltEntryIter->second);
646      }
647    }
648    return Result;
649  }
650