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