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