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