Index: llvm/include/llvm/Object/COFF.h =================================================================== --- llvm/include/llvm/Object/COFF.h +++ llvm/include/llvm/Object/COFF.h @@ -40,6 +40,7 @@ class ExportDirectoryEntryRef; class ImportDirectoryEntryRef; class ImportedSymbolRef; +class ResourceDirTableRef; using import_directory_iterator = content_iterator; using delay_import_directory_iterator = @@ -623,6 +624,15 @@ int getOffset() const { return Data & ((1 << 12) - 1); } }; +struct coff_resource_dir_table { + support::ulittle32_t Characteristics; + support::ulittle32_t TimeDateStamp; + support::ulittle16_t MajorVersion; + support::ulittle16_t MinorVersion; + support::ulittle16_t NumberOfNameEntries; + support::ulittle16_t NumberOfIDEntries; +}; + class COFFObjectFile : public ObjectFile { private: friend class ImportDirectoryEntryRef; @@ -1038,6 +1048,24 @@ const COFFObjectFile *OwningObject = nullptr; }; +class ResourceDirTableRef { +public: + ResourceDirTableRef() = default; + ResourceDirTableRef(const coff_resource_dir_table *Table, + const COFFObjectFile *Owner) + : Table(Table), Index(0), OwningObject(Owner) {} + + std::error_code getCharacteristics(uint32_t &Characteristics) const; + std::error_code getTimeDateStamp(uint32_t &Stamp) const; + std::error_code getNumberOfIDs(uint16_t &IDs) const; + std::error_code getNumberOfNames(uint16_t &Names) const; + +private: + const coff_resource_dir_table *Table; + uint32_t Index; + const COFFObjectFile *OwningObject = nullptr; +}; + // Corresponds to `_FPO_DATA` structure in the PE/COFF spec. struct FpoData { support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code Index: llvm/lib/Object/COFFObjectFile.cpp =================================================================== --- llvm/lib/Object/COFFObjectFile.cpp +++ llvm/lib/Object/COFFObjectFile.cpp @@ -451,8 +451,10 @@ // Returns the file offset for the given VA. std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { + llvm::outs() << "in get va ptr\n"; uint64_t ImageBase = getImageBase(); uint64_t Rva = Addr - ImageBase; + llvm::outs() << "Rva " << Rva << "\n"; assert(Rva <= UINT32_MAX); return getRvaPtr((uint32_t)Rva, Res); } @@ -464,6 +466,7 @@ uint32_t SectionStart = Section->VirtualAddress; uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; if (SectionStart <= Addr && Addr < SectionEnd) { + llvm::outs() << "found the section\n"; uint32_t Offset = Addr - SectionStart; Res = uintptr_t(base()) + Section->PointerToRawData + Offset; return std::error_code(); @@ -1591,3 +1594,24 @@ Result = Header->PageRVA + Entry[Index].getOffset(); return std::error_code(); } + +std::error_code +ResourceDirTableRef::getCharacteristics(uint32_t &Characteristics) const { + Characteristics = Table->Characteristics; + return std::error_code(); +} + +std::error_code ResourceDirTableRef::getTimeDateStamp(uint32_t &Stamp) const { + Stamp = Table->TimeDateStamp; + return std::error_code(); +} + +std::error_code ResourceDirTableRef::getNumberOfNames(uint16_t &Names) const { + Names = Table->NumberOfNameEntries; + return std::error_code(); +} + +std::error_code ResourceDirTableRef::getNumberOfIDs(uint16_t &IDs) const { + IDs = Table->NumberOfIDEntries; + return std::error_code(); +} Index: llvm/tools/llvm-readobj/COFFDumper.cpp =================================================================== --- llvm/tools/llvm-readobj/COFFDumper.cpp +++ llvm/tools/llvm-readobj/COFFDumper.cpp @@ -78,6 +78,7 @@ void printCOFFDirectives() override; void printCOFFBaseReloc() override; void printCOFFDebugDirectory() override; + void printCOFFResources() override; void printCodeViewDebugInfo() override; void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVIDs, llvm::codeview::TypeTableBuilder &CVTypes) override; @@ -1527,6 +1528,35 @@ } } +void COFFDumper::printCOFFResources() { + ListScope ResourcesD(W, "Resources"); + for (const SectionRef &S : Obj->sections()) { + StringRef Name; + error(S.getName(Name)); + if ((Name != ".rsrc$01") && (Name != ".rsrc$02")) + continue; + + if (Name == ".rsrc$01") { + StringRef Ref; + error(S.getContents(Ref)); + ResourceDirTableRef Table( + reinterpret_cast(Ref.data()), Obj); + uint32_t TimeDateStamp; + error(Table.getTimeDateStamp(TimeDateStamp)); + char FormattedTime[20] = { }; + time_t TDS = time_t(TimeDateStamp); + strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS)); + W.printHex("Time/Date Stamp", FormattedTime, TDS); + W.printBinaryBlock(".rsrc$01 Data", Ref); + } + else { + StringRef Ref; + error(S.getContents(Ref)); + W.printBinaryBlock(".rsrc$02 Data", Ref); + } + } +} + void COFFDumper::printStackMap() const { object::SectionRef StackMapSection; for (auto Sec : Obj->sections()) { Index: llvm/tools/llvm-readobj/ObjDumper.h =================================================================== --- llvm/tools/llvm-readobj/ObjDumper.h +++ llvm/tools/llvm-readobj/ObjDumper.h @@ -67,6 +67,7 @@ virtual void printCOFFDirectives() { } virtual void printCOFFBaseReloc() { } virtual void printCOFFDebugDirectory() { } + virtual void printCOFFResources() {} virtual void printCodeViewDebugInfo() { } virtual void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVIDs, llvm::codeview::TypeTableBuilder &CVTypes) {} Index: llvm/tools/llvm-readobj/llvm-readobj.cpp =================================================================== --- llvm/tools/llvm-readobj/llvm-readobj.cpp +++ llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -214,6 +214,10 @@ COFFDebugDirectory("coff-debug-directory", cl::desc("Display the PE/COFF debug directory")); + // -coff-resources + cl::opt COFFResources("coff-resources", + cl::desc("Display the PE/COFF .rsrc section")); + // -macho-data-in-code cl::opt MachODataInCode("macho-data-in-code", @@ -445,6 +449,8 @@ Dumper->printCOFFBaseReloc(); if (opts::COFFDebugDirectory) Dumper->printCOFFDebugDirectory(); + if (opts::COFFResources) + Dumper->printCOFFResources(); if (opts::CodeView) Dumper->printCodeViewDebugInfo(); if (opts::CodeViewMergedTypes)