Index: lld/COFF/DriverUtils.cpp =================================================================== --- lld/COFF/DriverUtils.cpp +++ lld/COFF/DriverUtils.cpp @@ -21,6 +21,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Object/COFF.h" +#include "llvm/Object/WindowsResource.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" @@ -592,40 +593,24 @@ // using cvtres.exe. std::unique_ptr convertResToCOFF(const std::vector &MBs) { - // Create an output file path. - TemporaryFile File("resource-file", "obj"); + object::WindowsResourceParser Parser; - // Execute cvtres.exe. - Executor E("cvtres.exe"); - E.add("/machine:" + machineToStr(Config->Machine)); - E.add("/readonly"); - E.add("/nologo"); - E.add("/out:" + Twine(File.Path)); - - // We must create new files because the memory buffers we have may have no - // underlying file still existing on the disk. - // It happens if it was created from a TemporaryFile, which usually delete - // the file just after creating the MemoryBuffer. - std::vector ResFiles; - ResFiles.reserve(MBs.size()); for (MemoryBufferRef MB : MBs) { - // We store the temporary file in a vector to avoid deletion - // before running cvtres - ResFiles.emplace_back("resource-file", "res"); - TemporaryFile& ResFile = ResFiles.back(); - // Write the content of the resource in a temporary file - std::error_code EC; - raw_fd_ostream OS(ResFile.Path, EC, sys::fs::F_None); - if (EC) - fatal(EC, "failed to open " + ResFile.Path); - OS << MB.getBuffer(); - OS.close(); - - E.add(ResFile.Path); + auto Binary = check(object::createBinary(MB)); + object::WindowsResource *RF = + dyn_cast(Binary.get()); + if (!RF) + fatal("Cannot compile non-resource file as resource"); + if (auto EC = Parser.parse(RF)) + fatal(EC, "Failed to parse .res file."); } - E.run(); - return File.getMemoryBuffer(); + std::unique_ptr OutputBuffer; + if (auto EC = llvm::object::writeWindowsResourceCOFF(OutputBuffer, + Config->Machine, Parser)) + fatal(EC, "Failed to write resources to buffer."); + + return OutputBuffer; } // Run MSVC link.exe for given in-memory object files. Index: lld/COFF/Writer.cpp =================================================================== --- lld/COFF/Writer.cpp +++ lld/COFF/Writer.cpp @@ -287,6 +287,7 @@ SC->printDiscardedMessage(); continue; } + llvm::outs() << "binning " << C->getSectionName() << "\n"; Map[C->getSectionName()].push_back(C); } @@ -298,7 +299,9 @@ for (auto Pair : Map) { StringRef Name = getOutputSection(Pair.first); OutputSection *&Sec = Sections[Name]; + llvm::outs() << "got " << Name << "\n"; if (!Sec) { + llvm::outs() << "pushing\n"; Sec = make(Name); OutputSections.push_back(Sec); } @@ -556,6 +559,9 @@ for (OutputSection *Sec : OutputSections) { if (Sec->getName() == ".reloc") addBaserels(Sec); + char hexRVA[20]; + sprintf(hexRVA, "%x", RVA); + llvm::outs() << Sec->getName() << ": " << hexRVA << "\n"; Sec->setRVA(RVA); Sec->setFileOffset(FileSize); RVA += alignTo(Sec->getVirtualSize(), PageSize); Index: lld/test/COFF/resource.test =================================================================== --- lld/test/COFF/resource.test +++ lld/test/COFF/resource.test @@ -1,5 +1,3 @@ -# REQUIRES: winres - # RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj # RUN: lld-link /out:%t.exe /entry:main %t.obj %p/Inputs/resource.res Index: lld/test/lit.cfg =================================================================== --- lld/test/lit.cfg +++ lld/test/lit.cfg @@ -261,9 +261,3 @@ # Set a fake constant version so that we get consitent output. config.environment['LLD_VERSION'] = 'LLD 1.0' - -# Check if Windows resource file compiler exists. -cvtres = lit.util.which('cvtres', config.environment['PATH']) -rc = lit.util.which('rc', config.environment['PATH']) -if cvtres and rc: - config.available_features.add('winres') Index: llvm/include/llvm/Object/WindowsResource.h =================================================================== --- llvm/include/llvm/Object/WindowsResource.h +++ llvm/include/llvm/Object/WindowsResource.h @@ -45,14 +45,10 @@ namespace llvm { -class FileOutputBuffer; - namespace object { class WindowsResource; -enum class Machine { UNKNOWN, ARM, X64, X86 }; - class ResourceEntryRef { public: Error moveNext(bool &End); @@ -185,7 +181,8 @@ std::vector> StringTable; }; -Error writeWindowsResourceCOFF(StringRef OutputFile, Machine MachineType, +Error writeWindowsResourceCOFF(std::unique_ptr &OutputBuffer, + llvm::COFF::MachineTypes MachineType, const WindowsResourceParser &Parser); } // namespace object Index: llvm/lib/Object/WindowsResource.cpp =================================================================== --- llvm/lib/Object/WindowsResource.cpp +++ llvm/lib/Object/WindowsResource.cpp @@ -21,6 +21,8 @@ #include #include +using namespace llvm; + namespace llvm { namespace object { @@ -305,7 +307,8 @@ class WindowsResourceCOFFWriter { public: - WindowsResourceCOFFWriter(StringRef OutputFile, Machine MachineType, + WindowsResourceCOFFWriter(std::unique_ptr &OutputBuffer, + llvm::COFF::MachineTypes MachineType, const WindowsResourceParser &Parser, Error &E); Error write(); @@ -323,10 +326,10 @@ void writeDirectoryTree(); void writeDirectoryStringTable(); void writeFirstSectionRelocations(); - std::unique_ptr Buffer; - uint8_t *BufferStart; + std::unique_ptr &OutputBuffer; + char *BufferStart; uint64_t CurrentOffset = 0; - Machine MachineType; + llvm::COFF::MachineTypes MachineType; const WindowsResourceParser::TreeNode &Resources; const ArrayRef> Data; uint64_t FileSize; @@ -343,20 +346,15 @@ }; WindowsResourceCOFFWriter::WindowsResourceCOFFWriter( - StringRef OutputFile, Machine MachineType, - const WindowsResourceParser &Parser, Error &E) - : MachineType(MachineType), Resources(Parser.getTree()), - Data(Parser.getData()), StringTable(Parser.getStringTable()) { + std::unique_ptr &OutputBuffer, + llvm::COFF::MachineTypes MachineType, const WindowsResourceParser &Parser, + Error &E) + : OutputBuffer(OutputBuffer), MachineType(MachineType), + Resources(Parser.getTree()), Data(Parser.getData()), + StringTable(Parser.getStringTable()) { performFileLayout(); - ErrorOr> BufferOrErr = - FileOutputBuffer::create(OutputFile, FileSize); - if (!BufferOrErr) { - E = errorCodeToError(BufferOrErr.getError()); - return; - } - - Buffer = std::move(*BufferOrErr); + OutputBuffer = std::move(MemoryBuffer::getNewMemBuffer(FileSize)); } void WindowsResourceCOFFWriter::performFileLayout() { @@ -421,7 +419,7 @@ } Error WindowsResourceCOFFWriter::write() { - BufferStart = Buffer->getBufferStart(); + BufferStart = const_cast(OutputBuffer->getBufferStart()); writeCOFFHeader(); writeFirstSectionHeader(); @@ -431,10 +429,6 @@ writeSymbolTable(); writeStringTable(); - if (auto EC = Buffer->commit()) { - return errorCodeToError(EC); - } - return Error::success(); } @@ -443,13 +437,13 @@ auto *Header = reinterpret_cast(BufferStart); switch (MachineType) { - case Machine::ARM: + case COFF::IMAGE_FILE_MACHINE_ARMNT: Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT; break; - case Machine::X64: + case COFF::IMAGE_FILE_MACHINE_AMD64: Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_AMD64; break; - case Machine::X86: + case COFF::IMAGE_FILE_MACHINE_I386: Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_I386; break; default: @@ -481,7 +475,8 @@ SectionOneHeader->Characteristics = llvm::COFF::IMAGE_SCN_ALIGN_1BYTES; SectionOneHeader->Characteristics += llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; - SectionOneHeader->Characteristics += llvm::COFF::IMAGE_SCN_MEM_DISCARDABLE; + SectionOneHeader->Characteristics += + llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; SectionOneHeader->Characteristics += llvm::COFF::IMAGE_SCN_MEM_READ; } @@ -715,13 +710,13 @@ Reloc->VirtualAddress = RelocationAddresses[i]; Reloc->SymbolTableIndex = NextSymbolIndex++; switch (MachineType) { - case Machine::ARM: + case COFF::IMAGE_FILE_MACHINE_ARMNT: Reloc->Type = llvm::COFF::IMAGE_REL_ARM_ADDR32NB; break; - case Machine::X64: + case COFF::IMAGE_FILE_MACHINE_AMD64: Reloc->Type = llvm::COFF::IMAGE_REL_AMD64_ADDR32NB; break; - case Machine::X86: + case COFF::IMAGE_FILE_MACHINE_I386: Reloc->Type = llvm::COFF::IMAGE_REL_I386_DIR32NB; break; default: @@ -731,10 +726,11 @@ } } -Error writeWindowsResourceCOFF(StringRef OutputFile, Machine MachineType, +Error writeWindowsResourceCOFF(std::unique_ptr &OutputBuffer, + COFF::MachineTypes MachineType, const WindowsResourceParser &Parser) { Error E = Error::success(); - WindowsResourceCOFFWriter Writer(OutputFile, MachineType, Parser, E); + WindowsResourceCOFFWriter Writer(OutputBuffer, MachineType, Parser, E); if (E) return E; return Writer.write(); Index: llvm/tools/llvm-cvtres/llvm-cvtres.cpp =================================================================== --- llvm/tools/llvm-cvtres/llvm-cvtres.cpp +++ llvm/tools/llvm-cvtres/llvm-cvtres.cpp @@ -114,21 +114,21 @@ bool Verbose = InputArgs.hasArg(OPT_VERBOSE); - Machine MachineType; + COFF::MachineTypes MachineType; if (InputArgs.hasArg(OPT_MACHINE)) { std::string MachineString = InputArgs.getLastArgValue(OPT_MACHINE).upper(); - MachineType = StringSwitch(MachineString) - .Case("ARM", Machine::ARM) - .Case("X64", Machine::X64) - .Case("X86", Machine::X86) - .Default(Machine::UNKNOWN); - if (MachineType == Machine::UNKNOWN) + MachineType = StringSwitch(MachineString) + .Case("ARM", COFF::IMAGE_FILE_MACHINE_ARMNT) + .Case("X64", COFF::IMAGE_FILE_MACHINE_AMD64) + .Case("X86", COFF::IMAGE_FILE_MACHINE_I386) + .Default(COFF::IMAGE_FILE_MACHINE_UNKNOWN); + if (MachineType == COFF::IMAGE_FILE_MACHINE_UNKNOWN) reportError("Unsupported machine architecture"); } else { if (Verbose) outs() << "Machine architecture not specified; assumed X64.\n"; - MachineType = Machine::X64; + MachineType = COFF::IMAGE_FILE_MACHINE_AMD64; } std::vector InputFiles = InputArgs.getAllArgValues(OPT_INPUT); @@ -149,10 +149,10 @@ if (Verbose) { outs() << "Machine: "; switch (MachineType) { - case Machine::ARM: + case COFF::IMAGE_FILE_MACHINE_ARMNT: outs() << "ARM\n"; break; - case Machine::X86: + case COFF::IMAGE_FILE_MACHINE_I386: outs() << "X86\n"; break; default: @@ -196,8 +196,18 @@ Parser.printTree(errs()); } - error( - llvm::object::writeWindowsResourceCOFF(OutputFile, MachineType, Parser)); + std::unique_ptr OutputBuffer; + error(llvm::object::writeWindowsResourceCOFF(OutputBuffer, MachineType, + Parser)); + auto FileOrErr = + FileOutputBuffer::create(OutputFile, OutputBuffer->getBufferSize()); + if (!FileOrErr) + reportError(OutputFile, FileOrErr.getError()); + std::unique_ptr FileBuffer = std::move(*FileOrErr); + std::copy(OutputBuffer->getBufferStart(), OutputBuffer->getBufferEnd(), + FileBuffer->getBufferStart()); + ; + error(FileBuffer->commit()); if (Verbose) { Expected> BinaryOrErr =