LLVM  15.0.0git
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"
19 #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 (COFFYAML::Section &Sec : Obj.Sections) {
69  // If the name is less than 8 bytes, store it in place, otherwise
70  // store it in the string table.
71  StringRef Name = Sec.Name;
72 
73  if (Name.size() <= COFF::NameSize) {
74  std::copy(Name.begin(), Name.end(), Sec.Header.Name);
75  } else {
76  // Add string to the string table and format the index for output.
77  unsigned Index = getStringIndex(Name);
78  std::string str = utostr(Index);
79  if (str.size() > 7) {
80  ErrHandler("string table got too large");
81  return false;
82  }
83  Sec.Header.Name[0] = '/';
84  std::copy(str.begin(), str.end(), Sec.Header.Name + 1);
85  }
86 
87  if (Sec.Alignment) {
88  if (Sec.Alignment > 8192) {
89  ErrHandler("section alignment is too large");
90  return false;
91  }
92  if (!isPowerOf2_32(Sec.Alignment)) {
93  ErrHandler("section alignment is not a power of 2");
94  return false;
95  }
96  Sec.Header.Characteristics |= (Log2_32(Sec.Alignment) + 1) << 20;
97  }
98  }
99  return true;
100  }
101 
102  bool parseSymbols() {
103  for (COFFYAML::Symbol &Sym : Obj.Symbols) {
104  // If the name is less than 8 bytes, store it in place, otherwise
105  // store it in the string table.
106  StringRef Name = Sym.Name;
107  if (Name.size() <= COFF::NameSize) {
108  std::copy(Name.begin(), Name.end(), Sym.Header.Name);
109  } else {
110  // Add string to the string table and format the index for output.
111  unsigned Index = getStringIndex(Name);
112  *reinterpret_cast<support::aligned_ulittle32_t *>(Sym.Header.Name + 4) =
113  Index;
114  }
115 
116  Sym.Header.Type = Sym.SimpleType;
118  }
119  return true;
120  }
121 
122  bool parse() {
123  if (!parseSections())
124  return false;
125  if (!parseSymbols())
126  return false;
127  return true;
128  }
129 
130  unsigned getStringIndex(StringRef Str) {
131  StringMap<unsigned>::iterator i = StringTableMap.find(Str);
132  if (i == StringTableMap.end()) {
133  unsigned Index = StringTable.size();
134  StringTable.append(Str.begin(), Str.end());
135  StringTable.push_back(0);
136  StringTableMap[Str] = Index;
137  return Index;
138  }
139  return i->second;
140  }
141 
142  COFFYAML::Object &Obj;
143 
144  codeview::StringsAndChecksums StringsAndChecksums;
146  StringMap<unsigned> StringTableMap;
147  std::string StringTable;
148  uint32_t SectionTableStart;
149  uint32_t SectionTableSize;
150 
151  yaml::ErrorHandler ErrHandler;
152 };
153 
154 enum { DOSStubSize = 128 };
155 
156 } // end anonymous namespace
157 
158 // Take a CP and assign addresses and sizes to everything. Returns false if the
159 // layout is not valid to do.
160 static bool layoutOptionalHeader(COFFParser &CP) {
161  if (!CP.isPE())
162  return true;
163  unsigned PEHeaderSize = CP.is64Bit() ? sizeof(object::pe32plus_header)
164  : sizeof(object::pe32_header);
165  CP.Obj.Header.SizeOfOptionalHeader =
166  PEHeaderSize + sizeof(object::data_directory) *
167  CP.Obj.OptionalHeader->Header.NumberOfRvaAndSize;
168  return true;
169 }
170 
171 static yaml::BinaryRef
174  using namespace codeview;
175  ExitOnError Err("Error occurred writing .debug$S section");
176  auto CVSS =
178 
179  std::vector<DebugSubsectionRecordBuilder> Builders;
180  uint32_t Size = sizeof(uint32_t);
181  for (auto &SS : CVSS) {
182  DebugSubsectionRecordBuilder B(SS);
183  Size += B.calculateSerializedLength();
184  Builders.push_back(std::move(B));
185  }
186  uint8_t *Buffer = Allocator.Allocate<uint8_t>(Size);
187  MutableArrayRef<uint8_t> Output(Buffer, Size);
188  BinaryStreamWriter Writer(Output, support::little);
189 
191  for (const auto &B : Builders) {
192  Err(B.commit(Writer, CodeViewContainer::ObjectFile));
193  }
194  return {Output};
195 }
196 
197 // Take a CP and assign addresses and sizes to everything. Returns false if the
198 // layout is not valid to do.
199 static bool layoutCOFF(COFFParser &CP) {
200  // The section table starts immediately after the header, including the
201  // optional header.
202  CP.SectionTableStart =
203  CP.getHeaderSize() + CP.Obj.Header.SizeOfOptionalHeader;
204  if (CP.isPE())
205  CP.SectionTableStart += DOSStubSize + sizeof(COFF::PEMagic);
206  CP.SectionTableSize = COFF::SectionSize * CP.Obj.Sections.size();
207 
208  uint32_t CurrentSectionDataOffset =
209  CP.SectionTableStart + CP.SectionTableSize;
210 
211  for (COFFYAML::Section &S : CP.Obj.Sections) {
212  // We support specifying exactly one of SectionData or Subsections. So if
213  // there is already some SectionData, then we don't need to do any of this.
214  if (S.Name == ".debug$S" && S.SectionData.binary_size() == 0) {
216  CP.StringsAndChecksums);
217  if (CP.StringsAndChecksums.hasChecksums() &&
218  CP.StringsAndChecksums.hasStrings())
219  break;
220  }
221  }
222 
223  // Assign each section data address consecutively.
224  for (COFFYAML::Section &S : CP.Obj.Sections) {
225  if (S.Name == ".debug$S") {
226  if (S.SectionData.binary_size() == 0) {
227  assert(CP.StringsAndChecksums.hasStrings() &&
228  "Object file does not have debug string table!");
229 
230  S.SectionData =
231  toDebugS(S.DebugS, CP.StringsAndChecksums, CP.Allocator);
232  }
233  } else if (S.Name == ".debug$T") {
234  if (S.SectionData.binary_size() == 0)
235  S.SectionData = CodeViewYAML::toDebugT(S.DebugT, CP.Allocator, S.Name);
236  } else if (S.Name == ".debug$P") {
237  if (S.SectionData.binary_size() == 0)
238  S.SectionData = CodeViewYAML::toDebugT(S.DebugP, CP.Allocator, S.Name);
239  } else if (S.Name == ".debug$H") {
240  if (S.DebugH.hasValue() && S.SectionData.binary_size() == 0)
241  S.SectionData = CodeViewYAML::toDebugH(*S.DebugH, CP.Allocator);
242  }
243 
244  if (S.SectionData.binary_size() > 0) {
245  CurrentSectionDataOffset = alignTo(CurrentSectionDataOffset,
246  CP.isPE() ? CP.getFileAlignment() : 4);
247  S.Header.SizeOfRawData = S.SectionData.binary_size();
248  if (CP.isPE())
249  S.Header.SizeOfRawData =
250  alignTo(S.Header.SizeOfRawData, CP.getFileAlignment());
251  S.Header.PointerToRawData = CurrentSectionDataOffset;
252  CurrentSectionDataOffset += S.Header.SizeOfRawData;
253  if (!S.Relocations.empty()) {
254  S.Header.PointerToRelocations = CurrentSectionDataOffset;
255  if (S.Header.Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) {
256  S.Header.NumberOfRelocations = 0xffff;
257  CurrentSectionDataOffset += COFF::RelocationSize;
258  } else
259  S.Header.NumberOfRelocations = S.Relocations.size();
260  CurrentSectionDataOffset += S.Relocations.size() * COFF::RelocationSize;
261  }
262  } else {
263  // Leave SizeOfRawData unaltered. For .bss sections in object files, it
264  // carries the section size.
265  S.Header.PointerToRawData = 0;
266  }
267  }
268 
269  uint32_t SymbolTableStart = CurrentSectionDataOffset;
270 
271  // Calculate number of symbols.
272  uint32_t NumberOfSymbols = 0;
273  for (std::vector<COFFYAML::Symbol>::iterator i = CP.Obj.Symbols.begin(),
274  e = CP.Obj.Symbols.end();
275  i != e; ++i) {
276  uint32_t NumberOfAuxSymbols = 0;
277  if (i->FunctionDefinition)
278  NumberOfAuxSymbols += 1;
279  if (i->bfAndefSymbol)
280  NumberOfAuxSymbols += 1;
281  if (i->WeakExternal)
282  NumberOfAuxSymbols += 1;
283  if (!i->File.empty())
284  NumberOfAuxSymbols +=
285  (i->File.size() + CP.getSymbolSize() - 1) / CP.getSymbolSize();
286  if (i->SectionDefinition)
287  NumberOfAuxSymbols += 1;
288  if (i->CLRToken)
289  NumberOfAuxSymbols += 1;
290  i->Header.NumberOfAuxSymbols = NumberOfAuxSymbols;
291  NumberOfSymbols += 1 + NumberOfAuxSymbols;
292  }
293 
294  // Store all the allocated start addresses in the header.
295  CP.Obj.Header.NumberOfSections = CP.Obj.Sections.size();
296  CP.Obj.Header.NumberOfSymbols = NumberOfSymbols;
297  if (NumberOfSymbols > 0 || CP.StringTable.size() > 4)
298  CP.Obj.Header.PointerToSymbolTable = SymbolTableStart;
299  else
300  CP.Obj.Header.PointerToSymbolTable = 0;
301 
302  *reinterpret_cast<support::ulittle32_t *>(&CP.StringTable[0]) =
303  CP.StringTable.size();
304 
305  return true;
306 }
307 
308 template <typename value_type> struct binary_le_impl {
309  value_type Value;
310  binary_le_impl(value_type V) : Value(V) {}
311 };
312 
313 template <typename value_type>
315  const binary_le_impl<value_type> &BLE) {
316  char Buffer[sizeof(BLE.Value)];
317  support::endian::write<value_type, support::little, support::unaligned>(
318  Buffer, BLE.Value);
319  OS.write(Buffer, sizeof(BLE.Value));
320  return OS;
321 }
322 
323 template <typename value_type>
325  return binary_le_impl<value_type>(V);
326 }
327 
328 template <size_t NumBytes> struct zeros_impl {};
329 
330 template <size_t NumBytes>
332  char Buffer[NumBytes];
333  memset(Buffer, 0, sizeof(Buffer));
334  OS.write(Buffer, sizeof(Buffer));
335  return OS;
336 }
337 
338 template <typename T> zeros_impl<sizeof(T)> zeros(const T &) {
339  return zeros_impl<sizeof(T)>();
340 }
341 
342 template <typename T>
344  T Header) {
345  memset(Header, 0, sizeof(*Header));
346  Header->Magic = Magic;
347  Header->SectionAlignment = CP.Obj.OptionalHeader->Header.SectionAlignment;
348  Header->FileAlignment = CP.Obj.OptionalHeader->Header.FileAlignment;
349  uint32_t SizeOfCode = 0, SizeOfInitializedData = 0,
350  SizeOfUninitializedData = 0;
351  uint32_t SizeOfHeaders = alignTo(CP.SectionTableStart + CP.SectionTableSize,
352  Header->FileAlignment);
353  uint32_t SizeOfImage = alignTo(SizeOfHeaders, Header->SectionAlignment);
354  uint32_t BaseOfData = 0;
355  for (const COFFYAML::Section &S : CP.Obj.Sections) {
356  if (S.Header.Characteristics & COFF::IMAGE_SCN_CNT_CODE)
357  SizeOfCode += S.Header.SizeOfRawData;
358  if (S.Header.Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
359  SizeOfInitializedData += S.Header.SizeOfRawData;
360  if (S.Header.Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
361  SizeOfUninitializedData += S.Header.SizeOfRawData;
362  if (S.Name.equals(".text"))
363  Header->BaseOfCode = S.Header.VirtualAddress; // RVA
364  else if (S.Name.equals(".data"))
365  BaseOfData = S.Header.VirtualAddress; // RVA
366  if (S.Header.VirtualAddress)
367  SizeOfImage += alignTo(S.Header.VirtualSize, Header->SectionAlignment);
368  }
369  Header->SizeOfCode = SizeOfCode;
370  Header->SizeOfInitializedData = SizeOfInitializedData;
371  Header->SizeOfUninitializedData = SizeOfUninitializedData;
372  Header->AddressOfEntryPoint =
373  CP.Obj.OptionalHeader->Header.AddressOfEntryPoint; // RVA
374  Header->ImageBase = CP.Obj.OptionalHeader->Header.ImageBase;
375  Header->MajorOperatingSystemVersion =
376  CP.Obj.OptionalHeader->Header.MajorOperatingSystemVersion;
377  Header->MinorOperatingSystemVersion =
378  CP.Obj.OptionalHeader->Header.MinorOperatingSystemVersion;
379  Header->MajorImageVersion = CP.Obj.OptionalHeader->Header.MajorImageVersion;
380  Header->MinorImageVersion = CP.Obj.OptionalHeader->Header.MinorImageVersion;
381  Header->MajorSubsystemVersion =
382  CP.Obj.OptionalHeader->Header.MajorSubsystemVersion;
383  Header->MinorSubsystemVersion =
384  CP.Obj.OptionalHeader->Header.MinorSubsystemVersion;
385  Header->SizeOfImage = SizeOfImage;
386  Header->SizeOfHeaders = SizeOfHeaders;
387  Header->Subsystem = CP.Obj.OptionalHeader->Header.Subsystem;
388  Header->DLLCharacteristics = CP.Obj.OptionalHeader->Header.DLLCharacteristics;
389  Header->SizeOfStackReserve = CP.Obj.OptionalHeader->Header.SizeOfStackReserve;
390  Header->SizeOfStackCommit = CP.Obj.OptionalHeader->Header.SizeOfStackCommit;
391  Header->SizeOfHeapReserve = CP.Obj.OptionalHeader->Header.SizeOfHeapReserve;
392  Header->SizeOfHeapCommit = CP.Obj.OptionalHeader->Header.SizeOfHeapCommit;
393  Header->NumberOfRvaAndSize = CP.Obj.OptionalHeader->Header.NumberOfRvaAndSize;
394  return BaseOfData;
395 }
396 
397 static bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
398  if (CP.isPE()) {
399  // PE files start with a DOS stub.
401  memset(&DH, 0, sizeof(DH));
402 
403  // DOS EXEs start with "MZ" magic.
404  DH.Magic[0] = 'M';
405  DH.Magic[1] = 'Z';
406  // Initializing the AddressOfRelocationTable is strictly optional but
407  // mollifies certain tools which expect it to have a value greater than
408  // 0x40.
409  DH.AddressOfRelocationTable = sizeof(DH);
410  // This is the address of the PE signature.
411  DH.AddressOfNewExeHeader = DOSStubSize;
412 
413  // Write out our DOS stub.
414  OS.write(reinterpret_cast<char *>(&DH), sizeof(DH));
415  // Write padding until we reach the position of where our PE signature
416  // should live.
417  OS.write_zeros(DOSStubSize - sizeof(DH));
418  // Write out the PE signature.
419  OS.write(COFF::PEMagic, sizeof(COFF::PEMagic));
420  }
421  if (CP.useBigObj()) {
422  OS << binary_le(static_cast<uint16_t>(COFF::IMAGE_FILE_MACHINE_UNKNOWN))
423  << binary_le(static_cast<uint16_t>(0xffff))
424  << binary_le(
426  << binary_le(CP.Obj.Header.Machine)
427  << binary_le(CP.Obj.Header.TimeDateStamp);
429  OS << zeros(uint32_t(0)) << zeros(uint32_t(0)) << zeros(uint32_t(0))
430  << zeros(uint32_t(0)) << binary_le(CP.Obj.Header.NumberOfSections)
431  << binary_le(CP.Obj.Header.PointerToSymbolTable)
432  << binary_le(CP.Obj.Header.NumberOfSymbols);
433  } else {
434  OS << binary_le(CP.Obj.Header.Machine)
435  << binary_le(static_cast<int16_t>(CP.Obj.Header.NumberOfSections))
436  << binary_le(CP.Obj.Header.TimeDateStamp)
437  << binary_le(CP.Obj.Header.PointerToSymbolTable)
438  << binary_le(CP.Obj.Header.NumberOfSymbols)
439  << binary_le(CP.Obj.Header.SizeOfOptionalHeader)
440  << binary_le(CP.Obj.Header.Characteristics);
441  }
442  if (CP.isPE()) {
443  if (CP.is64Bit()) {
446  OS.write(reinterpret_cast<char *>(&PEH), sizeof(PEH));
447  } else {
449  uint32_t BaseOfData =
451  PEH.BaseOfData = BaseOfData;
452  OS.write(reinterpret_cast<char *>(&PEH), sizeof(PEH));
453  }
454  for (uint32_t I = 0; I < CP.Obj.OptionalHeader->Header.NumberOfRvaAndSize;
455  ++I) {
456  const Optional<COFF::DataDirectory> *DataDirectories =
457  CP.Obj.OptionalHeader->DataDirectories;
458  uint32_t NumDataDir = sizeof(CP.Obj.OptionalHeader->DataDirectories) /
460  if (I >= NumDataDir || !DataDirectories[I].hasValue()) {
461  OS << zeros(uint32_t(0));
462  OS << zeros(uint32_t(0));
463  } else {
464  OS << binary_le(DataDirectories[I]->RelativeVirtualAddress);
465  OS << binary_le(DataDirectories[I]->Size);
466  }
467  }
468  }
469 
470  assert(OS.tell() == CP.SectionTableStart);
471  // Output section table.
472  for (const COFFYAML::Section &S : CP.Obj.Sections) {
473  OS.write(S.Header.Name, COFF::NameSize);
474  OS << binary_le(S.Header.VirtualSize)
475  << binary_le(S.Header.VirtualAddress)
476  << binary_le(S.Header.SizeOfRawData)
477  << binary_le(S.Header.PointerToRawData)
478  << binary_le(S.Header.PointerToRelocations)
479  << binary_le(S.Header.PointerToLineNumbers)
480  << binary_le(S.Header.NumberOfRelocations)
481  << binary_le(S.Header.NumberOfLineNumbers)
482  << binary_le(S.Header.Characteristics);
483  }
484  assert(OS.tell() == CP.SectionTableStart + CP.SectionTableSize);
485 
486  unsigned CurSymbol = 0;
487  StringMap<unsigned> SymbolTableIndexMap;
488  for (const COFFYAML::Symbol &Sym : CP.Obj.Symbols) {
489  SymbolTableIndexMap[Sym.Name] = CurSymbol;
490  CurSymbol += 1 + Sym.Header.NumberOfAuxSymbols;
491  }
492 
493  // Output section data.
494  for (const COFFYAML::Section &S : CP.Obj.Sections) {
495  if (S.Header.SizeOfRawData == 0 || S.Header.PointerToRawData == 0)
496  continue;
497  assert(S.Header.PointerToRawData >= OS.tell());
498  OS.write_zeros(S.Header.PointerToRawData - OS.tell());
499  S.SectionData.writeAsBinary(OS);
500  assert(S.Header.SizeOfRawData >= S.SectionData.binary_size());
501  OS.write_zeros(S.Header.SizeOfRawData - S.SectionData.binary_size());
502  if (S.Header.Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL)
503  OS << binary_le<uint32_t>(/*VirtualAddress=*/ S.Relocations.size() + 1)
504  << binary_le<uint32_t>(/*SymbolTableIndex=*/ 0)
505  << binary_le<uint16_t>(/*Type=*/ 0);
506  for (const COFFYAML::Relocation &R : S.Relocations) {
507  uint32_t SymbolTableIndex;
508  if (R.SymbolTableIndex) {
509  if (!R.SymbolName.empty())
511  << "Both SymbolName and SymbolTableIndex specified\n";
512  SymbolTableIndex = *R.SymbolTableIndex;
513  } else {
514  SymbolTableIndex = SymbolTableIndexMap[R.SymbolName];
515  }
516  OS << binary_le(R.VirtualAddress) << binary_le(SymbolTableIndex)
517  << binary_le(R.Type);
518  }
519  }
520 
521  // Output symbol table.
522 
523  for (std::vector<COFFYAML::Symbol>::const_iterator i = CP.Obj.Symbols.begin(),
524  e = CP.Obj.Symbols.end();
525  i != e; ++i) {
526  OS.write(i->Header.Name, COFF::NameSize);
527  OS << binary_le(i->Header.Value);
528  if (CP.useBigObj())
529  OS << binary_le(i->Header.SectionNumber);
530  else
531  OS << binary_le(static_cast<int16_t>(i->Header.SectionNumber));
532  OS << binary_le(i->Header.Type) << binary_le(i->Header.StorageClass)
533  << binary_le(i->Header.NumberOfAuxSymbols);
534 
535  if (i->FunctionDefinition) {
536  OS << binary_le(i->FunctionDefinition->TagIndex)
537  << binary_le(i->FunctionDefinition->TotalSize)
538  << binary_le(i->FunctionDefinition->PointerToLinenumber)
539  << binary_le(i->FunctionDefinition->PointerToNextFunction)
540  << zeros(i->FunctionDefinition->unused);
541  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
542  }
543  if (i->bfAndefSymbol) {
544  OS << zeros(i->bfAndefSymbol->unused1)
545  << binary_le(i->bfAndefSymbol->Linenumber)
546  << zeros(i->bfAndefSymbol->unused2)
547  << binary_le(i->bfAndefSymbol->PointerToNextFunction)
548  << zeros(i->bfAndefSymbol->unused3);
549  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
550  }
551  if (i->WeakExternal) {
552  OS << binary_le(i->WeakExternal->TagIndex)
553  << binary_le(i->WeakExternal->Characteristics)
554  << zeros(i->WeakExternal->unused);
555  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
556  }
557  if (!i->File.empty()) {
558  unsigned SymbolSize = CP.getSymbolSize();
559  uint32_t NumberOfAuxRecords =
560  (i->File.size() + SymbolSize - 1) / SymbolSize;
561  uint32_t NumberOfAuxBytes = NumberOfAuxRecords * SymbolSize;
562  uint32_t NumZeros = NumberOfAuxBytes - i->File.size();
563  OS.write(i->File.data(), i->File.size());
564  OS.write_zeros(NumZeros);
565  }
566  if (i->SectionDefinition) {
567  OS << binary_le(i->SectionDefinition->Length)
568  << binary_le(i->SectionDefinition->NumberOfRelocations)
569  << binary_le(i->SectionDefinition->NumberOfLinenumbers)
570  << binary_le(i->SectionDefinition->CheckSum)
571  << binary_le(static_cast<int16_t>(i->SectionDefinition->Number))
572  << binary_le(i->SectionDefinition->Selection)
573  << zeros(i->SectionDefinition->unused)
574  << binary_le(static_cast<int16_t>(i->SectionDefinition->Number >> 16));
575  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
576  }
577  if (i->CLRToken) {
578  OS << binary_le(i->CLRToken->AuxType) << zeros(i->CLRToken->unused1)
579  << binary_le(i->CLRToken->SymbolTableIndex)
580  << zeros(i->CLRToken->unused2);
581  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
582  }
583  }
584 
585  // Output string table.
586  if (CP.Obj.Header.PointerToSymbolTable)
587  OS.write(&CP.StringTable[0], CP.StringTable.size());
588  return true;
589 }
590 
591 namespace llvm {
592 namespace yaml {
593 
595  ErrorHandler ErrHandler) {
596  COFFParser CP(Doc, ErrHandler);
597  if (!CP.parse()) {
598  ErrHandler("failed to parse YAML file");
599  return false;
600  }
601 
602  if (!layoutOptionalHeader(CP)) {
603  ErrHandler("failed to layout optional header for COFF file");
604  return false;
605  }
606 
607  if (!layoutCOFF(CP)) {
608  ErrHandler("failed to layout COFF file");
609  return false;
610  }
611  if (!writeCOFF(CP, Out)) {
612  ErrHandler("failed to write COFF file");
613  return false;
614  }
615  return true;
616 }
617 
618 } // namespace yaml
619 } // namespace llvm
i
i
Definition: README.txt:29
MemoryBuffer.h
llvm::alignTo
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:148
llvm::raw_ostream::tell
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:136
zeros
zeros_impl< sizeof(T)> zeros(const T &)
Definition: COFFEmitter.cpp:338
writeCOFF
static bool writeCOFF(COFFParser &CP, raw_ostream &OS)
Definition: COFFEmitter.cpp:397
llvm::COFF::BigObjHeader::MinBigObjectVersion
@ MinBigObjectVersion
Definition: COFF.h:75
llvm::COFF::Header32Size
@ Header32Size
Definition: COFF.h:56
llvm::object::dos_header::AddressOfNewExeHeader
support::ulittle32_t AddressOfNewExeHeader
Definition: COFF.h:72
llvm::COFF::Header16Size
@ Header16Size
Definition: COFF.h:55
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
ObjectYAML.h
llvm::COFF::IMAGE_SCN_LNK_NRELOC_OVFL
@ IMAGE_SCN_LNK_NRELOC_OVFL
Definition: COFF.h:314
llvm::BinaryStreamWriter::writeInteger
Error writeInteger(T Value)
Write the integer Value to the underlying stream in the specified endianness.
Definition: BinaryStreamWriter.h:58
llvm::COFFYAML::Symbol::SimpleType
COFF::SymbolBaseType SimpleType
Definition: COFFYAML.h:85
llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
@ IMAGE_SCN_CNT_UNINITIALIZED_DATA
Definition: COFF.h:289
llvm::COFF::header::Machine
uint16_t Machine
Definition: COFF.h:65
llvm::support::detail::packed_endian_specific_integral
Definition: Endian.h:206
T
llvm::raw_ostream::write_zeros
raw_ostream & write_zeros(unsigned NumZeros)
write_zeros - Insert 'NumZeros' nulls.
Definition: raw_ostream.cpp:501
llvm::COFFYAML::Object::Sections
std::vector< Section > Sections
Definition: COFFYAML.h:106
is64Bit
static bool is64Bit(const char *name)
Definition: X86Disassembler.cpp:1019
llvm::X86AS::SS
@ SS
Definition: X86.h:189
llvm::codeview::StringsAndChecksums
Definition: StringsAndChecksums.h:83
llvm::BinaryStreamWriter
Provides write only access to a subclass of WritableBinaryStream.
Definition: BinaryStreamWriter.h:30
layoutOptionalHeader
static bool layoutOptionalHeader(COFFParser &CP)
Definition: COFFEmitter.cpp:160
llvm::COFF::symbol::Type
uint16_t Type
Definition: COFF.h:190
llvm::COFF::IMAGE_FILE_MACHINE_AMD64
@ IMAGE_FILE_MACHINE_AMD64
Definition: COFF.h:97
llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN
@ IMAGE_FILE_MACHINE_UNKNOWN
Definition: COFF.h:95
llvm::COFF::SCT_COMPLEX_TYPE_SHIFT
@ SCT_COMPLEX_TYPE_SHIFT
Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
Definition: COFF.h:264
llvm::COFFYAML::Symbol::ComplexType
COFF::SymbolComplexType ComplexType
Definition: COFFYAML.h:86
llvm::COFFYAML::Section::Name
StringRef Name
Definition: COFFYAML.h:78
llvm::COFFYAML::Object::OptionalHeader
Optional< PEHeader > OptionalHeader
Definition: COFFYAML.h:104
llvm::ExitOnError
Helper for check-and-exit error handling.
Definition: Error.h:1348
llvm::Optional
Definition: APInt.h:33
llvm::COFFYAML::Relocation
Definition: COFFYAML.h:57
llvm::codeview::DebugSubsectionKind::StringTable
@ StringTable
STLExtras.h
llvm::COFFYAML::Section
Definition: COFFYAML.h:69
llvm::isPowerOf2_32
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition: MathExtras.h:491
llvm::object::pe32plus_header
The 64-bit PE header that follows the COFF header.
Definition: COFF.h:140
llvm::COFF::PEMagic
static const char PEMagic[]
Definition: COFF.h:35
llvm::WithColor::error
static raw_ostream & error()
Convenience method for printing "error: " to stderr.
Definition: WithColor.cpp:83
llvm::object::dos_header
The DOS compatible header at the front of all PE/COFF executables.
Definition: COFF.h:53
llvm::object::dos_header::Magic
char Magic[2]
Definition: COFF.h:54
llvm::COFFYAML::Symbol::Name
StringRef Name
Definition: COFFYAML.h:93
llvm::CodeViewYAML::toDebugT
ArrayRef< uint8_t > toDebugT(ArrayRef< LeafRecord >, BumpPtrAllocator &Alloc, StringRef SectionName)
Definition: CodeViewYAMLTypes.cpp:801
llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
@ IMAGE_SCN_CNT_INITIALIZED_DATA
Definition: COFF.h:288
llvm::MutableArrayRef< uint8_t >
llvm::PPCISD::SC
@ SC
CHAIN = SC CHAIN, Imm128 - System call.
Definition: PPCISelLowering.h:418
llvm::support::little
@ little
Definition: Endian.h:27
llvm::COFF::NameSize
@ NameSize
Definition: COFF.h:57
llvm::yaml::yaml2coff
bool yaml2coff(COFFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH)
Definition: COFFEmitter.cpp:594
llvm::dwarf::Index
Index
Definition: Dwarf.h:472
llvm::Log2_32
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:623
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::raw_ostream::write
raw_ostream & write(unsigned char C)
Definition: raw_ostream.cpp:219
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:54
llvm::operator<<
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:230
StringMap.h
llvm::object::dos_header::AddressOfRelocationTable
support::ulittle16_t AddressOfRelocationTable
Definition: COFF.h:66
SourceMgr.h
llvm::COFFYAML::Object
Definition: COFFYAML.h:103
llvm::StringMap
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:110
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLFunctionalExtras.h:36
binary_le
binary_le_impl< value_type > binary_le(value_type V)
Definition: COFFEmitter.cpp:324
llvm::COFF::section::Characteristics
uint32_t Characteristics
Definition: COFF.h:279
llvm::CodeViewYAML::toCodeViewSubsectionList
Expected< std::vector< std::shared_ptr< codeview::DebugSubsection > > > toCodeViewSubsectionList(BumpPtrAllocator &Allocator, ArrayRef< YAMLDebugSubsection > Subsections, const codeview::StringsAndChecksums &SC)
Definition: CodeViewYAMLDebugSections.cpp:747
llvm::object::data_directory
Definition: COFF.h:172
llvm::CodeViewYAML::initializeStringsAndChecksums
void initializeStringsAndChecksums(ArrayRef< YAMLDebugSubsection > Sections, codeview::StringsAndChecksums &SC)
Definition: CodeViewYAMLDebugSections.cpp:922
binary_le_impl::Value
value_type Value
Definition: COFFEmitter.cpp:309
initializeOptionalHeader
static uint32_t initializeOptionalHeader(COFFParser &CP, uint16_t Magic, T Header)
Definition: COFFEmitter.cpp:343
llvm::COFF::symbol::NumberOfAuxSymbols
uint8_t NumberOfAuxSymbols
Definition: COFF.h:192
llvm::BumpPtrAllocatorImpl
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:63
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::numbers::e
constexpr double e
Definition: MathExtras.h:57
llvm::COFF::SectionSize
@ SectionSize
Definition: COFF.h:60
I
#define I(x, y, z)
Definition: MD5.cpp:58
layoutCOFF
static bool layoutCOFF(COFFParser &CP)
Definition: COFFEmitter.cpp:199
StringExtras.h
llvm::COFF::PE32Header::PE32
@ PE32
Definition: COFF.h:540
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::COFFYAML::Symbol
Definition: COFFYAML.h:83
llvm::codeview::CodeViewContainer::ObjectFile
@ ObjectFile
llvm::CodeViewYAML::toDebugH
ArrayRef< uint8_t > toDebugH(const DebugHSection &DebugH, BumpPtrAllocator &Alloc)
Definition: CodeViewYAMLTypeHashing.cpp:67
yaml2obj.h
binary_le_impl::binary_le_impl
binary_le_impl(value_type V)
Definition: COFFEmitter.cpp:310
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::COFF::BigObjMagic
static const char BigObjMagic[]
Definition: COFF.h:37
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::msf::Magic
static const char Magic[]
Definition: MSFCommon.h:23
llvm::yaml::BinaryRef
Specialized YAMLIO scalar type for representing a binary blob.
Definition: YAML.h:63
toDebugS
static yaml::BinaryRef toDebugS(ArrayRef< CodeViewYAML::YAMLDebugSubsection > Subsections, const codeview::StringsAndChecksums &SC, BumpPtrAllocator &Allocator)
Definition: COFFEmitter.cpp:172
uint32_t
parse
static llvm::Error parse(DataExtractor &Data, uint64_t BaseAddr, LineEntryCallback const &Callback)
Definition: LineTable.cpp:54
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::COFFYAML::Object::Symbols
std::vector< Symbol > Symbols
Definition: COFFYAML.h:107
llvm::COFF::IMAGE_FILE_MACHINE_ARM64
@ IMAGE_FILE_MACHINE_ARM64
Definition: COFF.h:100
binary_le_impl
Definition: COFFEmitter.cpp:308
llvm::HexagonISD::CP
@ CP
Definition: HexagonISelLowering.h:53
llvm::COFF::DEBUG_SECTION_MAGIC
@ DEBUG_SECTION_MAGIC
Definition: COFF.h:725
WithColor.h
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
llvm::object::pe32_header::BaseOfData
support::ulittle32_t BaseOfData
Definition: COFF.h:113
llvm::COFF::MaxNumberOfSections16
const int32_t MaxNumberOfSections16
Definition: COFF.h:32
uint16_t
StringsAndChecksums.h
llvm::COFF::IMAGE_SCN_CNT_CODE
@ IMAGE_SCN_CNT_CODE
Definition: COFF.h:287
zeros_impl
Definition: COFFEmitter.cpp:328
llvm::object::pe32_header
The 32-bit PE header that follows the COFF header.
Definition: COFF.h:104
llvm::COFF::Symbol32Size
@ Symbol32Size
Definition: COFF.h:59
DebugStringTableSubsection.h
llvm::COFF::Symbol16Size
@ Symbol16Size
Definition: COFF.h:58
COFF.h
llvm::COFFYAML::Section::Alignment
unsigned Alignment
Definition: COFFYAML.h:71
llvm::COFF::RelocationSize
@ RelocationSize
Definition: COFF.h:61
llvm::COFF::PE32Header::PE32_PLUS
@ PE32_PLUS
Definition: COFF.h:540
Allocator
Basic Register Allocator
Definition: RegAllocBasic.cpp:142
llvm::COFFYAML::Object::Header
COFF::header Header
Definition: COFFYAML.h:105
BinaryStreamWriter.h
llvm::COFFYAML::Symbol::Header
COFF::symbol Header
Definition: COFFYAML.h:84
llvm::COFF::symbol::Name
char Name[NameSize]
Definition: COFF.h:187
llvm::COFF::section::Name
char Name[NameSize]
Definition: COFF.h:270
raw_ostream.h
llvm::COFFYAML::Section::Header
COFF::section Header
Definition: COFFYAML.h:70
Endian.h
copy
we should consider alternate ways to model stack dependencies Lots of things could be done in WebAssemblyTargetTransformInfo cpp there are numerous optimization related hooks that can be overridden in WebAssemblyTargetLowering Instead of the OptimizeReturned which should consider preserving the returned attribute through to MachineInstrs and extending the MemIntrinsicResults pass to do this optimization on calls too That would also let the WebAssemblyPeephole pass clean up dead defs for such as it does for stores Consider implementing and or getMachineCombinerPatterns Find a clean way to fix the problem which leads to the Shrink Wrapping pass being run after the WebAssembly PEI pass When setting multiple variables to the same we currently get code like const It could be done with a smaller encoding like local tee $pop5 local copy
Definition: README.txt:101
llvm::Value
LLVM Value Representation.
Definition: Value.h:74