Eugene Zelenko | 1df42fa | 2017-04-24 23:21:38 +0000 | [diff] [blame] | 1 | //===- ELFObjectFile.cpp - ELF object file implementation -----------------===// |
Michael J. Spencer | b60a18d | 2011-01-20 06:38:47 +0000 | [diff] [blame] | 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 |
Michael J. Spencer | b60a18d | 2011-01-20 06:38:47 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
Eli Bendersky | c7d23dd | 2012-02-12 06:12:10 +0000 | [diff] [blame] | 9 | // Part of the ELFObjectFile class implementation. |
Michael J. Spencer | b60a18d | 2011-01-20 06:38:47 +0000 | [diff] [blame] | 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
Chandler Carruth | 6bda14b | 2017-06-06 11:49:48 +0000 | [diff] [blame] | 13 | #include "llvm/Object/ELFObjectFile.h" |
Eugene Zelenko | 1df42fa | 2017-04-24 23:21:38 +0000 | [diff] [blame] | 14 | #include "llvm/ADT/Triple.h" |
Zachary Turner | 264b5d9 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 15 | #include "llvm/BinaryFormat/ELF.h" |
Joel Galenson | d36fb48 | 2018-08-24 15:21:56 +0000 | [diff] [blame] | 16 | #include "llvm/MC/MCInstrAnalysis.h" |
Eugene Zelenko | 1df42fa | 2017-04-24 23:21:38 +0000 | [diff] [blame] | 17 | #include "llvm/MC/SubtargetFeature.h" |
| 18 | #include "llvm/Object/ELF.h" |
Eugene Zelenko | 1df42fa | 2017-04-24 23:21:38 +0000 | [diff] [blame] | 19 | #include "llvm/Object/ELFTypes.h" |
| 20 | #include "llvm/Object/Error.h" |
Sam Parker | b0de00d | 2017-01-18 15:52:11 +0000 | [diff] [blame] | 21 | #include "llvm/Support/ARMAttributeParser.h" |
Chandler Carruth | 6bda14b | 2017-06-06 11:49:48 +0000 | [diff] [blame] | 22 | #include "llvm/Support/ARMBuildAttributes.h" |
Eugene Zelenko | 1df42fa | 2017-04-24 23:21:38 +0000 | [diff] [blame] | 23 | #include "llvm/Support/Endian.h" |
| 24 | #include "llvm/Support/ErrorHandling.h" |
Michael J. Spencer | bae14ce | 2013-01-04 20:36:28 +0000 | [diff] [blame] | 25 | #include "llvm/Support/MathExtras.h" |
Joel Galenson | d36fb48 | 2018-08-24 15:21:56 +0000 | [diff] [blame] | 26 | #include "llvm/Support/TargetRegistry.h" |
Eugene Zelenko | 1df42fa | 2017-04-24 23:21:38 +0000 | [diff] [blame] | 27 | #include <algorithm> |
| 28 | #include <cstddef> |
| 29 | #include <cstdint> |
| 30 | #include <memory> |
| 31 | #include <string> |
| 32 | #include <system_error> |
| 33 | #include <utility> |
Eli Bendersky | c3c80f0 | 2012-01-22 09:01:03 +0000 | [diff] [blame] | 34 | |
Eugene Zelenko | 1df42fa | 2017-04-24 23:21:38 +0000 | [diff] [blame] | 35 | using namespace llvm; |
Eli Bendersky | c7d23dd | 2012-02-12 06:12:10 +0000 | [diff] [blame] | 36 | using namespace object; |
Eli Bendersky | c3c80f0 | 2012-01-22 09:01:03 +0000 | [diff] [blame] | 37 | |
Sunil Srivastava | ae8fe4e | 2019-03-08 22:00:50 +0000 | [diff] [blame] | 38 | const EnumEntry<unsigned> llvm::object::ElfSymbolTypes[NumElfSymbolTypes] = { |
| 39 | {"None", "NOTYPE", ELF::STT_NOTYPE}, |
| 40 | {"Object", "OBJECT", ELF::STT_OBJECT}, |
| 41 | {"Function", "FUNC", ELF::STT_FUNC}, |
| 42 | {"Section", "SECTION", ELF::STT_SECTION}, |
| 43 | {"File", "FILE", ELF::STT_FILE}, |
| 44 | {"Common", "COMMON", ELF::STT_COMMON}, |
| 45 | {"TLS", "TLS", ELF::STT_TLS}, |
Sunil Srivastava | 27f6f2f | 2019-08-09 16:54:51 +0000 | [diff] [blame] | 46 | {"Unknown", "<unknown>: 7", 7}, |
| 47 | {"Unknown", "<unknown>: 8", 8}, |
| 48 | {"Unknown", "<unknown>: 9", 9}, |
| 49 | {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC}, |
| 50 | {"OS Specific", "<OS specific>: 11", 11}, |
| 51 | {"OS Specific", "<OS specific>: 12", 12}, |
| 52 | {"Proc Specific", "<processor specific>: 13", 13}, |
| 53 | {"Proc Specific", "<processor specific>: 14", 14}, |
| 54 | {"Proc Specific", "<processor specific>: 15", 15} |
| 55 | }; |
Sunil Srivastava | ae8fe4e | 2019-03-08 22:00:50 +0000 | [diff] [blame] | 56 | |
Rafael Espindola | 48af1c2 | 2014-08-19 18:44:46 +0000 | [diff] [blame] | 57 | ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) |
| 58 | : ObjectFile(Type, Source) {} |
Rafael Espindola | ab73774 | 2014-08-17 17:52:10 +0000 | [diff] [blame] | 59 | |
Rafael Espindola | ef421f9 | 2017-10-10 21:21:16 +0000 | [diff] [blame] | 60 | template <class ELFT> |
| 61 | static Expected<std::unique_ptr<ELFObjectFile<ELFT>>> |
| 62 | createPtr(MemoryBufferRef Object) { |
| 63 | auto Ret = ELFObjectFile<ELFT>::create(Object); |
| 64 | if (Error E = Ret.takeError()) |
Bill Wendling | c55cf4a | 2020-02-10 07:06:45 -0800 | [diff] [blame] | 65 | return std::move(E); |
Jonas Devlieghere | 0eaee54 | 2019-08-15 15:54:37 +0000 | [diff] [blame] | 66 | return std::make_unique<ELFObjectFile<ELFT>>(std::move(*Ret)); |
Rafael Espindola | ef421f9 | 2017-10-10 21:21:16 +0000 | [diff] [blame] | 67 | } |
| 68 | |
Rafael Espindola | 12db383 | 2017-10-10 20:00:07 +0000 | [diff] [blame] | 69 | Expected<std::unique_ptr<ObjectFile>> |
Rafael Espindola | 48af1c2 | 2014-08-19 18:44:46 +0000 | [diff] [blame] | 70 | ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { |
Rafael Espindola | d5a8efe | 2014-07-05 11:38:52 +0000 | [diff] [blame] | 71 | std::pair<unsigned char, unsigned char> Ident = |
Rafael Espindola | 48af1c2 | 2014-08-19 18:44:46 +0000 | [diff] [blame] | 72 | getElfArchType(Obj.getBuffer()); |
Michael J. Spencer | bae14ce | 2013-01-04 20:36:28 +0000 | [diff] [blame] | 73 | std::size_t MaxAlignment = |
Rafael Espindola | 48af1c2 | 2014-08-19 18:44:46 +0000 | [diff] [blame] | 74 | 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart())); |
Michael J. Spencer | bae14ce | 2013-01-04 20:36:28 +0000 | [diff] [blame] | 75 | |
Rafael Espindola | ac729b4 | 2015-06-02 12:05:27 +0000 | [diff] [blame] | 76 | if (MaxAlignment < 2) |
Rafael Espindola | 12db383 | 2017-10-10 20:00:07 +0000 | [diff] [blame] | 77 | return createError("Insufficient alignment"); |
Rafael Espindola | ac729b4 | 2015-06-02 12:05:27 +0000 | [diff] [blame] | 78 | |
Rafael Espindola | ac729b4 | 2015-06-02 12:05:27 +0000 | [diff] [blame] | 79 | if (Ident.first == ELF::ELFCLASS32) { |
| 80 | if (Ident.second == ELF::ELFDATA2LSB) |
Rafael Espindola | ef421f9 | 2017-10-10 21:21:16 +0000 | [diff] [blame] | 81 | return createPtr<ELF32LE>(Obj); |
Rafael Espindola | ac729b4 | 2015-06-02 12:05:27 +0000 | [diff] [blame] | 82 | else if (Ident.second == ELF::ELFDATA2MSB) |
Rafael Espindola | ef421f9 | 2017-10-10 21:21:16 +0000 | [diff] [blame] | 83 | return createPtr<ELF32BE>(Obj); |
Michael J. Spencer | 39678d8 | 2013-02-03 10:48:31 +0000 | [diff] [blame] | 84 | else |
Rafael Espindola | 12db383 | 2017-10-10 20:00:07 +0000 | [diff] [blame] | 85 | return createError("Invalid ELF data"); |
Alexey Samsonov | 49179dd | 2015-06-04 23:14:43 +0000 | [diff] [blame] | 86 | } else if (Ident.first == ELF::ELFCLASS64) { |
Rafael Espindola | ac729b4 | 2015-06-02 12:05:27 +0000 | [diff] [blame] | 87 | if (Ident.second == ELF::ELFDATA2LSB) |
Rafael Espindola | ef421f9 | 2017-10-10 21:21:16 +0000 | [diff] [blame] | 88 | return createPtr<ELF64LE>(Obj); |
Rafael Espindola | ac729b4 | 2015-06-02 12:05:27 +0000 | [diff] [blame] | 89 | else if (Ident.second == ELF::ELFDATA2MSB) |
Rafael Espindola | ef421f9 | 2017-10-10 21:21:16 +0000 | [diff] [blame] | 90 | return createPtr<ELF64BE>(Obj); |
Michael J. Spencer | bae14ce | 2013-01-04 20:36:28 +0000 | [diff] [blame] | 91 | else |
Rafael Espindola | 12db383 | 2017-10-10 20:00:07 +0000 | [diff] [blame] | 92 | return createError("Invalid ELF data"); |
Eli Bendersky | c7d23dd | 2012-02-12 06:12:10 +0000 | [diff] [blame] | 93 | } |
Rafael Espindola | ef421f9 | 2017-10-10 21:21:16 +0000 | [diff] [blame] | 94 | return createError("Invalid ELF class"); |
Eli Bendersky | c7d23dd | 2012-02-12 06:12:10 +0000 | [diff] [blame] | 95 | } |
Michael J. Spencer | b60a18d | 2011-01-20 06:38:47 +0000 | [diff] [blame] | 96 | |
Sam Parker | b0de00d | 2017-01-18 15:52:11 +0000 | [diff] [blame] | 97 | SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const { |
| 98 | SubtargetFeatures Features; |
Rafael Espindola | d5f76ad | 2018-01-29 18:27:30 +0000 | [diff] [blame] | 99 | unsigned PlatformFlags = getPlatformFlags(); |
Sam Parker | b0de00d | 2017-01-18 15:52:11 +0000 | [diff] [blame] | 100 | |
| 101 | switch (PlatformFlags & ELF::EF_MIPS_ARCH) { |
| 102 | case ELF::EF_MIPS_ARCH_1: |
| 103 | break; |
| 104 | case ELF::EF_MIPS_ARCH_2: |
| 105 | Features.AddFeature("mips2"); |
| 106 | break; |
| 107 | case ELF::EF_MIPS_ARCH_3: |
| 108 | Features.AddFeature("mips3"); |
| 109 | break; |
| 110 | case ELF::EF_MIPS_ARCH_4: |
| 111 | Features.AddFeature("mips4"); |
| 112 | break; |
| 113 | case ELF::EF_MIPS_ARCH_5: |
| 114 | Features.AddFeature("mips5"); |
| 115 | break; |
| 116 | case ELF::EF_MIPS_ARCH_32: |
| 117 | Features.AddFeature("mips32"); |
| 118 | break; |
| 119 | case ELF::EF_MIPS_ARCH_64: |
| 120 | Features.AddFeature("mips64"); |
| 121 | break; |
| 122 | case ELF::EF_MIPS_ARCH_32R2: |
| 123 | Features.AddFeature("mips32r2"); |
| 124 | break; |
| 125 | case ELF::EF_MIPS_ARCH_64R2: |
| 126 | Features.AddFeature("mips64r2"); |
| 127 | break; |
| 128 | case ELF::EF_MIPS_ARCH_32R6: |
| 129 | Features.AddFeature("mips32r6"); |
| 130 | break; |
| 131 | case ELF::EF_MIPS_ARCH_64R6: |
| 132 | Features.AddFeature("mips64r6"); |
| 133 | break; |
| 134 | default: |
| 135 | llvm_unreachable("Unknown EF_MIPS_ARCH value"); |
| 136 | } |
| 137 | |
| 138 | switch (PlatformFlags & ELF::EF_MIPS_MACH) { |
| 139 | case ELF::EF_MIPS_MACH_NONE: |
| 140 | // No feature associated with this value. |
| 141 | break; |
| 142 | case ELF::EF_MIPS_MACH_OCTEON: |
| 143 | Features.AddFeature("cnmips"); |
| 144 | break; |
| 145 | default: |
| 146 | llvm_unreachable("Unknown EF_MIPS_ARCH value"); |
| 147 | } |
| 148 | |
| 149 | if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16) |
| 150 | Features.AddFeature("mips16"); |
| 151 | if (PlatformFlags & ELF::EF_MIPS_MICROMIPS) |
| 152 | Features.AddFeature("micromips"); |
| 153 | |
| 154 | return Features; |
| 155 | } |
| 156 | |
| 157 | SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { |
| 158 | SubtargetFeatures Features; |
| 159 | ARMAttributeParser Attributes; |
Fangrui Song | 791efb1 | 2020-02-21 11:32:33 -0800 | [diff] [blame] | 160 | if (Error E = getBuildAttributes(Attributes)) { |
| 161 | consumeError(std::move(E)); |
Sam Parker | b0de00d | 2017-01-18 15:52:11 +0000 | [diff] [blame] | 162 | return SubtargetFeatures(); |
Fangrui Song | 791efb1 | 2020-02-21 11:32:33 -0800 | [diff] [blame] | 163 | } |
Sam Parker | b0de00d | 2017-01-18 15:52:11 +0000 | [diff] [blame] | 164 | |
| 165 | // both ARMv7-M and R have to support thumb hardware div |
| 166 | bool isV7 = false; |
| 167 | if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) |
| 168 | isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch) |
| 169 | == ARMBuildAttrs::v7; |
| 170 | |
| 171 | if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) { |
| 172 | switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) { |
| 173 | case ARMBuildAttrs::ApplicationProfile: |
| 174 | Features.AddFeature("aclass"); |
| 175 | break; |
| 176 | case ARMBuildAttrs::RealTimeProfile: |
| 177 | Features.AddFeature("rclass"); |
| 178 | if (isV7) |
| 179 | Features.AddFeature("hwdiv"); |
| 180 | break; |
| 181 | case ARMBuildAttrs::MicroControllerProfile: |
| 182 | Features.AddFeature("mclass"); |
| 183 | if (isV7) |
| 184 | Features.AddFeature("hwdiv"); |
| 185 | break; |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) { |
| 190 | switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) { |
| 191 | default: |
| 192 | break; |
| 193 | case ARMBuildAttrs::Not_Allowed: |
| 194 | Features.AddFeature("thumb", false); |
| 195 | Features.AddFeature("thumb2", false); |
| 196 | break; |
| 197 | case ARMBuildAttrs::AllowThumb32: |
| 198 | Features.AddFeature("thumb2"); |
| 199 | break; |
| 200 | } |
| 201 | } |
| 202 | |
| 203 | if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) { |
| 204 | switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) { |
| 205 | default: |
| 206 | break; |
| 207 | case ARMBuildAttrs::Not_Allowed: |
Eli Friedman | ddf5e86 | 2019-09-17 21:42:38 +0000 | [diff] [blame] | 208 | Features.AddFeature("vfp2sp", false); |
Simon Tatham | 760df47 | 2019-05-28 16:13:20 +0000 | [diff] [blame] | 209 | Features.AddFeature("vfp3d16sp", false); |
| 210 | Features.AddFeature("vfp4d16sp", false); |
Sam Parker | b0de00d | 2017-01-18 15:52:11 +0000 | [diff] [blame] | 211 | break; |
| 212 | case ARMBuildAttrs::AllowFPv2: |
| 213 | Features.AddFeature("vfp2"); |
| 214 | break; |
| 215 | case ARMBuildAttrs::AllowFPv3A: |
| 216 | case ARMBuildAttrs::AllowFPv3B: |
| 217 | Features.AddFeature("vfp3"); |
| 218 | break; |
| 219 | case ARMBuildAttrs::AllowFPv4A: |
| 220 | case ARMBuildAttrs::AllowFPv4B: |
| 221 | Features.AddFeature("vfp4"); |
| 222 | break; |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) { |
| 227 | switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) { |
| 228 | default: |
| 229 | break; |
| 230 | case ARMBuildAttrs::Not_Allowed: |
| 231 | Features.AddFeature("neon", false); |
| 232 | Features.AddFeature("fp16", false); |
| 233 | break; |
| 234 | case ARMBuildAttrs::AllowNeon: |
| 235 | Features.AddFeature("neon"); |
| 236 | break; |
| 237 | case ARMBuildAttrs::AllowNeon2: |
| 238 | Features.AddFeature("neon"); |
| 239 | Features.AddFeature("fp16"); |
| 240 | break; |
| 241 | } |
| 242 | } |
| 243 | |
Sjoerd Meijer | 930dee2 | 2019-05-30 12:57:04 +0000 | [diff] [blame] | 244 | if (Attributes.hasAttribute(ARMBuildAttrs::MVE_arch)) { |
| 245 | switch(Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch)) { |
| 246 | default: |
| 247 | break; |
| 248 | case ARMBuildAttrs::Not_Allowed: |
| 249 | Features.AddFeature("mve", false); |
| 250 | Features.AddFeature("mve.fp", false); |
| 251 | break; |
| 252 | case ARMBuildAttrs::AllowMVEInteger: |
| 253 | Features.AddFeature("mve.fp", false); |
| 254 | Features.AddFeature("mve"); |
| 255 | break; |
| 256 | case ARMBuildAttrs::AllowMVEIntegerAndFloat: |
| 257 | Features.AddFeature("mve.fp"); |
| 258 | break; |
| 259 | } |
| 260 | } |
| 261 | |
Sam Parker | b0de00d | 2017-01-18 15:52:11 +0000 | [diff] [blame] | 262 | if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) { |
| 263 | switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) { |
| 264 | default: |
| 265 | break; |
| 266 | case ARMBuildAttrs::DisallowDIV: |
| 267 | Features.AddFeature("hwdiv", false); |
| 268 | Features.AddFeature("hwdiv-arm", false); |
| 269 | break; |
| 270 | case ARMBuildAttrs::AllowDIVExt: |
| 271 | Features.AddFeature("hwdiv"); |
| 272 | Features.AddFeature("hwdiv-arm"); |
| 273 | break; |
| 274 | } |
| 275 | } |
| 276 | |
| 277 | return Features; |
| 278 | } |
| 279 | |
Shiva Chen | 53489ad | 2018-02-02 06:01:02 +0000 | [diff] [blame] | 280 | SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const { |
| 281 | SubtargetFeatures Features; |
| 282 | unsigned PlatformFlags = getPlatformFlags(); |
| 283 | |
| 284 | if (PlatformFlags & ELF::EF_RISCV_RVC) { |
| 285 | Features.AddFeature("c"); |
| 286 | } |
| 287 | |
| 288 | return Features; |
| 289 | } |
| 290 | |
Daniel Sanders | 1d14864 | 2016-06-16 09:17:03 +0000 | [diff] [blame] | 291 | SubtargetFeatures ELFObjectFileBase::getFeatures() const { |
| 292 | switch (getEMachine()) { |
Sam Parker | b0de00d | 2017-01-18 15:52:11 +0000 | [diff] [blame] | 293 | case ELF::EM_MIPS: |
| 294 | return getMIPSFeatures(); |
| 295 | case ELF::EM_ARM: |
| 296 | return getARMFeatures(); |
Shiva Chen | 53489ad | 2018-02-02 06:01:02 +0000 | [diff] [blame] | 297 | case ELF::EM_RISCV: |
| 298 | return getRISCVFeatures(); |
Daniel Sanders | 1d14864 | 2016-06-16 09:17:03 +0000 | [diff] [blame] | 299 | default: |
| 300 | return SubtargetFeatures(); |
| 301 | } |
| 302 | } |
| 303 | |
Sam Parker | df7c6ef | 2017-01-18 13:52:12 +0000 | [diff] [blame] | 304 | // FIXME Encode from a tablegen description or target parser. |
| 305 | void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { |
| 306 | if (TheTriple.getSubArch() != Triple::NoSubArch) |
| 307 | return; |
| 308 | |
| 309 | ARMAttributeParser Attributes; |
Fangrui Song | 791efb1 | 2020-02-21 11:32:33 -0800 | [diff] [blame] | 310 | if (Error E = getBuildAttributes(Attributes)) { |
| 311 | // TODO Propagate Error. |
| 312 | consumeError(std::move(E)); |
Sam Parker | df7c6ef | 2017-01-18 13:52:12 +0000 | [diff] [blame] | 313 | return; |
Fangrui Song | 791efb1 | 2020-02-21 11:32:33 -0800 | [diff] [blame] | 314 | } |
Sam Parker | df7c6ef | 2017-01-18 13:52:12 +0000 | [diff] [blame] | 315 | |
| 316 | std::string Triple; |
| 317 | // Default to ARM, but use the triple if it's been set. |
Florian Hahn | a5ba4ee | 2017-08-12 17:40:18 +0000 | [diff] [blame] | 318 | if (TheTriple.isThumb()) |
Sam Parker | df7c6ef | 2017-01-18 13:52:12 +0000 | [diff] [blame] | 319 | Triple = "thumb"; |
| 320 | else |
| 321 | Triple = "arm"; |
| 322 | |
| 323 | if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) { |
| 324 | switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) { |
| 325 | case ARMBuildAttrs::v4: |
| 326 | Triple += "v4"; |
| 327 | break; |
| 328 | case ARMBuildAttrs::v4T: |
| 329 | Triple += "v4t"; |
| 330 | break; |
| 331 | case ARMBuildAttrs::v5T: |
| 332 | Triple += "v5t"; |
| 333 | break; |
| 334 | case ARMBuildAttrs::v5TE: |
| 335 | Triple += "v5te"; |
| 336 | break; |
| 337 | case ARMBuildAttrs::v5TEJ: |
| 338 | Triple += "v5tej"; |
| 339 | break; |
| 340 | case ARMBuildAttrs::v6: |
| 341 | Triple += "v6"; |
| 342 | break; |
| 343 | case ARMBuildAttrs::v6KZ: |
| 344 | Triple += "v6kz"; |
| 345 | break; |
| 346 | case ARMBuildAttrs::v6T2: |
| 347 | Triple += "v6t2"; |
| 348 | break; |
| 349 | case ARMBuildAttrs::v6K: |
| 350 | Triple += "v6k"; |
| 351 | break; |
| 352 | case ARMBuildAttrs::v7: |
| 353 | Triple += "v7"; |
| 354 | break; |
| 355 | case ARMBuildAttrs::v6_M: |
| 356 | Triple += "v6m"; |
| 357 | break; |
| 358 | case ARMBuildAttrs::v6S_M: |
| 359 | Triple += "v6sm"; |
| 360 | break; |
| 361 | case ARMBuildAttrs::v7E_M: |
| 362 | Triple += "v7em"; |
| 363 | break; |
Yi Kong | b9d87b9 | 2019-08-28 06:37:22 +0000 | [diff] [blame] | 364 | case ARMBuildAttrs::v8_A: |
| 365 | Triple += "v8a"; |
| 366 | break; |
| 367 | case ARMBuildAttrs::v8_R: |
| 368 | Triple += "v8r"; |
| 369 | break; |
| 370 | case ARMBuildAttrs::v8_M_Base: |
| 371 | Triple += "v8m.base"; |
| 372 | break; |
| 373 | case ARMBuildAttrs::v8_M_Main: |
| 374 | Triple += "v8m.main"; |
| 375 | break; |
| 376 | case ARMBuildAttrs::v8_1_M_Main: |
| 377 | Triple += "v8.1m.main"; |
| 378 | break; |
Sam Parker | df7c6ef | 2017-01-18 13:52:12 +0000 | [diff] [blame] | 379 | } |
| 380 | } |
| 381 | if (!isLittleEndian()) |
| 382 | Triple += "eb"; |
| 383 | |
| 384 | TheTriple.setArchName(Triple); |
| 385 | } |
Joel Galenson | d36fb48 | 2018-08-24 15:21:56 +0000 | [diff] [blame] | 386 | |
| 387 | std::vector<std::pair<DataRefImpl, uint64_t>> |
| 388 | ELFObjectFileBase::getPltAddresses() const { |
| 389 | std::string Err; |
| 390 | const auto Triple = makeTriple(); |
| 391 | const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err); |
| 392 | if (!T) |
| 393 | return {}; |
| 394 | uint64_t JumpSlotReloc = 0; |
| 395 | switch (Triple.getArch()) { |
| 396 | case Triple::x86: |
| 397 | JumpSlotReloc = ELF::R_386_JUMP_SLOT; |
| 398 | break; |
| 399 | case Triple::x86_64: |
| 400 | JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT; |
| 401 | break; |
| 402 | case Triple::aarch64: |
| 403 | JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT; |
| 404 | break; |
| 405 | default: |
| 406 | return {}; |
| 407 | } |
Vitaly Buka | 96cbeff | 2018-08-24 21:03:35 +0000 | [diff] [blame] | 408 | std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo()); |
Joel Galenson | 90f976a | 2018-08-24 19:40:35 +0000 | [diff] [blame] | 409 | std::unique_ptr<const MCInstrAnalysis> MIA( |
Vitaly Buka | 96cbeff | 2018-08-24 21:03:35 +0000 | [diff] [blame] | 410 | T->createMCInstrAnalysis(MII.get())); |
Joel Galenson | d36fb48 | 2018-08-24 15:21:56 +0000 | [diff] [blame] | 411 | if (!MIA) |
| 412 | return {}; |
| 413 | Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None; |
| 414 | for (const SectionRef &Section : sections()) { |
George Rimar | bcc00e1 | 2019-08-14 11:10:11 +0000 | [diff] [blame] | 415 | Expected<StringRef> NameOrErr = Section.getName(); |
| 416 | if (!NameOrErr) { |
| 417 | consumeError(NameOrErr.takeError()); |
Joel Galenson | d36fb48 | 2018-08-24 15:21:56 +0000 | [diff] [blame] | 418 | continue; |
George Rimar | bcc00e1 | 2019-08-14 11:10:11 +0000 | [diff] [blame] | 419 | } |
| 420 | StringRef Name = *NameOrErr; |
| 421 | |
Joel Galenson | d36fb48 | 2018-08-24 15:21:56 +0000 | [diff] [blame] | 422 | if (Name == ".plt") |
| 423 | Plt = Section; |
| 424 | else if (Name == ".rela.plt" || Name == ".rel.plt") |
| 425 | RelaPlt = Section; |
| 426 | else if (Name == ".got.plt") |
| 427 | GotPlt = Section; |
| 428 | } |
| 429 | if (!Plt || !RelaPlt || !GotPlt) |
| 430 | return {}; |
Fangrui Song | e183340 | 2019-05-16 13:24:04 +0000 | [diff] [blame] | 431 | Expected<StringRef> PltContents = Plt->getContents(); |
| 432 | if (!PltContents) { |
| 433 | consumeError(PltContents.takeError()); |
Joel Galenson | d36fb48 | 2018-08-24 15:21:56 +0000 | [diff] [blame] | 434 | return {}; |
Fangrui Song | e183340 | 2019-05-16 13:24:04 +0000 | [diff] [blame] | 435 | } |
| 436 | auto PltEntries = MIA->findPltEntries(Plt->getAddress(), |
| 437 | arrayRefFromStringRef(*PltContents), |
Joel Galenson | d36fb48 | 2018-08-24 15:21:56 +0000 | [diff] [blame] | 438 | GotPlt->getAddress(), Triple); |
| 439 | // Build a map from GOT entry virtual address to PLT entry virtual address. |
| 440 | DenseMap<uint64_t, uint64_t> GotToPlt; |
| 441 | for (const auto &Entry : PltEntries) |
| 442 | GotToPlt.insert(std::make_pair(Entry.second, Entry.first)); |
| 443 | // Find the relocations in the dynamic relocation table that point to |
| 444 | // locations in the GOT for which we know the corresponding PLT entry. |
| 445 | std::vector<std::pair<DataRefImpl, uint64_t>> Result; |
| 446 | for (const auto &Relocation : RelaPlt->relocations()) { |
| 447 | if (Relocation.getType() != JumpSlotReloc) |
| 448 | continue; |
| 449 | auto PltEntryIter = GotToPlt.find(Relocation.getOffset()); |
| 450 | if (PltEntryIter != GotToPlt.end()) |
| 451 | Result.push_back(std::make_pair( |
| 452 | Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second)); |
| 453 | } |
| 454 | return Result; |
| 455 | } |