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