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 = std::size(CP.Obj.OptionalHeader->DataDirectories);
460  if (I >= NumDataDir || !DataDirectories[I]) {
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:156
llvm::raw_ostream::tell
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:135
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
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
getStringIndex
static size_t getStringIndex(StringRef Name)
Definition: LVElement.cpp:77
llvm::COFFYAML::Object::OptionalHeader
Optional< PEHeader > OptionalHeader
Definition: COFFYAML.h:104
llvm::ExitOnError
Helper for check-and-exit error handling.
Definition: Error.h:1347
llvm::Optional
Definition: APInt.h:33
llvm::COFFYAML::Relocation
Definition: COFFYAML.h:57
T
#define T
Definition: Mips16ISelLowering.cpp:341
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:458
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::X86AS::SS
@ SS
Definition: X86.h:201
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::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:419
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:547
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:53
llvm::operator<<
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:291
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:83
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:53
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
size
i< reg-> size
Definition: README.txt:166
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