diff options
author | Eric Beckmann <ecbeckmann@google.com> | 2017-05-07 22:47:22 +0000 |
---|---|---|
committer | Eric Beckmann <ecbeckmann@google.com> | 2017-05-07 22:47:22 +0000 |
commit | 33fca46ec3868c9d840c9bdeb0a401ae8bf874a9 (patch) | |
tree | f073d7085d78730a2f2862b687050ab60f74daac | |
parent | 7e3e7afca87f5bbd6ce416e483b26c36ea384ecf (diff) | |
download | bcm5719-llvm-33fca46ec3868c9d840c9bdeb0a401ae8bf874a9.tar.gz bcm5719-llvm-33fca46ec3868c9d840c9bdeb0a401ae8bf874a9.zip |
Update llvm-readobj -coff-resources to display tree structure.
Summary: Continue making updates to llvm-readobj to display resource sections. This is necessary for testing the up and coming cvtres tool.
Reviewers: zturner
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D32609
llvm-svn: 302386
-rw-r--r-- | llvm/include/llvm/Object/COFF.h | 39 | ||||
-rw-r--r-- | llvm/include/llvm/Support/COFF.h | 24 | ||||
-rw-r--r-- | llvm/lib/Object/COFFObjectFile.cpp | 49 | ||||
-rw-r--r-- | llvm/test/tools/llvm-readobj/Inputs/resources/cursor_small.bmp | bin | 0 -> 822 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-readobj/Inputs/resources/okay_small.bmp | bin | 0 -> 822 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-readobj/Inputs/resources/test_resource.rc | 44 | ||||
-rw-r--r-- | llvm/test/tools/llvm-readobj/Inputs/resources/test_resource.res | bin | 0 -> 2200 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-readobj/resources.test | 128 | ||||
-rw-r--r-- | llvm/tools/llvm-readobj/COFFDumper.cpp | 101 |
9 files changed, 357 insertions, 28 deletions
diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h index 1b6aaf4be66..94fc10340e0 100644 --- a/llvm/include/llvm/Object/COFF.h +++ b/llvm/include/llvm/Object/COFF.h @@ -20,6 +20,7 @@ #include "llvm/Object/Binary.h" #include "llvm/Object/Error.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Support/BinaryByteStream.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" @@ -40,6 +41,7 @@ class DelayImportDirectoryEntryRef; class ExportDirectoryEntryRef; class ImportDirectoryEntryRef; class ImportedSymbolRef; +class ResourceSectionRef; using import_directory_iterator = content_iterator<ImportDirectoryEntryRef>; using delay_import_directory_iterator = @@ -623,6 +625,26 @@ struct coff_base_reloc_block_entry { int getOffset() const { return Data & ((1 << 12) - 1); } }; +struct coff_resource_dir_entry { + union { + support::ulittle32_t NameOffset; + support::ulittle32_t ID; + uint32_t getNameOffset() const { + return maskTrailingOnes<uint32_t>(31) & NameOffset; + } + } Identifier; + union { + support::ulittle32_t DataEntryOffset; + support::ulittle32_t SubdirOffset; + + bool isSubDir() const { return SubdirOffset >> 31; } + uint32_t value() const { + return maskTrailingOnes<uint32_t>(31) & SubdirOffset; + } + + } Offset; +}; + struct coff_resource_dir_table { support::ulittle32_t Characteristics; support::ulittle32_t TimeDateStamp; @@ -1047,6 +1069,23 @@ private: const COFFObjectFile *OwningObject = nullptr; }; +class ResourceSectionRef { +public: + ResourceSectionRef() = default; + explicit ResourceSectionRef(StringRef Ref) : BBS(Ref, support::little) {} + + ErrorOr<StringRef> getEntryNameString(const coff_resource_dir_entry &Entry); + ErrorOr<const coff_resource_dir_table &> + getEntrySubDir(const coff_resource_dir_entry &Entry); + ErrorOr<const coff_resource_dir_table &> getBaseTable(); + +private: + BinaryByteStream BBS; + + ErrorOr<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset); + ErrorOr<StringRef> getDirStringAtOffset(uint32_t Offset); +}; + // Corresponds to `_FPO_DATA` structure in the PE/COFF spec. struct FpoData { support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code diff --git a/llvm/include/llvm/Support/COFF.h b/llvm/include/llvm/Support/COFF.h index 8d2a2ac62c9..bc2098e2b5c 100644 --- a/llvm/include/llvm/Support/COFF.h +++ b/llvm/include/llvm/Support/COFF.h @@ -152,6 +152,30 @@ namespace COFF { IMAGE_FILE_BYTES_REVERSED_HI = 0x8000 }; + enum ResourceTypeID { + RID_Cursor = 1, + RID_Bitmap = 2, + RID_Icon = 3, + RID_Menu = 4, + RID_Dialog = 5, + RID_String = 6, + RID_FontDir = 7, + RID_Font = 8, + RID_Accelerator = 9, + RID_RCData = 10, + RID_MessageTable = 11, + RID_Group_Cursor = 12, + RID_Group_Icon = 14, + RID_Version = 16, + RID_DLGInclude = 17, + RID_PlugPlay = 19, + RID_VXD = 20, + RID_AniCursor = 21, + RID_AniIcon = 22, + RID_HTML = 23, + RID_Manifest = 24, + }; + struct symbol { char Name[NameSize]; uint32_t Value; diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp index 1866aba9b21..39762e1d216 100644 --- a/llvm/lib/Object/COFFObjectFile.cpp +++ b/llvm/lib/Object/COFFObjectFile.cpp @@ -19,7 +19,9 @@ #include "llvm/Object/COFF.h" #include "llvm/Object/Error.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/COFF.h" +#include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" @@ -159,8 +161,7 @@ void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); StringRef Result; - std::error_code EC = getSymbolName(Symb, Result); - if (EC) + if (std::error_code EC = getSymbolName(Symb, Result)) return errorCodeToError(EC); return Result; } @@ -1591,3 +1592,47 @@ std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { Result = Header->PageRVA + Entry[Index].getOffset(); return std::error_code(); } + +#define RETURN_IF_ERROR(X) \ + if (auto EC = errorToErrorCode(X)) \ + return EC; + +ErrorOr<StringRef> ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) { + BinaryStreamReader Reader = BinaryStreamReader(BBS); + Reader.setOffset(Offset); + uint16_t Length; + RETURN_IF_ERROR(Reader.readInteger(Length)); + ArrayRef<UTF16> RawDirString; + // Strings are stored as 2-byte aligned unicode characters but readFixedString + // assumes byte string, so we double length. + RETURN_IF_ERROR(Reader.readArray(RawDirString, Length)); + std::string DirString; + if (!llvm::convertUTF16ToUTF8String(RawDirString, DirString)) + return object_error::parse_failed; + return DirString; +} + +ErrorOr<StringRef> +ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) { + return getDirStringAtOffset(Entry.Identifier.getNameOffset()); +} + +ErrorOr<const coff_resource_dir_table &> +ResourceSectionRef::getTableAtOffset(uint32_t Offset) { + const coff_resource_dir_table *Table = nullptr; + + BinaryStreamReader Reader(BBS); + Reader.setOffset(Offset); + RETURN_IF_ERROR(Reader.readObject(Table)); + assert(Table != nullptr); + return *Table; +} + +ErrorOr<const coff_resource_dir_table &> +ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) { + return getTableAtOffset(Entry.Offset.value()); +} + +ErrorOr<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() { + return getTableAtOffset(0); +} diff --git a/llvm/test/tools/llvm-readobj/Inputs/resources/cursor_small.bmp b/llvm/test/tools/llvm-readobj/Inputs/resources/cursor_small.bmp Binary files differnew file mode 100644 index 00000000000..ce513261bc2 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/Inputs/resources/cursor_small.bmp diff --git a/llvm/test/tools/llvm-readobj/Inputs/resources/okay_small.bmp b/llvm/test/tools/llvm-readobj/Inputs/resources/okay_small.bmp Binary files differnew file mode 100644 index 00000000000..e4005bf5ef9 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/Inputs/resources/okay_small.bmp diff --git a/llvm/test/tools/llvm-readobj/Inputs/resources/test_resource.rc b/llvm/test/tools/llvm-readobj/Inputs/resources/test_resource.rc new file mode 100644 index 00000000000..fd616520dbe --- /dev/null +++ b/llvm/test/tools/llvm-readobj/Inputs/resources/test_resource.rc @@ -0,0 +1,44 @@ +#include "windows.h"
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+myaccelerators ACCELERATORS
+{
+ "^C", 999, VIRTKEY, ALT
+ "D", 1100, VIRTKEY, CONTROL, SHIFT
+ "^R", 444, ASCII, NOINVERT
+}
+
+cursor BITMAP "cursor_small.bmp"
+okay BITMAP "okay_small.bmp"
+
+14432 MENU
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
+{
+ MENUITEM "yu", 100
+ MENUITEM "shala", 101
+ MENUITEM "kaoya", 102
+}
+
+testdialog DIALOG 10, 10, 200, 300
+STYLE WS_POPUP | WS_BORDER
+CAPTION "Test"
+{
+ CTEXT "Continue:", 1, 10, 10, 230, 14
+ PUSHBUTTON "&OK", 2, 66, 134, 161, 13
+}
+
+12 ACCELERATORS
+{
+ "X", 164, VIRTKEY, ALT
+ "H", 5678, VIRTKEY, CONTROL, SHIFT
+ "^R", 444, ASCII, NOINVERT
+}
+
+"eat" MENU
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
+{
+ MENUITEM "fish", 100
+ MENUITEM "salad", 101
+ MENUITEM "duck", 102
+}
diff --git a/llvm/test/tools/llvm-readobj/Inputs/resources/test_resource.res b/llvm/test/tools/llvm-readobj/Inputs/resources/test_resource.res Binary files differnew file mode 100644 index 00000000000..c577ecc3d63 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/Inputs/resources/test_resource.res diff --git a/llvm/test/tools/llvm-readobj/resources.test b/llvm/test/tools/llvm-readobj/resources.test index 46ee8b99a65..6e9e39d1720 100644 --- a/llvm/test/tools/llvm-readobj/resources.test +++ b/llvm/test/tools/llvm-readobj/resources.test @@ -1,19 +1,111 @@ -RUN: llvm-readobj -coff-resources %p/Inputs/zero-string-table.obj.coff-i386 \ -RUN: | FileCheck %s -check-prefix RESOURCE +// Check dumping of the .rsrc section(s) +// The input was generated with the following commands, using the original Windows +// rc.exe and cvtres.exe: +// > rc /fo test_resource.res /nologo test_resource.rc +// > cvtres /machine:X86 /readonly /nologo /out:test_resource.o test_resource.res -RESOURCE: Resources [ -RESOURCE-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0) -RESOURCE-NEXT: .rsrc$01 Data ( -RESOURCE-NEXT: 0000: 00000000 00000000 00000000 00000100 |................| -RESOURCE-NEXT: 0010: 06000000 18000080 00000000 00000000 |................| -RESOURCE-NEXT: 0020: 00000000 00000100 01000000 30000080 |............0...| -RESOURCE-NEXT: 0030: 00000000 00000000 00000000 00000100 |................| -RESOURCE-NEXT: 0040: 09040000 48000000 00000000 2A000000 |....H.......*...| -RESOURCE-NEXT: 0050: 00000000 00000000 |........| -RESOURCE-NEXT: ) -RESOURCE-NEXT: .rsrc$02 Data ( -RESOURCE-NEXT: 0000: 00000500 48006500 6C006C00 6F000000 |....H.e.l.l.o...| -RESOURCE-NEXT: 0010: 00000000 00000000 00000000 00000000 |................| -RESOURCE-NEXT: 0020: 00000000 00000000 00000000 00000000 |................| -RESOURCE-NEXT: ) -RESOURCE-NEXT: ] +RUN: llvm-readobj -coff-resources -section-data %p/Inputs/zero-string-table.obj.coff-i386 \ +RUN: | FileCheck %s -check-prefix ZERO +RUN: llvm-readobj -coff-resources %p/Inputs/resources/test_resource.o \ +RUN: | FileCheck %s -check-prefix TEST_RES + +ZERO: Resources [ +ZERO-NEXT: String Name Entries: 0 +ZERO-NEXT: ID Entries: 1 +ZERO-NEXT: Type: kRT_STRING (ID 6) [ +ZERO-NEXT: String Name Entries: 0 +ZERO-NEXT: ID Entries: 1 +ZERO-NEXT: Name: (ID 1) [ +ZERO-NEXT: String Name Entries: 0 +ZERO-NEXT: ID Entries: 1 +ZERO-NEXT: Language: (ID 1033) [ +ZERO-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0) +ZERO-NEXT: Major Version: 0 +ZERO-NEXT: Minor Version: 0 +ZERO-NEXT: ] +ZERO-NEXT: ] +ZERO-NEXT: ] + + +TEST_RES: Resources [ +TEST_RES-NEXT: String Name Entries: 0 +TEST_RES-NEXT: ID Entries: 4 +TEST_RES-NEXT: Type: kRT_BITMAP (ID 2) [ +TEST_RES-NEXT: String Name Entries: 2 +TEST_RES-NEXT: ID Entries: 0 +TEST_RES-NEXT: Name: CURSOR [ +TEST_RES-NEXT: String Name Entries: 0 +TEST_RES-NEXT: ID Entries: 1 +TEST_RES-NEXT: Language: (ID 1033) [ +TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0) +TEST_RES-NEXT: Major Version: 0 +TEST_RES-NEXT: Minor Version: 0 +TEST_RES-NEXT: ] +TEST_RES-NEXT: ] +TEST_RES-NEXT: Name: OKAY [ +TEST_RES-NEXT: String Name Entries: 0 +TEST_RES-NEXT: ID Entries: 1 +TEST_RES-NEXT: Language: (ID 1033) [ +TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0) +TEST_RES-NEXT: Major Version: 0 +TEST_RES-NEXT: Minor Version: 0 +TEST_RES-NEXT: ] +TEST_RES-NEXT: ] +TEST_RES-NEXT: ] +TEST_RES-NEXT: Type: kRT_MENU (ID 4) [ +TEST_RES-NEXT: String Name Entries: 1 +TEST_RES-NEXT: ID Entries: 1 +TEST_RES-NEXT: Name: "EAT" [ +TEST_RES-NEXT: String Name Entries: 0 +TEST_RES-NEXT: ID Entries: 1 +TEST_RES-NEXT: Language: (ID 3081) [ +TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0) +TEST_RES-NEXT: Major Version: 0 +TEST_RES-NEXT: Minor Version: 0 +TEST_RES-NEXT: ] +TEST_RES-NEXT: ] +TEST_RES-NEXT: Name: (ID 14432) [ +TEST_RES-NEXT: String Name Entries: 0 +TEST_RES-NEXT: ID Entries: 1 +TEST_RES-NEXT: Language: (ID 2052) [ +TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0) +TEST_RES-NEXT: Major Version: 0 +TEST_RES-NEXT: Minor Version: 0 +TEST_RES-NEXT: ] +TEST_RES-NEXT: ] +TEST_RES-NEXT: ] +TEST_RES-NEXT: Type: kRT_DIALOG (ID 5) [ +TEST_RES-NEXT: String Name Entries: 1 +TEST_RES-NEXT: ID Entries: 0 +TEST_RES-NEXT: Name: TESTDIALOG [ +TEST_RES-NEXT: String Name Entries: 0 +TEST_RES-NEXT: ID Entries: 1 +TEST_RES-NEXT: Language: (ID 1033) [ +TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0) +TEST_RES-NEXT: Major Version: 0 +TEST_RES-NEXT: Minor Version: 0 +TEST_RES-NEXT: ] +TEST_RES-NEXT: ] +TEST_RES-NEXT: ] +TEST_RES-NEXT: Type: kRT_ACCELERATOR (ID 9) [ +TEST_RES-NEXT: String Name Entries: 1 +TEST_RES-NEXT: ID Entries: 1 +TEST_RES-NEXT: Name: MYACCELERATORS [ +TEST_RES-NEXT: String Name Entries: 0 +TEST_RES-NEXT: ID Entries: 1 +TEST_RES-NEXT: Language: (ID 1033) [ +TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0) +TEST_RES-NEXT: Major Version: 0 +TEST_RES-NEXT: Minor Version: 0 +TEST_RES-NEXT: ] +TEST_RES-NEXT: ] +TEST_RES-NEXT: Name: (ID 12) [ +TEST_RES-NEXT: String Name Entries: 0 +TEST_RES-NEXT: ID Entries: 1 +TEST_RES-NEXT: Language: (ID 1033) [ +TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0) +TEST_RES-NEXT: Major Version: 0 +TEST_RES-NEXT: Minor Version: 0 +TEST_RES-NEXT: ] +TEST_RES-NEXT: ] +TEST_RES-NEXT: ] diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp index 3f4b6c79178..64fd60ea209 100644 --- a/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -121,6 +121,10 @@ private: uint32_t RelocOffset, uint32_t Offset, StringRef *RelocSym = nullptr); + void printResourceDirectoryTable(ResourceSectionRef RSF, + const coff_resource_dir_table &Table, + StringRef Level); + void printBinaryBlockWithRelocs(StringRef Label, const SectionRef &Sec, StringRef SectionContents, StringRef Block); @@ -140,6 +144,9 @@ private: void printDelayImportedSymbols( const DelayImportDirectoryEntryRef &I, iterator_range<imported_symbol_iterator> Range); + ErrorOr<const coff_resource_dir_entry &> + getResourceDirectoryTableEntry(const coff_resource_dir_table &Table, + uint32_t Index); typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy; @@ -534,6 +541,29 @@ static const EnumEntry<uint8_t> FileChecksumKindNames[] = { LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, SHA256), }; +static const EnumEntry<COFF::ResourceTypeID> ResourceTypeNames[]{ + {"kRT_CURSOR (ID 1)", COFF::RID_Cursor}, + {"kRT_BITMAP (ID 2)", COFF::RID_Bitmap}, + {"kRT_ICON (ID 3)", COFF::RID_Icon}, + {"kRT_MENU (ID 4)", COFF::RID_Menu}, + {"kRT_DIALOG (ID 5)", COFF::RID_Dialog}, + {"kRT_STRING (ID 6)", COFF::RID_String}, + {"kRT_FONTDIR (ID 7)", COFF::RID_FontDir}, + {"kRT_FONT (ID 8)", COFF::RID_Font}, + {"kRT_ACCELERATOR (ID 9)", COFF::RID_Accelerator}, + {"kRT_RCDATA (ID 10)", COFF::RID_RCData}, + {"kRT_MESSAGETABLE (ID 11)", COFF::RID_MessageTable}, + {"kRT_GROUP_CURSOR (ID 12)", COFF::RID_Group_Cursor}, + {"kRT_GROUP_ICON (ID 14)", COFF::RID_Group_Icon}, + {"kRT_VERSION (ID 16)", COFF::RID_Version}, + {"kRT_DLGINCLUDE (ID 17)", COFF::RID_DLGInclude}, + {"kRT_PLUGPLAY (ID 19)", COFF::RID_PlugPlay}, + {"kRT_VXD (ID 20)", COFF::RID_VXD}, + {"kRT_ANICURSOR (ID 21)", COFF::RID_AniCursor}, + {"kRT_ANIICON (ID 22)", COFF::RID_AniIcon}, + {"kRT_HTML (ID 23)", COFF::RID_HTML}, + {"kRT_MANIFEST (ID 24)", COFF::RID_Manifest}}; + template <typename T> static std::error_code getSymbolAuxData(const COFFObjectFile *Obj, COFFSymbolRef Symbol, @@ -1503,18 +1533,73 @@ void COFFDumper::printCOFFResources() { error(S.getContents(Ref)); if ((Name == ".rsrc") || (Name == ".rsrc$01")) { - auto Table = - reinterpret_cast<const coff_resource_dir_table *>(Ref.data()); - char FormattedTime[20]; - time_t TDS = time_t(Table->TimeDateStamp); - strftime(FormattedTime, sizeof(FormattedTime), "%Y-%m-%d %H:%M:%S", - gmtime(&TDS)); - W.printHex("Time/Date Stamp", FormattedTime, Table->TimeDateStamp); + ResourceSectionRef RSF(Ref); + auto &BaseTable = unwrapOrError(RSF.getBaseTable()); + printResourceDirectoryTable(RSF, BaseTable, "Type"); + } + if (opts::SectionData) + W.printBinaryBlock(Name.str() + " Data", Ref); + } +} + +void COFFDumper::printResourceDirectoryTable( + ResourceSectionRef RSF, const coff_resource_dir_table &Table, + StringRef Level) { + W.printNumber("String Name Entries", Table.NumberOfNameEntries); + W.printNumber("ID Entries", Table.NumberOfIDEntries); + + char FormattedTime[20] = {}; + time_t TDS = time_t(Table.TimeDateStamp); + strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS)); + + // Iterate through level in resource directory tree. + for (int i = 0; i < Table.NumberOfNameEntries + Table.NumberOfIDEntries; + i++) { + auto Entry = unwrapOrError(getResourceDirectoryTableEntry(Table, i)); + StringRef Name; + SmallString<20> IDStr; + raw_svector_ostream OS(IDStr); + if (i < Table.NumberOfNameEntries) { + StringRef EntryNameString = unwrapOrError(RSF.getEntryNameString(Entry)); + OS << ": "; + OS << EntryNameString.str(); + } else { + if (Level == "Type") { + ScopedPrinter Printer(OS); + Printer.printEnum("", Entry.Identifier.ID, + makeArrayRef(ResourceTypeNames)); + IDStr = IDStr.slice(0, IDStr.find_first_of(")", 0) + 1); + } else { + OS << ": (ID " << Entry.Identifier.ID << ")"; + } + } + Name = StringRef(IDStr); + ListScope ResourceType(W, Level.str() + Name.str()); + if (Entry.Offset.isSubDir()) { + StringRef NextLevel; + if (Level == "Name") + NextLevel = "Language"; + else + NextLevel = "Name"; + auto &NextTable = unwrapOrError(RSF.getEntrySubDir(Entry)); + printResourceDirectoryTable(RSF, NextTable, NextLevel); + } else { + W.printHex("Time/Date Stamp", FormattedTime, Table.TimeDateStamp); + W.printNumber("Major Version", Table.MajorVersion); + W.printNumber("Minor Version", Table.MinorVersion); } - W.printBinaryBlock(Name.str() + " Data", Ref); } } +ErrorOr<const coff_resource_dir_entry &> +COFFDumper::getResourceDirectoryTableEntry(const coff_resource_dir_table &Table, + uint32_t Index) { + if (Index >= Table.NumberOfNameEntries + Table.NumberOfIDEntries) + return object_error::parse_failed; + auto TablePtr = reinterpret_cast<const coff_resource_dir_entry *>(&Table + 1); + return TablePtr[Index]; +} + void COFFDumper::printStackMap() const { object::SectionRef StackMapSection; for (auto Sec : Obj->sections()) { |