LLVM  16.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.has_value(); }
50  bool is64Bit() const {
54  }
55 
56  uint32_t getFileAlignment() const {
57  return Obj.OptionalHeader->Header.FileAlignment;
58  }
59 
60  unsigned getHeaderSize() const {
61  return useBigObj() ? COFF::Header32Size : COFF::Header16Size;
62  }
63 
64  unsigned getSymbolSize() const {
65  return useBigObj() ? COFF::Symbol32Size : COFF::Symbol16Size;
66  }
67 
68  bool parseSections() {
69  for (COFFYAML::Section &Sec : Obj.Sections) {
70  // If the name is less than 8 bytes, store it in place, otherwise
71  // store it in the string table.
72  StringRef Name = Sec.Name;
73 
74  if (Name.size() <= COFF::NameSize) {
75  std::copy(Name.begin(), Name.end(), Sec.Header.Name);
76  } else {
77  // Add string to the string table and format the index for output.
78  unsigned Index = getStringIndex(Name);
79  std::string str = utostr(Index);
80  if (str.size() > 7) {
81  ErrHandler("string table got too large");
82  return false;
83  }
84  Sec.Header.Name[0] = '/';
85  std::copy(str.begin(), str.end(), Sec.Header.Name + 1);
86  }
87 
88  if (Sec.Alignment) {
89  if (Sec.Alignment > 8192) {
90  ErrHandler("section alignment is too large");
91  return false;
92  }
93  if (!isPowerOf2_32(Sec.Alignment)) {
94  ErrHandler("section alignment is not a power of 2");
95  return false;
96  }
97  Sec.Header.Characteristics |= (Log2_32(Sec.Alignment) + 1) << 20;
98  }
99  }
100  return true;
101  }
102 
103  bool parseSymbols() {
104  for (COFFYAML::Symbol &Sym : Obj.Symbols) {
105  // If the name is less than 8 bytes, store it in place, otherwise
106  // store it in the string table.
107  StringRef Name = Sym.Name;
108  if (Name.size() <= COFF::NameSize) {
109  std::copy(Name.begin(), Name.end(), Sym.Header.Name);
110  } else {
111  // Add string to the string table and format the index for output.
112  unsigned Index = getStringIndex(Name);
113  *reinterpret_cast<support::aligned_ulittle32_t *>(Sym.Header.Name + 4) =
114  Index;
115  }
116 
117  Sym.Header.Type = Sym.SimpleType;
119  }
120  return true;
121  }
122 
123  bool parse() {
124  if (!parseSections())
125  return false;
126  if (!parseSymbols())
127  return false;
128  return true;
129  }
130 
131  unsigned getStringIndex(StringRef Str) {
132  StringMap<unsigned>::iterator i = StringTableMap.find(Str);
133  if (i == StringTableMap.end()) {
134  unsigned Index = StringTable.size();
135  StringTable.append(Str.begin(), Str.end());
136  StringTable.push_back(0);
137  StringTableMap[Str] = Index;
138  return Index;
139  }
140  return i->second;
141  }
142 
143  COFFYAML::Object &Obj;
144 
145  codeview::StringsAndChecksums StringsAndChecksums;
147  StringMap<unsigned> StringTableMap;
148  std::string StringTable;
149  uint32_t SectionTableStart;
150  uint32_t SectionTableSize;
151 
152  yaml::ErrorHandler ErrHandler;
153 };
154 
155 enum { DOSStubSize = 128 };
156 
157 } // end anonymous namespace
158 
159 // Take a CP and assign addresses and sizes to everything. Returns false if the
160 // layout is not valid to do.
161 static bool layoutOptionalHeader(COFFParser &CP) {
162  if (!CP.isPE())
163  return true;
164  unsigned PEHeaderSize = CP.is64Bit() ? sizeof(object::pe32plus_header)
165  : sizeof(object::pe32_header);
166  CP.Obj.Header.SizeOfOptionalHeader =
167  PEHeaderSize + sizeof(object::data_directory) *
168  CP.Obj.OptionalHeader->Header.NumberOfRvaAndSize;
169  return true;
170 }
171 
172 static yaml::BinaryRef
175  using namespace codeview;
176  ExitOnError Err("Error occurred writing .debug$S section");
177  auto CVSS =
179 
180  std::vector<DebugSubsectionRecordBuilder> Builders;
181  uint32_t Size = sizeof(uint32_t);
182  for (auto &SS : CVSS) {
183  DebugSubsectionRecordBuilder B(SS);
184  Size += B.calculateSerializedLength();
185  Builders.push_back(std::move(B));
186  }
187  uint8_t *Buffer = Allocator.Allocate<uint8_t>(Size);
188  MutableArrayRef<uint8_t> Output(Buffer, Size);
189  BinaryStreamWriter Writer(Output, support::little);
190 
192  for (const auto &B : Builders) {
193  Err(B.commit(Writer, CodeViewContainer::ObjectFile));
194  }
195  return {Output};
196 }
197 
198 // Take a CP and assign addresses and sizes to everything. Returns false if the
199 // layout is not valid to do.
200 static bool layoutCOFF(COFFParser &CP) {
201  // The section table starts immediately after the header, including the
202  // optional header.
203  CP.SectionTableStart =
204  CP.getHeaderSize() + CP.Obj.Header.SizeOfOptionalHeader;
205  if (CP.isPE())
206  CP.SectionTableStart += DOSStubSize + sizeof(COFF::PEMagic);
207  CP.SectionTableSize = COFF::SectionSize * CP.Obj.Sections.size();
208 
209  uint32_t CurrentSectionDataOffset =
210  CP.SectionTableStart + CP.SectionTableSize;
211 
212  for (COFFYAML::Section &S : CP.Obj.Sections) {
213  // We support specifying exactly one of SectionData or Subsections. So if
214  // there is already some SectionData, then we don't need to do any of this.
215  if (S.Name == ".debug$S" && S.SectionData.binary_size() == 0) {
217  CP.StringsAndChecksums);
218  if (CP.StringsAndChecksums.hasChecksums() &&
219  CP.StringsAndChecksums.hasStrings())
220  break;
221  }
222  }
223 
224  // Assign each section data address consecutively.
225  for (COFFYAML::Section &S : CP.Obj.Sections) {
226  if (S.Name == ".debug$S") {
227  if (S.SectionData.binary_size() == 0) {
228  assert(CP.StringsAndChecksums.hasStrings() &&
229  "Object file does not have debug string table!");
230 
231  S.SectionData =
232  toDebugS(S.DebugS, CP.StringsAndChecksums, CP.Allocator);
233  }
234  } else if (S.Name == ".debug$T") {
235  if (S.SectionData.binary_size() == 0)
236  S.SectionData = CodeViewYAML::toDebugT(S.DebugT, CP.Allocator, S.Name);
237  } else if (S.Name == ".debug$P") {
238  if (S.SectionData.binary_size() == 0)
239  S.SectionData = CodeViewYAML::toDebugT(S.DebugP, CP.Allocator, S.Name);
240  } else if (S.Name == ".debug$H") {
241  if (S.DebugH && S.SectionData.binary_size() == 0)
242  S.SectionData = CodeViewYAML::toDebugH(*S.DebugH, CP.Allocator);
243  }
244 
245  if (S.SectionData.binary_size() > 0) {
246  CurrentSectionDataOffset = alignTo(CurrentSectionDataOffset,
247  CP.isPE() ? CP.getFileAlignment() : 4);
248  S.Header.SizeOfRawData = S.SectionData.binary_size();
249  if (CP.isPE())
250  S.Header.SizeOfRawData =
251  alignTo(S.Header.SizeOfRawData, CP.getFileAlignment());
252  S.Header.PointerToRawData = CurrentSectionDataOffset;
253  CurrentSectionDataOffset += S.Header.SizeOfRawData;
254  if (!S.Relocations.empty()) {
255  S.Header.PointerToRelocations = CurrentSectionDataOffset;
256  if (S.Header.Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) {
257  S.Header.NumberOfRelocations = 0xffff;
258  CurrentSectionDataOffset += COFF::RelocationSize;
259  } else
260  S.Header.NumberOfRelocations = S.Relocations.size();
261  CurrentSectionDataOffset += S.Relocations.size() * COFF::RelocationSize;
262  }
263  } else {
264  // Leave SizeOfRawData unaltered. For .bss sections in object files, it
265  // carries the section size.
266  S.Header.PointerToRawData = 0;
267  }
268  }
269 
270  uint32_t SymbolTableStart = CurrentSectionDataOffset;
271 
272  // Calculate number of symbols.
273  uint32_t NumberOfSymbols = 0;
274  for (std::vector<COFFYAML::Symbol>::iterator i = CP.Obj.Symbols.begin(),
275  e = CP.Obj.Symbols.end();
276  i != e; ++i) {
277  uint32_t NumberOfAuxSymbols = 0;
278  if (i->FunctionDefinition)
279  NumberOfAuxSymbols += 1;
280  if (i->bfAndefSymbol)
281  NumberOfAuxSymbols += 1;
282  if (i->WeakExternal)
283  NumberOfAuxSymbols += 1;
284  if (!i->File.empty())
285  NumberOfAuxSymbols +=
286  (i->File.size() + CP.getSymbolSize() - 1) / CP.getSymbolSize();
287  if (i->SectionDefinition)
288  NumberOfAuxSymbols += 1;
289  if (i->CLRToken)
290  NumberOfAuxSymbols += 1;
291  i->Header.NumberOfAuxSymbols = NumberOfAuxSymbols;
292  NumberOfSymbols += 1 + NumberOfAuxSymbols;
293  }
294 
295  // Store all the allocated start addresses in the header.
296  CP.Obj.Header.NumberOfSections = CP.Obj.Sections.size();
297  CP.Obj.Header.NumberOfSymbols = NumberOfSymbols;
298  if (NumberOfSymbols > 0 || CP.StringTable.size() > 4)
299  CP.Obj.Header.PointerToSymbolTable = SymbolTableStart;
300  else
301  CP.Obj.Header.PointerToSymbolTable = 0;
302 
303  *reinterpret_cast<support::ulittle32_t *>(&CP.StringTable[0]) =
304  CP.StringTable.size();
305 
306  return true;
307 }
308 
309 template <typename value_type> struct binary_le_impl {
310  value_type Value;
311  binary_le_impl(value_type V) : Value(V) {}
312 };
313 
314 template <typename value_type>
316  const binary_le_impl<value_type> &BLE) {
317  char Buffer[sizeof(BLE.Value)];
318  support::endian::write<value_type, support::little, support::unaligned>(
319  Buffer, BLE.Value);
320  OS.write(Buffer, sizeof(BLE.Value));
321  return OS;
322 }
323 
324 template <typename value_type>
326  return binary_le_impl<value_type>(V);
327 }
328 
329 template <size_t NumBytes> struct zeros_impl {};
330 
331 template <size_t NumBytes>
333  char Buffer[NumBytes];
334  memset(Buffer, 0, sizeof(Buffer));
335  OS.write(Buffer, sizeof(Buffer));
336  return OS;
337 }
338 
339 template <typename T> zeros_impl<sizeof(T)> zeros(const T &) {
340  return zeros_impl<sizeof(T)>();
341 }
342 
343 template <typename T>
345  T Header) {
346  memset(Header, 0, sizeof(*Header));
347  Header->Magic = Magic;
348  Header->SectionAlignment = CP.Obj.OptionalHeader->Header.SectionAlignment;
349  Header->FileAlignment = CP.Obj.OptionalHeader->Header.FileAlignment;
350  uint32_t SizeOfCode = 0, SizeOfInitializedData = 0,
351  SizeOfUninitializedData = 0;
352  uint32_t SizeOfHeaders = alignTo(CP.SectionTableStart + CP.SectionTableSize,
353  Header->FileAlignment);
354  uint32_t SizeOfImage = alignTo(SizeOfHeaders, Header->SectionAlignment);
355  uint32_t BaseOfData = 0;
356  for (const COFFYAML::Section &S : CP.Obj.Sections) {
357  if (S.Header.Characteristics & COFF::IMAGE_SCN_CNT_CODE)
358  SizeOfCode += S.Header.SizeOfRawData;
359  if (S.Header.Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
360  SizeOfInitializedData += S.Header.SizeOfRawData;
361  if (S.Header.Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
362  SizeOfUninitializedData += S.Header.SizeOfRawData;
363  if (S.Name.equals(".text"))
364  Header->BaseOfCode = S.Header.VirtualAddress; // RVA
365  else if (S.Name.equals(".data"))
366  BaseOfData = S.Header.VirtualAddress; // RVA
367  if (S.Header.VirtualAddress)
368  SizeOfImage += alignTo(S.Header.VirtualSize, Header->SectionAlignment);
369  }
370  Header->SizeOfCode = SizeOfCode;
371  Header->SizeOfInitializedData = SizeOfInitializedData;
372  Header->SizeOfUninitializedData = SizeOfUninitializedData;
373  Header->AddressOfEntryPoint =
374  CP.Obj.OptionalHeader->Header.AddressOfEntryPoint; // RVA
375  Header->ImageBase = CP.Obj.OptionalHeader->Header.ImageBase;
376  Header->MajorOperatingSystemVersion =
377  CP.Obj.OptionalHeader->Header.MajorOperatingSystemVersion;
378  Header->MinorOperatingSystemVersion =
379  CP.Obj.OptionalHeader->Header.MinorOperatingSystemVersion;
380  Header->MajorImageVersion = CP.Obj.OptionalHeader->Header.MajorImageVersion;
381  Header->MinorImageVersion = CP.Obj.OptionalHeader->Header.MinorImageVersion;
382  Header->MajorSubsystemVersion =
383  CP.Obj.OptionalHeader->Header.MajorSubsystemVersion;
384  Header->MinorSubsystemVersion =
385  CP.Obj.OptionalHeader->Header.MinorSubsystemVersion;
386  Header->SizeOfImage = SizeOfImage;
387  Header->SizeOfHeaders = SizeOfHeaders;
388  Header->Subsystem = CP.Obj.OptionalHeader->Header.Subsystem;
389  Header->DLLCharacteristics = CP.Obj.OptionalHeader->Header.DLLCharacteristics;
390  Header->SizeOfStackReserve = CP.Obj.OptionalHeader->Header.SizeOfStackReserve;
391  Header->SizeOfStackCommit = CP.Obj.OptionalHeader->Header.SizeOfStackCommit;
392  Header->SizeOfHeapReserve = CP.Obj.OptionalHeader->Header.SizeOfHeapReserve;
393  Header->SizeOfHeapCommit = CP.Obj.OptionalHeader->Header.SizeOfHeapCommit;
394  Header->NumberOfRvaAndSize = CP.Obj.OptionalHeader->Header.NumberOfRvaAndSize;
395  return BaseOfData;
396 }
397 
398 static bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
399  if (CP.isPE()) {
400  // PE files start with a DOS stub.
402  memset(&DH, 0, sizeof(DH));
403 
404  // DOS EXEs start with "MZ" magic.
405  DH.Magic[0] = 'M';
406  DH.Magic[1] = 'Z';
407  // Initializing the AddressOfRelocationTable is strictly optional but
408  // mollifies certain tools which expect it to have a value greater than
409  // 0x40.
410  DH.AddressOfRelocationTable = sizeof(DH);
411  // This is the address of the PE signature.
412  DH.AddressOfNewExeHeader = DOSStubSize;
413 
414  // Write out our DOS stub.
415  OS.write(reinterpret_cast<char *>(&DH), sizeof(DH));
416  // Write padding until we reach the position of where our PE signature
417  // should live.
418  OS.write_zeros(DOSStubSize - sizeof(DH));
419  // Write out the PE signature.
420  OS.write(COFF::PEMagic, sizeof(COFF::PEMagic));
421  }
422  if (CP.useBigObj()) {
423  OS << binary_le(static_cast<uint16_t>(COFF::IMAGE_FILE_MACHINE_UNKNOWN))
424  << binary_le(static_cast<uint16_t>(0xffff))
425  << binary_le(
427  << binary_le(CP.Obj.Header.Machine)
428  << binary_le(CP.Obj.Header.TimeDateStamp);
430  OS << zeros(uint32_t(0)) << zeros(uint32_t(0)) << zeros(uint32_t(0))
431  << zeros(uint32_t(0)) << binary_le(CP.Obj.Header.NumberOfSections)
432  << binary_le(CP.Obj.Header.PointerToSymbolTable)
433  << binary_le(CP.Obj.Header.NumberOfSymbols);
434  } else {
435  OS << binary_le(CP.Obj.Header.Machine)
436  << binary_le(static_cast<int16_t>(CP.Obj.Header.NumberOfSections))
437  << binary_le(CP.Obj.Header.TimeDateStamp)
438  << binary_le(CP.Obj.Header.PointerToSymbolTable)
439  << binary_le(CP.Obj.Header.NumberOfSymbols)
440  << binary_le(CP.Obj.Header.SizeOfOptionalHeader)
441  << binary_le(CP.Obj.Header.Characteristics);
442  }
443  if (CP.isPE()) {
444  if (CP.is64Bit()) {
447  OS.write(reinterpret_cast<char *>(&PEH), sizeof(PEH));
448  } else {
450  uint32_t BaseOfData =
452  PEH.BaseOfData = BaseOfData;
453  OS.write(reinterpret_cast<char *>(&PEH), sizeof(PEH));
454  }
455  for (uint32_t I = 0; I < CP.Obj.OptionalHeader->Header.NumberOfRvaAndSize;
456  ++I) {
457  const Optional<COFF::DataDirectory> *DataDirectories =
458  CP.Obj.OptionalHeader->DataDirectories;
459  uint32_t NumDataDir = sizeof(CP.Obj.OptionalHeader->DataDirectories) /
461  if (I >= NumDataDir || !DataDirectories[I]) {
462  OS << zeros(uint32_t(0));
463  OS << zeros(uint32_t(0));
464  } else {
465  OS << binary_le(DataDirectories[I]->RelativeVirtualAddress);
466  OS << binary_le(DataDirectories[I]->Size);
467  }
468  }
469  }
470 
471  assert(OS.tell() == CP.SectionTableStart);
472  // Output section table.
473  for (const COFFYAML::Section &S : CP.Obj.Sections) {
474  OS.write(S.Header.Name, COFF::NameSize);
475  OS << binary_le(S.Header.VirtualSize)
476  << binary_le(S.Header.VirtualAddress)
477  << binary_le(S.Header.SizeOfRawData)
478  << binary_le(S.Header.PointerToRawData)
479  << binary_le(S.Header.PointerToRelocations)
480  << binary_le(S.Header.PointerToLineNumbers)
481  << binary_le(S.Header.NumberOfRelocations)
482  << binary_le(S.Header.NumberOfLineNumbers)
483  << binary_le(S.Header.Characteristics);
484  }
485  assert(OS.tell() == CP.SectionTableStart + CP.SectionTableSize);
486 
487  unsigned CurSymbol = 0;
488  StringMap<unsigned> SymbolTableIndexMap;
489  for (const COFFYAML::Symbol &Sym : CP.Obj.Symbols) {
490  SymbolTableIndexMap[Sym.Name] = CurSymbol;
491  CurSymbol += 1 + Sym.Header.NumberOfAuxSymbols;
492  }
493 
494  // Output section data.
495  for (const COFFYAML::Section &S : CP.Obj.Sections) {
496  if (S.Header.SizeOfRawData == 0 || S.Header.PointerToRawData == 0)
497  continue;
498  assert(S.Header.PointerToRawData >= OS.tell());
499  OS.write_zeros(S.Header.PointerToRawData - OS.tell());
500  S.SectionData.writeAsBinary(OS);
501  assert(S.Header.SizeOfRawData >= S.SectionData.binary_size());
502  OS.write_zeros(S.Header.SizeOfRawData - S.SectionData.binary_size());
503  if (S.Header.Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL)
504  OS << binary_le<uint32_t>(/*VirtualAddress=*/ S.Relocations.size() + 1)
505  << binary_le<uint32_t>(/*SymbolTableIndex=*/ 0)
506  << binary_le<uint16_t>(/*Type=*/ 0);
507  for (const COFFYAML::Relocation &R : S.Relocations) {
508  uint32_t SymbolTableIndex;
509  if (R.SymbolTableIndex) {
510  if (!R.SymbolName.empty())
512  << "Both SymbolName and SymbolTableIndex specified\n";
513  SymbolTableIndex = *R.SymbolTableIndex;
514  } else {
515  SymbolTableIndex = SymbolTableIndexMap[R.SymbolName];
516  }
517  OS << binary_le(R.VirtualAddress) << binary_le(SymbolTableIndex)
518  << binary_le(R.Type);
519  }
520  }
521 
522  // Output symbol table.
523 
524  for (std::vector<COFFYAML::Symbol>::const_iterator i = CP.Obj.Symbols.begin(),
525  e = CP.Obj.Symbols.end();
526  i != e; ++i) {
527  OS.write(i->Header.Name, COFF::NameSize);
528  OS << binary_le(i->Header.Value);
529  if (CP.useBigObj())
530  OS << binary_le(i->Header.SectionNumber);
531  else
532  OS << binary_le(static_cast<int16_t>(i->Header.SectionNumber));
533  OS << binary_le(i->Header.Type) << binary_le(i->Header.StorageClass)
534  << binary_le(i->Header.NumberOfAuxSymbols);
535 
536  if (i->FunctionDefinition) {
537  OS << binary_le(i->FunctionDefinition->TagIndex)
538  << binary_le(i->FunctionDefinition->TotalSize)
539  << binary_le(i->FunctionDefinition->PointerToLinenumber)
540  << binary_le(i->FunctionDefinition->PointerToNextFunction)
541  << zeros(i->FunctionDefinition->unused);
542  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
543  }
544  if (i->bfAndefSymbol) {
545  OS << zeros(i->bfAndefSymbol->unused1)
546  << binary_le(i->bfAndefSymbol->Linenumber)
547  << zeros(i->bfAndefSymbol->unused2)
548  << binary_le(i->bfAndefSymbol->PointerToNextFunction)
549  << zeros(i->bfAndefSymbol->unused3);
550  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
551  }
552  if (i->WeakExternal) {
553  OS << binary_le(i->WeakExternal->TagIndex)
554  << binary_le(i->WeakExternal->Characteristics)
555  << zeros(i->WeakExternal->unused);
556  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
557  }
558  if (!i->File.empty()) {
559  unsigned SymbolSize = CP.getSymbolSize();
560  uint32_t NumberOfAuxRecords =
561  (i->File.size() + SymbolSize - 1) / SymbolSize;
562  uint32_t NumberOfAuxBytes = NumberOfAuxRecords * SymbolSize;
563  uint32_t NumZeros = NumberOfAuxBytes - i->File.size();
564  OS.write(i->File.data(), i->File.size());
565  OS.write_zeros(NumZeros);
566  }
567  if (i->SectionDefinition) {
568  OS << binary_le(i->SectionDefinition->Length)
569  << binary_le(i->SectionDefinition->NumberOfRelocations)
570  << binary_le(i->SectionDefinition->NumberOfLinenumbers)
571  << binary_le(i->SectionDefinition->CheckSum)
572  << binary_le(static_cast<int16_t>(i->SectionDefinition->Number))
573  << binary_le(i->SectionDefinition->Selection)
574  << zeros(i->SectionDefinition->unused)
575  << binary_le(static_cast<int16_t>(i->SectionDefinition->Number >> 16));
576  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
577  }
578  if (i->CLRToken) {
579  OS << binary_le(i->CLRToken->AuxType) << zeros(i->CLRToken->unused1)
580  << binary_le(i->CLRToken->SymbolTableIndex)
581  << zeros(i->CLRToken->unused2);
582  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
583  }
584  }
585 
586  // Output string table.
587  if (CP.Obj.Header.PointerToSymbolTable)
588  OS.write(&CP.StringTable[0], CP.StringTable.size());
589  return true;
590 }
591 
592 namespace llvm {
593 namespace yaml {
594 
596  ErrorHandler ErrHandler) {
597  COFFParser CP(Doc, ErrHandler);
598  if (!CP.parse()) {
599  ErrHandler("failed to parse YAML file");
600  return false;
601  }
602 
603  if (!layoutOptionalHeader(CP)) {
604  ErrHandler("failed to layout optional header for COFF file");
605  return false;
606  }
607 
608  if (!layoutCOFF(CP)) {
609  ErrHandler("failed to layout COFF file");
610  return false;
611  }
612  if (!writeCOFF(CP, Out)) {
613  ErrHandler("failed to write COFF file");
614  return false;
615  }
616  return true;
617 }
618 
619 } // namespace yaml
620 } // 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:156
llvm::raw_ostream::tell
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:134
zeros
zeros_impl< sizeof(T)> zeros(const T &)
Definition: COFFEmitter.cpp:339
writeCOFF
static bool writeCOFF(COFFParser &CP, raw_ostream &OS)
Definition: COFFEmitter.cpp:398
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:18
ObjectYAML.h
llvm::COFF::IMAGE_SCN_LNK_NRELOC_OVFL
@ IMAGE_SCN_LNK_NRELOC_OVFL
Definition: COFF.h:315
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:290
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:499
llvm::COFFYAML::Object::Sections
std::vector< Section > Sections
Definition: COFFYAML.h:106
is64Bit
static bool is64Bit(const char *name)
Definition: X86Disassembler.cpp:1018
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:161
llvm::COFF::symbol::Type
uint16_t Type
Definition: COFF.h:191
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:265
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:459
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:804
llvm::X86AS::SS
@ SS
Definition: X86.h:201
llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
@ IMAGE_SCN_CNT_INITIALIZED_DATA
Definition: COFF.h:289
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:595
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:548
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:218
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
llvm::operator<<
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:230
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:325
llvm::COFF::section::Characteristics
uint32_t Characteristics
Definition: COFF.h:280
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:310
initializeOptionalHeader
static uint32_t initializeOptionalHeader(COFFParser &CP, uint16_t Magic, T Header)
Definition: COFFEmitter.cpp:344
Index
uint32_t Index
Definition: ELFObjHandler.cpp:82
llvm::COFF::symbol::NumberOfAuxSymbols
uint8_t NumberOfAuxSymbols
Definition: COFF.h:193
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:54
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:200
StringExtras.h
llvm::COFF::PE32Header::PE32
@ PE32
Definition: COFF.h:541
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::COFFYAML::Symbol
Definition: COFFYAML.h:83
llvm::codeview::CodeViewContainer::ObjectFile
@ ObjectFile
llvm::COFF::IMAGE_FILE_MACHINE_ARM64EC
@ IMAGE_FILE_MACHINE_ARM64EC
Definition: COFF.h:101
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:311
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:50
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:173
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:309
llvm::HexagonISD::CP
@ CP
Definition: HexagonISelLowering.h:53
llvm::COFF::DEBUG_SECTION_MAGIC
@ DEBUG_SECTION_MAGIC
Definition: COFF.h:771
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:288
zeros_impl
Definition: COFFEmitter.cpp:329
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:541
Allocator
Basic Register Allocator
Definition: RegAllocBasic.cpp:143
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:188
StringMap.h
llvm::COFF::section::Name
char Name[NameSize]
Definition: COFF.h:271
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