diff options
Diffstat (limited to 'lld/COFF/DriverUtils.cpp')
-rw-r--r-- | lld/COFF/DriverUtils.cpp | 109 |
1 files changed, 49 insertions, 60 deletions
diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index 14b40f2c217..1d2c8811386 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -20,7 +20,6 @@ #include "Symbols.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/BinaryFormat/COFF.h" #include "llvm/Object/COFF.h" #include "llvm/Object/WindowsResource.h" #include "llvm/Option/Arg.h" @@ -28,7 +27,6 @@ #include "llvm/Option/Option.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" @@ -44,9 +42,6 @@ namespace lld { namespace coff { namespace { -const uint16_t SUBLANG_ENGLISH_US = 0x0409; -const uint16_t RT_MANIFEST = 24; - class Executor { public: explicit Executor(StringRef S) : Prog(Saver.save(S)) {} @@ -266,6 +261,26 @@ void parseManifestUAC(StringRef Arg) { } } +// Quote each line with "". Existing double-quote is converted +// to two double-quotes. +static void quoteAndPrint(raw_ostream &Out, StringRef S) { + while (!S.empty()) { + StringRef Line; + std::tie(Line, S) = S.split("\n"); + if (Line.empty()) + continue; + Out << '\"'; + for (int I = 0, E = Line.size(); I != E; ++I) { + if (Line[I] == '\"') { + Out << "\"\""; + } else { + Out << Line[I]; + } + } + Out << "\"\n"; + } +} + // An RAII temporary file class that automatically removes a temporary file. namespace { class TemporaryFile { @@ -379,64 +394,38 @@ static std::string createManifestXml() { return readFile(File2.Path); } -static std::unique_ptr<MemoryBuffer> -createMemoryBufferForManifestRes(size_t ManifestSize) { - size_t ResSize = alignTo(object::WIN_RES_MAGIC_SIZE + - object::WIN_RES_NULL_ENTRY_SIZE + - sizeof(object::WinResHeaderPrefix) + - sizeof(object::WinResIDs) + - sizeof(object::WinResHeaderSuffix) + - ManifestSize, - object::WIN_RES_DATA_ALIGNMENT); - return MemoryBuffer::getNewMemBuffer(ResSize); -} - -static void writeResFileHeader(char *&Buf) { - memcpy(Buf, COFF::WinResMagic, sizeof(COFF::WinResMagic)); - Buf += sizeof(COFF::WinResMagic); - memset(Buf, 0, object::WIN_RES_NULL_ENTRY_SIZE); - Buf += object::WIN_RES_NULL_ENTRY_SIZE; -} - -static void writeResEntryHeader(char *&Buf, size_t ManifestSize) { - // Write the prefix. - auto *Prefix = reinterpret_cast<object::WinResHeaderPrefix *>(Buf); - Prefix->DataSize = ManifestSize; - Prefix->HeaderSize = sizeof(object::WinResHeaderPrefix) + - sizeof(object::WinResIDs) + - sizeof(object::WinResHeaderSuffix); - Buf += sizeof(object::WinResHeaderPrefix); - - // Write the Type/Name IDs. - auto *IDs = reinterpret_cast<object::WinResIDs *>(Buf); - IDs->setType(RT_MANIFEST); - IDs->setName(Config->ManifestID); - Buf += sizeof(object::WinResIDs); - - // Write the suffix. - auto *Suffix = reinterpret_cast<object::WinResHeaderSuffix *>(Buf); - Suffix->DataVersion = 0; - Suffix->MemoryFlags = object::WIN_RES_PURE_MOVEABLE; - Suffix->Language = SUBLANG_ENGLISH_US; - Suffix->Version = 0; - Suffix->Characteristics = 0; - Buf += sizeof(object::WinResHeaderSuffix); -} - // Create a resource file containing a manifest XML. std::unique_ptr<MemoryBuffer> createManifestRes() { - std::string Manifest = createManifestXml(); - - std::unique_ptr<MemoryBuffer> Res = - createMemoryBufferForManifestRes(Manifest.size()); + // Create a temporary file for the resource script file. + TemporaryFile RCFile("manifest", "rc"); - char *Buf = const_cast<char *>(Res->getBufferStart()); - writeResFileHeader(Buf); - writeResEntryHeader(Buf, Manifest.size()); - - // Copy the manifest data into the .res file. - std::copy(Manifest.begin(), Manifest.end(), Buf); - return Res; + // Open the temporary file for writing. + std::error_code EC; + raw_fd_ostream Out(RCFile.Path, EC, sys::fs::F_Text); + if (EC) + fatal(EC, "failed to open " + RCFile.Path); + + // Write resource script to the RC file. + Out << "#define LANG_ENGLISH 9\n" + << "#define SUBLANG_DEFAULT 1\n" + << "#define APP_MANIFEST " << Config->ManifestID << "\n" + << "#define RT_MANIFEST 24\n" + << "LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT\n" + << "APP_MANIFEST RT_MANIFEST {\n"; + quoteAndPrint(Out, createManifestXml()); + Out << "}\n"; + Out.close(); + + // Create output resource file. + TemporaryFile ResFile("output-resource", "res"); + + Executor E("rc.exe"); + E.add("/fo"); + E.add(ResFile.Path); + E.add("/nologo"); + E.add(RCFile.Path); + E.run(); + return ResFile.getMemoryBuffer(); } void createSideBySideManifest() { |