LLVM  10.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  {"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 };
56 
58  : ObjectFile(Type, Source) {}
59 
60 template <class ELFT>
63  auto Ret = ELFObjectFile<ELFT>::create(Object);
64  if (Error E = Ret.takeError())
65  return std::move(E);
66  return std::make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
67 }
68 
71  std::pair<unsigned char, unsigned char> Ident =
73  std::size_t MaxAlignment =
74  1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
75 
76  if (MaxAlignment < 2)
77  return createError("Insufficient alignment");
78 
79  if (Ident.first == ELF::ELFCLASS32) {
80  if (Ident.second == ELF::ELFDATA2LSB)
81  return createPtr<ELF32LE>(Obj);
82  else if (Ident.second == ELF::ELFDATA2MSB)
83  return createPtr<ELF32BE>(Obj);
84  else
85  return createError("Invalid ELF data");
86  } else if (Ident.first == ELF::ELFCLASS64) {
87  if (Ident.second == ELF::ELFDATA2LSB)
88  return createPtr<ELF64LE>(Obj);
89  else if (Ident.second == ELF::ELFDATA2MSB)
90  return createPtr<ELF64BE>(Obj);
91  else
92  return createError("Invalid ELF data");
93  }
94  return createError("Invalid ELF class");
95 }
96 
98  SubtargetFeatures Features;
99  unsigned PlatformFlags = getPlatformFlags();
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;
117  Features.AddFeature("mips32");
118  break;
120  Features.AddFeature("mips64");
121  break;
123  Features.AddFeature("mips32r2");
124  break;
126  Features.AddFeature("mips64r2");
127  break;
129  Features.AddFeature("mips32r6");
130  break;
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) {
140  // No feature associated with this value.
141  break;
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 
158  SubtargetFeatures Features;
159  ARMAttributeParser Attributes;
160  if (Error E = getBuildAttributes(Attributes))
161  return SubtargetFeatures();
162 
163  // both ARMv7-M and R have to support thumb hardware div
164  bool isV7 = false;
165  if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch))
166  isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)
168 
172  Features.AddFeature("aclass");
173  break;
175  Features.AddFeature("rclass");
176  if (isV7)
177  Features.AddFeature("hwdiv");
178  break;
180  Features.AddFeature("mclass");
181  if (isV7)
182  Features.AddFeature("hwdiv");
183  break;
184  }
185  }
186 
187  if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
188  switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
189  default:
190  break;
192  Features.AddFeature("thumb", false);
193  Features.AddFeature("thumb2", false);
194  break;
196  Features.AddFeature("thumb2");
197  break;
198  }
199  }
200 
201  if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
202  switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
203  default:
204  break;
206  Features.AddFeature("vfp2sp", false);
207  Features.AddFeature("vfp3d16sp", false);
208  Features.AddFeature("vfp4d16sp", false);
209  break;
211  Features.AddFeature("vfp2");
212  break;
215  Features.AddFeature("vfp3");
216  break;
219  Features.AddFeature("vfp4");
220  break;
221  }
222  }
223 
226  default:
227  break;
229  Features.AddFeature("neon", false);
230  Features.AddFeature("fp16", false);
231  break;
233  Features.AddFeature("neon");
234  break;
236  Features.AddFeature("neon");
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;
247  Features.AddFeature("mve", false);
248  Features.AddFeature("mve.fp", false);
249  break;
251  Features.AddFeature("mve.fp", false);
252  Features.AddFeature("mve");
253  break;
255  Features.AddFeature("mve.fp");
256  break;
257  }
258  }
259 
260  if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
261  switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
262  default:
263  break;
265  Features.AddFeature("hwdiv", false);
266  Features.AddFeature("hwdiv-arm", false);
267  break;
269  Features.AddFeature("hwdiv");
270  Features.AddFeature("hwdiv-arm");
271  break;
272  }
273  }
274 
275  return Features;
276 }
277 
279  SubtargetFeatures Features;
280  unsigned PlatformFlags = getPlatformFlags();
281 
282  if (PlatformFlags & ELF::EF_RISCV_RVC) {
283  Features.AddFeature("c");
284  }
285 
286  return Features;
287 }
288 
290  switch (getEMachine()) {
291  case ELF::EM_MIPS:
292  return getMIPSFeatures();
293  case ELF::EM_ARM:
294  return getARMFeatures();
295  case ELF::EM_RISCV:
296  return getRISCVFeatures();
297  default:
298  return SubtargetFeatures();
299  }
300 }
301 
302 // FIXME Encode from a tablegen description or target parser.
303 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
304  if (TheTriple.getSubArch() != Triple::NoSubArch)
305  return;
306 
307  ARMAttributeParser Attributes;
308  if (Error E = getBuildAttributes(Attributes))
309  return;
310 
311  std::string Triple;
312  // Default to ARM, but use the triple if it's been set.
313  if (TheTriple.isThumb())
314  Triple = "thumb";
315  else
316  Triple = "arm";
317 
318  if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
319  switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
320  case ARMBuildAttrs::v4:
321  Triple += "v4";
322  break;
323  case ARMBuildAttrs::v4T:
324  Triple += "v4t";
325  break;
326  case ARMBuildAttrs::v5T:
327  Triple += "v5t";
328  break;
329  case ARMBuildAttrs::v5TE:
330  Triple += "v5te";
331  break;
333  Triple += "v5tej";
334  break;
335  case ARMBuildAttrs::v6:
336  Triple += "v6";
337  break;
338  case ARMBuildAttrs::v6KZ:
339  Triple += "v6kz";
340  break;
341  case ARMBuildAttrs::v6T2:
342  Triple += "v6t2";
343  break;
344  case ARMBuildAttrs::v6K:
345  Triple += "v6k";
346  break;
347  case ARMBuildAttrs::v7:
348  Triple += "v7";
349  break;
350  case ARMBuildAttrs::v6_M:
351  Triple += "v6m";
352  break;
354  Triple += "v6sm";
355  break;
357  Triple += "v7em";
358  break;
359  case ARMBuildAttrs::v8_A:
360  Triple += "v8a";
361  break;
362  case ARMBuildAttrs::v8_R:
363  Triple += "v8r";
364  break;
366  Triple += "v8m.base";
367  break;
369  Triple += "v8m.main";
370  break;
372  Triple += "v8.1m.main";
373  break;
374  }
375  }
376  if (!isLittleEndian())
377  Triple += "eb";
378 
379  TheTriple.setArchName(Triple);
380 }
381 
382 std::vector<std::pair<DataRefImpl, uint64_t>>
384  std::string Err;
385  const auto Triple = makeTriple();
386  const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err);
387  if (!T)
388  return {};
389  uint64_t JumpSlotReloc = 0;
390  switch (Triple.getArch()) {
391  case Triple::x86:
392  JumpSlotReloc = ELF::R_386_JUMP_SLOT;
393  break;
394  case Triple::x86_64:
395  JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT;
396  break;
397  case Triple::aarch64:
398  JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT;
399  break;
400  default:
401  return {};
402  }
403  std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
404  std::unique_ptr<const MCInstrAnalysis> MIA(
405  T->createMCInstrAnalysis(MII.get()));
406  if (!MIA)
407  return {};
408  Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
409  for (const SectionRef &Section : sections()) {
410  Expected<StringRef> NameOrErr = Section.getName();
411  if (!NameOrErr) {
412  consumeError(NameOrErr.takeError());
413  continue;
414  }
415  StringRef Name = *NameOrErr;
416 
417  if (Name == ".plt")
418  Plt = Section;
419  else if (Name == ".rela.plt" || Name == ".rel.plt")
420  RelaPlt = Section;
421  else if (Name == ".got.plt")
422  GotPlt = Section;
423  }
424  if (!Plt || !RelaPlt || !GotPlt)
425  return {};
426  Expected<StringRef> PltContents = Plt->getContents();
427  if (!PltContents) {
428  consumeError(PltContents.takeError());
429  return {};
430  }
431  auto PltEntries = MIA->findPltEntries(Plt->getAddress(),
432  arrayRefFromStringRef(*PltContents),
433  GotPlt->getAddress(), Triple);
434  // Build a map from GOT entry virtual address to PLT entry virtual address.
436  for (const auto &Entry : PltEntries)
437  GotToPlt.insert(std::make_pair(Entry.second, Entry.first));
438  // Find the relocations in the dynamic relocation table that point to
439  // locations in the GOT for which we know the corresponding PLT entry.
440  std::vector<std::pair<DataRefImpl, uint64_t>> Result;
441  for (const auto &Relocation : RelaPlt->relocations()) {
442  if (Relocation.getType() != JumpSlotReloc)
443  continue;
444  auto PltEntryIter = GotToPlt.find(Relocation.getOffset());
445  if (PltEntryIter != GotToPlt.end())
446  Result.push_back(std::make_pair(
447  Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second));
448  }
449  return Result;
450 }
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:221
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:552
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
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:119
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:195
void setARMSubArch(Triple &TheTriple) const override
StringRef getBuffer() const
Definition: MemoryBuffer.h:272
Tagged union holding either a T or a Error.
Definition: yaml2obj.h:21
void AddFeature(StringRef String, bool Enable=true)
Adds Features.
SubArchType getSubArch() const
getSubArch - get the parsed subarchitecture type for this triple.
Definition: Triple.h:299
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:296
virtual Error getBuildAttributes(ARMAttributeParser &Attributes) const =0
std::pair< unsigned char, unsigned char > getElfArchType(StringRef Object)
Definition: ELF.h:39
section_iterator_range sections() const
Definition: ObjectFile.h:310
const llvm::EnumEntry< unsigned > ElfSymbolTypes[NumElfSymbolTypes]
constexpr int NumElfSymbolTypes
Definition: ELFObjectFile.h:44
const std::string & str() const
Definition: Triple.h:365
std::vector< std::pair< DataRefImpl, uint64_t > > getPltAddresses() const
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:1196
static Expected< ELFObjectFile< ELFT > > create(MemoryBufferRef Object)
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:981
#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: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:694
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:81