LLVM  10.0.0svn
COFFEmitter.cpp
Go to the documentation of this file.
1 //===- yaml2coff - Convert YAML to a COFF object file ---------------------===//
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 /// \file
10 /// The COFF component of yaml2obj.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/ADT/StringMap.h"
17 #include "llvm/ADT/StringSwitch.h"
20 #include "llvm/Object/COFF.h"
23 #include "llvm/Support/Endian.h"
25 #include "llvm/Support/SourceMgr.h"
26 #include "llvm/Support/WithColor.h"
28 #include <vector>
29 
30 using namespace llvm;
31 
32 namespace {
33 
34 /// This parses a yaml stream that represents a COFF object file.
35 /// See docs/yaml2obj for the yaml scheema.
36 struct COFFParser {
37  COFFParser(COFFYAML::Object &Obj, yaml::ErrorHandler EH)
38  : Obj(Obj), SectionTableStart(0), SectionTableSize(0), ErrHandler(EH) {
39  // A COFF string table always starts with a 4 byte size field. Offsets into
40  // it include this size, so allocate it now.
41  StringTable.append(4, char(0));
42  }
43 
44  bool useBigObj() const {
45  return static_cast<int32_t>(Obj.Sections.size()) >
47  }
48 
49  bool isPE() const { return Obj.OptionalHeader.hasValue(); }
50  bool is64Bit() const {
53  }
54 
55  uint32_t getFileAlignment() const {
56  return Obj.OptionalHeader->Header.FileAlignment;
57  }
58 
59  unsigned getHeaderSize() const {
60  return useBigObj() ? COFF::Header32Size : COFF::Header16Size;
61  }
62 
63  unsigned getSymbolSize() const {
64  return useBigObj() ? COFF::Symbol32Size : COFF::Symbol16Size;
65  }
66 
67  bool parseSections() {
68  for (std::vector<COFFYAML::Section>::iterator i = Obj.Sections.begin(),
69  e = Obj.Sections.end();
70  i != e; ++i) {
71  COFFYAML::Section &Sec = *i;
72 
73  // If the name is less than 8 bytes, store it in place, otherwise
74  // store it in the string table.
75  StringRef Name = Sec.Name;
76 
77  if (Name.size() <= COFF::NameSize) {
78  std::copy(Name.begin(), Name.end(), Sec.Header.Name);
79  } else {
80  // Add string to the string table and format the index for output.
81  unsigned Index = getStringIndex(Name);
82  std::string str = utostr(Index);
83  if (str.size() > 7) {
84  ErrHandler("string table got too large");
85  return false;
86  }
87  Sec.Header.Name[0] = '/';
88  std::copy(str.begin(), str.end(), Sec.Header.Name + 1);
89  }
90 
91  if (Sec.Alignment) {
92  if (Sec.Alignment > 8192) {
93  ErrHandler("section alignment is too large");
94  return false;
95  }
96  if (!isPowerOf2_32(Sec.Alignment)) {
97  ErrHandler("section alignment is not a power of 2");
98  return false;
99  }
100  Sec.Header.Characteristics |= (Log2_32(Sec.Alignment) + 1) << 20;
101  }
102  }
103  return true;
104  }
105 
106  bool parseSymbols() {
107  for (std::vector<COFFYAML::Symbol>::iterator i = Obj.Symbols.begin(),
108  e = Obj.Symbols.end();
109  i != e; ++i) {
110  COFFYAML::Symbol &Sym = *i;
111 
112  // If the name is less than 8 bytes, store it in place, otherwise
113  // store it in the string table.
114  StringRef Name = Sym.Name;
115  if (Name.size() <= COFF::NameSize) {
116  std::copy(Name.begin(), Name.end(), Sym.Header.Name);
117  } else {
118  // Add string to the string table and format the index for output.
119  unsigned Index = getStringIndex(Name);
120  *reinterpret_cast<support::aligned_ulittle32_t *>(Sym.Header.Name + 4) =
121  Index;
122  }
123 
124  Sym.Header.Type = Sym.SimpleType;
126  }
127  return true;
128  }
129 
130  bool parse() {
131  if (!parseSections())
132  return false;
133  if (!parseSymbols())
134  return false;
135  return true;
136  }
137 
138  unsigned getStringIndex(StringRef Str) {
139  StringMap<unsigned>::iterator i = StringTableMap.find(Str);
140  if (i == StringTableMap.end()) {
141  unsigned Index = StringTable.size();
142  StringTable.append(Str.begin(), Str.end());
143  StringTable.push_back(0);
144  StringTableMap[Str] = Index;
145  return Index;
146  }
147  return i->second;
148  }
149 
150  COFFYAML::Object &Obj;
151 
152  codeview::StringsAndChecksums StringsAndChecksums;
154  StringMap<unsigned> StringTableMap;
155  std::string StringTable;
156  uint32_t SectionTableStart;
157  uint32_t SectionTableSize;
158 
159  yaml::ErrorHandler ErrHandler;
160 };
161 
162 enum { DOSStubSize = 128 };
163 
164 } // end anonymous namespace
165 
166 // Take a CP and assign addresses and sizes to everything. Returns false if the
167 // layout is not valid to do.
168 static bool layoutOptionalHeader(COFFParser &CP) {
169  if (!CP.isPE())
170  return true;
171  unsigned PEHeaderSize = CP.is64Bit() ? sizeof(object::pe32plus_header)
172  : sizeof(object::pe32_header);
173  CP.Obj.Header.SizeOfOptionalHeader =
174  PEHeaderSize +
176  return true;
177 }
178 
179 static yaml::BinaryRef
182  using namespace codeview;
183  ExitOnError Err("Error occurred writing .debug$S section");
184  auto CVSS =
185  Err(CodeViewYAML::toCodeViewSubsectionList(Allocator, Subsections, SC));
186 
187  std::vector<DebugSubsectionRecordBuilder> Builders;
188  uint32_t Size = sizeof(uint32_t);
189  for (auto &SS : CVSS) {
190  DebugSubsectionRecordBuilder B(SS, CodeViewContainer::ObjectFile);
191  Size += B.calculateSerializedLength();
192  Builders.push_back(std::move(B));
193  }
194  uint8_t *Buffer = Allocator.Allocate<uint8_t>(Size);
195  MutableArrayRef<uint8_t> Output(Buffer, Size);
196  BinaryStreamWriter Writer(Output, support::little);
197 
199  for (const auto &B : Builders) {
200  Err(B.commit(Writer));
201  }
202  return {Output};
203 }
204 
205 // Take a CP and assign addresses and sizes to everything. Returns false if the
206 // layout is not valid to do.
207 static bool layoutCOFF(COFFParser &CP) {
208  // The section table starts immediately after the header, including the
209  // optional header.
210  CP.SectionTableStart =
211  CP.getHeaderSize() + CP.Obj.Header.SizeOfOptionalHeader;
212  if (CP.isPE())
213  CP.SectionTableStart += DOSStubSize + sizeof(COFF::PEMagic);
214  CP.SectionTableSize = COFF::SectionSize * CP.Obj.Sections.size();
215 
216  uint32_t CurrentSectionDataOffset =
217  CP.SectionTableStart + CP.SectionTableSize;
218 
219  for (COFFYAML::Section &S : CP.Obj.Sections) {
220  // We support specifying exactly one of SectionData or Subsections. So if
221  // there is already some SectionData, then we don't need to do any of this.
222  if (S.Name == ".debug$S" && S.SectionData.binary_size() == 0) {
224  CP.StringsAndChecksums);
225  if (CP.StringsAndChecksums.hasChecksums() &&
226  CP.StringsAndChecksums.hasStrings())
227  break;
228  }
229  }
230 
231  // Assign each section data address consecutively.
232  for (COFFYAML::Section &S : CP.Obj.Sections) {
233  if (S.Name == ".debug$S") {
234  if (S.SectionData.binary_size() == 0) {
235  assert(CP.StringsAndChecksums.hasStrings() &&
236  "Object file does not have debug string table!");
237 
238  S.SectionData =
239  toDebugS(S.DebugS, CP.StringsAndChecksums, CP.Allocator);
240  }
241  } else if (S.Name == ".debug$T") {
242  if (S.SectionData.binary_size() == 0)
243  S.SectionData = CodeViewYAML::toDebugT(S.DebugT, CP.Allocator, S.Name);
244  } else if (S.Name == ".debug$P") {
245  if (S.SectionData.binary_size() == 0)
246  S.SectionData = CodeViewYAML::toDebugT(S.DebugP, CP.Allocator, S.Name);
247  } else if (S.Name == ".debug$H") {
248  if (S.DebugH.hasValue() && S.SectionData.binary_size() == 0)
249  S.SectionData = CodeViewYAML::toDebugH(*S.DebugH, CP.Allocator);
250  }
251 
252  if (S.SectionData.binary_size() > 0) {
253  CurrentSectionDataOffset = alignTo(CurrentSectionDataOffset,
254  CP.isPE() ? CP.getFileAlignment() : 4);
256  if (CP.isPE())
258  alignTo(S.Header.SizeOfRawData, CP.getFileAlignment());
259  S.Header.PointerToRawData = CurrentSectionDataOffset;
260  CurrentSectionDataOffset += S.Header.SizeOfRawData;
261  if (!S.Relocations.empty()) {
262  S.Header.PointerToRelocations = CurrentSectionDataOffset;
264  CurrentSectionDataOffset +=
266  }
267  } else {
268  // Leave SizeOfRawData unaltered. For .bss sections in object files, it
269  // carries the section size.
270  S.Header.PointerToRawData = 0;
271  }
272  }
273 
274  uint32_t SymbolTableStart = CurrentSectionDataOffset;
275 
276  // Calculate number of symbols.
277  uint32_t NumberOfSymbols = 0;
278  for (std::vector<COFFYAML::Symbol>::iterator i = CP.Obj.Symbols.begin(),
279  e = CP.Obj.Symbols.end();
280  i != e; ++i) {
281  uint32_t NumberOfAuxSymbols = 0;
282  if (i->FunctionDefinition)
283  NumberOfAuxSymbols += 1;
284  if (i->bfAndefSymbol)
285  NumberOfAuxSymbols += 1;
286  if (i->WeakExternal)
287  NumberOfAuxSymbols += 1;
288  if (!i->File.empty())
289  NumberOfAuxSymbols +=
290  (i->File.size() + CP.getSymbolSize() - 1) / CP.getSymbolSize();
291  if (i->SectionDefinition)
292  NumberOfAuxSymbols += 1;
293  if (i->CLRToken)
294  NumberOfAuxSymbols += 1;
295  i->Header.NumberOfAuxSymbols = NumberOfAuxSymbols;
296  NumberOfSymbols += 1 + NumberOfAuxSymbols;
297  }
298 
299  // Store all the allocated start addresses in the header.
300  CP.Obj.Header.NumberOfSections = CP.Obj.Sections.size();
301  CP.Obj.Header.NumberOfSymbols = NumberOfSymbols;
302  if (NumberOfSymbols > 0 || CP.StringTable.size() > 4)
303  CP.Obj.Header.PointerToSymbolTable = SymbolTableStart;
304  else
305  CP.Obj.Header.PointerToSymbolTable = 0;
306 
307  *reinterpret_cast<support::ulittle32_t *>(&CP.StringTable[0]) =
308  CP.StringTable.size();
309 
310  return true;
311 }
312 
313 template <typename value_type> struct binary_le_impl {
314  value_type Value;
315  binary_le_impl(value_type V) : Value(V) {}
316 };
317 
318 template <typename value_type>
320  const binary_le_impl<value_type> &BLE) {
321  char Buffer[sizeof(BLE.Value)];
322  support::endian::write<value_type, support::little, support::unaligned>(
323  Buffer, BLE.Value);
324  OS.write(Buffer, sizeof(BLE.Value));
325  return OS;
326 }
327 
328 template <typename value_type>
330  return binary_le_impl<value_type>(V);
331 }
332 
333 template <size_t NumBytes> struct zeros_impl {};
334 
335 template <size_t NumBytes>
336 raw_ostream &operator<<(raw_ostream &OS, const zeros_impl<NumBytes> &) {
337  char Buffer[NumBytes];
338  memset(Buffer, 0, sizeof(Buffer));
339  OS.write(Buffer, sizeof(Buffer));
340  return OS;
341 }
342 
343 template <typename T> zeros_impl<sizeof(T)> zeros(const T &) {
344  return zeros_impl<sizeof(T)>();
345 }
346 
347 template <typename T>
348 static uint32_t initializeOptionalHeader(COFFParser &CP, uint16_t Magic,
349  T Header) {
350  memset(Header, 0, sizeof(*Header));
351  Header->Magic = Magic;
352  Header->SectionAlignment = CP.Obj.OptionalHeader->Header.SectionAlignment;
353  Header->FileAlignment = CP.Obj.OptionalHeader->Header.FileAlignment;
354  uint32_t SizeOfCode = 0, SizeOfInitializedData = 0,
355  SizeOfUninitializedData = 0;
356  uint32_t SizeOfHeaders = alignTo(CP.SectionTableStart + CP.SectionTableSize,
357  Header->FileAlignment);
358  uint32_t SizeOfImage = alignTo(SizeOfHeaders, Header->SectionAlignment);
359  uint32_t BaseOfData = 0;
360  for (const COFFYAML::Section &S : CP.Obj.Sections) {
362  SizeOfCode += S.Header.SizeOfRawData;
364  SizeOfInitializedData += S.Header.SizeOfRawData;
366  SizeOfUninitializedData += S.Header.SizeOfRawData;
367  if (S.Name.equals(".text"))
368  Header->BaseOfCode = S.Header.VirtualAddress; // RVA
369  else if (S.Name.equals(".data"))
370  BaseOfData = S.Header.VirtualAddress; // RVA
372  SizeOfImage += alignTo(S.Header.VirtualSize, Header->SectionAlignment);
373  }
374  Header->SizeOfCode = SizeOfCode;
375  Header->SizeOfInitializedData = SizeOfInitializedData;
376  Header->SizeOfUninitializedData = SizeOfUninitializedData;
377  Header->AddressOfEntryPoint =
378  CP.Obj.OptionalHeader->Header.AddressOfEntryPoint; // RVA
379  Header->ImageBase = CP.Obj.OptionalHeader->Header.ImageBase;
380  Header->MajorOperatingSystemVersion =
381  CP.Obj.OptionalHeader->Header.MajorOperatingSystemVersion;
382  Header->MinorOperatingSystemVersion =
383  CP.Obj.OptionalHeader->Header.MinorOperatingSystemVersion;
384  Header->MajorImageVersion = CP.Obj.OptionalHeader->Header.MajorImageVersion;
385  Header->MinorImageVersion = CP.Obj.OptionalHeader->Header.MinorImageVersion;
386  Header->MajorSubsystemVersion =
387  CP.Obj.OptionalHeader->Header.MajorSubsystemVersion;
388  Header->MinorSubsystemVersion =
389  CP.Obj.OptionalHeader->Header.MinorSubsystemVersion;
390  Header->SizeOfImage = SizeOfImage;
391  Header->SizeOfHeaders = SizeOfHeaders;
392  Header->Subsystem = CP.Obj.OptionalHeader->Header.Subsystem;
393  Header->DLLCharacteristics = CP.Obj.OptionalHeader->Header.DLLCharacteristics;
394  Header->SizeOfStackReserve = CP.Obj.OptionalHeader->Header.SizeOfStackReserve;
395  Header->SizeOfStackCommit = CP.Obj.OptionalHeader->Header.SizeOfStackCommit;
396  Header->SizeOfHeapReserve = CP.Obj.OptionalHeader->Header.SizeOfHeapReserve;
397  Header->SizeOfHeapCommit = CP.Obj.OptionalHeader->Header.SizeOfHeapCommit;
398  Header->NumberOfRvaAndSize = COFF::NUM_DATA_DIRECTORIES + 1;
399  return BaseOfData;
400 }
401 
402 static bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
403  if (CP.isPE()) {
404  // PE files start with a DOS stub.
406  memset(&DH, 0, sizeof(DH));
407 
408  // DOS EXEs start with "MZ" magic.
409  DH.Magic[0] = 'M';
410  DH.Magic[1] = 'Z';
411  // Initializing the AddressOfRelocationTable is strictly optional but
412  // mollifies certain tools which expect it to have a value greater than
413  // 0x40.
414  DH.AddressOfRelocationTable = sizeof(DH);
415  // This is the address of the PE signature.
416  DH.AddressOfNewExeHeader = DOSStubSize;
417 
418  // Write out our DOS stub.
419  OS.write(reinterpret_cast<char *>(&DH), sizeof(DH));
420  // Write padding until we reach the position of where our PE signature
421  // should live.
422  OS.write_zeros(DOSStubSize - sizeof(DH));
423  // Write out the PE signature.
424  OS.write(COFF::PEMagic, sizeof(COFF::PEMagic));
425  }
426  if (CP.useBigObj()) {
427  OS << binary_le(static_cast<uint16_t>(COFF::IMAGE_FILE_MACHINE_UNKNOWN))
428  << binary_le(static_cast<uint16_t>(0xffff))
429  << binary_le(
430  static_cast<uint16_t>(COFF::BigObjHeader::MinBigObjectVersion))
431  << binary_le(CP.Obj.Header.Machine)
432  << binary_le(CP.Obj.Header.TimeDateStamp);
434  OS << zeros(uint32_t(0)) << zeros(uint32_t(0)) << zeros(uint32_t(0))
435  << zeros(uint32_t(0)) << binary_le(CP.Obj.Header.NumberOfSections)
436  << binary_le(CP.Obj.Header.PointerToSymbolTable)
437  << binary_le(CP.Obj.Header.NumberOfSymbols);
438  } else {
439  OS << binary_le(CP.Obj.Header.Machine)
440  << binary_le(static_cast<int16_t>(CP.Obj.Header.NumberOfSections))
441  << binary_le(CP.Obj.Header.TimeDateStamp)
442  << binary_le(CP.Obj.Header.PointerToSymbolTable)
443  << binary_le(CP.Obj.Header.NumberOfSymbols)
444  << binary_le(CP.Obj.Header.SizeOfOptionalHeader)
445  << binary_le(CP.Obj.Header.Characteristics);
446  }
447  if (CP.isPE()) {
448  if (CP.is64Bit()) {
451  OS.write(reinterpret_cast<char *>(&PEH), sizeof(PEH));
452  } else {
454  uint32_t BaseOfData =
456  PEH.BaseOfData = BaseOfData;
457  OS.write(reinterpret_cast<char *>(&PEH), sizeof(PEH));
458  }
459  for (const Optional<COFF::DataDirectory> &DD :
460  CP.Obj.OptionalHeader->DataDirectories) {
461  if (!DD.hasValue()) {
462  OS << zeros(uint32_t(0));
463  OS << zeros(uint32_t(0));
464  } else {
466  OS << binary_le(DD->Size);
467  }
468  }
469  OS << zeros(uint32_t(0));
470  OS << zeros(uint32_t(0));
471  }
472 
473  assert(OS.tell() == CP.SectionTableStart);
474  // Output section table.
475  for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
476  e = CP.Obj.Sections.end();
477  i != e; ++i) {
478  OS.write(i->Header.Name, COFF::NameSize);
479  OS << binary_le(i->Header.VirtualSize)
480  << binary_le(i->Header.VirtualAddress)
481  << binary_le(i->Header.SizeOfRawData)
482  << binary_le(i->Header.PointerToRawData)
483  << binary_le(i->Header.PointerToRelocations)
484  << binary_le(i->Header.PointerToLineNumbers)
485  << binary_le(i->Header.NumberOfRelocations)
486  << binary_le(i->Header.NumberOfLineNumbers)
487  << binary_le(i->Header.Characteristics);
488  }
489  assert(OS.tell() == CP.SectionTableStart + CP.SectionTableSize);
490 
491  unsigned CurSymbol = 0;
492  StringMap<unsigned> SymbolTableIndexMap;
493  for (std::vector<COFFYAML::Symbol>::iterator I = CP.Obj.Symbols.begin(),
494  E = CP.Obj.Symbols.end();
495  I != E; ++I) {
496  SymbolTableIndexMap[I->Name] = CurSymbol;
497  CurSymbol += 1 + I->Header.NumberOfAuxSymbols;
498  }
499 
500  // Output section data.
501  for (const COFFYAML::Section &S : CP.Obj.Sections) {
502  if (S.Header.SizeOfRawData == 0 || S.Header.PointerToRawData == 0)
503  continue;
504  assert(S.Header.PointerToRawData >= OS.tell());
509  for (const COFFYAML::Relocation &R : S.Relocations) {
510  uint32_t SymbolTableIndex;
511  if (R.SymbolTableIndex) {
512  if (!R.SymbolName.empty())
514  << "Both SymbolName and SymbolTableIndex specified\n";
515  SymbolTableIndex = *R.SymbolTableIndex;
516  } else {
517  SymbolTableIndex = SymbolTableIndexMap[R.SymbolName];
518  }
519  OS << binary_le(R.VirtualAddress) << binary_le(SymbolTableIndex)
520  << binary_le(R.Type);
521  }
522  }
523 
524  // Output symbol table.
525 
526  for (std::vector<COFFYAML::Symbol>::const_iterator i = CP.Obj.Symbols.begin(),
527  e = CP.Obj.Symbols.end();
528  i != e; ++i) {
529  OS.write(i->Header.Name, COFF::NameSize);
530  OS << binary_le(i->Header.Value);
531  if (CP.useBigObj())
532  OS << binary_le(i->Header.SectionNumber);
533  else
534  OS << binary_le(static_cast<int16_t>(i->Header.SectionNumber));
535  OS << binary_le(i->Header.Type) << binary_le(i->Header.StorageClass)
536  << binary_le(i->Header.NumberOfAuxSymbols);
537 
538  if (i->FunctionDefinition) {
539  OS << binary_le(i->FunctionDefinition->TagIndex)
540  << binary_le(i->FunctionDefinition->TotalSize)
541  << binary_le(i->FunctionDefinition->PointerToLinenumber)
542  << binary_le(i->FunctionDefinition->PointerToNextFunction)
543  << zeros(i->FunctionDefinition->unused);
544  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
545  }
546  if (i->bfAndefSymbol) {
547  OS << zeros(i->bfAndefSymbol->unused1)
548  << binary_le(i->bfAndefSymbol->Linenumber)
549  << zeros(i->bfAndefSymbol->unused2)
550  << binary_le(i->bfAndefSymbol->PointerToNextFunction)
551  << zeros(i->bfAndefSymbol->unused3);
552  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
553  }
554  if (i->WeakExternal) {
555  OS << binary_le(i->WeakExternal->TagIndex)
556  << binary_le(i->WeakExternal->Characteristics)
557  << zeros(i->WeakExternal->unused);
558  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
559  }
560  if (!i->File.empty()) {
561  unsigned SymbolSize = CP.getSymbolSize();
562  uint32_t NumberOfAuxRecords =
563  (i->File.size() + SymbolSize - 1) / SymbolSize;
564  uint32_t NumberOfAuxBytes = NumberOfAuxRecords * SymbolSize;
565  uint32_t NumZeros = NumberOfAuxBytes - i->File.size();
566  OS.write(i->File.data(), i->File.size());
567  OS.write_zeros(NumZeros);
568  }
569  if (i->SectionDefinition) {
570  OS << binary_le(i->SectionDefinition->Length)
571  << binary_le(i->SectionDefinition->NumberOfRelocations)
572  << binary_le(i->SectionDefinition->NumberOfLinenumbers)
573  << binary_le(i->SectionDefinition->CheckSum)
574  << binary_le(static_cast<int16_t>(i->SectionDefinition->Number))
575  << binary_le(i->SectionDefinition->Selection)
576  << zeros(i->SectionDefinition->unused)
577  << binary_le(static_cast<int16_t>(i->SectionDefinition->Number >> 16));
578  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
579  }
580  if (i->CLRToken) {
581  OS << binary_le(i->CLRToken->AuxType) << zeros(i->CLRToken->unused1)
582  << binary_le(i->CLRToken->SymbolTableIndex)
583  << zeros(i->CLRToken->unused2);
584  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
585  }
586  }
587 
588  // Output string table.
589  if (CP.Obj.Header.PointerToSymbolTable)
590  OS.write(&CP.StringTable[0], CP.StringTable.size());
591  return true;
592 }
593 
594 namespace llvm {
595 namespace yaml {
596 
598  ErrorHandler ErrHandler) {
599  COFFParser CP(Doc, ErrHandler);
600  if (!CP.parse()) {
601  ErrHandler("failed to parse YAML file");
602  return false;
603  }
604 
605  if (!layoutOptionalHeader(CP)) {
606  ErrHandler("failed to layout optional header for COFF file");
607  return false;
608  }
609 
610  if (!layoutCOFF(CP)) {
611  ErrHandler("failed to layout COFF file");
612  return false;
613  }
614  if (!writeCOFF(CP, Out)) {
615  ErrHandler("failed to write COFF file");
616  return false;
617  }
618  return true;
619 }
620 
621 } // namespace yaml
622 } // namespace llvm
COFF::section Header
Definition: COFFYAML.h:70
The 64-bit PE header that follows the COFF header.
Definition: COFF.h:140
COFF::SymbolBaseType SimpleType
Definition: COFFYAML.h:85
This class represents lattice values for constants.
Definition: AllocatorList.h:23
bool yaml2coff(COFFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH)
uint32_t SizeOfRawData
Definition: COFF.h:274
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
uint16_t Type
Definition: COFF.h:191
raw_ostream & write_zeros(unsigned NumZeros)
write_zeros - Insert &#39;NumZeros&#39; nulls.
static raw_ostream & error()
Convenience method for printing "error: " to stderr.
Definition: WithColor.cpp:60
Helper for check-and-exit error handling.
Definition: Error.h:1293
COFF::symbol Header
Definition: COFFYAML.h:84
char Name[NameSize]
Definition: COFF.h:271
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:104
iterator find(StringRef Key)
Definition: StringMap.h:355
uint16_t Machine
Definition: COFF.h:66
static const char BigObjMagic[]
Definition: COFF.h:38
COFF::header Header
Definition: COFFYAML.h:105
unsigned size() const
Definition: StringMap.h:111
std::vector< Relocation > Relocations
Definition: COFFYAML.h:77
const int32_t MaxNumberOfSections16
Definition: COFF.h:33
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:140
std::vector< Section > Sections
Definition: COFFYAML.h:106
static uint32_t initializeOptionalHeader(COFFParser &CP, uint16_t Magic, T Header)
void initializeStringsAndChecksums(ArrayRef< YAMLDebugSubsection > Sections, codeview::StringsAndChecksums &SC)
ArrayRef< uint8_t > toDebugH(const DebugHSection &DebugH, BumpPtrAllocator &Alloc)
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:144
Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
Definition: COFF.h:265
std::vector< CodeViewYAML::LeafRecord > DebugP
Definition: COFFYAML.h:75
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition: MathExtras.h:465
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:141
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
void writeAsBinary(raw_ostream &OS) const
Write the contents (regardless of whether it is binary or a hex string) as binary to the given raw_os...
Definition: YAML.cpp:40
static bool is64Bit(const char *name)
static yaml::BinaryRef toDebugS(ArrayRef< CodeViewYAML::YAMLDebugSubsection > Subsections, const codeview::StringsAndChecksums &SC, BumpPtrAllocator &Allocator)
The 32-bit PE header that follows the COFF header.
Definition: COFF.h:104
static bool layoutCOFF(COFFParser &CP)
Provides write only access to a subclass of WritableBinaryStream.
constexpr double e
Definition: MathExtras.h:57
Error writeInteger(T Value)
Write the integer Value to the underlying stream in the specified endianness.
uint32_t VirtualAddress
Definition: COFF.h:273
raw_ostream & write(unsigned char C)
ArrayRef< uint8_t >::size_type binary_size() const
The number of bytes that are represented by this BinaryRef.
Definition: YAML.h:80
static const char *const Magic
Definition: Archive.cpp:41
yaml::BinaryRef SectionData
Definition: COFFYAML.h:72
binary_le_impl< value_type > binary_le(value_type V)
Basic Register Allocator
support::ulittle16_t AddressOfRelocationTable
Definition: COFF.h:66
support::ulittle32_t BaseOfData
Definition: COFF.h:113
uint32_t PointerToRelocations
Definition: COFF.h:276
std::vector< CodeViewYAML::LeafRecord > DebugT
Definition: COFFYAML.h:74
Common declarations for yaml2obj.
value_type Value
CHAIN = SC CHAIN, Imm128 - System call.
std::string utostr(uint64_t X, bool isNeg=false)
Definition: StringExtras.h:223
uint32_t PointerToRawData
Definition: COFF.h:275
uint32_t RelativeVirtualAddress
Definition: COFF.h:576
The DOS compatible header at the front of all PE/COFF executables.
Definition: COFF.h:53
uint32_t VirtualSize
Definition: COFF.h:272
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:585
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:242
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * Allocate(size_t Size, Align Alignment)
Allocate space at the specified alignment.
Definition: Allocator.h:215
iterator begin() const
Definition: StringRef.h:115
Specialized YAMLIO scalar type for representing a binary blob.
Definition: YAML.h:63
LLVM_NODISCARD bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
Definition: StringRef.h:174
bool hasValue() const
Definition: Optional.h:259
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:163
#define I(x, y, z)
Definition: MD5.cpp:58
binary_le_impl(value_type V)
static const char PEMagic[]
Definition: COFF.h:36
ArrayRef< uint8_t > toDebugT(ArrayRef< LeafRecord >, BumpPtrAllocator &Alloc, StringRef SectionName)
uint32_t Size
Definition: Profile.cpp:46
raw_ostream & operator<<(raw_ostream &OS, const APInt &I)
Definition: APInt.h:2047
char Name[NameSize]
Definition: COFF.h:188
std::vector< CodeViewYAML::YAMLDebugSubsection > DebugS
Definition: COFFYAML.h:73
zeros_impl< sizeof(T)> zeros(const T &)
bool empty() const
Definition: StringMap.h:110
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
support::ulittle32_t AddressOfNewExeHeader
Definition: COFF.h:72
uint16_t NumberOfRelocations
Definition: COFF.h:278
Optional< uint32_t > SymbolTableIndex
Definition: COFFYAML.h:66
std::vector< Symbol > Symbols
Definition: COFFYAML.h:107
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:111
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
COFF::SymbolComplexType ComplexType
Definition: COFFYAML.h:86
Optional< CodeViewYAML::DebugHSection > DebugH
Definition: COFFYAML.h:76
static llvm::Error parse(DataExtractor &Data, uint64_t BaseAddr, LineEntryCallback const &Callback)
Definition: LineTable.cpp:54
Optional< PEHeader > OptionalHeader
Definition: COFFYAML.h:104
Expected< std::vector< std::shared_ptr< codeview::DebugSubsection > > > toCodeViewSubsectionList(BumpPtrAllocator &Allocator, ArrayRef< YAMLDebugSubsection > Subsections, const codeview::StringsAndChecksums &SC)
OutputIt copy(R &&Range, OutputIt Out)
Definition: STLExtras.h:1217
iterator end() const
Definition: StringRef.h:117
uint32_t Characteristics
Definition: COFF.h:280
iterator end()
Definition: StringMap.h:340
static bool layoutOptionalHeader(COFFParser &CP)
static bool writeCOFF(COFFParser &CP, raw_ostream &OS)