[WindowsResource] Remove use of global variables in WindowsResourceParser

Instead of updating a global variable counter for the next index of
strings and data blobs, pass along a reference to actual data/string
vectors and let the TreeNode insertion methods add their data/strings to
the vectors when a new entry is needed.

Additionally, if the resource tree had duplicates, that were ignored
with -force:multipleres in lld, we no longer store all versions of the
duplicated resource data, now we only keep the one that actually ends
up referenced.

Differential Revision: https://reviews.llvm.org/D66823

llvm-svn: 370435
This commit is contained in:
Martin Storsjo 2019-08-30 06:56:02 +00:00
parent e62d5682fb
commit d8d63ff24b
2 changed files with 62 additions and 70 deletions

View File

@ -181,32 +181,37 @@ public:
private: private:
friend class WindowsResourceParser; friend class WindowsResourceParser;
static uint32_t StringCount; // Index is the StringTable vector index for this node's name.
static uint32_t DataCount; static std::unique_ptr<TreeNode> createStringNode(uint32_t Index);
static std::unique_ptr<TreeNode> createStringNode();
static std::unique_ptr<TreeNode> createIDNode(); static std::unique_ptr<TreeNode> createIDNode();
// DataIndex is the Data vector index that the data node points at.
static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion, static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion,
uint16_t MinorVersion, uint16_t MinorVersion,
uint32_t Characteristics, uint32_t Characteristics,
uint32_t Origin); uint32_t Origin,
uint32_t DataIndex);
explicit TreeNode(bool IsStringNode); explicit TreeNode(uint32_t StringIndex);
TreeNode(uint16_t MajorVersion, uint16_t MinorVersion, TreeNode(uint16_t MajorVersion, uint16_t MinorVersion,
uint32_t Characteristics, uint32_t Origin); uint32_t Characteristics, uint32_t Origin, uint32_t DataIndex);
bool addEntry(const ResourceEntryRef &Entry, uint32_t Origin, bool addEntry(const ResourceEntryRef &Entry, uint32_t Origin,
bool &IsNewTypeString, bool &IsNewNameString, std::vector<std::vector<uint8_t>> &Data,
std::vector<std::vector<UTF16>> &StringTable,
TreeNode *&Result); TreeNode *&Result);
TreeNode &addTypeNode(const ResourceEntryRef &Entry, bool &IsNewTypeString); TreeNode &addTypeNode(const ResourceEntryRef &Entry,
TreeNode &addNameNode(const ResourceEntryRef &Entry, bool &IsNewNameString); std::vector<std::vector<UTF16>> &StringTable);
TreeNode &addNameNode(const ResourceEntryRef &Entry,
std::vector<std::vector<UTF16>> &StringTable);
bool addLanguageNode(const ResourceEntryRef &Entry, uint32_t Origin, bool addLanguageNode(const ResourceEntryRef &Entry, uint32_t Origin,
std::vector<std::vector<uint8_t>> &Data,
TreeNode *&Result); TreeNode *&Result);
bool addDataChild(uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion, bool addDataChild(uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion,
uint32_t Characteristics, uint32_t Origin, uint32_t Characteristics, uint32_t Origin,
TreeNode *&Result); uint32_t DataIndex, TreeNode *&Result);
TreeNode &addIDChild(uint32_t ID); TreeNode &addIDChild(uint32_t ID);
TreeNode &addNameChild(ArrayRef<UTF16> NameRef, bool &IsNewString); TreeNode &addNameChild(ArrayRef<UTF16> NameRef,
std::vector<std::vector<UTF16>> &StringTable);
bool IsDataNode = false; bool IsDataNode = false;
uint32_t StringIndex; uint32_t StringIndex;

View File

@ -36,9 +36,6 @@ const uint32_t MIN_HEADER_SIZE = 7 * sizeof(uint32_t) + 2 * sizeof(uint16_t);
// 8-byte because it makes everyone happy. // 8-byte because it makes everyone happy.
const uint32_t SECTION_ALIGNMENT = sizeof(uint64_t); const uint32_t SECTION_ALIGNMENT = sizeof(uint64_t);
uint32_t WindowsResourceParser::TreeNode::StringCount = 0;
uint32_t WindowsResourceParser::TreeNode::DataCount = 0;
WindowsResource::WindowsResource(MemoryBufferRef Source) WindowsResource::WindowsResource(MemoryBufferRef Source)
: Binary(Binary::ID_WinRes, Source) { : Binary(Binary::ID_WinRes, Source) {
size_t LeadingSize = WIN_RES_MAGIC_SIZE + WIN_RES_NULL_ENTRY_SIZE; size_t LeadingSize = WIN_RES_MAGIC_SIZE + WIN_RES_NULL_ENTRY_SIZE;
@ -223,25 +220,14 @@ Error WindowsResourceParser::parse(WindowsResource *WR,
InputFilenames.push_back(WR->getFileName()); InputFilenames.push_back(WR->getFileName());
bool End = false; bool End = false;
while (!End) { while (!End) {
Data.push_back(Entry.getData());
bool IsNewTypeString = false;
bool IsNewNameString = false;
TreeNode *Node; TreeNode *Node;
bool IsNewNode = bool IsNewNode = Root.addEntry(Entry, Origin, Data, StringTable, Node);
Root.addEntry(Entry, Origin, IsNewTypeString, IsNewNameString, Node);
if (!IsNewNode) { if (!IsNewNode) {
Duplicates.push_back(makeDuplicateResourceError( Duplicates.push_back(makeDuplicateResourceError(
Entry, InputFilenames[Node->Origin], WR->getFileName())); Entry, InputFilenames[Node->Origin], WR->getFileName()));
} }
if (IsNewTypeString)
StringTable.push_back(Entry.getTypeString());
if (IsNewNameString)
StringTable.push_back(Entry.getNameString());
RETURN_IF_ERROR(Entry.moveNext(End)); RETURN_IF_ERROR(Entry.moveNext(End));
} }
@ -253,79 +239,81 @@ void WindowsResourceParser::printTree(raw_ostream &OS) const {
Root.print(Writer, "Resource Tree"); Root.print(Writer, "Resource Tree");
} }
bool WindowsResourceParser::TreeNode::addEntry(const ResourceEntryRef &Entry, bool WindowsResourceParser::TreeNode::addEntry(
uint32_t Origin, const ResourceEntryRef &Entry, uint32_t Origin,
bool &IsNewTypeString, std::vector<std::vector<uint8_t>> &Data,
bool &IsNewNameString, std::vector<std::vector<UTF16>> &StringTable, TreeNode *&Result) {
TreeNode *&Result) { TreeNode &TypeNode = addTypeNode(Entry, StringTable);
TreeNode &TypeNode = addTypeNode(Entry, IsNewTypeString); TreeNode &NameNode = TypeNode.addNameNode(Entry, StringTable);
TreeNode &NameNode = TypeNode.addNameNode(Entry, IsNewNameString); return NameNode.addLanguageNode(Entry, Origin, Data, Result);
return NameNode.addLanguageNode(Entry, Origin, Result);
} }
WindowsResourceParser::TreeNode::TreeNode(bool IsStringNode) { WindowsResourceParser::TreeNode::TreeNode(uint32_t StringIndex)
if (IsStringNode) : StringIndex(StringIndex) {}
StringIndex = StringCount++;
}
WindowsResourceParser::TreeNode::TreeNode(uint16_t MajorVersion, WindowsResourceParser::TreeNode::TreeNode(uint16_t MajorVersion,
uint16_t MinorVersion, uint16_t MinorVersion,
uint32_t Characteristics, uint32_t Characteristics,
uint32_t Origin) uint32_t Origin, uint32_t DataIndex)
: IsDataNode(true), MajorVersion(MajorVersion), MinorVersion(MinorVersion), : IsDataNode(true), DataIndex(DataIndex), MajorVersion(MajorVersion),
Characteristics(Characteristics), Origin(Origin) { MinorVersion(MinorVersion), Characteristics(Characteristics),
DataIndex = DataCount++; Origin(Origin) {}
}
std::unique_ptr<WindowsResourceParser::TreeNode> std::unique_ptr<WindowsResourceParser::TreeNode>
WindowsResourceParser::TreeNode::createStringNode() { WindowsResourceParser::TreeNode::createStringNode(uint32_t Index) {
return std::unique_ptr<TreeNode>(new TreeNode(true)); return std::unique_ptr<TreeNode>(new TreeNode(Index));
} }
std::unique_ptr<WindowsResourceParser::TreeNode> std::unique_ptr<WindowsResourceParser::TreeNode>
WindowsResourceParser::TreeNode::createIDNode() { WindowsResourceParser::TreeNode::createIDNode() {
return std::unique_ptr<TreeNode>(new TreeNode(false)); return std::unique_ptr<TreeNode>(new TreeNode(0));
} }
std::unique_ptr<WindowsResourceParser::TreeNode> std::unique_ptr<WindowsResourceParser::TreeNode>
WindowsResourceParser::TreeNode::createDataNode(uint16_t MajorVersion, WindowsResourceParser::TreeNode::createDataNode(uint16_t MajorVersion,
uint16_t MinorVersion, uint16_t MinorVersion,
uint32_t Characteristics, uint32_t Characteristics,
uint32_t Origin) { uint32_t Origin,
return std::unique_ptr<TreeNode>( uint32_t DataIndex) {
new TreeNode(MajorVersion, MinorVersion, Characteristics, Origin)); return std::unique_ptr<TreeNode>(new TreeNode(
MajorVersion, MinorVersion, Characteristics, Origin, DataIndex));
} }
WindowsResourceParser::TreeNode & WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addTypeNode(
WindowsResourceParser::TreeNode::addTypeNode(const ResourceEntryRef &Entry, const ResourceEntryRef &Entry,
bool &IsNewTypeString) { std::vector<std::vector<UTF16>> &StringTable) {
if (Entry.checkTypeString()) if (Entry.checkTypeString())
return addNameChild(Entry.getTypeString(), IsNewTypeString); return addNameChild(Entry.getTypeString(), StringTable);
else else
return addIDChild(Entry.getTypeID()); return addIDChild(Entry.getTypeID());
} }
WindowsResourceParser::TreeNode & WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addNameNode(
WindowsResourceParser::TreeNode::addNameNode(const ResourceEntryRef &Entry, const ResourceEntryRef &Entry,
bool &IsNewNameString) { std::vector<std::vector<UTF16>> &StringTable) {
if (Entry.checkNameString()) if (Entry.checkNameString())
return addNameChild(Entry.getNameString(), IsNewNameString); return addNameChild(Entry.getNameString(), StringTable);
else else
return addIDChild(Entry.getNameID()); return addIDChild(Entry.getNameID());
} }
bool WindowsResourceParser::TreeNode::addLanguageNode( bool WindowsResourceParser::TreeNode::addLanguageNode(
const ResourceEntryRef &Entry, uint32_t Origin, TreeNode *&Result) { const ResourceEntryRef &Entry, uint32_t Origin,
return addDataChild(Entry.getLanguage(), Entry.getMajorVersion(), std::vector<std::vector<uint8_t>> &Data, TreeNode *&Result) {
Entry.getMinorVersion(), Entry.getCharacteristics(), bool Added = addDataChild(Entry.getLanguage(), Entry.getMajorVersion(),
Origin, Result); Entry.getMinorVersion(), Entry.getCharacteristics(),
Origin, Data.size(), Result);
if (Added)
Data.push_back(Entry.getData());
return Added;
} }
bool WindowsResourceParser::TreeNode::addDataChild( bool WindowsResourceParser::TreeNode::addDataChild(
uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion, uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion,
uint32_t Characteristics, uint32_t Origin, TreeNode *&Result) { uint32_t Characteristics, uint32_t Origin, uint32_t DataIndex,
auto NewChild = TreeNode *&Result) {
createDataNode(MajorVersion, MinorVersion, Characteristics, Origin); auto NewChild = createDataNode(MajorVersion, MinorVersion, Characteristics,
Origin, DataIndex);
auto ElementInserted = IDChildren.emplace(ID, std::move(NewChild)); auto ElementInserted = IDChildren.emplace(ID, std::move(NewChild));
Result = ElementInserted.first->second.get(); Result = ElementInserted.first->second.get();
return ElementInserted.second; return ElementInserted.second;
@ -343,16 +331,15 @@ WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addIDChild(
return *(Child->second); return *(Child->second);
} }
WindowsResourceParser::TreeNode & WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addNameChild(
WindowsResourceParser::TreeNode::addNameChild(ArrayRef<UTF16> NameRef, ArrayRef<UTF16> NameRef, std::vector<std::vector<UTF16>> &StringTable) {
bool &IsNewString) {
std::string NameString; std::string NameString;
convertUTF16LEToUTF8String(NameRef, NameString); convertUTF16LEToUTF8String(NameRef, NameString);
auto Child = StringChildren.find(NameString); auto Child = StringChildren.find(NameString);
if (Child == StringChildren.end()) { if (Child == StringChildren.end()) {
auto NewChild = createStringNode(); auto NewChild = createStringNode(StringTable.size());
IsNewString = true; StringTable.push_back(NameRef);
WindowsResourceParser::TreeNode &Node = *NewChild; WindowsResourceParser::TreeNode &Node = *NewChild;
StringChildren.emplace(NameString, std::move(NewChild)); StringChildren.emplace(NameString, std::move(NewChild));
return Node; return Node;