LLVM  8.0.0svn
ELFObjectFile.cpp
Go to the documentation of this file.
1 //===- ELFObjectFile.cpp - ELF object file implementation -----------------===//
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 //
10 // Part of the ELFObjectFile class implementation.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm/ADT/Triple.h"
16 #include "llvm/BinaryFormat/ELF.h"
19 #include "llvm/Object/ELF.h"
20 #include "llvm/Object/ELFTypes.h"
21 #include "llvm/Object/Error.h"
24 #include "llvm/Support/Endian.h"
28 #include <algorithm>
29 #include <cstddef>
30 #include <cstdint>
31 #include <memory>
32 #include <string>
33 #include <system_error>
34 #include <utility>
35 
36 using namespace llvm;
37 using namespace object;
38 
40  : ObjectFile(Type, Source) {}
41 
42 template <class ELFT>
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 
53  std::pair<unsigned char, unsigned char> Ident =
55  std::size_t MaxAlignment =
56  1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
57 
58  if (MaxAlignment < 2)
59  return createError("Insufficient alignment");
60 
61  if (Ident.first == ELF::ELFCLASS32) {
62  if (Ident.second == ELF::ELFDATA2LSB)
63  return createPtr<ELF32LE>(Obj);
64  else if (Ident.second == ELF::ELFDATA2MSB)
65  return createPtr<ELF32BE>(Obj);
66  else
67  return createError("Invalid ELF data");
68  } else if (Ident.first == ELF::ELFCLASS64) {
69  if (Ident.second == ELF::ELFDATA2LSB)
70  return createPtr<ELF64LE>(Obj);
71  else if (Ident.second == ELF::ELFDATA2MSB)
72  return createPtr<ELF64BE>(Obj);
73  else
74  return createError("Invalid ELF data");
75  }
76  return createError("Invalid ELF class");
77 }
78 
81  unsigned PlatformFlags = getPlatformFlags();
82 
83  switch (PlatformFlags & ELF::EF_MIPS_ARCH) {
85  break;
87  Features.AddFeature("mips2");
88  break;
90  Features.AddFeature("mips3");
91  break;
93  Features.AddFeature("mips4");
94  break;
96  Features.AddFeature("mips5");
97  break;
99  Features.AddFeature("mips32");
100  break;
102  Features.AddFeature("mips64");
103  break;
105  Features.AddFeature("mips32r2");
106  break;
108  Features.AddFeature("mips64r2");
109  break;
111  Features.AddFeature("mips32r6");
112  break;
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) {
122  // No feature associated with this value.
123  break;
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 
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)
151 
155  Features.AddFeature("aclass");
156  break;
158  Features.AddFeature("rclass");
159  if (isV7)
160  Features.AddFeature("hwdiv");
161  break;
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;
175  Features.AddFeature("thumb", false);
176  Features.AddFeature("thumb2", false);
177  break;
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;
189  Features.AddFeature("vfp2", false);
190  Features.AddFeature("vfp3", false);
191  Features.AddFeature("vfp4", false);
192  break;
194  Features.AddFeature("vfp2");
195  break;
198  Features.AddFeature("vfp3");
199  break;
202  Features.AddFeature("vfp4");
203  break;
204  }
205  }
206 
209  default:
210  break;
212  Features.AddFeature("neon", false);
213  Features.AddFeature("fp16", false);
214  break;
216  Features.AddFeature("neon");
217  break;
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;
230  Features.AddFeature("hwdiv", false);
231  Features.AddFeature("hwdiv-arm", false);
232  break;
234  Features.AddFeature("hwdiv");
235  Features.AddFeature("hwdiv-arm");
236  break;
237  }
238  }
239 
240  return Features;
241 }
242 
245  unsigned PlatformFlags = getPlatformFlags();
246 
247  if (PlatformFlags & ELF::EF_RISCV_RVC) {
248  Features.AddFeature("c");
249  }
250 
251  return Features;
252 }
253 
255  switch (getEMachine()) {
256  case ELF::EM_MIPS:
257  return getMIPSFeatures();
258  case ELF::EM_ARM:
259  return getARMFeatures();
260  case ELF::EM_RISCV:
261  return getRISCVFeatures();
262  default:
263  return SubtargetFeatures();
264  }
265 }
266 
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.
279  if (TheTriple.isThumb())
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;
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;
320  Triple += "v6sm";
321  break;
323  Triple += "v7em";
324  break;
325  }
326  }
327  if (!isLittleEndian())
328  Triple += "eb";
329 
330  TheTriple.setArchName(Triple);
331 }
332 
333 std::vector<std::pair<DataRefImpl, uint64_t>>
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  }
354  std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
355  std::unique_ptr<const MCInstrAnalysis> MIA(
356  T->createMCInstrAnalysis(MII.get()));
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.
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 }
const NoneType None
Definition: None.h:24
bool hasAttribute(unsigned Tag) const
virtual uint16_t getEMachine() const =0
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
SubtargetFeatures getFeatures() const override
Triple makeTriple() const
Create a triple from the data in this object file.
Definition: ObjectFile.cpp:84
This class is the base class for all object file types.
Definition: ObjectFile.h:190
static Error createError(StringRef Err)
Definition: ELF.h:48
static const Target * lookupTarget(const std::string &Triple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.
unsigned getAttributeValue(unsigned Tag) const
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:128
virtual std::error_code getBuildAttributes(ARMAttributeParser &Attributes) const
Definition: ObjectFile.h:298
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:191
void setARMSubArch(Triple &TheTriple) const override
StringRef getBuffer() const
Definition: MemoryBuffer.h:273
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
void AddFeature(StringRef String, bool Enable=true)
Adds Features.
SubArchType getSubArch() const
getSubArch - get the parsed subarchitecture type for this triple.
Definition: Triple.h:289
ArchType getArch() const
getArch - Get the parsed architecture type of this triple.
Definition: Triple.h:286
std::pair< unsigned char, unsigned char > getElfArchType(StringRef Object)
Definition: ELF.h:40
section_iterator_range sections() const
Definition: ObjectFile.h:278
const std::string & str() const
Definition: Triple.h:355
std::vector< std::pair< DataRefImpl, uint64_t > > getPltAddresses() const
std::size_t countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0&#39;s from the least significant bit to the most stopping at the first 1...
Definition: MathExtras.h:120
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static Expected< std::unique_ptr< ObjectFile > > createELFObjectFile(MemoryBufferRef Object)
void setArchName(StringRef Str)
setArchName - Set the architecture (first) component of the triple by name.
Definition: Triple.cpp:1165
static Expected< ELFObjectFile< ELFT > > create(MemoryBufferRef Object)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isLittleEndian() const
Definition: Binary.h:131
ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
virtual unsigned getPlatformFlags() const =0
Returns platform-specific object flags, if any.
Manages the enabling and disabling of subtarget specific features.
SubtargetFeatures getMIPSFeatures() const
static Expected< std::unique_ptr< ELFObjectFile< ELFT > > > createPtr(MemoryBufferRef Object)
bool isThumb() const
Tests whether the target is Thumb (little and big endian).
Definition: Triple.h:650
const char * getBufferStart() const
Definition: MemoryBuffer.h:277
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
const FeatureBitset Features
SubtargetFeatures getARMFeatures() const
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
SubtargetFeatures getRISCVFeatures() const
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:81