38 : Obj(Obj), SectionTableStart(0), SectionTableSize(0), ErrHandler(EH) {
44 bool useBigObj()
const {
45 return static_cast<int32_t
>(Obj.
Sections.size()) >
59 unsigned getHeaderSize()
const {
63 unsigned getSymbolSize()
const {
67 bool parseSections() {
78 std::string str = utostr(Index);
80 ErrHandler(
"string table got too large");
89 ErrHandler(
"section alignment is too large");
93 ErrHandler(
"section alignment is not a power of 2");
102 bool parseSymbols() {
123 if (!parseSections())
132 if (
i == StringTableMap.end()) {
136 StringTableMap[Str] =
Index;
154 enum { DOSStubSize = 128 };
165 CP.Obj.Header.SizeOfOptionalHeader =
167 CP.Obj.OptionalHeader->Header.NumberOfRvaAndSize;
174 using namespace codeview;
175 ExitOnError Err(
"Error occurred writing .debug$S section");
179 std::vector<DebugSubsectionRecordBuilder> Builders;
181 for (
auto &
SS : CVSS) {
182 DebugSubsectionRecordBuilder
B(
SS);
183 Size +=
B.calculateSerializedLength();
186 uint8_t *Buffer =
Allocator.Allocate<uint8_t>(Size);
191 for (
const auto &
B : Builders) {
202 CP.SectionTableStart =
203 CP.getHeaderSize() +
CP.Obj.Header.SizeOfOptionalHeader;
209 CP.SectionTableStart +
CP.SectionTableSize;
214 if (
S.Name ==
".debug$S" &&
S.SectionData.binary_size() == 0) {
216 CP.StringsAndChecksums);
217 if (
CP.StringsAndChecksums.hasChecksums() &&
218 CP.StringsAndChecksums.hasStrings())
225 if (
S.Name ==
".debug$S") {
226 if (
S.SectionData.binary_size() == 0) {
227 assert(
CP.StringsAndChecksums.hasStrings() &&
228 "Object file does not have debug string table!");
233 }
else if (
S.Name ==
".debug$T") {
234 if (
S.SectionData.binary_size() == 0)
236 }
else if (
S.Name ==
".debug$P") {
237 if (
S.SectionData.binary_size() == 0)
239 }
else if (
S.Name ==
".debug$H") {
240 if (
S.DebugH.hasValue() &&
S.SectionData.binary_size() == 0)
244 if (
S.SectionData.binary_size() > 0) {
245 CurrentSectionDataOffset =
alignTo(CurrentSectionDataOffset,
246 CP.isPE() ?
CP.getFileAlignment() : 4);
247 S.Header.SizeOfRawData =
S.SectionData.binary_size();
249 S.Header.SizeOfRawData =
250 alignTo(
S.Header.SizeOfRawData,
CP.getFileAlignment());
251 S.Header.PointerToRawData = CurrentSectionDataOffset;
252 CurrentSectionDataOffset +=
S.Header.SizeOfRawData;
253 if (!
S.Relocations.empty()) {
254 S.Header.PointerToRelocations = CurrentSectionDataOffset;
256 S.Header.NumberOfRelocations = 0xffff;
259 S.Header.NumberOfRelocations =
S.Relocations.size();
265 S.Header.PointerToRawData = 0;
269 uint32_t SymbolTableStart = CurrentSectionDataOffset;
273 for (std::vector<COFFYAML::Symbol>::iterator
i =
CP.Obj.Symbols.begin(),
274 e =
CP.Obj.Symbols.end();
277 if (
i->FunctionDefinition)
278 NumberOfAuxSymbols += 1;
279 if (
i->bfAndefSymbol)
280 NumberOfAuxSymbols += 1;
282 NumberOfAuxSymbols += 1;
283 if (!
i->File.empty())
284 NumberOfAuxSymbols +=
285 (
i->File.size() +
CP.getSymbolSize() - 1) /
CP.getSymbolSize();
286 if (
i->SectionDefinition)
287 NumberOfAuxSymbols += 1;
289 NumberOfAuxSymbols += 1;
290 i->Header.NumberOfAuxSymbols = NumberOfAuxSymbols;
291 NumberOfSymbols += 1 + NumberOfAuxSymbols;
295 CP.Obj.Header.NumberOfSections =
CP.Obj.Sections.size();
296 CP.Obj.Header.NumberOfSymbols = NumberOfSymbols;
297 if (NumberOfSymbols > 0 ||
CP.StringTable.size() > 4)
298 CP.Obj.Header.PointerToSymbolTable = SymbolTableStart;
300 CP.Obj.Header.PointerToSymbolTable = 0;
303 CP.StringTable.size();
313 template <
typename value_type>
316 char Buffer[
sizeof(BLE.
Value)];
317 support::endian::write<value_type, support::little, support::unaligned>(
323 template <
typename value_type>
330 template <
size_t NumBytes>
332 char Buffer[NumBytes];
333 memset(Buffer, 0,
sizeof(Buffer));
334 OS.
write(Buffer,
sizeof(Buffer));
342 template <
typename T>
345 memset(Header, 0,
sizeof(*Header));
346 Header->Magic =
Magic;
347 Header->SectionAlignment =
CP.Obj.OptionalHeader->Header.SectionAlignment;
348 Header->FileAlignment =
CP.Obj.OptionalHeader->Header.FileAlignment;
349 uint32_t SizeOfCode = 0, SizeOfInitializedData = 0,
350 SizeOfUninitializedData = 0;
352 Header->FileAlignment);
353 uint32_t SizeOfImage =
alignTo(SizeOfHeaders, Header->SectionAlignment);
357 SizeOfCode +=
S.Header.SizeOfRawData;
359 SizeOfInitializedData +=
S.Header.SizeOfRawData;
361 SizeOfUninitializedData +=
S.Header.SizeOfRawData;
362 if (
S.Name.equals(
".text"))
363 Header->BaseOfCode =
S.Header.VirtualAddress;
364 else if (
S.Name.equals(
".data"))
365 BaseOfData =
S.Header.VirtualAddress;
366 if (
S.Header.VirtualAddress)
367 SizeOfImage +=
alignTo(
S.Header.VirtualSize, Header->SectionAlignment);
369 Header->SizeOfCode = SizeOfCode;
370 Header->SizeOfInitializedData = SizeOfInitializedData;
371 Header->SizeOfUninitializedData = SizeOfUninitializedData;
372 Header->AddressOfEntryPoint =
373 CP.Obj.OptionalHeader->Header.AddressOfEntryPoint;
374 Header->ImageBase =
CP.Obj.OptionalHeader->Header.ImageBase;
375 Header->MajorOperatingSystemVersion =
376 CP.Obj.OptionalHeader->Header.MajorOperatingSystemVersion;
377 Header->MinorOperatingSystemVersion =
378 CP.Obj.OptionalHeader->Header.MinorOperatingSystemVersion;
379 Header->MajorImageVersion =
CP.Obj.OptionalHeader->Header.MajorImageVersion;
380 Header->MinorImageVersion =
CP.Obj.OptionalHeader->Header.MinorImageVersion;
381 Header->MajorSubsystemVersion =
382 CP.Obj.OptionalHeader->Header.MajorSubsystemVersion;
383 Header->MinorSubsystemVersion =
384 CP.Obj.OptionalHeader->Header.MinorSubsystemVersion;
385 Header->SizeOfImage = SizeOfImage;
386 Header->SizeOfHeaders = SizeOfHeaders;
387 Header->Subsystem =
CP.Obj.OptionalHeader->Header.Subsystem;
388 Header->DLLCharacteristics =
CP.Obj.OptionalHeader->Header.DLLCharacteristics;
389 Header->SizeOfStackReserve =
CP.Obj.OptionalHeader->Header.SizeOfStackReserve;
390 Header->SizeOfStackCommit =
CP.Obj.OptionalHeader->Header.SizeOfStackCommit;
391 Header->SizeOfHeapReserve =
CP.Obj.OptionalHeader->Header.SizeOfHeapReserve;
392 Header->SizeOfHeapCommit =
CP.Obj.OptionalHeader->Header.SizeOfHeapCommit;
393 Header->NumberOfRvaAndSize =
CP.Obj.OptionalHeader->Header.NumberOfRvaAndSize;
401 memset(&DH, 0,
sizeof(DH));
414 OS.
write(
reinterpret_cast<char *
>(&DH),
sizeof(DH));
421 if (
CP.useBigObj()) {
435 <<
binary_le(
static_cast<int16_t
>(
CP.Obj.Header.NumberOfSections))
446 OS.
write(
reinterpret_cast<char *
>(&PEH),
sizeof(PEH));
452 OS.
write(
reinterpret_cast<char *
>(&PEH),
sizeof(PEH));
454 for (
uint32_t I = 0;
I <
CP.Obj.OptionalHeader->Header.NumberOfRvaAndSize;
457 CP.Obj.OptionalHeader->DataDirectories;
458 uint32_t NumDataDir =
sizeof(
CP.Obj.OptionalHeader->DataDirectories) /
460 if (
I >= NumDataDir || !DataDirectories[
I].hasValue()) {
464 OS <<
binary_le(DataDirectories[
I]->RelativeVirtualAddress);
486 unsigned CurSymbol = 0;
489 SymbolTableIndexMap[Sym.
Name] = CurSymbol;
495 if (
S.Header.SizeOfRawData == 0 ||
S.Header.PointerToRawData == 0)
499 S.SectionData.writeAsBinary(OS);
500 assert(
S.Header.SizeOfRawData >=
S.SectionData.binary_size());
501 OS.
write_zeros(
S.Header.SizeOfRawData -
S.SectionData.binary_size());
503 OS << binary_le<uint32_t>(
S.Relocations.size() + 1)
504 << binary_le<uint32_t>( 0)
505 << binary_le<uint16_t>( 0);
508 if (R.SymbolTableIndex) {
509 if (!R.SymbolName.empty())
511 <<
"Both SymbolName and SymbolTableIndex specified\n";
512 SymbolTableIndex = *R.SymbolTableIndex;
514 SymbolTableIndex = SymbolTableIndexMap[R.SymbolName];
523 for (std::vector<COFFYAML::Symbol>::const_iterator
i =
CP.Obj.Symbols.begin(),
524 e =
CP.Obj.Symbols.end();
531 OS << binary_le(static_cast<int16_t>(
i->Header.SectionNumber));
535 if (
i->FunctionDefinition) {
536 OS <<
binary_le(
i->FunctionDefinition->TagIndex)
537 <<
binary_le(
i->FunctionDefinition->TotalSize)
538 <<
binary_le(
i->FunctionDefinition->PointerToLinenumber)
539 <<
binary_le(
i->FunctionDefinition->PointerToNextFunction)
540 <<
zeros(
i->FunctionDefinition->unused);
543 if (
i->bfAndefSymbol) {
544 OS <<
zeros(
i->bfAndefSymbol->unused1)
546 <<
zeros(
i->bfAndefSymbol->unused2)
547 <<
binary_le(
i->bfAndefSymbol->PointerToNextFunction)
548 <<
zeros(
i->bfAndefSymbol->unused3);
551 if (
i->WeakExternal) {
553 <<
binary_le(
i->WeakExternal->Characteristics)
554 <<
zeros(
i->WeakExternal->unused);
557 if (!
i->File.empty()) {
558 unsigned SymbolSize =
CP.getSymbolSize();
560 (
i->File.size() + SymbolSize - 1) / SymbolSize;
561 uint32_t NumberOfAuxBytes = NumberOfAuxRecords * SymbolSize;
562 uint32_t NumZeros = NumberOfAuxBytes -
i->File.size();
563 OS.
write(
i->File.data(),
i->File.size());
566 if (
i->SectionDefinition) {
568 <<
binary_le(
i->SectionDefinition->NumberOfRelocations)
569 <<
binary_le(
i->SectionDefinition->NumberOfLinenumbers)
571 <<
binary_le(
static_cast<int16_t
>(
i->SectionDefinition->Number))
573 <<
zeros(
i->SectionDefinition->unused)
574 <<
binary_le(
static_cast<int16_t
>(
i->SectionDefinition->Number >> 16));
580 <<
zeros(
i->CLRToken->unused2);
586 if (
CP.Obj.Header.PointerToSymbolTable)
587 OS.
write(&
CP.StringTable[0],
CP.StringTable.size());
596 COFFParser
CP(Doc, ErrHandler);
598 ErrHandler(
"failed to parse YAML file");
603 ErrHandler(
"failed to layout optional header for COFF file");
608 ErrHandler(
"failed to layout COFF file");
612 ErrHandler(
"failed to write COFF file");