Eugene Zelenko | c581c4f | 2017-04-24 23:21:38 +0000 | [diff] [blame] | 1 | //===- ELFObjectFile.cpp - ELF object file implementation -----------------===// |
Michael J. Spencer | b84551a | 2011-01-20 06:38:47 +0000 | [diff] [blame] | 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
Eli Bendersky | f4eff4b | 2012-02-12 06:12:10 +0000 | [diff] [blame] | 10 | // Part of the ELFObjectFile class implementation. |
Michael J. Spencer | b84551a | 2011-01-20 06:38:47 +0000 | [diff] [blame] | 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
Chandler Carruth | e3e43d9 | 2017-06-06 11:49:48 +0000 | [diff] [blame] | 14 | #include "llvm/Object/ELFObjectFile.h" |
Eugene Zelenko | c581c4f | 2017-04-24 23:21:38 +0000 | [diff] [blame] | 15 | #include "llvm/ADT/Triple.h" |
Zachary Turner | 19ca2b0 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 16 | #include "llvm/BinaryFormat/ELF.h" |
Joel Galenson | 77a17af | 2018-08-24 15:21:56 +0000 | [diff] [blame] | 17 | #include "llvm/MC/MCInstrAnalysis.h" |
Eugene Zelenko | c581c4f | 2017-04-24 23:21:38 +0000 | [diff] [blame] | 18 | #include "llvm/MC/SubtargetFeature.h" |
| 19 | #include "llvm/Object/ELF.h" |
Eugene Zelenko | c581c4f | 2017-04-24 23:21:38 +0000 | [diff] [blame] | 20 | #include "llvm/Object/ELFTypes.h" |
| 21 | #include "llvm/Object/Error.h" |
Sam Parker | 56e5bde | 2017-01-18 15:52:11 +0000 | [diff] [blame] | 22 | #include "llvm/Support/ARMAttributeParser.h" |
Chandler Carruth | e3e43d9 | 2017-06-06 11:49:48 +0000 | [diff] [blame] | 23 | #include "llvm/Support/ARMBuildAttributes.h" |
Eugene Zelenko | c581c4f | 2017-04-24 23:21:38 +0000 | [diff] [blame] | 24 | #include "llvm/Support/Endian.h" |
| 25 | #include "llvm/Support/ErrorHandling.h" |
Michael J. Spencer | 4d9c539 | 2013-01-04 20:36:28 +0000 | [diff] [blame] | 26 | #include "llvm/Support/MathExtras.h" |
Joel Galenson | 77a17af | 2018-08-24 15:21:56 +0000 | [diff] [blame] | 27 | #include "llvm/Support/TargetRegistry.h" |
Eugene Zelenko | c581c4f | 2017-04-24 23:21:38 +0000 | [diff] [blame] | 28 | #include <algorithm> |
| 29 | #include <cstddef> |
| 30 | #include <cstdint> |
| 31 | #include <memory> |
| 32 | #include <string> |
| 33 | #include <system_error> |
| 34 | #include <utility> |
Eli Bendersky | 24973c1 | 2012-01-22 09:01:03 +0000 | [diff] [blame] | 35 | |
Eugene Zelenko | c581c4f | 2017-04-24 23:21:38 +0000 | [diff] [blame] | 36 | using namespace llvm; |
Eli Bendersky | f4eff4b | 2012-02-12 06:12:10 +0000 | [diff] [blame] | 37 | using namespace object; |
Eli Bendersky | 24973c1 | 2012-01-22 09:01:03 +0000 | [diff] [blame] | 38 | |
Rafael Espindola | 548f2b6 | 2014-08-19 18:44:46 +0000 | [diff] [blame] | 39 | ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) |
| 40 | : ObjectFile(Type, Source) {} |
Rafael Espindola | db7cdc8 | 2014-08-17 17:52:10 +0000 | [diff] [blame] | 41 | |
Rafael Espindola | 5c1b443 | 2017-10-10 21:21:16 +0000 | [diff] [blame] | 42 | template <class ELFT> |
| 43 | static Expected<std::unique_ptr<ELFObjectFile<ELFT>>> |
| 44 | createPtr(MemoryBufferRef Object) { |
| 45 | auto Ret = ELFObjectFile<ELFT>::create(Object); |
| 46 | if (Error E = Ret.takeError()) |
| 47 | return std::move(E); |
| 48 | return make_unique<ELFObjectFile<ELFT>>(std::move(*Ret)); |
| 49 | } |
| 50 | |
Rafael Espindola | e2d20cb | 2017-10-10 20:00:07 +0000 | [diff] [blame] | 51 | Expected<std::unique_ptr<ObjectFile>> |
Rafael Espindola | 548f2b6 | 2014-08-19 18:44:46 +0000 | [diff] [blame] | 52 | ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { |
Rafael Espindola | db8cb22 | 2014-07-05 11:38:52 +0000 | [diff] [blame] | 53 | std::pair<unsigned char, unsigned char> Ident = |
Rafael Espindola | 548f2b6 | 2014-08-19 18:44:46 +0000 | [diff] [blame] | 54 | getElfArchType(Obj.getBuffer()); |
Michael J. Spencer | 4d9c539 | 2013-01-04 20:36:28 +0000 | [diff] [blame] | 55 | std::size_t MaxAlignment = |
Rafael Espindola | 548f2b6 | 2014-08-19 18:44:46 +0000 | [diff] [blame] | 56 | 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart())); |
Michael J. Spencer | 4d9c539 | 2013-01-04 20:36:28 +0000 | [diff] [blame] | 57 | |
Rafael Espindola | 9751e35 | 2015-06-02 12:05:27 +0000 | [diff] [blame] | 58 | if (MaxAlignment < 2) |
Rafael Espindola | e2d20cb | 2017-10-10 20:00:07 +0000 | [diff] [blame] | 59 | return createError("Insufficient alignment"); |
Rafael Espindola | 9751e35 | 2015-06-02 12:05:27 +0000 | [diff] [blame] | 60 | |
Rafael Espindola | 9751e35 | 2015-06-02 12:05:27 +0000 | [diff] [blame] | 61 | if (Ident.first == ELF::ELFCLASS32) { |
| 62 | if (Ident.second == ELF::ELFDATA2LSB) |
Rafael Espindola | 5c1b443 | 2017-10-10 21:21:16 +0000 | [diff] [blame] | 63 | return createPtr<ELF32LE>(Obj); |
Rafael Espindola | 9751e35 | 2015-06-02 12:05:27 +0000 | [diff] [blame] | 64 | else if (Ident.second == ELF::ELFDATA2MSB) |
Rafael Espindola | 5c1b443 | 2017-10-10 21:21:16 +0000 | [diff] [blame] | 65 | return createPtr<ELF32BE>(Obj); |
Michael J. Spencer | d9d2f18 | 2013-02-03 10:48:31 +0000 | [diff] [blame] | 66 | else |
Rafael Espindola | e2d20cb | 2017-10-10 20:00:07 +0000 | [diff] [blame] | 67 | return createError("Invalid ELF data"); |
Alexey Samsonov | 196340c | 2015-06-04 23:14:43 +0000 | [diff] [blame] | 68 | } else if (Ident.first == ELF::ELFCLASS64) { |
Rafael Espindola | 9751e35 | 2015-06-02 12:05:27 +0000 | [diff] [blame] | 69 | if (Ident.second == ELF::ELFDATA2LSB) |
Rafael Espindola | 5c1b443 | 2017-10-10 21:21:16 +0000 | [diff] [blame] | 70 | return createPtr<ELF64LE>(Obj); |
Rafael Espindola | 9751e35 | 2015-06-02 12:05:27 +0000 | [diff] [blame] | 71 | else if (Ident.second == ELF::ELFDATA2MSB) |
Rafael Espindola | 5c1b443 | 2017-10-10 21:21:16 +0000 | [diff] [blame] | 72 | return createPtr<ELF64BE>(Obj); |
Michael J. Spencer | 4d9c539 | 2013-01-04 20:36:28 +0000 | [diff] [blame] | 73 | else |
Rafael Espindola | e2d20cb | 2017-10-10 20:00:07 +0000 | [diff] [blame] | 74 | return createError("Invalid ELF data"); |
Eli Bendersky | f4eff4b | 2012-02-12 06:12:10 +0000 | [diff] [blame] | 75 | } |
Rafael Espindola | 5c1b443 | 2017-10-10 21:21:16 +0000 | [diff] [blame] | 76 | return createError("Invalid ELF class"); |
Eli Bendersky | f4eff4b | 2012-02-12 06:12:10 +0000 | [diff] [blame] | 77 | } |
Michael J. Spencer | b84551a | 2011-01-20 06:38:47 +0000 | [diff] [blame] | 78 | |
Sam Parker | 56e5bde | 2017-01-18 15:52:11 +0000 | [diff] [blame] | 79 | SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const { |
| 80 | SubtargetFeatures Features; |
Rafael Espindola | f1e44df | 2018-01-29 18:27:30 +0000 | [diff] [blame] | 81 | unsigned PlatformFlags = getPlatformFlags(); |
Sam Parker | 56e5bde | 2017-01-18 15:52:11 +0000 | [diff] [blame] | 82 | |
| 83 | switch (PlatformFlags & ELF::EF_MIPS_ARCH) { |
| 84 | case ELF::EF_MIPS_ARCH_1: |
| 85 | break; |
| 86 | case ELF::EF_MIPS_ARCH_2: |
| 87 | Features.AddFeature("mips2"); |
| 88 | break; |
| 89 | case ELF::EF_MIPS_ARCH_3: |
| 90 | Features.AddFeature("mips3"); |
| 91 | break; |
| 92 | case ELF::EF_MIPS_ARCH_4: |
| 93 | Features.AddFeature("mips4"); |
| 94 | break; |
| 95 | case ELF::EF_MIPS_ARCH_5: |
| 96 | Features.AddFeature("mips5"); |
| 97 | break; |
| 98 | case ELF::EF_MIPS_ARCH_32: |
| 99 | Features.AddFeature("mips32"); |
| 100 | break; |
| 101 | case ELF::EF_MIPS_ARCH_64: |
| 102 | Features.AddFeature("mips64"); |
| 103 | break; |
| 104 | case ELF::EF_MIPS_ARCH_32R2: |
| 105 | Features.AddFeature("mips32r2"); |
| 106 | break; |
| 107 | case ELF::EF_MIPS_ARCH_64R2: |
| 108 | Features.AddFeature("mips64r2"); |
| 109 | break; |
| 110 | case ELF::EF_MIPS_ARCH_32R6: |
| 111 | Features.AddFeature("mips32r6"); |
| 112 | break; |
| 113 | case ELF::EF_MIPS_ARCH_64R6: |
| 114 | Features.AddFeature("mips64r6"); |
| 115 | break; |
| 116 | default: |
| 117 | llvm_unreachable("Unknown EF_MIPS_ARCH value"); |
| 118 | } |
| 119 | |
| 120 | switch (PlatformFlags & ELF::EF_MIPS_MACH) { |
| 121 | case ELF::EF_MIPS_MACH_NONE: |
| 122 | // No feature associated with this value. |
| 123 | break; |
| 124 | case ELF::EF_MIPS_MACH_OCTEON: |
| 125 | Features.AddFeature("cnmips"); |
| 126 | break; |
| 127 | default: |
| 128 | llvm_unreachable("Unknown EF_MIPS_ARCH value"); |
| 129 | } |
| 130 | |
| 131 | if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16) |
| 132 | Features.AddFeature("mips16"); |
| 133 | if (PlatformFlags & ELF::EF_MIPS_MICROMIPS) |
| 134 | Features.AddFeature("micromips"); |
| 135 | |
| 136 | return Features; |
| 137 | } |
| 138 | |
| 139 | SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { |
| 140 | SubtargetFeatures Features; |
| 141 | ARMAttributeParser Attributes; |
| 142 | std::error_code EC = getBuildAttributes(Attributes); |
| 143 | if (EC) |
| 144 | return SubtargetFeatures(); |
| 145 | |
| 146 | // both ARMv7-M and R have to support thumb hardware div |
| 147 | bool isV7 = false; |
| 148 | if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) |
| 149 | isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch) |
| 150 | == ARMBuildAttrs::v7; |
| 151 | |
| 152 | if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) { |
| 153 | switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) { |
| 154 | case ARMBuildAttrs::ApplicationProfile: |
| 155 | Features.AddFeature("aclass"); |
| 156 | break; |
| 157 | case ARMBuildAttrs::RealTimeProfile: |
| 158 | Features.AddFeature("rclass"); |
| 159 | if (isV7) |
| 160 | Features.AddFeature("hwdiv"); |
| 161 | break; |
| 162 | case ARMBuildAttrs::MicroControllerProfile: |
| 163 | Features.AddFeature("mclass"); |
| 164 | if (isV7) |
| 165 | Features.AddFeature("hwdiv"); |
| 166 | break; |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) { |
| 171 | switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) { |
| 172 | default: |
| 173 | break; |
| 174 | case ARMBuildAttrs::Not_Allowed: |
| 175 | Features.AddFeature("thumb", false); |
| 176 | Features.AddFeature("thumb2", false); |
| 177 | break; |
| 178 | case ARMBuildAttrs::AllowThumb32: |
| 179 | Features.AddFeature("thumb2"); |
| 180 | break; |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) { |
| 185 | switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) { |
| 186 | default: |
| 187 | break; |
| 188 | case ARMBuildAttrs::Not_Allowed: |
| 189 | Features.AddFeature("vfp2", false); |
| 190 | Features.AddFeature("vfp3", false); |
| 191 | Features.AddFeature("vfp4", false); |
| 192 | break; |
| 193 | case ARMBuildAttrs::AllowFPv2: |
| 194 | Features.AddFeature("vfp2"); |
| 195 | break; |
| 196 | case ARMBuildAttrs::AllowFPv3A: |
| 197 | case ARMBuildAttrs::AllowFPv3B: |
| 198 | Features.AddFeature("vfp3"); |
| 199 | break; |
| 200 | case ARMBuildAttrs::AllowFPv4A: |
| 201 | case ARMBuildAttrs::AllowFPv4B: |
| 202 | Features.AddFeature("vfp4"); |
| 203 | break; |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) { |
| 208 | switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) { |
| 209 | default: |
| 210 | break; |
| 211 | case ARMBuildAttrs::Not_Allowed: |
| 212 | Features.AddFeature("neon", false); |
| 213 | Features.AddFeature("fp16", false); |
| 214 | break; |
| 215 | case ARMBuildAttrs::AllowNeon: |
| 216 | Features.AddFeature("neon"); |
| 217 | break; |
| 218 | case ARMBuildAttrs::AllowNeon2: |
| 219 | Features.AddFeature("neon"); |
| 220 | Features.AddFeature("fp16"); |
| 221 | break; |
| 222 | } |
| 223 | } |
| 224 | |
| 225 | if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) { |
| 226 | switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) { |
| 227 | default: |
| 228 | break; |
| 229 | case ARMBuildAttrs::DisallowDIV: |
| 230 | Features.AddFeature("hwdiv", false); |
| 231 | Features.AddFeature("hwdiv-arm", false); |
| 232 | break; |
| 233 | case ARMBuildAttrs::AllowDIVExt: |
| 234 | Features.AddFeature("hwdiv"); |
| 235 | Features.AddFeature("hwdiv-arm"); |
| 236 | break; |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | return Features; |
| 241 | } |
| 242 | |
Shiva Chen | 10bc294 | 2018-02-02 06:01:02 +0000 | [diff] [blame] | 243 | SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const { |
| 244 | SubtargetFeatures Features; |
| 245 | unsigned PlatformFlags = getPlatformFlags(); |
| 246 | |
| 247 | if (PlatformFlags & ELF::EF_RISCV_RVC) { |
| 248 | Features.AddFeature("c"); |
| 249 | } |
| 250 | |
| 251 | return Features; |
| 252 | } |
| 253 | |
Daniel Sanders | 0b8fc77 | 2016-06-16 09:17:03 +0000 | [diff] [blame] | 254 | SubtargetFeatures ELFObjectFileBase::getFeatures() const { |
| 255 | switch (getEMachine()) { |
Sam Parker | 56e5bde | 2017-01-18 15:52:11 +0000 | [diff] [blame] | 256 | case ELF::EM_MIPS: |
| 257 | return getMIPSFeatures(); |
| 258 | case ELF::EM_ARM: |
| 259 | return getARMFeatures(); |
Shiva Chen | 10bc294 | 2018-02-02 06:01:02 +0000 | [diff] [blame] | 260 | case ELF::EM_RISCV: |
| 261 | return getRISCVFeatures(); |
Daniel Sanders | 0b8fc77 | 2016-06-16 09:17:03 +0000 | [diff] [blame] | 262 | default: |
| 263 | return SubtargetFeatures(); |
| 264 | } |
| 265 | } |
| 266 | |
Sam Parker | aa96763 | 2017-01-18 13:52:12 +0000 | [diff] [blame] | 267 | // FIXME Encode from a tablegen description or target parser. |
| 268 | void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { |
| 269 | if (TheTriple.getSubArch() != Triple::NoSubArch) |
| 270 | return; |
| 271 | |
| 272 | ARMAttributeParser Attributes; |
| 273 | std::error_code EC = getBuildAttributes(Attributes); |
| 274 | if (EC) |
| 275 | return; |
| 276 | |
| 277 | std::string Triple; |
| 278 | // Default to ARM, but use the triple if it's been set. |
Florian Hahn | ace970e | 2017-08-12 17:40:18 +0000 | [diff] [blame] | 279 | if (TheTriple.isThumb()) |
Sam Parker | aa96763 | 2017-01-18 13:52:12 +0000 | [diff] [blame] | 280 | Triple = "thumb"; |
| 281 | else |
| 282 | Triple = "arm"; |
| 283 | |
| 284 | if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) { |
| 285 | switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) { |
| 286 | case ARMBuildAttrs::v4: |
| 287 | Triple += "v4"; |
| 288 | break; |
| 289 | case ARMBuildAttrs::v4T: |
| 290 | Triple += "v4t"; |
| 291 | break; |
| 292 | case ARMBuildAttrs::v5T: |
| 293 | Triple += "v5t"; |
| 294 | break; |
| 295 | case ARMBuildAttrs::v5TE: |
| 296 | Triple += "v5te"; |
| 297 | break; |
| 298 | case ARMBuildAttrs::v5TEJ: |
| 299 | Triple += "v5tej"; |
| 300 | break; |
| 301 | case ARMBuildAttrs::v6: |
| 302 | Triple += "v6"; |
| 303 | break; |
| 304 | case ARMBuildAttrs::v6KZ: |
| 305 | Triple += "v6kz"; |
| 306 | break; |
| 307 | case ARMBuildAttrs::v6T2: |
| 308 | Triple += "v6t2"; |
| 309 | break; |
| 310 | case ARMBuildAttrs::v6K: |
| 311 | Triple += "v6k"; |
| 312 | break; |
| 313 | case ARMBuildAttrs::v7: |
| 314 | Triple += "v7"; |
| 315 | break; |
| 316 | case ARMBuildAttrs::v6_M: |
| 317 | Triple += "v6m"; |
| 318 | break; |
| 319 | case ARMBuildAttrs::v6S_M: |
| 320 | Triple += "v6sm"; |
| 321 | break; |
| 322 | case ARMBuildAttrs::v7E_M: |
| 323 | Triple += "v7em"; |
| 324 | break; |
| 325 | } |
| 326 | } |
| 327 | if (!isLittleEndian()) |
| 328 | Triple += "eb"; |
| 329 | |
| 330 | TheTriple.setArchName(Triple); |
| 331 | } |
Joel Galenson | 77a17af | 2018-08-24 15:21:56 +0000 | [diff] [blame] | 332 | |
| 333 | std::vector<std::pair<DataRefImpl, uint64_t>> |
| 334 | ELFObjectFileBase::getPltAddresses() const { |
| 335 | std::string Err; |
| 336 | const auto Triple = makeTriple(); |
| 337 | const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err); |
| 338 | if (!T) |
| 339 | return {}; |
| 340 | uint64_t JumpSlotReloc = 0; |
| 341 | switch (Triple.getArch()) { |
| 342 | case Triple::x86: |
| 343 | JumpSlotReloc = ELF::R_386_JUMP_SLOT; |
| 344 | break; |
| 345 | case Triple::x86_64: |
| 346 | JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT; |
| 347 | break; |
| 348 | case Triple::aarch64: |
| 349 | JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT; |
| 350 | break; |
| 351 | default: |
| 352 | return {}; |
| 353 | } |
Vitaly Buka | a4da437 | 2018-08-24 21:03:35 +0000 | [diff] [blame] | 354 | std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo()); |
Joel Galenson | ddf0892 | 2018-08-24 19:40:35 +0000 | [diff] [blame] | 355 | std::unique_ptr<const MCInstrAnalysis> MIA( |
Vitaly Buka | a4da437 | 2018-08-24 21:03:35 +0000 | [diff] [blame] | 356 | T->createMCInstrAnalysis(MII.get())); |
Joel Galenson | 77a17af | 2018-08-24 15:21:56 +0000 | [diff] [blame] | 357 | if (!MIA) |
| 358 | return {}; |
| 359 | Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None; |
| 360 | for (const SectionRef &Section : sections()) { |
| 361 | StringRef Name; |
| 362 | if (Section.getName(Name)) |
| 363 | continue; |
| 364 | if (Name == ".plt") |
| 365 | Plt = Section; |
| 366 | else if (Name == ".rela.plt" || Name == ".rel.plt") |
| 367 | RelaPlt = Section; |
| 368 | else if (Name == ".got.plt") |
| 369 | GotPlt = Section; |
| 370 | } |
| 371 | if (!Plt || !RelaPlt || !GotPlt) |
| 372 | return {}; |
| 373 | StringRef PltContents; |
| 374 | if (Plt->getContents(PltContents)) |
| 375 | return {}; |
| 376 | ArrayRef<uint8_t> PltBytes((const uint8_t *)PltContents.data(), |
| 377 | Plt->getSize()); |
| 378 | auto PltEntries = MIA->findPltEntries(Plt->getAddress(), PltBytes, |
| 379 | GotPlt->getAddress(), Triple); |
| 380 | // Build a map from GOT entry virtual address to PLT entry virtual address. |
| 381 | DenseMap<uint64_t, uint64_t> GotToPlt; |
| 382 | for (const auto &Entry : PltEntries) |
| 383 | GotToPlt.insert(std::make_pair(Entry.second, Entry.first)); |
| 384 | // Find the relocations in the dynamic relocation table that point to |
| 385 | // locations in the GOT for which we know the corresponding PLT entry. |
| 386 | std::vector<std::pair<DataRefImpl, uint64_t>> Result; |
| 387 | for (const auto &Relocation : RelaPlt->relocations()) { |
| 388 | if (Relocation.getType() != JumpSlotReloc) |
| 389 | continue; |
| 390 | auto PltEntryIter = GotToPlt.find(Relocation.getOffset()); |
| 391 | if (PltEntryIter != GotToPlt.end()) |
| 392 | Result.push_back(std::make_pair( |
| 393 | Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second)); |
| 394 | } |
| 395 | return Result; |
| 396 | } |