LLVM  12.0.0git
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"
29 #include <algorithm>
30 #include <cstddef>
31 #include <cstdint>
32 #include <memory>
33 #include <string>
34 #include <system_error>
35 #include <utility>
36 
37 using namespace llvm;
38 using namespace object;
39 
41  {"None", "NOTYPE", ELF::STT_NOTYPE},
42  {"Object", "OBJECT", ELF::STT_OBJECT},
43  {"Function", "FUNC", ELF::STT_FUNC},
44  {"Section", "SECTION", ELF::STT_SECTION},
45  {"File", "FILE", ELF::STT_FILE},
46  {"Common", "COMMON", ELF::STT_COMMON},
47  {"TLS", "TLS", ELF::STT_TLS},
48  {"Unknown", "<unknown>: 7", 7},
49  {"Unknown", "<unknown>: 8", 8},
50  {"Unknown", "<unknown>: 9", 9},
51  {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC},
52  {"OS Specific", "<OS specific>: 11", 11},
53  {"OS Specific", "<OS specific>: 12", 12},
54  {"Proc Specific", "<processor specific>: 13", 13},
55  {"Proc Specific", "<processor specific>: 14", 14},
56  {"Proc Specific", "<processor specific>: 15", 15}
57 };
58 
60  : ObjectFile(Type, Source) {}
61 
62 template <class ELFT>
65  auto Ret = ELFObjectFile<ELFT>::create(Object);
66  if (Error E = Ret.takeError())
67  return std::move(E);
68  return std::make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
69 }
70 
73  std::pair<unsigned char, unsigned char> Ident =
75  std::size_t MaxAlignment =
76  1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
77 
78  if (MaxAlignment < 2)
79  return createError("Insufficient alignment");
80 
81  if (Ident.first == ELF::ELFCLASS32) {
82  if (Ident.second == ELF::ELFDATA2LSB)
83  return createPtr<ELF32LE>(Obj);
84  else if (Ident.second == ELF::ELFDATA2MSB)
85  return createPtr<ELF32BE>(Obj);
86  else
87  return createError("Invalid ELF data");
88  } else if (Ident.first == ELF::ELFCLASS64) {
89  if (Ident.second == ELF::ELFDATA2LSB)
90  return createPtr<ELF64LE>(Obj);
91  else if (Ident.second == ELF::ELFDATA2MSB)
92  return createPtr<ELF64BE>(Obj);
93  else
94  return createError("Invalid ELF data");
95  }
96  return createError("Invalid ELF class");
97 }
98 
100  SubtargetFeatures Features;
101  unsigned PlatformFlags = getPlatformFlags();
102 
103  switch (PlatformFlags & ELF::EF_MIPS_ARCH) {
104  case ELF::EF_MIPS_ARCH_1:
105  break;
106  case ELF::EF_MIPS_ARCH_2:
107  Features.AddFeature("mips2");
108  break;
109  case ELF::EF_MIPS_ARCH_3:
110  Features.AddFeature("mips3");
111  break;
112  case ELF::EF_MIPS_ARCH_4:
113  Features.AddFeature("mips4");
114  break;
115  case ELF::EF_MIPS_ARCH_5:
116  Features.AddFeature("mips5");
117  break;
119  Features.AddFeature("mips32");
120  break;
122  Features.AddFeature("mips64");
123  break;
125  Features.AddFeature("mips32r2");
126  break;
128  Features.AddFeature("mips64r2");
129  break;
131  Features.AddFeature("mips32r6");
132  break;
134  Features.AddFeature("mips64r6");
135  break;
136  default:
137  llvm_unreachable("Unknown EF_MIPS_ARCH value");
138  }
139 
140  switch (PlatformFlags & ELF::EF_MIPS_MACH) {
142  // No feature associated with this value.
143  break;
145  Features.AddFeature("cnmips");
146  break;
147  default:
148  llvm_unreachable("Unknown EF_MIPS_ARCH value");
149  }
150 
151  if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16)
152  Features.AddFeature("mips16");
153  if (PlatformFlags & ELF::EF_MIPS_MICROMIPS)
154  Features.AddFeature("micromips");
155 
156  return Features;
157 }
158 
160  SubtargetFeatures Features;
161  ARMAttributeParser Attributes;
162  if (Error E = getBuildAttributes(Attributes)) {
163  consumeError(std::move(E));
164  return SubtargetFeatures();
165  }
166 
167  // both ARMv7-M and R have to support thumb hardware div
168  bool isV7 = false;
169  Optional<unsigned> Attr =
171  if (Attr.hasValue())
172  isV7 = Attr.getValue() == ARMBuildAttrs::v7;
173 
175  if (Attr.hasValue()) {
176  switch (Attr.getValue()) {
178  Features.AddFeature("aclass");
179  break;
181  Features.AddFeature("rclass");
182  if (isV7)
183  Features.AddFeature("hwdiv");
184  break;
186  Features.AddFeature("mclass");
187  if (isV7)
188  Features.AddFeature("hwdiv");
189  break;
190  }
191  }
192 
194  if (Attr.hasValue()) {
195  switch (Attr.getValue()) {
196  default:
197  break;
199  Features.AddFeature("thumb", false);
200  Features.AddFeature("thumb2", false);
201  break;
203  Features.AddFeature("thumb2");
204  break;
205  }
206  }
207 
208  Attr = Attributes.getAttributeValue(ARMBuildAttrs::FP_arch);
209  if (Attr.hasValue()) {
210  switch (Attr.getValue()) {
211  default:
212  break;
214  Features.AddFeature("vfp2sp", false);
215  Features.AddFeature("vfp3d16sp", false);
216  Features.AddFeature("vfp4d16sp", false);
217  break;
219  Features.AddFeature("vfp2");
220  break;
223  Features.AddFeature("vfp3");
224  break;
227  Features.AddFeature("vfp4");
228  break;
229  }
230  }
231 
233  if (Attr.hasValue()) {
234  switch (Attr.getValue()) {
235  default:
236  break;
238  Features.AddFeature("neon", false);
239  Features.AddFeature("fp16", false);
240  break;
242  Features.AddFeature("neon");
243  break;
245  Features.AddFeature("neon");
246  Features.AddFeature("fp16");
247  break;
248  }
249  }
250 
251  Attr = Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch);
252  if (Attr.hasValue()) {
253  switch (Attr.getValue()) {
254  default:
255  break;
257  Features.AddFeature("mve", false);
258  Features.AddFeature("mve.fp", false);
259  break;
261  Features.AddFeature("mve.fp", false);
262  Features.AddFeature("mve");
263  break;
265  Features.AddFeature("mve.fp");
266  break;
267  }
268  }
269 
270  Attr = Attributes.getAttributeValue(ARMBuildAttrs::DIV_use);
271  if (Attr.hasValue()) {
272  switch (Attr.getValue()) {
273  default:
274  break;
276  Features.AddFeature("hwdiv", false);
277  Features.AddFeature("hwdiv-arm", false);
278  break;
280  Features.AddFeature("hwdiv");
281  Features.AddFeature("hwdiv-arm");
282  break;
283  }
284  }
285 
286  return Features;
287 }
288 
290  SubtargetFeatures Features;
291  unsigned PlatformFlags = getPlatformFlags();
292 
293  if (PlatformFlags & ELF::EF_RISCV_RVC) {
294  Features.AddFeature("c");
295  }
296 
297  // Add features according to the ELF attribute section.
298  // If there are any unrecognized features, ignore them.
299  RISCVAttributeParser Attributes;
300  if (Error E = getBuildAttributes(Attributes)) {
301  // TODO Propagate Error.
302  consumeError(std::move(E));
303  return Features; // Keep "c" feature if there is one in PlatformFlags.
304  }
305 
307  if (Attr.hasValue()) {
308  // The Arch pattern is [rv32|rv64][i|e]version(_[m|a|f|d|c]version)*
309  // Version string pattern is (major)p(minor). Major and minor are optional.
310  // For example, a version number could be 2p0, 2, or p92.
311  StringRef Arch = Attr.getValue();
312  if (Arch.consume_front("rv32"))
313  Features.AddFeature("64bit", false);
314  else if (Arch.consume_front("rv64"))
315  Features.AddFeature("64bit");
316 
317  while (!Arch.empty()) {
318  switch (Arch[0]) {
319  default:
320  break; // Ignore unexpected features.
321  case 'i':
322  Features.AddFeature("e", false);
323  break;
324  case 'd':
325  Features.AddFeature("f"); // D-ext will imply F-ext.
327  case 'e':
328  case 'm':
329  case 'a':
330  case 'f':
331  case 'c':
332  Features.AddFeature(Arch.take_front());
333  break;
334  }
335 
336  // FIXME: Handle version numbers.
337  Arch = Arch.drop_until([](char c) { return c == '_' || c == '\0'; });
338  Arch = Arch.drop_while([](char c) { return c == '_'; });
339  }
340  }
341 
342  return Features;
343 }
344 
346  switch (getEMachine()) {
347  case ELF::EM_MIPS:
348  return getMIPSFeatures();
349  case ELF::EM_ARM:
350  return getARMFeatures();
351  case ELF::EM_RISCV:
352  return getRISCVFeatures();
353  default:
354  return SubtargetFeatures();
355  }
356 }
357 
358 // FIXME Encode from a tablegen description or target parser.
359 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
360  if (TheTriple.getSubArch() != Triple::NoSubArch)
361  return;
362 
363  ARMAttributeParser Attributes;
364  if (Error E = getBuildAttributes(Attributes)) {
365  // TODO Propagate Error.
366  consumeError(std::move(E));
367  return;
368  }
369 
370  std::string Triple;
371  // Default to ARM, but use the triple if it's been set.
372  if (TheTriple.isThumb())
373  Triple = "thumb";
374  else
375  Triple = "arm";
376 
377  Optional<unsigned> Attr =
379  if (Attr.hasValue()) {
380  switch (Attr.getValue()) {
381  case ARMBuildAttrs::v4:
382  Triple += "v4";
383  break;
384  case ARMBuildAttrs::v4T:
385  Triple += "v4t";
386  break;
387  case ARMBuildAttrs::v5T:
388  Triple += "v5t";
389  break;
390  case ARMBuildAttrs::v5TE:
391  Triple += "v5te";
392  break;
394  Triple += "v5tej";
395  break;
396  case ARMBuildAttrs::v6:
397  Triple += "v6";
398  break;
399  case ARMBuildAttrs::v6KZ:
400  Triple += "v6kz";
401  break;
402  case ARMBuildAttrs::v6T2:
403  Triple += "v6t2";
404  break;
405  case ARMBuildAttrs::v6K:
406  Triple += "v6k";
407  break;
408  case ARMBuildAttrs::v7:
409  Triple += "v7";
410  break;
411  case ARMBuildAttrs::v6_M:
412  Triple += "v6m";
413  break;
415  Triple += "v6sm";
416  break;
418  Triple += "v7em";
419  break;
420  case ARMBuildAttrs::v8_A:
421  Triple += "v8a";
422  break;
423  case ARMBuildAttrs::v8_R:
424  Triple += "v8r";
425  break;
427  Triple += "v8m.base";
428  break;
430  Triple += "v8m.main";
431  break;
433  Triple += "v8.1m.main";
434  break;
435  }
436  }
437  if (!isLittleEndian())
438  Triple += "eb";
439 
440  TheTriple.setArchName(Triple);
441 }
442 
443 std::vector<std::pair<DataRefImpl, uint64_t>>
445  std::string Err;
446  const auto Triple = makeTriple();
447  const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err);
448  if (!T)
449  return {};
450  uint64_t JumpSlotReloc = 0;
451  switch (Triple.getArch()) {
452  case Triple::x86:
453  JumpSlotReloc = ELF::R_386_JUMP_SLOT;
454  break;
455  case Triple::x86_64:
456  JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT;
457  break;
458  case Triple::aarch64:
459  JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT;
460  break;
461  default:
462  return {};
463  }
464  std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
465  std::unique_ptr<const MCInstrAnalysis> MIA(
466  T->createMCInstrAnalysis(MII.get()));
467  if (!MIA)
468  return {};
469  Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
470  for (const SectionRef &Section : sections()) {
471  Expected<StringRef> NameOrErr = Section.getName();
472  if (!NameOrErr) {
473  consumeError(NameOrErr.takeError());
474  continue;
475  }
476  StringRef Name = *NameOrErr;
477 
478  if (Name == ".plt")
479  Plt = Section;
480  else if (Name == ".rela.plt" || Name == ".rel.plt")
481  RelaPlt = Section;
482  else if (Name == ".got.plt")
483  GotPlt = Section;
484  }
485  if (!Plt || !RelaPlt || !GotPlt)
486  return {};
487  Expected<StringRef> PltContents = Plt->getContents();
488  if (!PltContents) {
489  consumeError(PltContents.takeError());
490  return {};
491  }
492  auto PltEntries = MIA->findPltEntries(Plt->getAddress(),
493  arrayRefFromStringRef(*PltContents),
494  GotPlt->getAddress(), Triple);
495  // Build a map from GOT entry virtual address to PLT entry virtual address.
497  for (const auto &Entry : PltEntries)
498  GotToPlt.insert(std::make_pair(Entry.second, Entry.first));
499  // Find the relocations in the dynamic relocation table that point to
500  // locations in the GOT for which we know the corresponding PLT entry.
501  std::vector<std::pair<DataRefImpl, uint64_t>> Result;
502  for (const auto &Relocation : RelaPlt->relocations()) {
503  if (Relocation.getType() != JumpSlotReloc)
504  continue;
505  auto PltEntryIter = GotToPlt.find(Relocation.getOffset());
506  if (PltEntryIter != GotToPlt.end())
507  Result.push_back(std::make_pair(
508  Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second));
509  }
510  return Result;
511 }
const NoneType None
Definition: None.h:23
LLVM_NODISCARD StringRef take_front(size_t N=1) const
Return a StringRef equal to &#39;this&#39; but with only the first N elements remaining.
Definition: StringRef.h:621
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:106
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition: StringRef.h:683
This class is the base class for all object file types.
Definition: ObjectFile.h:225
ArrayRef< uint8_t > arrayRefFromStringRef(StringRef Input)
Construct a string ref from an array ref of unsigned chars.
Definition: StringExtras.h:60
Error takeError()
Take ownership of the stored error.
Definition: Error.h:557
static const Target * lookupTarget(const std::string &Triple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.
virtual Error getBuildAttributes(ELFAttributeParser &Attributes) const =0
unsigned 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:157
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:207
void setARMSubArch(Triple &TheTriple) const override
StringRef getBuffer() const
Definition: MemoryBuffer.h:274
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
Optional< StringRef > getAttributeString(unsigned tag) const
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:156
void AddFeature(StringRef String, bool Enable=true)
Adds Features.
SubArchType getSubArch() const
getSubArch - get the parsed subarchitecture type for this triple.
Definition: Triple.h:303
static Error createError(const Twine &Err)
Definition: ELF.h:47
ArchType getArch() const
getArch - Get the parsed architecture type of this triple.
Definition: Triple.h:300
const T & getValue() const LLVM_LVALUE_FUNCTION
Definition: Optional.h:255
std::pair< unsigned char, unsigned char > getElfArchType(StringRef Object)
Definition: ELF.h:39
section_iterator_range sections() const
Definition: ObjectFile.h:319
const llvm::EnumEntry< unsigned > ElfSymbolTypes[NumElfSymbolTypes]
constexpr int NumElfSymbolTypes
Definition: ELFObjectFile.h:44
const std::string & str() const
Definition: Triple.h:369
std::vector< std::pair< DataRefImpl, uint64_t > > getPltAddresses() const
LLVM_NODISCARD StringRef drop_until(function_ref< bool(char)> F) const
Return a StringRef equal to &#39;this&#39;, but with all characters not satisfying the given predicate droppe...
Definition: StringRef.h:677
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:1206
static Expected< ELFObjectFile< ELFT > > create(MemoryBufferRef Object)
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1006
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isLittleEndian() const
Definition: Binary.h:146
ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:45
Optional< unsigned > getAttributeValue(unsigned tag) const
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 hasValue() const
Definition: Optional.h:259
bool isThumb() const
Tests whether the target is Thumb (little and big endian).
Definition: Triple.h:695
LLVM_NODISCARD StringRef drop_while(function_ref< bool(char)> F) const
Return a StringRef equal to &#39;this&#39;, but with all characters satisfying the given predicate dropped fr...
Definition: StringRef.h:670
const char * getBufferStart() const
Definition: MemoryBuffer.h:278
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:280
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:57
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