LLVM  9.0.0svn
ELFObjectFile.cpp
Go to the documentation of this file.
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 
14 #include "llvm/ADT/Triple.h"
15 #include "llvm/BinaryFormat/ELF.h"
18 #include "llvm/Object/ELF.h"
19 #include "llvm/Object/ELFTypes.h"
20 #include "llvm/Object/Error.h"
23 #include "llvm/Support/Endian.h"
27 #include <algorithm>
28 #include <cstddef>
29 #include <cstdint>
30 #include <memory>
31 #include <string>
32 #include <system_error>
33 #include <utility>
34 
35 using namespace llvm;
36 using namespace object;
37 
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  {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC}};
47 
49  : ObjectFile(Type, Source) {}
50 
51 template <class ELFT>
54  auto Ret = ELFObjectFile<ELFT>::create(Object);
55  if (Error E = Ret.takeError())
56  return std::move(E);
57  return make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
58 }
59 
62  std::pair<unsigned char, unsigned char> Ident =
64  std::size_t MaxAlignment =
65  1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
66 
67  if (MaxAlignment < 2)
68  return createError("Insufficient alignment");
69 
70  if (Ident.first == ELF::ELFCLASS32) {
71  if (Ident.second == ELF::ELFDATA2LSB)
72  return createPtr<ELF32LE>(Obj);
73  else if (Ident.second == ELF::ELFDATA2MSB)
74  return createPtr<ELF32BE>(Obj);
75  else
76  return createError("Invalid ELF data");
77  } else if (Ident.first == ELF::ELFCLASS64) {
78  if (Ident.second == ELF::ELFDATA2LSB)
79  return createPtr<ELF64LE>(Obj);
80  else if (Ident.second == ELF::ELFDATA2MSB)
81  return createPtr<ELF64BE>(Obj);
82  else
83  return createError("Invalid ELF data");
84  }
85  return createError("Invalid ELF class");
86 }
87 
89  SubtargetFeatures Features;
90  unsigned PlatformFlags = getPlatformFlags();
91 
92  switch (PlatformFlags & ELF::EF_MIPS_ARCH) {
94  break;
96  Features.AddFeature("mips2");
97  break;
99  Features.AddFeature("mips3");
100  break;
101  case ELF::EF_MIPS_ARCH_4:
102  Features.AddFeature("mips4");
103  break;
104  case ELF::EF_MIPS_ARCH_5:
105  Features.AddFeature("mips5");
106  break;
108  Features.AddFeature("mips32");
109  break;
111  Features.AddFeature("mips64");
112  break;
114  Features.AddFeature("mips32r2");
115  break;
117  Features.AddFeature("mips64r2");
118  break;
120  Features.AddFeature("mips32r6");
121  break;
123  Features.AddFeature("mips64r6");
124  break;
125  default:
126  llvm_unreachable("Unknown EF_MIPS_ARCH value");
127  }
128 
129  switch (PlatformFlags & ELF::EF_MIPS_MACH) {
131  // No feature associated with this value.
132  break;
134  Features.AddFeature("cnmips");
135  break;
136  default:
137  llvm_unreachable("Unknown EF_MIPS_ARCH value");
138  }
139 
140  if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16)
141  Features.AddFeature("mips16");
142  if (PlatformFlags & ELF::EF_MIPS_MICROMIPS)
143  Features.AddFeature("micromips");
144 
145  return Features;
146 }
147 
149  SubtargetFeatures Features;
150  ARMAttributeParser Attributes;
151  std::error_code EC = getBuildAttributes(Attributes);
152  if (EC)
153  return SubtargetFeatures();
154 
155  // both ARMv7-M and R have to support thumb hardware div
156  bool isV7 = false;
157  if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch))
158  isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)
160 
164  Features.AddFeature("aclass");
165  break;
167  Features.AddFeature("rclass");
168  if (isV7)
169  Features.AddFeature("hwdiv");
170  break;
172  Features.AddFeature("mclass");
173  if (isV7)
174  Features.AddFeature("hwdiv");
175  break;
176  }
177  }
178 
179  if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
180  switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
181  default:
182  break;
184  Features.AddFeature("thumb", false);
185  Features.AddFeature("thumb2", false);
186  break;
188  Features.AddFeature("thumb2");
189  break;
190  }
191  }
192 
193  if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
194  switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
195  default:
196  break;
198  Features.AddFeature("vfp2", false);
199  Features.AddFeature("vfp3", false);
200  Features.AddFeature("vfp4", false);
201  break;
203  Features.AddFeature("vfp2");
204  break;
207  Features.AddFeature("vfp3");
208  break;
211  Features.AddFeature("vfp4");
212  break;
213  }
214  }
215 
218  default:
219  break;
221  Features.AddFeature("neon", false);
222  Features.AddFeature("fp16", false);
223  break;
225  Features.AddFeature("neon");
226  break;
228  Features.AddFeature("neon");
229  Features.AddFeature("fp16");
230  break;
231  }
232  }
233 
234  if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
235  switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
236  default:
237  break;
239  Features.AddFeature("hwdiv", false);
240  Features.AddFeature("hwdiv-arm", false);
241  break;
243  Features.AddFeature("hwdiv");
244  Features.AddFeature("hwdiv-arm");
245  break;
246  }
247  }
248 
249  return Features;
250 }
251 
253  SubtargetFeatures Features;
254  unsigned PlatformFlags = getPlatformFlags();
255 
256  if (PlatformFlags & ELF::EF_RISCV_RVC) {
257  Features.AddFeature("c");
258  }
259 
260  return Features;
261 }
262 
264  switch (getEMachine()) {
265  case ELF::EM_MIPS:
266  return getMIPSFeatures();
267  case ELF::EM_ARM:
268  return getARMFeatures();
269  case ELF::EM_RISCV:
270  return getRISCVFeatures();
271  default:
272  return SubtargetFeatures();
273  }
274 }
275 
276 // FIXME Encode from a tablegen description or target parser.
277 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
278  if (TheTriple.getSubArch() != Triple::NoSubArch)
279  return;
280 
281  ARMAttributeParser Attributes;
282  std::error_code EC = getBuildAttributes(Attributes);
283  if (EC)
284  return;
285 
286  std::string Triple;
287  // Default to ARM, but use the triple if it's been set.
288  if (TheTriple.isThumb())
289  Triple = "thumb";
290  else
291  Triple = "arm";
292 
293  if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
294  switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
295  case ARMBuildAttrs::v4:
296  Triple += "v4";
297  break;
298  case ARMBuildAttrs::v4T:
299  Triple += "v4t";
300  break;
301  case ARMBuildAttrs::v5T:
302  Triple += "v5t";
303  break;
304  case ARMBuildAttrs::v5TE:
305  Triple += "v5te";
306  break;
308  Triple += "v5tej";
309  break;
310  case ARMBuildAttrs::v6:
311  Triple += "v6";
312  break;
313  case ARMBuildAttrs::v6KZ:
314  Triple += "v6kz";
315  break;
316  case ARMBuildAttrs::v6T2:
317  Triple += "v6t2";
318  break;
319  case ARMBuildAttrs::v6K:
320  Triple += "v6k";
321  break;
322  case ARMBuildAttrs::v7:
323  Triple += "v7";
324  break;
325  case ARMBuildAttrs::v6_M:
326  Triple += "v6m";
327  break;
329  Triple += "v6sm";
330  break;
332  Triple += "v7em";
333  break;
334  }
335  }
336  if (!isLittleEndian())
337  Triple += "eb";
338 
339  TheTriple.setArchName(Triple);
340 }
341 
342 std::vector<std::pair<DataRefImpl, uint64_t>>
344  std::string Err;
345  const auto Triple = makeTriple();
346  const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err);
347  if (!T)
348  return {};
349  uint64_t JumpSlotReloc = 0;
350  switch (Triple.getArch()) {
351  case Triple::x86:
352  JumpSlotReloc = ELF::R_386_JUMP_SLOT;
353  break;
354  case Triple::x86_64:
355  JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT;
356  break;
357  case Triple::aarch64:
358  JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT;
359  break;
360  default:
361  return {};
362  }
363  std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
364  std::unique_ptr<const MCInstrAnalysis> MIA(
365  T->createMCInstrAnalysis(MII.get()));
366  if (!MIA)
367  return {};
368  Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
369  for (const SectionRef &Section : sections()) {
370  StringRef Name;
371  if (Section.getName(Name))
372  continue;
373  if (Name == ".plt")
374  Plt = Section;
375  else if (Name == ".rela.plt" || Name == ".rel.plt")
376  RelaPlt = Section;
377  else if (Name == ".got.plt")
378  GotPlt = Section;
379  }
380  if (!Plt || !RelaPlt || !GotPlt)
381  return {};
382  StringRef PltContents;
383  if (Plt->getContents(PltContents))
384  return {};
385  ArrayRef<uint8_t> PltBytes((const uint8_t *)PltContents.data(),
386  Plt->getSize());
387  auto PltEntries = MIA->findPltEntries(Plt->getAddress(), PltBytes,
388  GotPlt->getAddress(), Triple);
389  // Build a map from GOT entry virtual address to PLT entry virtual address.
391  for (const auto &Entry : PltEntries)
392  GotToPlt.insert(std::make_pair(Entry.second, Entry.first));
393  // Find the relocations in the dynamic relocation table that point to
394  // locations in the GOT for which we know the corresponding PLT entry.
395  std::vector<std::pair<DataRefImpl, uint64_t>> Result;
396  for (const auto &Relocation : RelaPlt->relocations()) {
397  if (Relocation.getType() != JumpSlotReloc)
398  continue;
399  auto PltEntryIter = GotToPlt.find(Relocation.getOffset());
400  if (PltEntryIter != GotToPlt.end())
401  Result.push_back(std::make_pair(
402  Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second));
403  }
404  return Result;
405 }
const NoneType None
Definition: None.h:23
bool hasAttribute(unsigned Tag) const
virtual uint16_t getEMachine() const =0
This class represents lattice values for constants.
Definition: AllocatorList.h:23
SubtargetFeatures getFeatures() const override
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
Triple makeTriple() const
Create a triple from the data in this object file.
Definition: ObjectFile.cpp:91
This class is the base class for all object file types.
Definition: ObjectFile.h:225
static Error createError(StringRef Err)
Definition: ELF.h:47
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
virtual std::error_code getBuildAttributes(ARMAttributeParser &Attributes) const
Definition: ObjectFile.h:335
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:221
void setARMSubArch(Triple &TheTriple) const override
StringRef getBuffer() const
Definition: MemoryBuffer.h:272
Tagged union holding either a T or a Error.
Definition: CachePruning.h:22
void AddFeature(StringRef String, bool Enable=true)
Adds Features.
SubArchType getSubArch() const
getSubArch - get the parsed subarchitecture type for this triple.
Definition: Triple.h:293
ArchType getArch() const
getArch - Get the parsed architecture type of this triple.
Definition: Triple.h:290
std::pair< unsigned char, unsigned char > getElfArchType(StringRef Object)
Definition: ELF.h:39
section_iterator_range sections() const
Definition: ObjectFile.h:315
const llvm::EnumEntry< unsigned > ElfSymbolTypes[NumElfSymbolTypes]
constexpr int NumElfSymbolTypes
Definition: ELFObjectFile.h:44
const std::string & str() const
Definition: Triple.h:359
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:119
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
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:1179
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:130
ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:43
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:674
LLVM_NODISCARD const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:122
const char * getBufferStart() const
Definition: MemoryBuffer.h:276
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
SubtargetFeatures getARMFeatures() const
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
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:80