From a6bdf751a2f995e531c4c59cf3b060dc2d3d05c3 Mon Sep 17 00:00:00 2001 From: Eric Beckmann Date: Sat, 20 May 2017 01:49:19 +0000 Subject: Add functionality to cvtres to parse all entries in res file. Summary: Added the new modules in the Object/ folder. Updated the llvm-cvtres interface as well, and added additional tests. Subscribers: llvm-commits, mgorny Differential Revision: https://reviews.llvm.org/D33180 llvm-svn: 303480 --- llvm/lib/Object/WindowsResource.cpp | 92 +++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 llvm/lib/Object/WindowsResource.cpp (limited to 'llvm/lib/Object/WindowsResource.cpp') diff --git a/llvm/lib/Object/WindowsResource.cpp b/llvm/lib/Object/WindowsResource.cpp new file mode 100644 index 00000000000..29a02b8a27d --- /dev/null +++ b/llvm/lib/Object/WindowsResource.cpp @@ -0,0 +1,92 @@ +//===-- WindowsResource.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the .res file class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/WindowsResource.h" +#include "llvm/Object/Error.h" +#include + +namespace llvm { +namespace object { + +static const char ResourceMagic[] = { + '\0', '\0', '\0', '\0', '\x20', '\0', '\0', '\0', + '\xff', '\xff', '\0', '\0', '\xff', '\xff', '\0', '\0'}; + +static const char NullEntry[16] = {'\0'}; + +#define RETURN_IF_ERROR(X) \ + if (auto EC = X) \ + return EC; + +WindowsResource::WindowsResource(MemoryBufferRef Source) + : Binary(Binary::ID_WinRes, Source) { + size_t LeadingSize = sizeof(ResourceMagic) + sizeof(NullEntry); + BBS = BinaryByteStream(Data.getBuffer().drop_front(LeadingSize), + support::little); +} + +WindowsResource::~WindowsResource() = default; + +Expected> +WindowsResource::createWindowsResource(MemoryBufferRef Source) { + if (Source.getBufferSize() < sizeof(ResourceMagic) + sizeof(NullEntry)) + return make_error( + "File too small to be a resource file", + object_error::invalid_file_type); + std::unique_ptr Ret(new WindowsResource(Source)); + return std::move(Ret); +} + +Expected WindowsResource::getHeadEntry() { + Error Err = Error::success(); + auto Ref = ResourceEntryRef(BinaryStreamRef(BBS), this, Err); + if (Err) + return std::move(Err); + return Ref; +} + +ResourceEntryRef::ResourceEntryRef(BinaryStreamRef Ref, + const WindowsResource *Owner, Error &Err) + : Reader(Ref), OwningRes(Owner) { + if (loadNext()) + Err = make_error("Could not read first entry.", + object_error::unexpected_eof); +} + +Error ResourceEntryRef::moveNext(bool &End) { + // Reached end of all the entries. + if (Reader.bytesRemaining() == 0) { + End = true; + return Error::success(); + } + RETURN_IF_ERROR(loadNext()); + + 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)); + RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t))); + return Error::success(); +} + +} // namespace object +} // namespace llvm -- cgit v1.2.3