[llvm] r305092 - Implement COFF emission for parsed Windows Resource ( .res) files.
Vedant Kumar via llvm-commits
llvm-commits at lists.llvm.org
Sat Jun 10 11:08:31 PDT 2017
I patched this in r305149 to unblock our bots. PTAL to make sure it looks ok.
vedant
> On Jun 9, 2017, at 3:02 PM, Evgenii Stepanov via llvm-commits <llvm-commits at lists.llvm.org> wrote:
>
> Hi,
>
> http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/5572
>
> lib/Object/WindowsResource.cpp:578:3: runtime error: store to
> misaligned address 0x7fa09aedebbe for type 'unsigned int', which
> requires 4 byte alignment
> 0x7fa09aedebbe: note: pointer points here
> 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 00 00 00 00 00 00 00 00
> ^
> #0 0x44f81b in
> llvm::object::WindowsResourceCOFFWriter::writeStringTable()
> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/Object/WindowsResource.cpp:578:20
> #1 0x44ef9b in llvm::object::WindowsResourceCOFFWriter::write()
> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/Object/WindowsResource.cpp:419:3
> #2 0x450540 in
> llvm::object::writeWindowsResourceCOFF(llvm::StringRef,
> llvm::object::Machine, llvm::object::WindowsResourceParser const&)
> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/Object/WindowsResource.cpp:716:17
> #3 0x43348f in main
> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/llvm-cvtres/llvm-cvtres.cpp:198:7
>
>
> On Fri, Jun 9, 2017 at 10:34 AM, Eric Beckmann via llvm-commits
> <llvm-commits at lists.llvm.org> wrote:
>> Author: ecbeckmann
>> Date: Fri Jun 9 12:34:30 2017
>> New Revision: 305092
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=305092&view=rev
>> Log:
>> Implement COFF emission for parsed Windows Resource ( .res) files.
>>
>> Summary: Add the WindowsResourceCOFFWriter class for producing the final COFF after all parsing is done.
>>
>> Reviewers: hiraditya!, zturner, ruiu
>>
>> Subscribers: llvm-commits
>>
>> Differential Revision: https://reviews.llvm.org/D34020
>>
>> Added:
>> llvm/trunk/test/tools/llvm-cvtres/Inputs/test_resource.obj.coff (with props)
>> llvm/trunk/test/tools/llvm-cvtres/object.test
>> llvm/trunk/test/tools/llvm-cvtres/parse.test
>> Removed:
>> llvm/trunk/test/tools/llvm-cvtres/resource.test
>> Modified:
>> llvm/trunk/include/llvm/Object/COFF.h
>> llvm/trunk/include/llvm/Object/WindowsResource.h
>> llvm/trunk/lib/Object/WindowsResource.cpp
>> llvm/trunk/tools/llvm-cvtres/LLVMBuild.txt
>> llvm/trunk/tools/llvm-cvtres/llvm-cvtres.cpp
>> llvm/trunk/tools/llvm-cvtres/llvm-cvtres.h
>>
>> Modified: llvm/trunk/include/llvm/Object/COFF.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/COFF.h?rev=305092&r1=305091&r2=305092&view=diff
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Object/COFF.h (original)
>> +++ llvm/trunk/include/llvm/Object/COFF.h Fri Jun 9 12:34:30 2017
>> @@ -646,6 +646,13 @@ struct coff_resource_dir_entry {
>> } Offset;
>> };
>>
>> +struct coff_resource_data_entry {
>> + support::ulittle32_t DataRVA;
>> + support::ulittle32_t DataSize;
>> + support::ulittle32_t Codepage;
>> + support::ulittle32_t Reserved;
>> +};
>> +
>> struct coff_resource_dir_table {
>> support::ulittle32_t Characteristics;
>> support::ulittle32_t TimeDateStamp;
>>
>> Modified: llvm/trunk/include/llvm/Object/WindowsResource.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/WindowsResource.h?rev=305092&r1=305091&r2=305092&view=diff
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Object/WindowsResource.h (original)
>> +++ llvm/trunk/include/llvm/Object/WindowsResource.h Fri Jun 9 12:34:30 2017
>> @@ -44,10 +44,15 @@
>> #include <map>
>>
>> namespace llvm {
>> +
>> +class FileOutputBuffer;
>> +
>> namespace object {
>>
>> class WindowsResource;
>>
>> +enum class Machine { UNKNOWN, ARM, X64, X86 };
>> +
>> class ResourceEntryRef {
>> public:
>> Error moveNext(bool &End);
>> @@ -58,6 +63,10 @@ public:
>> ArrayRef<UTF16> getNameString() const { return Name; }
>> uint16_t getNameID() const { return NameID; }
>> uint16_t getLanguage() const { return Suffix->Language; }
>> + uint16_t getMajorVersion() const { return Suffix->Version >> 16; }
>> + uint16_t getMinorVersion() const { return Suffix->Version; }
>> + uint32_t getCharacteristics() const { return Suffix->Characteristics; }
>> + ArrayRef<uint8_t> getData() const { return Data; }
>>
>> private:
>> friend class WindowsResource;
>> @@ -106,34 +115,77 @@ private:
>>
>> class WindowsResourceParser {
>> public:
>> + class TreeNode;
>> WindowsResourceParser();
>> -
>> Error parse(WindowsResource *WR);
>> -
>> void printTree() const;
>> + const TreeNode &getTree() const { return Root; }
>> + const ArrayRef<std::vector<uint8_t>> getData() const { return Data; }
>> + const ArrayRef<std::vector<UTF16>> getStringTable() const {
>> + return StringTable;
>> + }
>>
>> -private:
>> class TreeNode {
>> public:
>> - TreeNode() = default;
>> - explicit TreeNode(ArrayRef<UTF16> Ref);
>> - void addEntry(const ResourceEntryRef &Entry);
>> + template <typename T>
>> + using Children = std::map<T, std::unique_ptr<TreeNode>>;
>> +
>> void print(ScopedPrinter &Writer, StringRef Name) const;
>> + uint32_t getTreeSize() const;
>> + uint32_t getStringIndex() const { return StringIndex; }
>> + uint32_t getDataIndex() const { return DataIndex; }
>> + uint16_t getMajorVersion() const { return MajorVersion; }
>> + uint16_t getMinorVersion() const { return MinorVersion; }
>> + uint32_t getCharacteristics() const { return Characteristics; }
>> + bool checkIsDataNode() const { return IsDataNode; }
>> + const Children<uint32_t> &getIDChildren() const { return IDChildren; }
>> + const Children<std::string> &getStringChildren() const {
>> + return StringChildren;
>> + }
>>
>> private:
>> + friend class WindowsResourceParser;
>> +
>> + static uint32_t StringCount;
>> + static uint32_t DataCount;
>> +
>> + static std::unique_ptr<TreeNode> createStringNode();
>> + static std::unique_ptr<TreeNode> createIDNode();
>> + static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion,
>> + uint16_t MinorVersion,
>> + uint32_t Characteristics);
>> +
>> + explicit TreeNode(bool IsStringNode);
>> + TreeNode(uint16_t MajorVersion, uint16_t MinorVersion,
>> + uint32_t Characteristics);
>> +
>> + void addEntry(const ResourceEntryRef &Entry);
>> TreeNode &addTypeNode(const ResourceEntryRef &Entry);
>> TreeNode &addNameNode(const ResourceEntryRef &Entry);
>> TreeNode &addLanguageNode(const ResourceEntryRef &Entry);
>> - TreeNode &addChild(uint32_t ID);
>> + TreeNode &addChild(uint32_t ID, bool IsDataNode = false,
>> + uint16_t MajorVersion = 0, uint16_t MinorVersion = 0,
>> + uint32_t Characteristics = 0);
>> TreeNode &addChild(ArrayRef<UTF16> NameRef);
>> - std::vector<UTF16> Name;
>> - std::map<uint32_t, std::unique_ptr<TreeNode>> IDChildren;
>> - std::map<std::string, std::unique_ptr<TreeNode>> StringChildren;
>> + bool IsDataNode = false;
>> + uint32_t StringIndex;
>> + uint32_t DataIndex;
>> + Children<uint32_t> IDChildren;
>> + Children<std::string> StringChildren;
>> + uint16_t MajorVersion = 0;
>> + uint16_t MinorVersion = 0;
>> + uint32_t Characteristics = 0;
>> };
>>
>> +private:
>> TreeNode Root;
>> + std::vector<std::vector<uint8_t>> Data;
>> + std::vector<std::vector<UTF16>> StringTable;
>> };
>>
>> +Error writeWindowsResourceCOFF(StringRef OutputFile, Machine MachineType,
>> + const WindowsResourceParser &Parser);
>> +
>> } // namespace object
>> } // namespace llvm
>>
>>
>> Modified: llvm/trunk/lib/Object/WindowsResource.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/WindowsResource.cpp?rev=305092&r1=305091&r2=305092&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Object/WindowsResource.cpp (original)
>> +++ llvm/trunk/lib/Object/WindowsResource.cpp Fri Jun 9 12:34:30 2017
>> @@ -13,6 +13,11 @@
>>
>> #include "llvm/Object/WindowsResource.h"
>> #include "llvm/BinaryFormat/COFF.h"
>> +#include "llvm/Object/COFF.h"
>> +#include "llvm/Support/FileOutputBuffer.h"
>> +#include "llvm/Support/MathExtras.h"
>> +#include <ctime>
>> +#include <queue>
>> #include <sstream>
>> #include <system_error>
>>
>> @@ -29,6 +34,9 @@ static const size_t ResourceMagicSize =
>>
>> static const size_t NullEntrySize = 16;
>>
>> +uint32_t WindowsResourceParser::TreeNode::StringCount = 0;
>> +uint32_t WindowsResourceParser::TreeNode::DataCount = 0;
>> +
>> WindowsResource::WindowsResource(MemoryBufferRef Source)
>> : Binary(Binary::ID_WinRes, Source) {
>> size_t LeadingSize = ResourceMagicSize + NullEntrySize;
>> @@ -115,7 +123,7 @@ Error ResourceEntryRef::loadNext() {
>> return Error::success();
>> }
>>
>> -WindowsResourceParser::WindowsResourceParser() {}
>> +WindowsResourceParser::WindowsResourceParser() : Root(false) {}
>>
>> Error WindowsResourceParser::parse(WindowsResource *WR) {
>> auto EntryOrErr = WR->getHeadEntry();
>> @@ -124,9 +132,16 @@ Error WindowsResourceParser::parse(Windo
>>
>> ResourceEntryRef Entry = EntryOrErr.get();
>> bool End = false;
>> -
>> while (!End) {
>>
>> + Data.push_back(Entry.getData());
>> +
>> + if (Entry.checkTypeString())
>> + StringTable.push_back(Entry.getTypeString());
>> +
>> + if (Entry.checkNameString())
>> + StringTable.push_back(Entry.getNameString());
>> +
>> Root.addEntry(Entry);
>>
>> RETURN_IF_ERROR(Entry.moveNext(End));
>> @@ -146,8 +161,37 @@ void WindowsResourceParser::TreeNode::ad
>> NameNode.addLanguageNode(Entry);
>> }
>>
>> -WindowsResourceParser::TreeNode::TreeNode(ArrayRef<UTF16> NameRef)
>> - : Name(NameRef) {}
>> +WindowsResourceParser::TreeNode::TreeNode(bool IsStringNode) {
>> + if (IsStringNode)
>> + StringIndex = StringCount++;
>> +}
>> +
>> +WindowsResourceParser::TreeNode::TreeNode(uint16_t MajorVersion,
>> + uint16_t MinorVersion,
>> + uint32_t Characteristics)
>> + : IsDataNode(true), MajorVersion(MajorVersion), MinorVersion(MinorVersion),
>> + Characteristics(Characteristics) {
>> + if (IsDataNode)
>> + DataIndex = DataCount++;
>> +}
>> +
>> +std::unique_ptr<WindowsResourceParser::TreeNode>
>> +WindowsResourceParser::TreeNode::createStringNode() {
>> + return std::unique_ptr<TreeNode>(new TreeNode(true));
>> +}
>> +
>> +std::unique_ptr<WindowsResourceParser::TreeNode>
>> +WindowsResourceParser::TreeNode::createIDNode() {
>> + return std::unique_ptr<TreeNode>(new TreeNode(false));
>> +}
>> +
>> +std::unique_ptr<WindowsResourceParser::TreeNode>
>> +WindowsResourceParser::TreeNode::createDataNode(uint16_t MajorVersion,
>> + uint16_t MinorVersion,
>> + uint32_t Characteristics) {
>> + return std::unique_ptr<TreeNode>(
>> + new TreeNode(MajorVersion, MinorVersion, Characteristics));
>> +}
>>
>> WindowsResourceParser::TreeNode &
>> WindowsResourceParser::TreeNode::addTypeNode(const ResourceEntryRef &Entry) {
>> @@ -168,14 +212,18 @@ WindowsResourceParser::TreeNode::addName
>> WindowsResourceParser::TreeNode &
>> WindowsResourceParser::TreeNode::addLanguageNode(
>> const ResourceEntryRef &Entry) {
>> - return addChild(Entry.getLanguage());
>> + return addChild(Entry.getLanguage(), true, Entry.getMajorVersion(),
>> + Entry.getMinorVersion(), Entry.getCharacteristics());
>> }
>>
>> -WindowsResourceParser::TreeNode &
>> -WindowsResourceParser::TreeNode::addChild(uint32_t ID) {
>> +WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addChild(
>> + uint32_t ID, bool IsDataNode, uint16_t MajorVersion, uint16_t MinorVersion,
>> + uint32_t Characteristics) {
>> auto Child = IDChildren.find(ID);
>> if (Child == IDChildren.end()) {
>> - auto NewChild = llvm::make_unique<WindowsResourceParser::TreeNode>(ID);
>> + auto NewChild =
>> + IsDataNode ? createDataNode(MajorVersion, MinorVersion, Characteristics)
>> + : createIDNode();
>> WindowsResourceParser::TreeNode &Node = *NewChild;
>> IDChildren.emplace(ID, std::move(NewChild));
>> return Node;
>> @@ -199,7 +247,7 @@ WindowsResourceParser::TreeNode::addChil
>>
>> auto Child = StringChildren.find(NameString);
>> if (Child == StringChildren.end()) {
>> - auto NewChild = llvm::make_unique<WindowsResourceParser::TreeNode>(NameRef);
>> + auto NewChild = createStringNode();
>> WindowsResourceParser::TreeNode &Node = *NewChild;
>> StringChildren.emplace(NameString, std::move(NewChild));
>> return Node;
>> @@ -218,5 +266,455 @@ void WindowsResourceParser::TreeNode::pr
>> }
>> }
>>
>> +// This function returns the size of the entire resource tree, including
>> +// directory tables, directory entries, and data entries. It does not include
>> +// the directory strings or the relocations of the .rsrc section.
>> +uint32_t WindowsResourceParser::TreeNode::getTreeSize() const {
>> + uint32_t Size = (IDChildren.size() + StringChildren.size()) *
>> + sizeof(llvm::object::coff_resource_dir_entry);
>> +
>> + // Reached a node pointing to a data entry.
>> + if (IsDataNode) {
>> + Size += sizeof(llvm::object::coff_resource_data_entry);
>> + return Size;
>> + }
>> +
>> + // If the node does not point to data, it must have a directory table pointing
>> + // to other nodes.
>> + Size += sizeof(llvm::object::coff_resource_dir_table);
>> +
>> + for (auto const &Child : StringChildren) {
>> + Size += Child.second->getTreeSize();
>> + }
>> + for (auto const &Child : IDChildren) {
>> + Size += Child.second->getTreeSize();
>> + }
>> + return Size;
>> +}
>> +
>> +class WindowsResourceCOFFWriter {
>> +public:
>> + WindowsResourceCOFFWriter(StringRef OutputFile, Machine MachineType,
>> + const WindowsResourceParser &Parser, Error &E);
>> +
>> + Error write();
>> +
>> +private:
>> + void performFileLayout();
>> + void performSectionOneLayout();
>> + void performSectionTwoLayout();
>> + void writeCOFFHeader();
>> + void writeFirstSectionHeader();
>> + void writeSecondSectionHeader();
>> + void writeFirstSection();
>> + void writeSecondSection();
>> + void writeSymbolTable();
>> + void writeStringTable();
>> + void writeDirectoryTree();
>> + void writeDirectoryStringTable();
>> + void writeFirstSectionRelocations();
>> + std::unique_ptr<FileOutputBuffer> Buffer;
>> + uint8_t *Current;
>> + Machine MachineType;
>> + const WindowsResourceParser::TreeNode &Resources;
>> + const ArrayRef<std::vector<uint8_t>> Data;
>> + uint64_t FileSize;
>> + uint32_t SymbolTableOffset;
>> + uint32_t SectionOneSize;
>> + uint32_t SectionOneOffset;
>> + uint32_t SectionOneRelocations;
>> + uint32_t SectionTwoSize;
>> + uint32_t SectionTwoOffset;
>> + const ArrayRef<std::vector<UTF16>> StringTable;
>> + std::vector<uint32_t> StringTableOffsets;
>> + std::vector<uint32_t> DataOffsets;
>> + std::vector<uint32_t> RelocationAddresses;
>> +};
>> +
>> +WindowsResourceCOFFWriter::WindowsResourceCOFFWriter(
>> + StringRef OutputFile, Machine MachineType,
>> + const WindowsResourceParser &Parser, Error &E)
>> + : MachineType(MachineType), Resources(Parser.getTree()),
>> + Data(Parser.getData()), StringTable(Parser.getStringTable()) {
>> + performFileLayout();
>> +
>> + ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
>> + FileOutputBuffer::create(OutputFile, FileSize);
>> + if (!BufferOrErr) {
>> + E = errorCodeToError(BufferOrErr.getError());
>> + return;
>> + }
>> +
>> + Buffer = std::move(*BufferOrErr);
>> +}
>> +
>> +void WindowsResourceCOFFWriter::performFileLayout() {
>> + // Add size of COFF header.
>> + FileSize = llvm::COFF::Header16Size;
>> +
>> + // one .rsrc section header for directory tree, another for resource data.
>> + FileSize += 2 * llvm::COFF::SectionSize;
>> +
>> + performSectionOneLayout();
>> + performSectionTwoLayout();
>> +
>> + // We have reached the address of the symbol table.
>> + SymbolTableOffset = FileSize;
>> +
>> + FileSize += llvm::COFF::Symbol16Size; // size of the @feat.00 symbol.
>> + FileSize += 4 * llvm::COFF::Symbol16Size; // symbol + aux for each section.
>> + FileSize += Data.size() * llvm::COFF::Symbol16Size; // 1 symbol per resource.
>> + FileSize += 4; // four null bytes for the string table.
>> +}
>> +
>> +void WindowsResourceCOFFWriter::performSectionOneLayout() {
>> + SectionOneOffset = FileSize;
>> +
>> + SectionOneSize = Resources.getTreeSize();
>> + uint32_t CurrentStringOffset = SectionOneSize;
>> + uint32_t TotalStringTableSize = 0;
>> + for (auto const &String : StringTable) {
>> + StringTableOffsets.push_back(CurrentStringOffset);
>> + uint32_t StringSize = String.size() * sizeof(UTF16) + sizeof(uint16_t);
>> + CurrentStringOffset += StringSize;
>> + TotalStringTableSize += StringSize;
>> + }
>> + SectionOneSize += alignTo(TotalStringTableSize, sizeof(uint32_t));
>> +
>> + // account for the relocations of section one.
>> + SectionOneRelocations = FileSize + SectionOneSize;
>> + FileSize += SectionOneSize;
>> + FileSize += Data.size() *
>> + llvm::COFF::RelocationSize; // one relocation for each resource.
>> +}
>> +
>> +void WindowsResourceCOFFWriter::performSectionTwoLayout() {
>> + // add size of .rsrc$2 section, which contains all resource data on 8-byte
>> + // alignment.
>> + SectionTwoOffset = FileSize;
>> + SectionTwoSize = 0;
>> + for (auto const &Entry : Data) {
>> + DataOffsets.push_back(SectionTwoSize);
>> + SectionTwoSize += llvm::alignTo(Entry.size(), sizeof(uint64_t));
>> + }
>> + FileSize += SectionTwoSize;
>> +}
>> +
>> +static std::time_t getTime() {
>> + std::time_t Now = time(nullptr);
>> + if (Now < 0 || !isUInt<32>(Now))
>> + return UINT32_MAX;
>> + return Now;
>> +}
>> +
>> +Error WindowsResourceCOFFWriter::write() {
>> + Current = Buffer->getBufferStart();
>> +
>> + writeCOFFHeader();
>> + writeFirstSectionHeader();
>> + writeSecondSectionHeader();
>> + writeFirstSection();
>> + writeSecondSection();
>> + writeSymbolTable();
>> + writeStringTable();
>> +
>> + if (auto EC = Buffer->commit()) {
>> + return errorCodeToError(EC);
>> + }
>> +
>> + return Error::success();
>> +}
>> +
>> +void WindowsResourceCOFFWriter::writeCOFFHeader() {
>> + // Write the COFF header.
>> + auto *Header = reinterpret_cast<llvm::object::coff_file_header *>(Current);
>> + switch (MachineType) {
>> + case Machine::ARM:
>> + Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT;
>> + break;
>> + case Machine::X64:
>> + Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
>> + break;
>> + case Machine::X86:
>> + Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_I386;
>> + break;
>> + default:
>> + Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;
>> + }
>> + Header->NumberOfSections = 2;
>> + Header->TimeDateStamp = getTime();
>> + Header->PointerToSymbolTable = SymbolTableOffset;
>> + // One symbol for every resource plus 2 for each section and @feat.00
>> + Header->NumberOfSymbols = Data.size() + 5;
>> + Header->SizeOfOptionalHeader = 0;
>> + Header->Characteristics = llvm::COFF::IMAGE_FILE_32BIT_MACHINE;
>> +}
>> +
>> +void WindowsResourceCOFFWriter::writeFirstSectionHeader() {
>> + // Write the first section header.
>> + Current += sizeof(llvm::object::coff_file_header);
>> + auto *SectionOneHeader =
>> + reinterpret_cast<llvm::object::coff_section *>(Current);
>> + strncpy(SectionOneHeader->Name, ".rsrc$01", (size_t)llvm::COFF::NameSize);
>> + SectionOneHeader->VirtualSize = 0;
>> + SectionOneHeader->VirtualAddress = 0;
>> + SectionOneHeader->SizeOfRawData = SectionOneSize;
>> + SectionOneHeader->PointerToRawData = SectionOneOffset;
>> + SectionOneHeader->PointerToRelocations = SectionOneRelocations;
>> + SectionOneHeader->PointerToLinenumbers = 0;
>> + SectionOneHeader->NumberOfRelocations = Data.size();
>> + SectionOneHeader->NumberOfLinenumbers = 0;
>> + SectionOneHeader->Characteristics = llvm::COFF::IMAGE_SCN_ALIGN_1BYTES;
>> + SectionOneHeader->Characteristics +=
>> + llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
>> + SectionOneHeader->Characteristics += llvm::COFF::IMAGE_SCN_MEM_DISCARDABLE;
>> + SectionOneHeader->Characteristics += llvm::COFF::IMAGE_SCN_MEM_READ;
>> +}
>> +
>> +void WindowsResourceCOFFWriter::writeSecondSectionHeader() {
>> + // Write the second section header.
>> + Current += sizeof(llvm::object::coff_section);
>> + auto *SectionTwoHeader =
>> + reinterpret_cast<llvm::object::coff_section *>(Current);
>> + strncpy(SectionTwoHeader->Name, ".rsrc$02", (size_t)llvm::COFF::NameSize);
>> + SectionTwoHeader->VirtualSize = 0;
>> + SectionTwoHeader->VirtualAddress = 0;
>> + SectionTwoHeader->SizeOfRawData = SectionTwoSize;
>> + SectionTwoHeader->PointerToRawData = SectionTwoOffset;
>> + SectionTwoHeader->PointerToRelocations = 0;
>> + SectionTwoHeader->PointerToLinenumbers = 0;
>> + SectionTwoHeader->NumberOfRelocations = 0;
>> + SectionTwoHeader->NumberOfLinenumbers = 0;
>> + SectionTwoHeader->Characteristics =
>> + llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
>> + SectionTwoHeader->Characteristics += llvm::COFF::IMAGE_SCN_MEM_READ;
>> +}
>> +
>> +void WindowsResourceCOFFWriter::writeFirstSection() {
>> + // Write section one.
>> + Current += sizeof(llvm::object::coff_section);
>> +
>> + writeDirectoryTree();
>> + writeDirectoryStringTable();
>> + writeFirstSectionRelocations();
>> +}
>> +
>> +void WindowsResourceCOFFWriter::writeSecondSection() {
>> + // Now write the .rsrc$02 section.
>> + for (auto const &RawDataEntry : Data) {
>> + std::copy(RawDataEntry.begin(), RawDataEntry.end(), Current);
>> + Current += alignTo(RawDataEntry.size(), sizeof(uint64_t));
>> + }
>> +}
>> +
>> +void WindowsResourceCOFFWriter::writeSymbolTable() {
>> + // Now write the symbol table.
>> + // First, the feat symbol.
>> + auto *Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(Current);
>> + strncpy(Symbol->Name.ShortName, "@feat.00", (size_t)llvm::COFF::NameSize);
>> + Symbol->Value = 0x11;
>> + Symbol->SectionNumber = 0xffff;
>> + Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL;
>> + Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC;
>> + Symbol->NumberOfAuxSymbols = 0;
>> + Current += sizeof(llvm::object::coff_symbol16);
>> +
>> + // Now write the .rsrc1 symbol + aux.
>> + Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(Current);
>> + strncpy(Symbol->Name.ShortName, ".rsrc$01", (size_t)llvm::COFF::NameSize);
>> + Symbol->Value = 0;
>> + Symbol->SectionNumber = 1;
>> + Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL;
>> + Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC;
>> + Symbol->NumberOfAuxSymbols = 1;
>> + Current += sizeof(llvm::object::coff_symbol16);
>> + auto *Aux =
>> + reinterpret_cast<llvm::object::coff_aux_section_definition *>(Current);
>> + Aux->Length = SectionOneSize;
>> + Aux->NumberOfRelocations = Data.size();
>> + Aux->NumberOfLinenumbers = 0;
>> + Aux->CheckSum = 0;
>> + Aux->NumberLowPart = 0;
>> + Aux->Selection = 0;
>> + Current += sizeof(llvm::object::coff_aux_section_definition);
>> +
>> + // Now write the .rsrc2 symbol + aux.
>> + Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(Current);
>> + strncpy(Symbol->Name.ShortName, ".rsrc$02", (size_t)llvm::COFF::NameSize);
>> + Symbol->Value = 0;
>> + Symbol->SectionNumber = 2;
>> + Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL;
>> + Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC;
>> + Symbol->NumberOfAuxSymbols = 1;
>> + Current += sizeof(llvm::object::coff_symbol16);
>> + Aux = reinterpret_cast<llvm::object::coff_aux_section_definition *>(Current);
>> + Aux->Length = SectionTwoSize;
>> + Aux->NumberOfRelocations = 0;
>> + Aux->NumberOfLinenumbers = 0;
>> + Aux->CheckSum = 0;
>> + Aux->NumberLowPart = 0;
>> + Aux->Selection = 0;
>> + Current += sizeof(llvm::object::coff_aux_section_definition);
>> +
>> + // Now write a symbol for each relocation.
>> + for (unsigned i = 0; i < Data.size(); i++) {
>> + char RelocationName[9];
>> + sprintf(RelocationName, "$R%06X", DataOffsets[i]);
>> + Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(Current);
>> + strncpy(Symbol->Name.ShortName, RelocationName,
>> + (size_t)llvm::COFF::NameSize);
>> + Symbol->Value = DataOffsets[i];
>> + Symbol->SectionNumber = 1;
>> + Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL;
>> + Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC;
>> + Symbol->NumberOfAuxSymbols = 0;
>> + Current += sizeof(llvm::object::coff_symbol16);
>> + }
>> +}
>> +
>> +void WindowsResourceCOFFWriter::writeStringTable() {
>> + // Just 4 null bytes for the string table.
>> + auto COFFStringTable = reinterpret_cast<uint32_t *>(Current);
>> + *COFFStringTable = 0;
>> +}
>> +
>> +void WindowsResourceCOFFWriter::writeDirectoryTree() {
>> + // Traverse parsed resource tree breadth-first and write the corresponding
>> + // COFF objects.
>> + std::queue<const WindowsResourceParser::TreeNode *> Queue;
>> + Queue.push(&Resources);
>> + uint32_t NextLevelOffset = sizeof(llvm::object::coff_resource_dir_table) +
>> + (Resources.getStringChildren().size() +
>> + Resources.getIDChildren().size()) *
>> + sizeof(llvm::object::coff_resource_dir_entry);
>> + std::vector<const WindowsResourceParser::TreeNode *> DataEntriesTreeOrder;
>> + uint32_t CurrentRelativeOffset = 0;
>> +
>> + while (!Queue.empty()) {
>> + auto CurrentNode = Queue.front();
>> + Queue.pop();
>> + auto *Table =
>> + reinterpret_cast<llvm::object::coff_resource_dir_table *>(Current);
>> + Table->Characteristics = CurrentNode->getCharacteristics();
>> + Table->TimeDateStamp = 0;
>> + Table->MajorVersion = CurrentNode->getMajorVersion();
>> + Table->MinorVersion = CurrentNode->getMinorVersion();
>> + auto &IDChildren = CurrentNode->getIDChildren();
>> + auto &StringChildren = CurrentNode->getStringChildren();
>> + Table->NumberOfNameEntries = StringChildren.size();
>> + Table->NumberOfIDEntries = IDChildren.size();
>> + Current += sizeof(llvm::object::coff_resource_dir_table);
>> + CurrentRelativeOffset += sizeof(llvm::object::coff_resource_dir_table);
>> +
>> + // Write the directory entries immediately following each directory table.
>> + for (auto const &Child : StringChildren) {
>> + auto *Entry =
>> + reinterpret_cast<llvm::object::coff_resource_dir_entry *>(Current);
>> + Entry->Identifier.NameOffset =
>> + StringTableOffsets[Child.second->getStringIndex()];
>> + if (Child.second->checkIsDataNode()) {
>> + Entry->Offset.DataEntryOffset = NextLevelOffset;
>> + NextLevelOffset += sizeof(llvm::object::coff_resource_data_entry);
>> + DataEntriesTreeOrder.push_back(Child.second.get());
>> + } else {
>> + Entry->Offset.SubdirOffset = NextLevelOffset + (1 << 31);
>> + NextLevelOffset += sizeof(llvm::object::coff_resource_dir_table) +
>> + (Child.second->getStringChildren().size() +
>> + Child.second->getIDChildren().size()) *
>> + sizeof(llvm::object::coff_resource_dir_entry);
>> + Queue.push(Child.second.get());
>> + }
>> + Current += sizeof(llvm::object::coff_resource_dir_entry);
>> + CurrentRelativeOffset += sizeof(llvm::object::coff_resource_dir_entry);
>> + }
>> + for (auto const &Child : IDChildren) {
>> + auto *Entry =
>> + reinterpret_cast<llvm::object::coff_resource_dir_entry *>(Current);
>> + Entry->Identifier.ID = Child.first;
>> + if (Child.second->checkIsDataNode()) {
>> + Entry->Offset.DataEntryOffset = NextLevelOffset;
>> + NextLevelOffset += sizeof(llvm::object::coff_resource_data_entry);
>> + DataEntriesTreeOrder.push_back(Child.second.get());
>> + } else {
>> + Entry->Offset.SubdirOffset = NextLevelOffset + (1 << 31);
>> + NextLevelOffset += sizeof(llvm::object::coff_resource_dir_table) +
>> + (Child.second->getStringChildren().size() +
>> + Child.second->getIDChildren().size()) *
>> + sizeof(llvm::object::coff_resource_dir_entry);
>> + Queue.push(Child.second.get());
>> + }
>> + Current += sizeof(llvm::object::coff_resource_dir_entry);
>> + CurrentRelativeOffset += sizeof(llvm::object::coff_resource_dir_entry);
>> + }
>> + }
>> +
>> + RelocationAddresses.resize(Data.size());
>> + // Now write all the resource data entries.
>> + for (auto DataNodes : DataEntriesTreeOrder) {
>> + auto *Entry =
>> + reinterpret_cast<llvm::object::coff_resource_data_entry *>(Current);
>> + RelocationAddresses[DataNodes->getDataIndex()] = CurrentRelativeOffset;
>> + Entry->DataRVA = 0; // Set to zero because it is a relocation.
>> + Entry->DataSize = Data[DataNodes->getDataIndex()].size();
>> + Entry->Codepage = 0;
>> + Entry->Reserved = 0;
>> + Current += sizeof(llvm::object::coff_resource_data_entry);
>> + CurrentRelativeOffset += sizeof(llvm::object::coff_resource_data_entry);
>> + }
>> +}
>> +
>> +void WindowsResourceCOFFWriter::writeDirectoryStringTable() {
>> + // Now write the directory string table for .rsrc$01
>> + uint32_t TotalStringTableSize = 0;
>> + for (auto String : StringTable) {
>> + auto *LengthField = reinterpret_cast<uint16_t *>(Current);
>> + uint16_t Length = String.size();
>> + *LengthField = Length;
>> + Current += sizeof(uint16_t);
>> + auto *Start = reinterpret_cast<UTF16 *>(Current);
>> + std::copy(String.begin(), String.end(), Start);
>> + Current += Length * sizeof(UTF16);
>> + TotalStringTableSize += Length * sizeof(UTF16) + sizeof(uint16_t);
>> + }
>> + Current +=
>> + alignTo(TotalStringTableSize, sizeof(uint32_t)) - TotalStringTableSize;
>> +}
>> +
>> +void WindowsResourceCOFFWriter::writeFirstSectionRelocations() {
>> +
>> + // Now write the relocations for .rsrc$01
>> + // Five symbols already in table before we start, @feat.00 and 2 for each
>> + // .rsrc section.
>> + uint32_t NextSymbolIndex = 5;
>> + for (unsigned i = 0; i < Data.size(); i++) {
>> + auto *Reloc = reinterpret_cast<llvm::object::coff_relocation *>(Current);
>> + Reloc->VirtualAddress = RelocationAddresses[i];
>> + Reloc->SymbolTableIndex = NextSymbolIndex++;
>> + switch (MachineType) {
>> + case Machine::ARM:
>> + Reloc->Type = llvm::COFF::IMAGE_REL_ARM_ADDR32NB;
>> + break;
>> + case Machine::X64:
>> + Reloc->Type = llvm::COFF::IMAGE_REL_AMD64_ADDR32NB;
>> + break;
>> + case Machine::X86:
>> + Reloc->Type = llvm::COFF::IMAGE_REL_I386_DIR32NB;
>> + break;
>> + default:
>> + Reloc->Type = 0;
>> + }
>> + Current += sizeof(llvm::object::coff_relocation);
>> + }
>> +}
>> +
>> +Error writeWindowsResourceCOFF(StringRef OutputFile, Machine MachineType,
>> + const WindowsResourceParser &Parser) {
>> + Error E = Error::success();
>> + WindowsResourceCOFFWriter Writer(OutputFile, MachineType, Parser, E);
>> + if (E)
>> + return E;
>> + return Writer.write();
>> +}
>> +
>> } // namespace object
>> } // namespace llvm
>>
>> Added: llvm/trunk/test/tools/llvm-cvtres/Inputs/test_resource.obj.coff
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cvtres/Inputs/test_resource.obj.coff?rev=305092&view=auto
>> ==============================================================================
>> Binary file - no diff available.
>>
>> Propchange: llvm/trunk/test/tools/llvm-cvtres/Inputs/test_resource.obj.coff
>> ------------------------------------------------------------------------------
>> svn:mime-type = application/octet-stream
>>
>> Added: llvm/trunk/test/tools/llvm-cvtres/object.test
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cvtres/object.test?rev=305092&view=auto
>> ==============================================================================
>> --- llvm/trunk/test/tools/llvm-cvtres/object.test (added)
>> +++ llvm/trunk/test/tools/llvm-cvtres/object.test Fri Jun 9 12:34:30 2017
>> @@ -0,0 +1,229 @@
>> +// Check COFF emission of cvtres
>> +// The input was generated with the following command, using the original Windows
>> +// rc.exe:
>> +// > rc /fo test_resource.res /nologo test_resource.rc
>> +// The object file we are comparing against was generated with this command using
>> +// the original cvtres.
>> +// > cvtres /machine:X86 /readonly /nologo /out:test_resource.o test_resource.res
>> +
>> +RUN: llvm-cvtres /out:%t %p/Inputs/test_resource.res
>> +RUN: llvm-readobj -coff-resources -section-data %t | FileCheck %s
>> +
>> +CHECK: Resources [
>> +CHECK-NEXT: String Name Entries: 1
>> +CHECK-NEXT: ID Entries: 4
>> +CHECK-NEXT: Type: STRINGARRAY [
>> +CHECK-NEXT: String Name Entries: 1
>> +CHECK-NEXT: ID Entries: 0
>> +CHECK-NEXT: Name: MYRESOURCE [
>> +CHECK-NEXT: String Name Entries: 0
>> +CHECK-NEXT: ID Entries: 1
>> +CHECK-NEXT: Language: (ID 1033) [
>> +CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
>> +CHECK-NEXT: Major Version: 0
>> +CHECK-NEXT: Minor Version: 0
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: Type: kRT_BITMAP (ID 2) [
>> +CHECK-NEXT: String Name Entries: 2
>> +CHECK-NEXT: ID Entries: 0
>> +CHECK-NEXT: Name: CURSOR [
>> +CHECK-NEXT: String Name Entries: 0
>> +CHECK-NEXT: ID Entries: 1
>> +CHECK-NEXT: Language: (ID 1033) [
>> +CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
>> +CHECK-NEXT: Major Version: 0
>> +CHECK-NEXT: Minor Version: 0
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: Name: OKAY [
>> +CHECK-NEXT: String Name Entries: 0
>> +CHECK-NEXT: ID Entries: 1
>> +CHECK-NEXT: Language: (ID 1033) [
>> +CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
>> +CHECK-NEXT: Major Version: 0
>> +CHECK-NEXT: Minor Version: 0
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: Type: kRT_MENU (ID 4) [
>> +CHECK-NEXT: String Name Entries: 1
>> +CHECK-NEXT: ID Entries: 1
>> +CHECK-NEXT: Name: "EAT" [
>> +CHECK-NEXT: String Name Entries: 0
>> +CHECK-NEXT: ID Entries: 1
>> +CHECK-NEXT: Language: (ID 3081) [
>> +CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
>> +CHECK-NEXT: Major Version: 0
>> +CHECK-NEXT: Minor Version: 0
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: Name: (ID 14432) [
>> +CHECK-NEXT: String Name Entries: 0
>> +CHECK-NEXT: ID Entries: 1
>> +CHECK-NEXT: Language: (ID 2052) [
>> +CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
>> +CHECK-NEXT: Major Version: 0
>> +CHECK-NEXT: Minor Version: 0
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: Type: kRT_DIALOG (ID 5) [
>> +CHECK-NEXT: String Name Entries: 1
>> +CHECK-NEXT: ID Entries: 0
>> +CHECK-NEXT: Name: TESTDIALOG [
>> +CHECK-NEXT: String Name Entries: 0
>> +CHECK-NEXT: ID Entries: 1
>> +CHECK-NEXT: Language: (ID 1033) [
>> +CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
>> +CHECK-NEXT: Major Version: 0
>> +CHECK-NEXT: Minor Version: 0
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: Type: kRT_ACCELERATOR (ID 9) [
>> +CHECK-NEXT: String Name Entries: 1
>> +CHECK-NEXT: ID Entries: 1
>> +CHECK-NEXT: Name: MYACCELERATORS [
>> +CHECK-NEXT: String Name Entries: 0
>> +CHECK-NEXT: ID Entries: 1
>> +CHECK-NEXT: Language: (ID 1033) [
>> +CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
>> +CHECK-NEXT: Major Version: 0
>> +CHECK-NEXT: Minor Version: 0
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: Name: (ID 12) [
>> +CHECK-NEXT: String Name Entries: 0
>> +CHECK-NEXT: ID Entries: 1
>> +CHECK-NEXT: Language: (ID 1033) [
>> +CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
>> +CHECK-NEXT: Major Version: 0
>> +CHECK-NEXT: Minor Version: 0
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-DAG: .rsrc$02 Data (
>> +CHECK-NEXT: 0000: 11000300 E7030000 0D004400 4C040000 |..........D.L...|
>> +CHECK-NEXT: 0010: 82001200 BC010000 28000000 10000000 |........(.......|
>> +CHECK-NEXT: 0020: 10000000 01001800 00000000 00030000 |................|
>> +CHECK-NEXT: 0030: C40E0000 C40E0000 00000000 00000000 |................|
>> +CHECK-NEXT: 0040: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0050: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0060: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0070: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0080: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0090: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 00A0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 00B0: FFFFFFFF FF7F7F7F 7C7C7C78 78787575 |........|||xxxuu|
>> +CHECK-NEXT: 00C0: 75FFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |u...............|
>> +CHECK-NEXT: 00D0: FFFFFFFF FFFFFFFF FFFFFFFF 979797FF |................|
>> +CHECK-NEXT: 00E0: FFFFFFFF FF838383 AAAAAADB DBDB7979 |..............yy|
>> +CHECK-NEXT: 00F0: 79757575 FFFFFFFF FFFFFFFF FFFFFFFF |yuuu............|
>> +CHECK-NEXT: 0100: FFFFFFFF FFFFFFFF FFFFFFFF 9C9C9C98 |................|
>> +CHECK-NEXT: 0110: 9898FFFF FF888888 DBDBDBB7 B7B77D7D |..............}}|
>> +CHECK-NEXT: 0120: 7DFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |}...............|
>> +CHECK-NEXT: 0130: FFFFFFFF FFFFFFFF FFFFFFFF A0A0A09C |................|
>> +CHECK-NEXT: 0140: 9C9C9393 93ADADAD F2F2F284 84848181 |................|
>> +CHECK-NEXT: 0150: 81FFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0160: FFFFFFFF FFFFFFFF FFFFFFFF A4A4A4D7 |................|
>> +CHECK-NEXT: 0170: D7D79D9D 9DD0D0D0 EEEEEE91 91918D8D |................|
>> +CHECK-NEXT: 0180: 8DFFFFFF FFFFFF81 81817E7E 7EFFFFFF |..........~~~...|
>> +CHECK-NEXT: 0190: FFFFFFFF FFFFFFFF FFFFFFFF A9A9A9F2 |................|
>> +CHECK-NEXT: 01A0: F2F2E5E5 E5E2E2E2 95959591 91918D8D |................|
>> +CHECK-NEXT: 01B0: 8D898989 868686FF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 01C0: FFFFFFFF FFFFFFFF FFFFFFFF ADADADF2 |................|
>> +CHECK-NEXT: 01D0: F2F2E1E1 E1DFDFDF E7E7E7E4 E4E4BBBB |................|
>> +CHECK-NEXT: 01E0: BB8E8E8E FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 01F0: FFFFFFFF FFFFFFFF FFFFFFFF B5B5B5F2 |................|
>> +CHECK-NEXT: 0200: F2F2E8E8 E8E7E7E7 EAEAEAC6 C6C69E9E |................|
>> +CHECK-NEXT: 0210: 9EFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0220: FFFFFFFF FFFFFFFF FFFFFFFF B9B9B9F4 |................|
>> +CHECK-NEXT: 0230: F4F4ECEC ECEDEDED CBCBCBA7 A7A7FFFF |................|
>> +CHECK-NEXT: 0240: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0250: FFFFFFFF FFFFFFFF FFFFFFFF BDBDBDF7 |................|
>> +CHECK-NEXT: 0260: F7F7EFEF EFD0D0D0 AFAFAFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0270: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0280: FFFFFFFF FFFFFFFF FFFFFFFF C1C1C1F7 |................|
>> +CHECK-NEXT: 0290: F7F7D5D5 D5B6B6B6 FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 02A0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 02B0: FFFFFFFF FFFFFFFF FFFFFFFF C4C4C4D9 |................|
>> +CHECK-NEXT: 02C0: D9D9BEBE BEFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 02D0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 02E0: FFFFFFFF FFFFFFFF FFFFFFFF C8C8C8C5 |................|
>> +CHECK-NEXT: 02F0: C5C5FFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0300: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0310: FFFFFFFF FFFFFFFF FFFFFFFF CBCBCBFF |................|
>> +CHECK-NEXT: 0320: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0330: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0340: 28000000 10000000 10000000 01001800 |(...............|
>> +CHECK-NEXT: 0350: 00000000 00030000 C40E0000 C40E0000 |................|
>> +CHECK-NEXT: 0360: 00000000 00000000 FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0370: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0380: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0390: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 03A0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 03B0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 03C0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 03D0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 03E0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 03F0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0400: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0410: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0420: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0430: FFFFFFFF A0E3A901 B31801B3 1801B318 |................|
>> +CHECK-NEXT: 0440: 01B31801 B31801B3 1861D06F FFFFFFFF |.........a.o....|
>> +CHECK-NEXT: 0450: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0460: FFFFFFFF 01B31800 D7331CDB 49DBF9E2 |.........3..I...|
>> +CHECK-NEXT: 0470: 9BEFAF00 D73300D7 3301B318 FFFFFFFF |.....3..3.......|
>> +CHECK-NEXT: 0480: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0490: FFFFFFFF 01B31800 DE55F6FE F9DBFAE7 |.........U......|
>> +CHECK-NEXT: 04A0: FEFFFE86 EFAE00DE 5501B318 FFFFFFFF |........U.......|
>> +CHECK-NEXT: 04B0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 04C0: FFFFFFFF 01B31800 E676DBFB EC00E676 |.........v.....v|
>> +CHECK-NEXT: 04D0: 57EFA5FB FFFD55EE A401B318 FFFFFFFF |W.....U.........|
>> +CHECK-NEXT: 04E0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 04F0: FFFFFFFF 01B31800 ED9800ED 9800ED98 |................|
>> +CHECK-NEXT: 0500: 00ED9887 F7CFFEFF FF01B318 FFFFFFFF |................|
>> +CHECK-NEXT: 0510: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0520: FFFFFFFF 01B31800 F4BA00F4 BA00F4BA |................|
>> +CHECK-NEXT: 0530: 00F4BA00 F4BA9CFB E401B318 FFFFFFFF |................|
>> +CHECK-NEXT: 0540: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0550: FFFFFFFF 01B31800 FBDB00FB DB00FBDB |................|
>> +CHECK-NEXT: 0560: 00FBDB00 FBDB00FB DB01B318 FFFFFFFF |................|
>> +CHECK-NEXT: 0570: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0580: FFFFFFFF 9FE2A801 B31801B3 1801B318 |................|
>> +CHECK-NEXT: 0590: 01B31801 B31801B3 1861D06F FFFFFFFF |.........a.o....|
>> +CHECK-NEXT: 05A0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 05B0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 05C0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 05D0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 05E0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 05F0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0600: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0610: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0620: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0630: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0640: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0650: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
>> +CHECK-NEXT: 0660: FFFFFFFF FFFFFFFF 00000000 00006400 |..............d.|
>> +CHECK-NEXT: 0670: 79007500 00000000 65007300 68006100 |y.u.....e.s.h.a.|
>> +CHECK-NEXT: 0680: 6C006100 00008000 66006B00 61006F00 |l.a.....f.k.a.o.|
>> +CHECK-NEXT: 0690: 79006100 00000000 0000C080 00000000 |y.a.............|
>> +CHECK-NEXT: 06A0: 02000A00 0A00C800 2C010000 00005400 |........,.....T.|
>> +CHECK-NEXT: 06B0: 65007300 74000000 01000250 00000000 |e.s.t......P....|
>> +CHECK-NEXT: 06C0: 0A000A00 E6000E00 0100FFFF 82004300 |..............C.|
>> +CHECK-NEXT: 06D0: 6F006E00 74006900 6E007500 65003A00 |o.n.t.i.n.u.e.:.|
>> +CHECK-NEXT: 06E0: 00000000 00000150 00000000 42008600 |.......P....B...|
>> +CHECK-NEXT: 06F0: A1000D00 0200FFFF 80002600 4F004B00 |..........&.O.K.|
>> +CHECK-NEXT: 0700: 00000000 00000000 11005800 A4000000 |..........X.....|
>> +CHECK-NEXT: 0710: 0D004800 2E160000 82001200 BC010000 |..H.............|
>> +CHECK-NEXT: 0720: 00000000 00006400 66006900 73006800 |......d.f.i.s.h.|
>> +CHECK-NEXT: 0730: 00000000 65007300 61006C00 61006400 |....e.s.a.l.a.d.|
>> +CHECK-NEXT: 0740: 00008000 66006400 75006300 6B000000 |....f.d.u.c.k...|
>> +CHECK-NEXT: 0750: 74686973 20697320 61207573 65722064 |this is a user d|
>> +CHECK-NEXT: 0760: 6566696E 65642072 65736F75 72636500 |efined resource.|
>> +CHECK-NEXT: 0770: 69742063 6F6E7461 696E7320 6D616E79 |it contains many|
>> +CHECK-NEXT: 0780: 20737472 696E6773 00000000 00000000 | strings........|
>> +CHECK-NEXT: )
>>
>> Added: llvm/trunk/test/tools/llvm-cvtres/parse.test
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cvtres/parse.test?rev=305092&view=auto
>> ==============================================================================
>> --- llvm/trunk/test/tools/llvm-cvtres/parse.test (added)
>> +++ llvm/trunk/test/tools/llvm-cvtres/parse.test Fri Jun 9 12:34:30 2017
>> @@ -0,0 +1,51 @@
>> +// The input was generated with the following command, using the original Windows
>> +// rc.exe:
>> +// > rc /fo test_resource.res /nologo test_resource.rc
>> +
>> +RUN: llvm-cvtres /verbose %p/Inputs/test_resource.res | FileCheck %s
>> +
>> +CHECK: Number of resources: 8
>> +CHECK-NEXT: Resource Tree [
>> +CHECK-NEXT: STRINGARRAY [
>> +CHECK-NEXT: MYRESOURCE [
>> +CHECK-NEXT: 1033 [
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: 2 [
>> +CHECK-NEXT: CURSOR [
>> +CHECK-NEXT: 1033 [
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: OKAY [
>> +CHECK-NEXT: 1033 [
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: 4 [
>> +CHECK-NEXT: "EAT" [
>> +CHECK-NEXT: 3081 [
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: 14432 [
>> +CHECK-NEXT: 2052 [
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: 5 [
>> +CHECK-NEXT: TESTDIALOG [
>> +CHECK-NEXT: 1033 [
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: 9 [
>> +CHECK-NEXT: MYACCELERATORS [
>> +CHECK-NEXT: 1033 [
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: 12 [
>> +CHECK-NEXT: 1033 [
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>> +CHECK-NEXT: ]
>>
>> Removed: llvm/trunk/test/tools/llvm-cvtres/resource.test
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cvtres/resource.test?rev=305091&view=auto
>> ==============================================================================
>> --- llvm/trunk/test/tools/llvm-cvtres/resource.test (original)
>> +++ llvm/trunk/test/tools/llvm-cvtres/resource.test (removed)
>> @@ -1,51 +0,0 @@
>> -// The input was generated with the following command, using the original Windows
>> -// rc.exe:
>> -// > rc /fo test_resource.res /nologo test_resource.rc
>> -
>> -RUN: llvm-cvtres %p/Inputs/test_resource.res | FileCheck %s
>> -
>> -CHECK: Number of resources: 8
>> -CHECK-NEXT: Resource Tree [
>> -CHECK-NEXT: STRINGARRAY [
>> -CHECK-NEXT: MYRESOURCE [
>> -CHECK-NEXT: 1033 [
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: 2 [
>> -CHECK-NEXT: CURSOR [
>> -CHECK-NEXT: 1033 [
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: OKAY [
>> -CHECK-NEXT: 1033 [
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: 4 [
>> -CHECK-NEXT: "EAT" [
>> -CHECK-NEXT: 3081 [
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: 14432 [
>> -CHECK-NEXT: 2052 [
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: 5 [
>> -CHECK-NEXT: TESTDIALOG [
>> -CHECK-NEXT: 1033 [
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: 9 [
>> -CHECK-NEXT: MYACCELERATORS [
>> -CHECK-NEXT: 1033 [
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: 12 [
>> -CHECK-NEXT: 1033 [
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: ]
>> -CHECK-NEXT: ]
>>
>> Modified: llvm/trunk/tools/llvm-cvtres/LLVMBuild.txt
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cvtres/LLVMBuild.txt?rev=305092&r1=305091&r2=305092&view=diff
>> ==============================================================================
>> --- llvm/trunk/tools/llvm-cvtres/LLVMBuild.txt (original)
>> +++ llvm/trunk/tools/llvm-cvtres/LLVMBuild.txt Fri Jun 9 12:34:30 2017
>> @@ -19,4 +19,4 @@
>> type = Tool
>> name = llvm-cvtres
>> parent = Tools
>> -required_libraries = Option Support
>> +required_libraries = Object Option Support
>>
>> Modified: llvm/trunk/tools/llvm-cvtres/llvm-cvtres.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cvtres/llvm-cvtres.cpp?rev=305092&r1=305091&r2=305092&view=diff
>> ==============================================================================
>> --- llvm/trunk/tools/llvm-cvtres/llvm-cvtres.cpp (original)
>> +++ llvm/trunk/tools/llvm-cvtres/llvm-cvtres.cpp Fri Jun 9 12:34:30 2017
>> @@ -112,20 +112,23 @@ int main(int argc_, const char *argv_[])
>> return 0;
>> }
>>
>> - machine Machine;
>> + bool Verbose = InputArgs.hasArg(OPT_VERBOSE);
>> +
>> + Machine MachineType;
>>
>> if (InputArgs.hasArg(OPT_MACHINE)) {
>> std::string MachineString = InputArgs.getLastArgValue(OPT_MACHINE).upper();
>> - Machine = StringSwitch<machine>(MachineString)
>> - .Case("ARM", machine::ARM)
>> - .Case("X64", machine::X64)
>> - .Case("X86", machine::X86)
>> - .Default(machine::UNKNOWN);
>> - if (Machine == machine::UNKNOWN)
>> + MachineType = StringSwitch<Machine>(MachineString)
>> + .Case("ARM", Machine::ARM)
>> + .Case("X64", Machine::X64)
>> + .Case("X86", Machine::X86)
>> + .Default(Machine::UNKNOWN);
>> + if (MachineType == Machine::UNKNOWN)
>> reportError("Unsupported machine architecture");
>> } else {
>> - outs() << "Machine architecture not specified; assumed X64.\n";
>> - Machine = machine::X64;
>> + if (Verbose)
>> + outs() << "Machine architecture not specified; assumed X64.\n";
>> + MachineType = Machine::X64;
>> }
>>
>> std::vector<std::string> InputFiles = InputArgs.getAllArgValues(OPT_INPUT);
>> @@ -139,20 +142,22 @@ int main(int argc_, const char *argv_[])
>> if (InputArgs.hasArg(OPT_OUT)) {
>> OutputFile = InputArgs.getLastArgValue(OPT_OUT);
>> } else {
>> - OutputFile = StringRef(InputFiles[0]);
>> + OutputFile = llvm::sys::path::filename(StringRef(InputFiles[0]));
>> 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";
>> + if (Verbose) {
>> + outs() << "Machine: ";
>> + switch (MachineType) {
>> + case Machine::ARM:
>> + outs() << "ARM\n";
>> + break;
>> + case Machine::X86:
>> + outs() << "X86\n";
>> + break;
>> + default:
>> + outs() << "X64\n";
>> + }
>> }
>>
>> WindowsResourceParser Parser;
>> @@ -169,22 +174,28 @@ int main(int argc_, const char *argv_[])
>> if (!RF)
>> reportError(File + ": unrecognized file format.\n");
>>
>> - int EntryNumber = 0;
>> - Expected<ResourceEntryRef> EntryOrErr = RF->getHeadEntry();
>> - if (!EntryOrErr)
>> - error(EntryOrErr.takeError());
>> - ResourceEntryRef Entry = EntryOrErr.get();
>> - bool End = false;
>> - while (!End) {
>> - error(Entry.moveNext(End));
>> - EntryNumber++;
>> + if (Verbose) {
>> + int EntryNumber = 0;
>> + Expected<ResourceEntryRef> EntryOrErr = RF->getHeadEntry();
>> + if (!EntryOrErr)
>> + error(EntryOrErr.takeError());
>> + ResourceEntryRef Entry = EntryOrErr.get();
>> + bool End = false;
>> + while (!End) {
>> + error(Entry.moveNext(End));
>> + EntryNumber++;
>> + }
>> + outs() << "Number of resources: " << EntryNumber << "\n";
>> }
>> - outs() << "Number of resources: " << EntryNumber << "\n";
>>
>> error(Parser.parse(RF));
>> }
>>
>> - Parser.printTree();
>> + if (Verbose)
>> + Parser.printTree();
>> +
>> + error(
>> + llvm::object::writeWindowsResourceCOFF(OutputFile, MachineType, Parser));
>>
>> return 0;
>> }
>>
>> Modified: llvm/trunk/tools/llvm-cvtres/llvm-cvtres.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cvtres/llvm-cvtres.h?rev=305092&r1=305091&r2=305092&view=diff
>> ==============================================================================
>> --- llvm/trunk/tools/llvm-cvtres/llvm-cvtres.h (original)
>> +++ llvm/trunk/tools/llvm-cvtres/llvm-cvtres.h Fri Jun 9 12:34:30 2017
>> @@ -14,6 +14,4 @@
>>
>> void error(std::error_code EC);
>>
>> -enum class machine { UNKNOWN = 0, ARM, X64, X86 };
>> -
>> #endif
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list