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 +
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 = COFF::NUM_DATA_DIRECTORIES + 1;
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 (const Optional<COFF::DataDirectory> &DD :
462  CP.Obj.OptionalHeader->DataDirectories) {
463  if (!DD.hasValue()) {
464  OS << zeros(uint32_t(0));
465  OS << zeros(uint32_t(0));
466  } else {
468  OS << binary_le(DD->Size);
469  }
470  }
471  OS << zeros(uint32_t(0));
472  OS << zeros(uint32_t(0));
473  }
474 
475  assert(OS.tell() == CP.SectionTableStart);
476  // Output section table.
477  for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
478  e = CP.Obj.Sections.end();
479  i != e; ++i) {
480  OS.write(i->Header.Name, COFF::NameSize);
481  OS << binary_le(i->Header.VirtualSize)
482  << binary_le(i->Header.VirtualAddress)
483  << binary_le(i->Header.SizeOfRawData)
484  << binary_le(i->Header.PointerToRawData)
485  << binary_le(i->Header.PointerToRelocations)
486  << binary_le(i->Header.PointerToLineNumbers)
487  << binary_le(i->Header.NumberOfRelocations)
488  << binary_le(i->Header.NumberOfLineNumbers)
489  << binary_le(i->Header.Characteristics);
490  }
491  assert(OS.tell() == CP.SectionTableStart + CP.SectionTableSize);
492 
493  unsigned CurSymbol = 0;
494  StringMap<unsigned> SymbolTableIndexMap;
495  for (std::vector<COFFYAML::Symbol>::iterator I = CP.Obj.Symbols.begin(),
496  E = CP.Obj.Symbols.end();
497  I != E; ++I) {
498  SymbolTableIndexMap[I->Name] = CurSymbol;
499  CurSymbol += 1 + I->Header.NumberOfAuxSymbols;
500  }
501 
502  // Output section data.
503  for (const COFFYAML::Section &S : CP.Obj.Sections) {
504  if (S.Header.SizeOfRawData == 0 || S.Header.PointerToRawData == 0)
505  continue;
506  assert(S.Header.PointerToRawData >= OS.tell());
507  OS.write_zeros(S.Header.PointerToRawData - OS.tell());
508  S.SectionData.writeAsBinary(OS);
509  assert(S.Header.SizeOfRawData >= S.SectionData.binary_size());
510  OS.write_zeros(S.Header.SizeOfRawData - S.SectionData.binary_size());
511  if (S.Header.Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL)
512  OS << binary_le<uint32_t>(/*VirtualAddress=*/ S.Relocations.size() + 1)
513  << binary_le<uint32_t>(/*SymbolTableIndex=*/ 0)
514  << binary_le<uint16_t>(/*Type=*/ 0);
515  for (const COFFYAML::Relocation &R : S.Relocations) {
516  uint32_t SymbolTableIndex;
517  if (R.SymbolTableIndex) {
518  if (!R.SymbolName.empty())
520  << "Both SymbolName and SymbolTableIndex specified\n";
521  SymbolTableIndex = *R.SymbolTableIndex;
522  } else {
523  SymbolTableIndex = SymbolTableIndexMap[R.SymbolName];
524  }
525  OS << binary_le(R.VirtualAddress) << binary_le(SymbolTableIndex)
526  << binary_le(R.Type);
527  }
528  }
529 
530  // Output symbol table.
531 
532  for (std::vector<COFFYAML::Symbol>::const_iterator i = CP.Obj.Symbols.begin(),
533  e = CP.Obj.Symbols.end();
534  i != e; ++i) {
535  OS.write(i->Header.Name, COFF::NameSize);
536  OS << binary_le(i->Header.Value);
537  if (CP.useBigObj())
538  OS << binary_le(i->Header.SectionNumber);
539  else
540  OS << binary_le(static_cast<int16_t>(i->Header.SectionNumber));
541  OS << binary_le(i->Header.Type) << binary_le(i->Header.StorageClass)
542  << binary_le(i->Header.NumberOfAuxSymbols);
543 
544  if (i->FunctionDefinition) {
545  OS << binary_le(i->FunctionDefinition->TagIndex)
546  << binary_le(i->FunctionDefinition->TotalSize)
547  << binary_le(i->FunctionDefinition->PointerToLinenumber)
548  << binary_le(i->FunctionDefinition->PointerToNextFunction)
549  << zeros(i->FunctionDefinition->unused);
550  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
551  }
552  if (i->bfAndefSymbol) {
553  OS << zeros(i->bfAndefSymbol->unused1)
554  << binary_le(i->bfAndefSymbol->Linenumber)
555  << zeros(i->bfAndefSymbol->unused2)
556  << binary_le(i->bfAndefSymbol->PointerToNextFunction)
557  << zeros(i->bfAndefSymbol->unused3);
558  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
559  }
560  if (i->WeakExternal) {
561  OS << binary_le(i->WeakExternal->TagIndex)
562  << binary_le(i->WeakExternal->Characteristics)
563  << zeros(i->WeakExternal->unused);
564  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
565  }
566  if (!i->File.empty()) {
567  unsigned SymbolSize = CP.getSymbolSize();
568  uint32_t NumberOfAuxRecords =
569  (i->File.size() + SymbolSize - 1) / SymbolSize;
570  uint32_t NumberOfAuxBytes = NumberOfAuxRecords * SymbolSize;
571  uint32_t NumZeros = NumberOfAuxBytes - i->File.size();
572  OS.write(i->File.data(), i->File.size());
573  OS.write_zeros(NumZeros);
574  }
575  if (i->SectionDefinition) {
576  OS << binary_le(i->SectionDefinition->Length)
577  << binary_le(i->SectionDefinition->NumberOfRelocations)
578  << binary_le(i->SectionDefinition->NumberOfLinenumbers)
579  << binary_le(i->SectionDefinition->CheckSum)
580  << binary_le(static_cast<int16_t>(i->SectionDefinition->Number))
581  << binary_le(i->SectionDefinition->Selection)
582  << zeros(i->SectionDefinition->unused)
583  << binary_le(static_cast<int16_t>(i->SectionDefinition->Number >> 16));
584  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
585  }
586  if (i->CLRToken) {
587  OS << binary_le(i->CLRToken->AuxType) << zeros(i->CLRToken->unused1)
588  << binary_le(i->CLRToken->SymbolTableIndex)
589  << zeros(i->CLRToken->unused2);
590  OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
591  }
592  }
593 
594  // Output string table.
595  if (CP.Obj.Header.PointerToSymbolTable)
596  OS.write(&CP.StringTable[0], CP.StringTable.size());
597  return true;
598 }
599 
600 namespace llvm {
601 namespace yaml {
602 
604  ErrorHandler ErrHandler) {
605  COFFParser CP(Doc, ErrHandler);
606  if (!CP.parse()) {
607  ErrHandler("failed to parse YAML file");
608  return false;
609  }
610 
611  if (!layoutOptionalHeader(CP)) {
612  ErrHandler("failed to layout optional header for COFF file");
613  return false;
614  }
615 
616  if (!layoutCOFF(CP)) {
617  ErrHandler("failed to layout COFF file");
618  return false;
619  }
620  if (!writeCOFF(CP, Out)) {
621  ErrHandler("failed to write COFF file");
622  return false;
623  }
624  return true;
625 }
626 
627 } // namespace yaml
628 } // 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
---------------------— PointerInfo ------------------------------------—
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::COFF::DataDirectory::Size
uint32_t Size
Definition: COFF.h:579
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:502
llvm::COFFYAML::Object::Sections
std::vector< Section > Sections
Definition: COFFYAML.h:106
is64Bit
static bool is64Bit(const char *name)
Definition: X86Disassembler.cpp:1005
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:1335
llvm::Optional
Definition: APInt.h:33
llvm::COFFYAML::Relocation
Definition: COFFYAML.h:57
T
#define T
Definition: Mips16ISelLowering.cpp:341
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::Optional::hasValue
constexpr bool hasValue() const
Definition: Optional.h:288
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:603
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
llvm::COFF::NUM_DATA_DIRECTORIES
@ NUM_DATA_DIRECTORIES
Definition: COFF.h:599
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
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::DataDirectory::RelativeVirtualAddress
uint32_t RelativeVirtualAddress
Definition: COFF.h:578
llvm::COFF::symbol::Name
char Name[NameSize]
Definition: COFF.h:188
llvm::X86AS::SS
@ SS
Definition: X86.h:189
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:75