]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Object/WindowsResource.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r304222, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Object / WindowsResource.cpp
1 //===-- WindowsResource.cpp -------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the .res file class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Object/WindowsResource.h"
15 #include "llvm/Object/Error.h"
16 #include <system_error>
17
18 namespace llvm {
19 namespace object {
20
21 static const size_t ResourceMagicSize = 16;
22
23 static const size_t NullEntrySize = 16;
24
25 #define RETURN_IF_ERROR(X)                                                     \
26   if (auto EC = X)                                                             \
27     return EC;
28
29 WindowsResource::WindowsResource(MemoryBufferRef Source)
30     : Binary(Binary::ID_WinRes, Source) {
31   size_t LeadingSize = ResourceMagicSize + NullEntrySize;
32   BBS = BinaryByteStream(Data.getBuffer().drop_front(LeadingSize),
33                          support::little);
34 }
35
36 WindowsResource::~WindowsResource() = default;
37
38 Expected<std::unique_ptr<WindowsResource>>
39 WindowsResource::createWindowsResource(MemoryBufferRef Source) {
40   if (Source.getBufferSize() < ResourceMagicSize + NullEntrySize)
41     return make_error<GenericBinaryError>(
42         "File too small to be a resource file",
43         object_error::invalid_file_type);
44   std::unique_ptr<WindowsResource> Ret(new WindowsResource(Source));
45   return std::move(Ret);
46 }
47
48 Expected<ResourceEntryRef> WindowsResource::getHeadEntry() {
49   Error Err = Error::success();
50   auto Ref = ResourceEntryRef(BinaryStreamRef(BBS), this, Err);
51   if (Err)
52     return std::move(Err);
53   return Ref;
54 }
55
56 ResourceEntryRef::ResourceEntryRef(BinaryStreamRef Ref,
57                                    const WindowsResource *Owner, Error &Err)
58     : Reader(Ref), OwningRes(Owner) {
59   if (loadNext())
60     Err = make_error<GenericBinaryError>("Could not read first entry.",
61                                          object_error::unexpected_eof);
62 }
63
64 Error ResourceEntryRef::moveNext(bool &End) {
65   // Reached end of all the entries.
66   if (Reader.bytesRemaining() == 0) {
67     End = true;
68     return Error::success();
69   }
70   RETURN_IF_ERROR(loadNext());
71
72   return Error::success();
73 }
74
75 Error ResourceEntryRef::loadNext() {
76   uint32_t DataSize;
77   RETURN_IF_ERROR(Reader.readInteger(DataSize));
78   uint32_t HeaderSize;
79   RETURN_IF_ERROR(Reader.readInteger(HeaderSize));
80   // The data and header size ints are themselves part of the header, so we must
81   // subtract them from the size.
82   RETURN_IF_ERROR(
83       Reader.readStreamRef(HeaderBytes, HeaderSize - 2 * sizeof(uint32_t)));
84   RETURN_IF_ERROR(Reader.readStreamRef(DataBytes, DataSize));
85   RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t)));
86   return Error::success();
87 }
88
89 } // namespace object
90 } // namespace llvm