LLVM  8.0.1
COFFImportFile.cpp
Go to the documentation of this file.
1 //===- COFFImportFile.cpp - COFF short import 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 // This file defines the writeImportLibrary function.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/Object/Archive.h"
18 #include "llvm/Object/COFF.h"
19 #include "llvm/Support/Error.h"
20 #include "llvm/Support/Path.h"
21 
22 #include <cstdint>
23 #include <string>
24 #include <vector>
25 
26 using namespace llvm::COFF;
27 using namespace llvm::object;
28 using namespace llvm;
29 
30 namespace llvm {
31 namespace object {
32 
34  switch (Machine) {
35  default:
36  llvm_unreachable("unsupported machine");
39  return false;
42  return true;
43  }
44 }
45 
47  switch (Machine) {
48  default:
49  llvm_unreachable("unsupported machine");
58  }
59 }
60 
61 template <class T> static void append(std::vector<uint8_t> &B, const T &Data) {
62  size_t S = B.size();
63  B.resize(S + sizeof(T));
64  memcpy(&B[S], &Data, sizeof(T));
65 }
66 
67 static void writeStringTable(std::vector<uint8_t> &B,
69  // The COFF string table consists of a 4-byte value which is the size of the
70  // table, including the length field itself. This value is followed by the
71  // string content itself, which is an array of null-terminated C-style
72  // strings. The termination is important as they are referenced to by offset
73  // by the symbol entity in the file format.
74 
75  size_t Pos = B.size();
76  size_t Offset = B.size();
77 
78  // Skip over the length field, we will fill it in later as we will have
79  // computed the length while emitting the string content itself.
80  Pos += sizeof(uint32_t);
81 
82  for (const auto &S : Strings) {
83  B.resize(Pos + S.length() + 1);
84  strcpy(reinterpret_cast<char *>(&B[Pos]), S.c_str());
85  Pos += S.length() + 1;
86  }
87 
88  // Backfill the length of the table now that it has been computed.
89  support::ulittle32_t Length(B.size() - Offset);
90  support::endian::write32le(&B[Offset], Length);
91 }
92 
94  MachineTypes Machine, bool MinGW) {
95  // A decorated stdcall function in MSVC is exported with the
96  // type IMPORT_NAME, and the exported function name includes the
97  // the leading underscore. In MinGW on the other hand, a decorated
98  // stdcall function still omits the underscore (IMPORT_NAME_NOPREFIX).
99  // See the comment in isDecorated in COFFModuleDefinition.cpp for more
100  // details.
101  if (ExtName.startswith("_") && ExtName.contains('@') && !MinGW)
102  return IMPORT_NAME;
103  if (Sym != ExtName)
104  return IMPORT_NAME_UNDECORATE;
105  if (Machine == IMAGE_FILE_MACHINE_I386 && Sym.startswith("_"))
106  return IMPORT_NAME_NOPREFIX;
107  return IMPORT_NAME;
108 }
109 
111  StringRef To) {
112  size_t Pos = S.find(From);
113 
114  // From and To may be mangled, but substrings in S may not.
115  if (Pos == StringRef::npos && From.startswith("_") && To.startswith("_")) {
116  From = From.substr(1);
117  To = To.substr(1);
118  Pos = S.find(From);
119  }
120 
121  if (Pos == StringRef::npos) {
122  return make_error<StringError>(
123  StringRef(Twine(S + ": replacing '" + From +
124  "' with '" + To + "' failed").str()), object_error::parse_failed);
125  }
126 
127  return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str();
128 }
129 
130 static const std::string NullImportDescriptorSymbolName =
131  "__NULL_IMPORT_DESCRIPTOR";
132 
133 namespace {
134 // This class constructs various small object files necessary to support linking
135 // symbols imported from a DLL. The contents are pretty strictly defined and
136 // nearly entirely static. The details of the structures files are defined in
137 // WINNT.h and the PE/COFF specification.
138 class ObjectFactory {
139  using u16 = support::ulittle16_t;
140  using u32 = support::ulittle32_t;
142  BumpPtrAllocator Alloc;
143  StringRef ImportName;
144  StringRef Library;
145  std::string ImportDescriptorSymbolName;
146  std::string NullThunkSymbolName;
147 
148 public:
149  ObjectFactory(StringRef S, MachineTypes M)
150  : Machine(M), ImportName(S), Library(S.drop_back(4)),
151  ImportDescriptorSymbolName(("__IMPORT_DESCRIPTOR_" + Library).str()),
152  NullThunkSymbolName(("\x7f" + Library + "_NULL_THUNK_DATA").str()) {}
153 
154  // Creates an Import Descriptor. This is a small object file which contains a
155  // reference to the terminators and contains the library name (entry) for the
156  // import name table. It will force the linker to construct the necessary
157  // structure to import symbols from the DLL.
158  NewArchiveMember createImportDescriptor(std::vector<uint8_t> &Buffer);
159 
160  // Creates a NULL import descriptor. This is a small object file whcih
161  // contains a NULL import descriptor. It is used to terminate the imports
162  // from a specific DLL.
163  NewArchiveMember createNullImportDescriptor(std::vector<uint8_t> &Buffer);
164 
165  // Create a NULL Thunk Entry. This is a small object file which contains a
166  // NULL Import Address Table entry and a NULL Import Lookup Table Entry. It
167  // is used to terminate the IAT and ILT.
168  NewArchiveMember createNullThunk(std::vector<uint8_t> &Buffer);
169 
170  // Create a short import file which is described in PE/COFF spec 7. Import
171  // Library Format.
172  NewArchiveMember createShortImport(StringRef Sym, uint16_t Ordinal,
173  ImportType Type, ImportNameType NameType);
174 
175  // Create a weak external file which is described in PE/COFF Aux Format 3.
176  NewArchiveMember createWeakExternal(StringRef Sym, StringRef Weak, bool Imp);
177 };
178 } // namespace
179 
181 ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
182  const uint32_t NumberOfSections = 2;
183  const uint32_t NumberOfSymbols = 7;
184  const uint32_t NumberOfRelocations = 3;
185 
186  // COFF Header
187  coff_file_header Header{
188  u16(Machine),
189  u16(NumberOfSections),
190  u32(0),
191  u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
192  // .idata$2
194  NumberOfRelocations * sizeof(coff_relocation) +
195  // .idata$4
196  (ImportName.size() + 1)),
197  u32(NumberOfSymbols),
198  u16(0),
200  };
201  append(Buffer, Header);
202 
203  // Section Header Table
204  const coff_section SectionTable[NumberOfSections] = {
205  {{'.', 'i', 'd', 'a', 't', 'a', '$', '2'},
206  u32(0),
207  u32(0),
209  u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
210  u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
212  u32(0),
213  u16(NumberOfRelocations),
214  u16(0),
217  {{'.', 'i', 'd', 'a', 't', 'a', '$', '6'},
218  u32(0),
219  u32(0),
220  u32(ImportName.size() + 1),
221  u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
223  NumberOfRelocations * sizeof(coff_relocation)),
224  u32(0),
225  u32(0),
226  u16(0),
227  u16(0),
230  };
231  append(Buffer, SectionTable);
232 
233  // .idata$2
234  const coff_import_directory_table_entry ImportDescriptor{
235  u32(0), u32(0), u32(0), u32(0), u32(0),
236  };
237  append(Buffer, ImportDescriptor);
238 
239  const coff_relocation RelocationTable[NumberOfRelocations] = {
240  {u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(2),
242  {u32(offsetof(coff_import_directory_table_entry, ImportLookupTableRVA)),
243  u32(3), u16(getImgRelRelocation(Machine))},
244  {u32(offsetof(coff_import_directory_table_entry, ImportAddressTableRVA)),
245  u32(4), u16(getImgRelRelocation(Machine))},
246  };
247  append(Buffer, RelocationTable);
248 
249  // .idata$6
250  auto S = Buffer.size();
251  Buffer.resize(S + ImportName.size() + 1);
252  memcpy(&Buffer[S], ImportName.data(), ImportName.size());
253  Buffer[S + ImportName.size()] = '\0';
254 
255  // Symbol Table
256  coff_symbol16 SymbolTable[NumberOfSymbols] = {
257  {{{0, 0, 0, 0, 0, 0, 0, 0}},
258  u32(0),
259  u16(1),
260  u16(0),
262  0},
263  {{{'.', 'i', 'd', 'a', 't', 'a', '$', '2'}},
264  u32(0),
265  u16(1),
266  u16(0),
268  0},
269  {{{'.', 'i', 'd', 'a', 't', 'a', '$', '6'}},
270  u32(0),
271  u16(2),
272  u16(0),
274  0},
275  {{{'.', 'i', 'd', 'a', 't', 'a', '$', '4'}},
276  u32(0),
277  u16(0),
278  u16(0),
280  0},
281  {{{'.', 'i', 'd', 'a', 't', 'a', '$', '5'}},
282  u32(0),
283  u16(0),
284  u16(0),
286  0},
287  {{{0, 0, 0, 0, 0, 0, 0, 0}},
288  u32(0),
289  u16(0),
290  u16(0),
292  0},
293  {{{0, 0, 0, 0, 0, 0, 0, 0}},
294  u32(0),
295  u16(0),
296  u16(0),
298  0},
299  };
300  // TODO: Name.Offset.Offset here and in the all similar places below
301  // suggests a names refactoring. Maybe StringTableOffset.Value?
302  SymbolTable[0].Name.Offset.Offset =
303  sizeof(uint32_t);
304  SymbolTable[5].Name.Offset.Offset =
305  sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1;
306  SymbolTable[6].Name.Offset.Offset =
307  sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1 +
308  NullImportDescriptorSymbolName.length() + 1;
309  append(Buffer, SymbolTable);
310 
311  // String Table
312  writeStringTable(Buffer,
313  {ImportDescriptorSymbolName, NullImportDescriptorSymbolName,
314  NullThunkSymbolName});
315 
316  StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
317  return {MemoryBufferRef(F, ImportName)};
318 }
319 
321 ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
322  const uint32_t NumberOfSections = 1;
323  const uint32_t NumberOfSymbols = 1;
324 
325  // COFF Header
326  coff_file_header Header{
327  u16(Machine),
328  u16(NumberOfSections),
329  u32(0),
330  u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
331  // .idata$3
333  u32(NumberOfSymbols),
334  u16(0),
336  };
337  append(Buffer, Header);
338 
339  // Section Header Table
340  const coff_section SectionTable[NumberOfSections] = {
341  {{'.', 'i', 'd', 'a', 't', 'a', '$', '3'},
342  u32(0),
343  u32(0),
345  u32(sizeof(coff_file_header) +
346  (NumberOfSections * sizeof(coff_section))),
347  u32(0),
348  u32(0),
349  u16(0),
350  u16(0),
353  };
354  append(Buffer, SectionTable);
355 
356  // .idata$3
357  const coff_import_directory_table_entry ImportDescriptor{
358  u32(0), u32(0), u32(0), u32(0), u32(0),
359  };
360  append(Buffer, ImportDescriptor);
361 
362  // Symbol Table
363  coff_symbol16 SymbolTable[NumberOfSymbols] = {
364  {{{0, 0, 0, 0, 0, 0, 0, 0}},
365  u32(0),
366  u16(1),
367  u16(0),
369  0},
370  };
371  SymbolTable[0].Name.Offset.Offset = sizeof(uint32_t);
372  append(Buffer, SymbolTable);
373 
374  // String Table
375  writeStringTable(Buffer, {NullImportDescriptorSymbolName});
376 
377  StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
378  return {MemoryBufferRef(F, ImportName)};
379 }
380 
381 NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
382  const uint32_t NumberOfSections = 2;
383  const uint32_t NumberOfSymbols = 1;
384  uint32_t VASize = is32bit(Machine) ? 4 : 8;
385 
386  // COFF Header
387  coff_file_header Header{
388  u16(Machine),
389  u16(NumberOfSections),
390  u32(0),
391  u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
392  // .idata$5
393  VASize +
394  // .idata$4
395  VASize),
396  u32(NumberOfSymbols),
397  u16(0),
399  };
400  append(Buffer, Header);
401 
402  // Section Header Table
403  const coff_section SectionTable[NumberOfSections] = {
404  {{'.', 'i', 'd', 'a', 't', 'a', '$', '5'},
405  u32(0),
406  u32(0),
407  u32(VASize),
408  u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
409  u32(0),
410  u32(0),
411  u16(0),
412  u16(0),
417  {{'.', 'i', 'd', 'a', 't', 'a', '$', '4'},
418  u32(0),
419  u32(0),
420  u32(VASize),
421  u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
422  VASize),
423  u32(0),
424  u32(0),
425  u16(0),
426  u16(0),
431  };
432  append(Buffer, SectionTable);
433 
434  // .idata$5, ILT
435  append(Buffer, u32(0));
436  if (!is32bit(Machine))
437  append(Buffer, u32(0));
438 
439  // .idata$4, IAT
440  append(Buffer, u32(0));
441  if (!is32bit(Machine))
442  append(Buffer, u32(0));
443 
444  // Symbol Table
445  coff_symbol16 SymbolTable[NumberOfSymbols] = {
446  {{{0, 0, 0, 0, 0, 0, 0, 0}},
447  u32(0),
448  u16(1),
449  u16(0),
451  0},
452  };
453  SymbolTable[0].Name.Offset.Offset = sizeof(uint32_t);
454  append(Buffer, SymbolTable);
455 
456  // String Table
457  writeStringTable(Buffer, {NullThunkSymbolName});
458 
459  StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
460  return {MemoryBufferRef{F, ImportName}};
461 }
462 
463 NewArchiveMember ObjectFactory::createShortImport(StringRef Sym,
464  uint16_t Ordinal,
466  ImportNameType NameType) {
467  size_t ImpSize = ImportName.size() + Sym.size() + 2; // +2 for NULs
468  size_t Size = sizeof(coff_import_header) + ImpSize;
469  char *Buf = Alloc.Allocate<char>(Size);
470  memset(Buf, 0, Size);
471  char *P = Buf;
472 
473  // Write short import library.
474  auto *Imp = reinterpret_cast<coff_import_header *>(P);
475  P += sizeof(*Imp);
476  Imp->Sig2 = 0xFFFF;
477  Imp->Machine = Machine;
478  Imp->SizeOfData = ImpSize;
479  if (Ordinal > 0)
480  Imp->OrdinalHint = Ordinal;
481  Imp->TypeInfo = (NameType << 2) | ImportType;
482 
483  // Write symbol name and DLL name.
484  memcpy(P, Sym.data(), Sym.size());
485  P += Sym.size() + 1;
486  memcpy(P, ImportName.data(), ImportName.size());
487 
488  return {MemoryBufferRef(StringRef(Buf, Size), ImportName)};
489 }
490 
491 NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,
492  StringRef Weak, bool Imp) {
493  std::vector<uint8_t> Buffer;
494  const uint32_t NumberOfSections = 1;
495  const uint32_t NumberOfSymbols = 5;
496 
497  // COFF Header
498  coff_file_header Header{
499  u16(Machine),
500  u16(NumberOfSections),
501  u32(0),
502  u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section))),
503  u32(NumberOfSymbols),
504  u16(0),
505  u16(0),
506  };
507  append(Buffer, Header);
508 
509  // Section Header Table
510  const coff_section SectionTable[NumberOfSections] = {
511  {{'.', 'd', 'r', 'e', 'c', 't', 'v', 'e'},
512  u32(0),
513  u32(0),
514  u32(0),
515  u32(0),
516  u32(0),
517  u32(0),
518  u16(0),
519  u16(0),
521  append(Buffer, SectionTable);
522 
523  // Symbol Table
524  coff_symbol16 SymbolTable[NumberOfSymbols] = {
525  {{{'@', 'c', 'o', 'm', 'p', '.', 'i', 'd'}},
526  u32(0),
527  u16(0xFFFF),
528  u16(0),
530  0},
531  {{{'@', 'f', 'e', 'a', 't', '.', '0', '0'}},
532  u32(0),
533  u16(0xFFFF),
534  u16(0),
536  0},
537  {{{0, 0, 0, 0, 0, 0, 0, 0}},
538  u32(0),
539  u16(0),
540  u16(0),
542  0},
543  {{{0, 0, 0, 0, 0, 0, 0, 0}},
544  u32(0),
545  u16(0),
546  u16(0),
548  1},
549  {{{2, 0, 0, 0, IMAGE_WEAK_EXTERN_SEARCH_ALIAS, 0, 0, 0}},
550  u32(0),
551  u16(0),
552  u16(0),
554  0},
555  };
556  SymbolTable[2].Name.Offset.Offset = sizeof(uint32_t);
557 
558  //__imp_ String Table
559  StringRef Prefix = Imp ? "__imp_" : "";
560  SymbolTable[3].Name.Offset.Offset =
561  sizeof(uint32_t) + Sym.size() + Prefix.size() + 1;
562  append(Buffer, SymbolTable);
563  writeStringTable(Buffer, {(Prefix + Sym).str(),
564  (Prefix + Weak).str()});
565 
566  // Copied here so we can still use writeStringTable
567  char *Buf = Alloc.Allocate<char>(Buffer.size());
568  memcpy(Buf, Buffer.data(), Buffer.size());
569  return {MemoryBufferRef(StringRef(Buf, Buffer.size()), ImportName)};
570 }
571 
574  MachineTypes Machine, bool MinGW) {
575 
576  std::vector<NewArchiveMember> Members;
577  ObjectFactory OF(llvm::sys::path::filename(ImportName), Machine);
578 
579  std::vector<uint8_t> ImportDescriptor;
580  Members.push_back(OF.createImportDescriptor(ImportDescriptor));
581 
582  std::vector<uint8_t> NullImportDescriptor;
583  Members.push_back(OF.createNullImportDescriptor(NullImportDescriptor));
584 
585  std::vector<uint8_t> NullThunk;
586  Members.push_back(OF.createNullThunk(NullThunk));
587 
588  for (COFFShortExport E : Exports) {
589  if (E.Private)
590  continue;
591 
592  ImportType ImportType = IMPORT_CODE;
593  if (E.Data)
594  ImportType = IMPORT_DATA;
595  if (E.Constant)
596  ImportType = IMPORT_CONST;
597 
598  StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName;
599  ImportNameType NameType = getNameType(SymbolName, E.Name, Machine, MinGW);
600  Expected<std::string> Name = E.ExtName.empty()
601  ? SymbolName
602  : replace(SymbolName, E.Name, E.ExtName);
603 
604  if (!Name)
605  return Name.takeError();
606 
607  if (!E.AliasTarget.empty() && *Name != E.AliasTarget) {
608  Members.push_back(OF.createWeakExternal(E.AliasTarget, *Name, false));
609  Members.push_back(OF.createWeakExternal(E.AliasTarget, *Name, true));
610  continue;
611  }
612 
613  Members.push_back(
614  OF.createShortImport(*Name, E.Ordinal, ImportType, NameType));
615  }
616 
617  return writeArchive(Path, Members, /*WriteSymtab*/ true,
619  /*Deterministic*/ true, /*Thin*/ false);
620 }
621 
622 } // namespace object
623 } // namespace llvm
static const std::string NullImportDescriptorSymbolName
This class represents lattice values for constants.
Definition: AllocatorList.h:24
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition: StringRef.h:448
union llvm::object::coff_symbol::@273 Name
static void append(std::vector< uint8_t > &B, const T &Data)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
static ImportNameType getNameType(StringRef Sym, StringRef ExtName, MachineTypes Machine, bool MinGW)
void write32le(void *P, uint32_t V)
Definition: Endian.h:404
F(f)
Error takeError()
Take ownership of the stored error.
Definition: Error.h:553
detail::packed_endian_specific_integral< uint16_t, little, unaligned > ulittle16_t
Definition: Endian.h:269
ImportNameType
Definition: COFF.h:682
static bool is32bit(MachineTypes Machine)
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
Error writeArchive(StringRef ArcName, ArrayRef< NewArchiveMember > NewMembers, bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, std::unique_ptr< MemoryBuffer > OldArchiveBuf=nullptr)
MachineTypes
Definition: COFF.h:94
amdgpu Simplify well known AMD library false Value Value const Twine & Name
Machine is based on a 32bit word architecture.
Definition: COFF.h:146
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:267
Error writeImportLibrary(StringRef ImportName, StringRef Path, ArrayRef< COFFShortExport > Exports, COFF::MachineTypes Machine, bool MinGW)
ImportType
Definition: COFF.h:676
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
COFF::MachineTypes Machine
Definition: COFFYAML.cpp:363
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:598
#define P(N)
static uint16_t getImgRelRelocation(MachineTypes Machine)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
detail::packed_endian_specific_integral< uint32_t, little, unaligned > ulittle32_t
Definition: Endian.h:271
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:141
Line number, reformatted as symbol.
Definition: COFF.h:234
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * Allocate(size_t Size, size_t Alignment)
Allocate space at the specified alignment.
Definition: Allocator.h:215
#define offsetof(TYPE, MEMBER)
static void replace(Module &M, GlobalVariable *Old, GlobalVariable *New)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: COFF.h:553
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef drop_back(size_t N=1) const
Return a StringRef equal to &#39;this&#39; but with the last N elements dropped.
Definition: StringRef.h:654
BlockVerifier::State From
The import name is the public symbol name, but skipping the leading ?, @, or optionally _...
Definition: COFF.h:692
static const size_t npos
Definition: StringRef.h:51
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:590
static void writeStringTable(std::vector< uint8_t > &B, ArrayRef< const std::string > Strings)
uint32_t Size
Definition: Profile.cpp:47
The import name is identical to the public symbol name.
Definition: COFF.h:689
The import name is the public symbol name, but skipping the leading ?, @, or optionally _...
Definition: COFF.h:695
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:298
StringTableOffset Offset
Definition: COFF.h:254
support::ulittle32_t Offset
Definition: COFF.h:247