summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Object/WindowsResource.cpp
diff options
context:
space:
mode:
authorEric Beckmann <ecbeckmann@google.com>2017-05-30 18:19:06 +0000
committerEric Beckmann <ecbeckmann@google.com>2017-05-30 18:19:06 +0000
commit72fb6a87fb2e2f87a192aa9d80eefc484bf3e41a (patch)
tree5bc310d384fcf4991550c9a31a98ea889f6b3c02 /llvm/lib/Object/WindowsResource.cpp
parent4cec434a1bd3d30c263bdb4e07ecb4db32caee6c (diff)
downloadbcm5719-llvm-72fb6a87fb2e2f87a192aa9d80eefc484bf3e41a.tar.gz
bcm5719-llvm-72fb6a87fb2e2f87a192aa9d80eefc484bf3e41a.zip
Adding parsing ability for .res file.
Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D33566 llvm-svn: 304225
Diffstat (limited to 'llvm/lib/Object/WindowsResource.cpp')
-rw-r--r--llvm/lib/Object/WindowsResource.cpp157
1 files changed, 145 insertions, 12 deletions
diff --git a/llvm/lib/Object/WindowsResource.cpp b/llvm/lib/Object/WindowsResource.cpp
index b5256346909..9dea5539858 100644
--- a/llvm/lib/Object/WindowsResource.cpp
+++ b/llvm/lib/Object/WindowsResource.cpp
@@ -12,20 +12,22 @@
//===----------------------------------------------------------------------===//
#include "llvm/Object/WindowsResource.h"
-#include "llvm/Object/Error.h"
+#include "llvm/Support/COFF.h"
#include <system_error>
namespace llvm {
namespace object {
+#define RETURN_IF_ERROR(X) \
+ if (auto EC = X) \
+ return std::move(EC);
+
+const uint32_t MIN_HEADER_SIZE = 7 * sizeof(uint32_t) + 2 * sizeof(uint16_t);
+
static const size_t ResourceMagicSize = 16;
static const size_t NullEntrySize = 16;
-#define RETURN_IF_ERROR(X) \
- if (auto EC = X) \
- return EC;
-
WindowsResource::WindowsResource(MemoryBufferRef Source)
: Binary(Binary::ID_WinRes, Source) {
size_t LeadingSize = ResourceMagicSize + NullEntrySize;
@@ -33,8 +35,6 @@ WindowsResource::WindowsResource(MemoryBufferRef Source)
support::little);
}
-WindowsResource::~WindowsResource() = default;
-
Expected<std::unique_ptr<WindowsResource>>
WindowsResource::createWindowsResource(MemoryBufferRef Source) {
if (Source.getBufferSize() < ResourceMagicSize + NullEntrySize)
@@ -72,19 +72,152 @@ Error ResourceEntryRef::moveNext(bool &End) {
return Error::success();
}
+static Error readStringOrId(BinaryStreamReader &Reader, uint16_t &ID,
+ ArrayRef<UTF16> &Str, bool &IsString) {
+ uint16_t IDFlag;
+ RETURN_IF_ERROR(Reader.readInteger(IDFlag));
+ IsString = IDFlag != 0xffff;
+
+ if (IsString) {
+ Reader.setOffset(
+ Reader.getOffset() -
+ sizeof(uint16_t)); // Re-read the bytes which we used to check the flag.
+ RETURN_IF_ERROR(Reader.readWideString(Str));
+ } else
+ RETURN_IF_ERROR(Reader.readInteger(ID));
+
+ return Error::success();
+}
+
Error ResourceEntryRef::loadNext() {
uint32_t DataSize;
RETURN_IF_ERROR(Reader.readInteger(DataSize));
uint32_t HeaderSize;
RETURN_IF_ERROR(Reader.readInteger(HeaderSize));
- // The data and header size ints are themselves part of the header, so we must
- // subtract them from the size.
- RETURN_IF_ERROR(
- Reader.readStreamRef(HeaderBytes, HeaderSize - 2 * sizeof(uint32_t)));
- RETURN_IF_ERROR(Reader.readStreamRef(DataBytes, DataSize));
+
+ if (HeaderSize < MIN_HEADER_SIZE)
+ return make_error<GenericBinaryError>("Header size is too small.",
+ object_error::parse_failed);
+
+ RETURN_IF_ERROR(readStringOrId(Reader, TypeID, Type, IsStringType));
+
+ RETURN_IF_ERROR(readStringOrId(Reader, NameID, Name, IsStringName));
+
+ RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t)));
+
+ RETURN_IF_ERROR(Reader.readObject(Suffix));
+
+ RETURN_IF_ERROR(Reader.readArray(Data, DataSize));
+
RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t)));
+
return Error::success();
}
+WindowsResourceParser::WindowsResourceParser() {}
+
+Error WindowsResourceParser::parse(WindowsResource *WR) {
+ auto EntryOrErr = WR->getHeadEntry();
+ if (!EntryOrErr)
+ return EntryOrErr.takeError();
+
+ ResourceEntryRef Entry = EntryOrErr.get();
+ bool End = false;
+
+ while (!End) {
+
+ Root.addEntry(Entry);
+
+ RETURN_IF_ERROR(Entry.moveNext(End));
+ }
+
+ return Error::success();
+}
+
+void WindowsResourceParser::printTree() const {
+ ScopedPrinter Writer(outs());
+ Root.print(Writer, "Resource Tree");
+}
+
+void WindowsResourceParser::TreeNode::addEntry(const ResourceEntryRef &Entry) {
+ TreeNode &TypeNode = addTypeNode(Entry);
+ TreeNode &NameNode = TypeNode.addNameNode(Entry);
+ NameNode.addLanguageNode(Entry);
+}
+
+WindowsResourceParser::TreeNode::TreeNode(uint32_t ID) : ID(ID) {}
+
+WindowsResourceParser::TreeNode::TreeNode(ArrayRef<UTF16> NameRef)
+ : Name(NameRef) {}
+
+WindowsResourceParser::TreeNode &
+WindowsResourceParser::TreeNode::addTypeNode(const ResourceEntryRef &Entry) {
+ if (Entry.checkTypeString())
+ return addChild(Entry.getTypeString());
+ else
+ return addChild(Entry.getTypeID());
+}
+
+WindowsResourceParser::TreeNode &
+WindowsResourceParser::TreeNode::addNameNode(const ResourceEntryRef &Entry) {
+ if (Entry.checkNameString())
+ return addChild(Entry.getNameString());
+ else
+ return addChild(Entry.getNameID());
+}
+
+WindowsResourceParser::TreeNode &
+WindowsResourceParser::TreeNode::addLanguageNode(
+ const ResourceEntryRef &Entry) {
+ return addChild(Entry.getLanguage());
+}
+
+WindowsResourceParser::TreeNode &
+WindowsResourceParser::TreeNode::addChild(uint32_t ID) {
+ auto Child = IDChildren.find(ID);
+ if (Child == IDChildren.end()) {
+ auto NewChild = llvm::make_unique<WindowsResourceParser::TreeNode>(ID);
+ WindowsResourceParser::TreeNode &Node = *NewChild;
+ IDChildren.emplace(ID, std::move(NewChild));
+ return Node;
+ } else
+ return *(Child->second);
+}
+
+WindowsResourceParser::TreeNode &
+WindowsResourceParser::TreeNode::addChild(ArrayRef<UTF16> NameRef) {
+ std::string NameString;
+ ArrayRef<UTF16> CorrectedName;
+ if (llvm::sys::IsBigEndianHost) {
+ std::vector<UTF16> EndianCorrectedName;
+ EndianCorrectedName.resize(NameRef.size() + 1);
+ std::copy(NameRef.begin(), NameRef.end(), EndianCorrectedName.begin() + 1);
+ EndianCorrectedName[0] = UNI_UTF16_BYTE_ORDER_MARK_SWAPPED;
+ CorrectedName = makeArrayRef(EndianCorrectedName);
+ } else
+ CorrectedName = NameRef;
+ llvm::convertUTF16ToUTF8String(CorrectedName, NameString);
+
+ auto Child = StringChildren.find(NameString);
+ if (Child == StringChildren.end()) {
+ auto NewChild = llvm::make_unique<WindowsResourceParser::TreeNode>(NameRef);
+ WindowsResourceParser::TreeNode &Node = *NewChild;
+ StringChildren.emplace(NameString, std::move(NewChild));
+ return Node;
+ } else
+ return *(Child->second);
+}
+
+void WindowsResourceParser::TreeNode::print(ScopedPrinter &Writer,
+ StringRef Name) const {
+ ListScope NodeScope(Writer, Name);
+ for (auto const &Child : StringChildren) {
+ Child.second->print(Writer, Child.first);
+ }
+ for (auto const &Child : IDChildren) {
+ Child.second->print(Writer, std::to_string(Child.first));
+ }
+}
+
} // namespace object
} // namespace llvm
OpenPOWER on IntegriCloud