Index: llvm/include/llvm/Object/WindowsResource.h =================================================================== --- llvm/include/llvm/Object/WindowsResource.h +++ llvm/include/llvm/Object/WindowsResource.h @@ -36,6 +36,8 @@ #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" +#include + namespace llvm { namespace object { @@ -44,12 +46,15 @@ class ResourceEntryRef { public: Error moveNext(bool &End); + Error getType(uint16_t &Type); + Error checkNameString(bool &isString); private: friend class WindowsResource; ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner, Error &Err); + Error loadNext(); BinaryStreamReader Reader; @@ -76,6 +81,36 @@ BinaryByteStream BBS; }; +class WindowsResourceParser { +public: + Parser(); + + Error parse(std::unique_ptr Bin); + +private: + class TreeNode { + public: + explicit TreeNode(uint32_t ID) + : ID(ID), Name("") {} + TreeNode& addChild(uint32_t ID) { + auto Child = Children.find(ID); + if ( Child == Children.end()) { + struct TreeNode NewChild(ID); + Child = Children.insert(std::make_pair(ID, NewChild)); + } + return *Child; + } + + private: + uint32_t ID; + std::string Name; + std::unordered_map Children; + + }; + + TreeNode Root; +}; + } // namespace object } // namespace llvm Index: llvm/lib/Object/WindowsResource.cpp =================================================================== --- llvm/lib/Object/WindowsResource.cpp +++ llvm/lib/Object/WindowsResource.cpp @@ -13,6 +13,7 @@ #include "llvm/Object/WindowsResource.h" #include "llvm/Object/Error.h" +#include "llvm/Support/COFF.h" #include namespace llvm { @@ -72,6 +73,24 @@ return Error::success(); } +Error ResourceEntryRef::getType(uint16_t &TypeID) { + BinaryStreamReader TypeReader(HeaderBytes); + RETURN_IF_ERROR(TypeReader.skip(sizeof(uint16_t))); + RETURN_IF_ERROR(TypeReader.readInteger(TypeID)); +} + +Error ResourceEntryRef::checkNameString(bool &isString) { + BinaryStreamReader NameChecker(HeaderBytes); + RETURN_IF_ERROR(NameChecker.skip(4)); + uint16_t IDFlag; + RETURN_IF_ERROR(NameChecker.readInteger(IDFlag)); + if (IDFlag == 0xffff) + isString = false; + else + isString = true; + return Error::success(); +} + Error ResourceEntryRef::loadNext() { uint32_t DataSize; RETURN_IF_ERROR(Reader.readInteger(DataSize)); @@ -86,5 +105,33 @@ return Error::success(); } +WindowsResourceParser::WindowsResourceParser() { +} + +Error WindowsResourceParser::parse(std::unique_ptr Bin) { + WindowsResource *RF = dyn_cast(Bin.get()); + if (!RF) { + return make_error("Parser not given valid resource file!", + object_error::invalid_file_type); + } + + auto EntryOrErr = RF->getHeadEntry(); + if (!EntryOrErr) + return EntryOrErr.takeError(); + + ResourceEntryRef Entry = EntryOrErr.get(); + bool End = false; + + while (!End) { + uint16_t Type = Entry.getType(); + TreeNode& TypeNode = Root.addChild(Type); + + bool IsStringName; + RETURN_IF_ERROR(Entry.checkNameString(IsStringName)); + } + + return Error::success(); +} + } // namespace object } // namespace llvm Index: llvm/tools/llvm-cvtres/llvm-cvtres.cpp =================================================================== --- llvm/tools/llvm-cvtres/llvm-cvtres.cpp +++ llvm/tools/llvm-cvtres/llvm-cvtres.cpp @@ -143,13 +143,28 @@ llvm::sys::path::replace_extension(OutputFile, ".obj"); } + outs() << "Machine: "; + switch (Machine) { + case machine::ARM: + outs() << "ARM\n"; + break; + case machine::X86: + outs() << "X86\n"; + break; + default: + outs() << "X64\n"; + } + + + WindowsResourceParser Parser(); + for (const auto &File : InputFiles) { - Expected> BinaryOrErr = + Expected> BinaryOrErr = object::createBinary(File); if (!BinaryOrErr) reportError(File, errorToErrorCode(BinaryOrErr.takeError())); - Binary &Binary = *BinaryOrErr.get().getBinary(); + Binary &Binary = BinaryOrErr.get()->getBinary(); WindowsResource *RF = dyn_cast(&Binary); if (!RF) @@ -166,17 +181,12 @@ EntryNumber++; } outs() << "Number of resources: " << EntryNumber << "\n"; + + error(Parser.parse(std::move(BinaryOrErr.get()))); + } - outs() << "Machine: "; - switch (Machine) { - case machine::ARM: - outs() << "ARM\n"; - break; - case machine::X86: - outs() << "X86\n"; - break; - default: - outs() << "X64\n"; - } + + WriteCOFF(&Parser); + return 0; }