[lld] r307191 - Revert "Revert "Replace trivial use of external rc.exe by writing our own .res file.""

Eric Beckmann via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 5 12:04:48 PDT 2017


Author: ecbeckmann
Date: Wed Jul  5 12:04:48 2017
New Revision: 307191

URL: http://llvm.org/viewvc/llvm-project?rev=307191&view=rev
Log:
Revert "Revert "Replace trivial use of external rc.exe by writing our own .res file.""

This reverts commit 8c8dce3b8f15d6ebaefc35ce88f15a85c8cdbd6e.

Modified:
    lld/trunk/COFF/DriverUtils.cpp
    lld/trunk/test/COFF/manifestinput.test
    lld/trunk/test/lit.cfg

Modified: lld/trunk/COFF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DriverUtils.cpp?rev=307191&r1=307190&r2=307191&view=diff
==============================================================================
--- lld/trunk/COFF/DriverUtils.cpp (original)
+++ lld/trunk/COFF/DriverUtils.cpp Wed Jul  5 12:04:48 2017
@@ -20,6 +20,7 @@
 #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"
@@ -27,6 +28,7 @@
 #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"
@@ -42,6 +44,9 @@ 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)) {}
@@ -261,26 +266,6 @@ 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 {
@@ -394,38 +379,64 @@ 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() {
-  // Create a temporary file for the resource script file.
-  TemporaryFile RCFile("manifest", "rc");
+  std::string Manifest = createManifestXml();
 
-  // 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);
+  std::unique_ptr<MemoryBuffer> Res =
+      createMemoryBufferForManifestRes(Manifest.size());
 
-  // 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();
+  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;
 }
 
 void createSideBySideManifest() {

Modified: lld/trunk/test/COFF/manifestinput.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/manifestinput.test?rev=307191&r1=307190&r2=307191&view=diff
==============================================================================
--- lld/trunk/test/COFF/manifestinput.test (original)
+++ lld/trunk/test/COFF/manifestinput.test Wed Jul  5 12:04:48 2017
@@ -8,3 +8,28 @@
 
 CHECK: <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 CHECK: <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity></dependentAssembly></dependency><trustInfo><security><requestedPrivileges><requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security></trustInfo></assembly>
+
+# RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main \
+# RUN:   /manifest:embed \
+# RUN:   /manifestuac:"level='requireAdministrator'" \
+# RUN:   /manifestinput:%p/Inputs/manifestinput.test %t.obj
+# RUN: llvm-readobj -coff-resources -file-headers %t.exe | FileCheck %s \
+# RUN:   -check-prefix TEST_EMBED
+
+TEST_EMBED:          ResourceTableRVA: 0x1000
+TEST_EMBED-NEXT:     ResourceTableSize: 0x298
+TEST_EMBED-DAG:      Resources [
+TEST_EMBED-NEXT:       Total Number of Resources: 1 
+TEST_EMBED-DAG:        Number of String Entries: 0
+TEST_EMBED-NEXT:       Number of ID Entries: 1
+TEST_EMBED-NEXT:       Type: kRT_MANIFEST (ID 24) [
+TEST_EMBED-NEXT:         Table Offset: 0x18
+TEST_EMBED-NEXT:         Number of String Entries: 0
+TEST_EMBED-NEXT:         Number of ID Entries: 1
+TEST_EMBED-NEXT:         Name: (ID 1) [
+TEST_EMBED-NEXT:           Table Offset: 0x30
+TEST_EMBED-NEXT:           Number of String Entries: 0
+TEST_EMBED-NEXT:           Number of ID Entries: 1
+TEST_EMBED-NEXT:           Language: (ID 1033) [
+TEST_EMBED-NEXT:             Entry Offset: 0x48

Modified: lld/trunk/test/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/lit.cfg?rev=307191&r1=307190&r2=307191&view=diff
==============================================================================
--- lld/trunk/test/lit.cfg (original)
+++ lld/trunk/test/lit.cfg Wed Jul  5 12:04:48 2017
@@ -264,6 +264,7 @@ llvm_config_cmd.wait()
 # Set a fake constant version so that we get consitent output.
 config.environment['LLD_VERSION'] = 'LLD 1.0'
 
-# Check if the mt.exe Microsoft utility exists.
-if lit.util.which('mt.exe', config.environment['PATH']):
+# Indirectly check if the mt.exe Microsoft utility exists by searching for
+# cvtres, which always accompanies it.
+if lit.util.which('cvtres', config.environment['PATH']):
     config.available_features.add('win_mt')




More information about the llvm-commits mailing list