Mercurial > hg > CbC > CbC_llvm
comparison lib/Object/ELFObjectFile.cpp @ 148:63bd29f05246
merged
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 14 Aug 2019 19:46:37 +0900 |
parents | c2174574ed3a |
children |
comparison
equal
deleted
inserted
replaced
146:3fc4d5c3e21e | 148:63bd29f05246 |
---|---|
1 //===- ELFObjectFile.cpp - ELF object file implementation -----------------===// | 1 //===- ELFObjectFile.cpp - ELF object file implementation -----------------===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 // | 4 // See https://llvm.org/LICENSE.txt for license information. |
5 // This file is distributed under the University of Illinois Open Source | 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 // License. See LICENSE.TXT for details. | |
7 // | 6 // |
8 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
9 // | 8 // |
10 // Part of the ELFObjectFile class implementation. | 9 // Part of the ELFObjectFile class implementation. |
11 // | 10 // |
12 //===----------------------------------------------------------------------===// | 11 //===----------------------------------------------------------------------===// |
13 | 12 |
14 #include "llvm/Object/ELFObjectFile.h" | 13 #include "llvm/Object/ELFObjectFile.h" |
15 #include "llvm/ADT/Triple.h" | 14 #include "llvm/ADT/Triple.h" |
16 #include "llvm/BinaryFormat/ELF.h" | 15 #include "llvm/BinaryFormat/ELF.h" |
16 #include "llvm/MC/MCInstrAnalysis.h" | |
17 #include "llvm/MC/SubtargetFeature.h" | 17 #include "llvm/MC/SubtargetFeature.h" |
18 #include "llvm/Object/ELF.h" | 18 #include "llvm/Object/ELF.h" |
19 #include "llvm/Object/ELFTypes.h" | 19 #include "llvm/Object/ELFTypes.h" |
20 #include "llvm/Object/Error.h" | 20 #include "llvm/Object/Error.h" |
21 #include "llvm/Support/ARMAttributeParser.h" | 21 #include "llvm/Support/ARMAttributeParser.h" |
22 #include "llvm/Support/ARMBuildAttributes.h" | 22 #include "llvm/Support/ARMBuildAttributes.h" |
23 #include "llvm/Support/Endian.h" | 23 #include "llvm/Support/Endian.h" |
24 #include "llvm/Support/ErrorHandling.h" | 24 #include "llvm/Support/ErrorHandling.h" |
25 #include "llvm/Support/MathExtras.h" | 25 #include "llvm/Support/MathExtras.h" |
26 #include "llvm/Support/TargetRegistry.h" | |
26 #include <algorithm> | 27 #include <algorithm> |
27 #include <cstddef> | 28 #include <cstddef> |
28 #include <cstdint> | 29 #include <cstdint> |
29 #include <memory> | 30 #include <memory> |
30 #include <string> | 31 #include <string> |
31 #include <system_error> | 32 #include <system_error> |
32 #include <utility> | 33 #include <utility> |
33 | 34 |
34 using namespace llvm; | 35 using namespace llvm; |
35 using namespace object; | 36 using namespace object; |
37 | |
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}, | |
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 }; | |
36 | 56 |
37 ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) | 57 ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) |
38 : ObjectFile(Type, Source) {} | 58 : ObjectFile(Type, Source) {} |
39 | 59 |
40 template <class ELFT> | 60 template <class ELFT> |
135 } | 155 } |
136 | 156 |
137 SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { | 157 SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { |
138 SubtargetFeatures Features; | 158 SubtargetFeatures Features; |
139 ARMAttributeParser Attributes; | 159 ARMAttributeParser Attributes; |
140 std::error_code EC = getBuildAttributes(Attributes); | 160 if (Error E = getBuildAttributes(Attributes)) |
141 if (EC) | |
142 return SubtargetFeatures(); | 161 return SubtargetFeatures(); |
143 | 162 |
144 // both ARMv7-M and R have to support thumb hardware div | 163 // both ARMv7-M and R have to support thumb hardware div |
145 bool isV7 = false; | 164 bool isV7 = false; |
146 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) | 165 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) |
182 if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) { | 201 if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) { |
183 switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) { | 202 switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) { |
184 default: | 203 default: |
185 break; | 204 break; |
186 case ARMBuildAttrs::Not_Allowed: | 205 case ARMBuildAttrs::Not_Allowed: |
187 Features.AddFeature("vfp2", false); | 206 Features.AddFeature("vfp2d16sp", false); |
188 Features.AddFeature("vfp3", false); | 207 Features.AddFeature("vfp3d16sp", false); |
189 Features.AddFeature("vfp4", false); | 208 Features.AddFeature("vfp4d16sp", false); |
190 break; | 209 break; |
191 case ARMBuildAttrs::AllowFPv2: | 210 case ARMBuildAttrs::AllowFPv2: |
192 Features.AddFeature("vfp2"); | 211 Features.AddFeature("vfp2"); |
193 break; | 212 break; |
194 case ARMBuildAttrs::AllowFPv3A: | 213 case ARMBuildAttrs::AllowFPv3A: |
214 Features.AddFeature("neon"); | 233 Features.AddFeature("neon"); |
215 break; | 234 break; |
216 case ARMBuildAttrs::AllowNeon2: | 235 case ARMBuildAttrs::AllowNeon2: |
217 Features.AddFeature("neon"); | 236 Features.AddFeature("neon"); |
218 Features.AddFeature("fp16"); | 237 Features.AddFeature("fp16"); |
238 break; | |
239 } | |
240 } | |
241 | |
242 if (Attributes.hasAttribute(ARMBuildAttrs::MVE_arch)) { | |
243 switch(Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch)) { | |
244 default: | |
245 break; | |
246 case ARMBuildAttrs::Not_Allowed: | |
247 Features.AddFeature("mve", false); | |
248 Features.AddFeature("mve.fp", false); | |
249 break; | |
250 case ARMBuildAttrs::AllowMVEInteger: | |
251 Features.AddFeature("mve.fp", false); | |
252 Features.AddFeature("mve"); | |
253 break; | |
254 case ARMBuildAttrs::AllowMVEIntegerAndFloat: | |
255 Features.AddFeature("mve.fp"); | |
219 break; | 256 break; |
220 } | 257 } |
221 } | 258 } |
222 | 259 |
223 if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) { | 260 if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) { |
266 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { | 303 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { |
267 if (TheTriple.getSubArch() != Triple::NoSubArch) | 304 if (TheTriple.getSubArch() != Triple::NoSubArch) |
268 return; | 305 return; |
269 | 306 |
270 ARMAttributeParser Attributes; | 307 ARMAttributeParser Attributes; |
271 std::error_code EC = getBuildAttributes(Attributes); | 308 if (Error E = getBuildAttributes(Attributes)) |
272 if (EC) | |
273 return; | 309 return; |
274 | 310 |
275 std::string Triple; | 311 std::string Triple; |
276 // Default to ARM, but use the triple if it's been set. | 312 // Default to ARM, but use the triple if it's been set. |
277 if (TheTriple.isThumb()) | 313 if (TheTriple.isThumb()) |
325 if (!isLittleEndian()) | 361 if (!isLittleEndian()) |
326 Triple += "eb"; | 362 Triple += "eb"; |
327 | 363 |
328 TheTriple.setArchName(Triple); | 364 TheTriple.setArchName(Triple); |
329 } | 365 } |
366 | |
367 std::vector<std::pair<DataRefImpl, uint64_t>> | |
368 ELFObjectFileBase::getPltAddresses() const { | |
369 std::string Err; | |
370 const auto Triple = makeTriple(); | |
371 const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err); | |
372 if (!T) | |
373 return {}; | |
374 uint64_t JumpSlotReloc = 0; | |
375 switch (Triple.getArch()) { | |
376 case Triple::x86: | |
377 JumpSlotReloc = ELF::R_386_JUMP_SLOT; | |
378 break; | |
379 case Triple::x86_64: | |
380 JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT; | |
381 break; | |
382 case Triple::aarch64: | |
383 JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT; | |
384 break; | |
385 default: | |
386 return {}; | |
387 } | |
388 std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo()); | |
389 std::unique_ptr<const MCInstrAnalysis> MIA( | |
390 T->createMCInstrAnalysis(MII.get())); | |
391 if (!MIA) | |
392 return {}; | |
393 Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None; | |
394 for (const SectionRef &Section : sections()) { | |
395 StringRef Name; | |
396 if (Section.getName(Name)) | |
397 continue; | |
398 if (Name == ".plt") | |
399 Plt = Section; | |
400 else if (Name == ".rela.plt" || Name == ".rel.plt") | |
401 RelaPlt = Section; | |
402 else if (Name == ".got.plt") | |
403 GotPlt = Section; | |
404 } | |
405 if (!Plt || !RelaPlt || !GotPlt) | |
406 return {}; | |
407 Expected<StringRef> PltContents = Plt->getContents(); | |
408 if (!PltContents) { | |
409 consumeError(PltContents.takeError()); | |
410 return {}; | |
411 } | |
412 auto PltEntries = MIA->findPltEntries(Plt->getAddress(), | |
413 arrayRefFromStringRef(*PltContents), | |
414 GotPlt->getAddress(), Triple); | |
415 // Build a map from GOT entry virtual address to PLT entry virtual address. | |
416 DenseMap<uint64_t, uint64_t> GotToPlt; | |
417 for (const auto &Entry : PltEntries) | |
418 GotToPlt.insert(std::make_pair(Entry.second, Entry.first)); | |
419 // Find the relocations in the dynamic relocation table that point to | |
420 // locations in the GOT for which we know the corresponding PLT entry. | |
421 std::vector<std::pair<DataRefImpl, uint64_t>> Result; | |
422 for (const auto &Relocation : RelaPlt->relocations()) { | |
423 if (Relocation.getType() != JumpSlotReloc) | |
424 continue; | |
425 auto PltEntryIter = GotToPlt.find(Relocation.getOffset()); | |
426 if (PltEntryIter != GotToPlt.end()) | |
427 Result.push_back(std::make_pair( | |
428 Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second)); | |
429 } | |
430 return Result; | |
431 } |