+ if (PEHeader)
+ printPEHeader<pe32_header>(PEHeader);
+
+ const pe32plus_header *PEPlusHeader = 0;
+ if (error(Obj->getPE32PlusHeader(PEPlusHeader)))
+ return;
+ if (PEPlusHeader)
+ printPEHeader<pe32plus_header>(PEPlusHeader);
+}
+
+template <class PEHeader>
+void COFFDumper::printPEHeader(const PEHeader *Hdr) {
+ DictScope D(W, "ImageOptionalHeader");
+ W.printNumber("MajorLinkerVersion", Hdr->MajorLinkerVersion);
+ W.printNumber("MinorLinkerVersion", Hdr->MinorLinkerVersion);
+ W.printNumber("SizeOfCode", Hdr->SizeOfCode);
+ W.printNumber("SizeOfInitializedData", Hdr->SizeOfInitializedData);
+ W.printNumber("SizeOfUninitializedData", Hdr->SizeOfUninitializedData);
+ W.printHex ("AddressOfEntryPoint", Hdr->AddressOfEntryPoint);
+ W.printHex ("BaseOfCode", Hdr->BaseOfCode);
+ printBaseOfDataField(Hdr);
+ W.printHex ("ImageBase", Hdr->ImageBase);
+ W.printNumber("SectionAlignment", Hdr->SectionAlignment);
+ W.printNumber("FileAlignment", Hdr->FileAlignment);
+ W.printNumber("MajorOperatingSystemVersion",
+ Hdr->MajorOperatingSystemVersion);
+ W.printNumber("MinorOperatingSystemVersion",
+ Hdr->MinorOperatingSystemVersion);
+ W.printNumber("MajorImageVersion", Hdr->MajorImageVersion);
+ W.printNumber("MinorImageVersion", Hdr->MinorImageVersion);
+ W.printNumber("MajorSubsystemVersion", Hdr->MajorSubsystemVersion);
+ W.printNumber("MinorSubsystemVersion", Hdr->MinorSubsystemVersion);
+ W.printNumber("SizeOfImage", Hdr->SizeOfImage);
+ W.printNumber("SizeOfHeaders", Hdr->SizeOfHeaders);
+ W.printEnum ("Subsystem", Hdr->Subsystem, makeArrayRef(PEWindowsSubsystem));
+ W.printFlags ("Subsystem", Hdr->DLLCharacteristics,
+ makeArrayRef(PEDLLCharacteristics));
+ W.printNumber("SizeOfStackReserve", Hdr->SizeOfStackReserve);
+ W.printNumber("SizeOfStackCommit", Hdr->SizeOfStackCommit);
+ W.printNumber("SizeOfHeapReserve", Hdr->SizeOfHeapReserve);
+ W.printNumber("SizeOfHeapCommit", Hdr->SizeOfHeapCommit);
+ W.printNumber("NumberOfRvaAndSize", Hdr->NumberOfRvaAndSize);
+
+ if (Hdr->NumberOfRvaAndSize > 0) {
+ DictScope D(W, "DataDirectory");
+ static const char * const directory[] = {
+ "ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",
+ "CertificateTable", "BaseRelocationTable", "Debug", "Architecture",
+ "GlobalPtr", "TLSTable", "LoadConfigTable", "BoundImport", "IAT",
+ "DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
+ };
+
+ for (uint32_t i = 0; i < Hdr->NumberOfRvaAndSize; ++i) {
+ printDataDirectory(i, directory[i]);
+ }
+ }
+}
+
+void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) {
+ W.printHex("BaseOfData", Hdr->BaseOfData);
+}
+
+void COFFDumper::printBaseOfDataField(const pe32plus_header *) {}
+
+void COFFDumper::printCodeViewLineTables(section_iterator SecI) {
+ StringRef Data;
+ if (error(SecI->getContents(Data))) return;
+
+ SmallVector<StringRef, 10> FunctionNames;
+ StringMap<StringRef> FunctionLineTables;
+ StringRef FileIndexToStringOffsetTable;
+ StringRef StringTable;
+
+ ListScope D(W, "CodeViewLineTables");
+ {
+ DataExtractor DE(Data, true, 4);
+ uint32_t Offset = 0,
+ Magic = DE.getU32(&Offset);
+ W.printHex("Magic", Magic);
+ if (Magic != COFF::DEBUG_SECTION_MAGIC) {
+ error(object_error::parse_failed);
+ return;
+ }
+
+ bool Finished = false;
+ while (DE.isValidOffset(Offset) && !Finished) {
+ // The section consists of a number of subsection in the following format:
+ // |Type|PayloadSize|Payload...|
+ uint32_t SubSectionType = DE.getU32(&Offset),
+ PayloadSize = DE.getU32(&Offset);
+ ListScope S(W, "Subsection");
+ W.printHex("Type", SubSectionType);
+ W.printHex("PayloadSize", PayloadSize);
+ if (PayloadSize > Data.size() - Offset) {
+ error(object_error::parse_failed);
+ return;
+ }
+
+ // Print the raw contents to simplify debugging if anything goes wrong
+ // afterwards.
+ StringRef Contents = Data.substr(Offset, PayloadSize);
+ W.printBinaryBlock("Contents", Contents);
+
+ switch (SubSectionType) {
+ case COFF::DEBUG_LINE_TABLE_SUBSECTION: {
+ // Holds a PC to file:line table. Some data to parse this subsection is
+ // stored in the other subsections, so just check sanity and store the
+ // pointers for deferred processing.
+
+ if (PayloadSize < 12) {
+ // There should be at least three words to store two function
+ // relocations and size of the code.
+ error(object_error::parse_failed);
+ return;
+ }