diff options
Diffstat (limited to 'gnu/llvm/lib/Object/WindowsResource.cpp')
| -rw-r--r-- | gnu/llvm/lib/Object/WindowsResource.cpp | 65 |
1 files changed, 35 insertions, 30 deletions
diff --git a/gnu/llvm/lib/Object/WindowsResource.cpp b/gnu/llvm/lib/Object/WindowsResource.cpp index 246eee5ddb3..271224ec631 100644 --- a/gnu/llvm/lib/Object/WindowsResource.cpp +++ b/gnu/llvm/lib/Object/WindowsResource.cpp @@ -14,10 +14,10 @@ #include "llvm/Object/WindowsResource.h" #include "llvm/Object/COFF.h" #include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MathExtras.h" #include <ctime> #include <queue> -#include <sstream> #include <system_error> using namespace llvm; @@ -57,19 +57,22 @@ WindowsResource::createWindowsResource(MemoryBufferRef Source) { } Expected<ResourceEntryRef> WindowsResource::getHeadEntry() { - Error Err = Error::success(); - auto Ref = ResourceEntryRef(BinaryStreamRef(BBS), this, Err); - if (Err) - return std::move(Err); - return Ref; + if (BBS.getLength() < sizeof(WinResHeaderPrefix) + sizeof(WinResHeaderSuffix)) + return make_error<EmptyResError>(".res contains no entries", + object_error::unexpected_eof); + return ResourceEntryRef::create(BinaryStreamRef(BBS), this); } ResourceEntryRef::ResourceEntryRef(BinaryStreamRef Ref, - const WindowsResource *Owner, Error &Err) - : Reader(Ref), OwningRes(Owner) { - if (loadNext()) - Err = make_error<GenericBinaryError>("Could not read first entry.\n", - object_error::unexpected_eof); + const WindowsResource *Owner) + : Reader(Ref) {} + +Expected<ResourceEntryRef> +ResourceEntryRef::create(BinaryStreamRef BSR, const WindowsResource *Owner) { + auto Ref = ResourceEntryRef(BSR, Owner); + if (auto E = Ref.loadNext()) + return std::move(E); + return Ref; } Error ResourceEntryRef::moveNext(bool &End) { @@ -127,8 +130,20 @@ WindowsResourceParser::WindowsResourceParser() : Root(false) {} Error WindowsResourceParser::parse(WindowsResource *WR) { auto EntryOrErr = WR->getHeadEntry(); - if (!EntryOrErr) - return EntryOrErr.takeError(); + if (!EntryOrErr) { + auto E = EntryOrErr.takeError(); + if (E.isA<EmptyResError>()) { + // Check if the .res file contains no entries. In this case we don't have + // to throw an error but can rather just return without parsing anything. + // This applies for files which have a valid PE header magic and the + // mandatory empty null resource entry. Files which do not fit this + // criteria would have already been filtered out by + // WindowsResource::createWindowsResource(). + consumeError(std::move(E)); + return Error::success(); + } + return E; + } ResourceEntryRef Entry = EntryOrErr.get(); bool End = false; @@ -426,19 +441,7 @@ std::unique_ptr<MemoryBuffer> WindowsResourceCOFFWriter::write() { void WindowsResourceCOFFWriter::writeCOFFHeader() { // Write the COFF header. auto *Header = reinterpret_cast<coff_file_header *>(BufferStart); - switch (MachineType) { - case COFF::IMAGE_FILE_MACHINE_ARMNT: - Header->Machine = COFF::IMAGE_FILE_MACHINE_ARMNT; - break; - case COFF::IMAGE_FILE_MACHINE_AMD64: - Header->Machine = COFF::IMAGE_FILE_MACHINE_AMD64; - break; - case COFF::IMAGE_FILE_MACHINE_I386: - Header->Machine = COFF::IMAGE_FILE_MACHINE_I386; - break; - default: - Header->Machine = COFF::IMAGE_FILE_MACHINE_UNKNOWN; - } + Header->Machine = MachineType; Header->NumberOfSections = 2; Header->TimeDateStamp = getTime(); Header->PointerToSymbolTable = SymbolTableOffset; @@ -558,10 +561,9 @@ void WindowsResourceCOFFWriter::writeSymbolTable() { // Now write a symbol for each relocation. for (unsigned i = 0; i < Data.size(); i++) { - char RelocationName[9]; - sprintf(RelocationName, "$R%06X", DataOffsets[i]); + auto RelocationName = formatv("$R{0:X-6}", i & 0xffffff).sstr<COFF::NameSize>(); Symbol = reinterpret_cast<coff_symbol16 *>(BufferStart + CurrentOffset); - strncpy(Symbol->Name.ShortName, RelocationName, (size_t)COFF::NameSize); + memcpy(Symbol->Name.ShortName, RelocationName.data(), (size_t) COFF::NameSize); Symbol->Value = DataOffsets[i]; Symbol->SectionNumber = 2; Symbol->Type = COFF::IMAGE_SYM_DTYPE_NULL; @@ -699,8 +701,11 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() { case COFF::IMAGE_FILE_MACHINE_I386: Reloc->Type = COFF::IMAGE_REL_I386_DIR32NB; break; + case COFF::IMAGE_FILE_MACHINE_ARM64: + Reloc->Type = COFF::IMAGE_REL_ARM64_ADDR32NB; + break; default: - Reloc->Type = 0; + llvm_unreachable("unknown machine type"); } CurrentOffset += sizeof(coff_relocation); } |
