[llvm] r309064 - Reapply "llvm-mt: implement simple merging of manifests, not factoring namespaces.

Eric Beckmann via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 25 17:25:12 PDT 2017


Author: ecbeckmann
Date: Tue Jul 25 17:25:12 2017
New Revision: 309064

URL: http://llvm.org/viewvc/llvm-project?rev=309064&view=rev
Log:
Reapply "llvm-mt: implement simple merging of manifests, not factoring namespaces.

This time with correct #if.

This reverts commit 9cf4eca0e0383040c1ff1416815c7f649650c2a0.

Added:
    llvm/trunk/test/tools/llvm-mt/Inputs/additional.manifest
    llvm/trunk/test/tools/llvm-mt/Inputs/conflicting.manifest
    llvm/trunk/test/tools/llvm-mt/conflicting.test
    llvm/trunk/test/tools/llvm-mt/simple_merge.test
Modified:
    llvm/trunk/include/llvm/Support/WindowsManifestMerger.h
    llvm/trunk/lib/Support/WindowsManifestMerger.cpp
    llvm/trunk/test/tools/llvm-mt/Inputs/test_manifest.manifest
    llvm/trunk/tools/llvm-mt/llvm-mt.cpp

Modified: llvm/trunk/include/llvm/Support/WindowsManifestMerger.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/WindowsManifestMerger.h?rev=309064&r1=309063&r2=309064&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/WindowsManifestMerger.h (original)
+++ llvm/trunk/include/llvm/Support/WindowsManifestMerger.h Tue Jul 25 17:25:12 2017
@@ -57,6 +57,8 @@ private:
 
 class WindowsManifestMerger {
 public:
+  ~WindowsManifestMerger();
+
   Error merge(const MemoryBuffer &Manifest);
 
   // Returns vector containing merged xml manifest, or uninitialized vector for
@@ -68,7 +70,8 @@ private:
   Error getParseError();
 
 #if LLVM_LIBXML2_ENABLED
-  XMLNodeImpl CombinedRoot = nullptr;
+  XMLDocumentImpl CombinedDoc = nullptr;
+  std::vector<XMLDocumentImpl> MergedDocs;
 #endif
   bool ParseErrorOccurred = false;
 };

Modified: llvm/trunk/lib/Support/WindowsManifestMerger.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/WindowsManifestMerger.cpp?rev=309064&r1=309063&r2=309064&view=diff
==============================================================================
--- llvm/trunk/lib/Support/WindowsManifestMerger.cpp (original)
+++ llvm/trunk/lib/Support/WindowsManifestMerger.cpp Tue Jul 25 17:25:12 2017
@@ -16,6 +16,11 @@
 
 #include <stdarg.h>
 
+#define TO_XML_CHAR(X) reinterpret_cast<const unsigned char *>(X)
+#define FROM_XML_CHAR(X) reinterpret_cast<const char *>(X)
+
+using namespace llvm;
+
 namespace llvm {
 
 char WindowsManifestError::ID = 0;
@@ -24,16 +29,152 @@ WindowsManifestError::WindowsManifestErr
 
 void WindowsManifestError::log(raw_ostream &OS) const { OS << Msg; }
 
+#if LLVM_LIBXML2_ENABLED
+static bool xmlStringsEqual(const unsigned char *A, const unsigned char *B) {
+  return strcmp(FROM_XML_CHAR(A), FROM_XML_CHAR(B)) == 0;
+}
+#endif
+
+bool isMergeableElement(const unsigned char *ElementName) {
+  for (StringRef S : {"application", "assembly", "assemblyIdentity",
+                      "compatibility", "noInherit", "requestedExecutionLevel",
+                      "requestedPrivileges", "security", "trustInfo"}) {
+    if (S == FROM_XML_CHAR(ElementName))
+      return true;
+  }
+  return false;
+}
+
+XMLNodeImpl getChildWithName(XMLNodeImpl Parent,
+                             const unsigned char *ElementName) {
+#if LLVM_LIBXML2_ENABLED
+  for (XMLNodeImpl Child = Parent->children; Child; Child = Child->next)
+    if (xmlStringsEqual(Child->name, ElementName)) {
+      return Child;
+    }
+#endif
+  return nullptr;
+}
+
+const unsigned char *getAttribute(XMLNodeImpl Node,
+                                  const unsigned char *AttributeName) {
+#if LLVM_LIBXML2_ENABLED
+  for (xmlAttrPtr Attribute = Node->properties; Attribute != nullptr;
+       Attribute = Attribute->next) {
+    if (xmlStringsEqual(Attribute->name, AttributeName))
+      return Attribute->children->content;
+  }
+#endif
+  return nullptr;
+}
+
+Error mergeAttributes(XMLNodeImpl OriginalNode, XMLNodeImpl AdditionalNode) {
+#if LLVM_LIBXML2_ENABLED
+  for (xmlAttrPtr Attribute = AdditionalNode->properties; Attribute != nullptr;
+       Attribute = Attribute->next) {
+    if (const unsigned char *OriginalValue =
+            getAttribute(OriginalNode, Attribute->name)) {
+      // Attributes of the same name must also have the same value.  Otherwise
+      // an error is thrown.
+      if (!xmlStringsEqual(OriginalValue, Attribute->children->content))
+        return make_error<WindowsManifestError>(
+            Twine("conflicting attributes for ") +
+            FROM_XML_CHAR(OriginalNode->name));
+    } else {
+      char *NameCopy = strdup(FROM_XML_CHAR(Attribute->name));
+      char *ContentCopy = strdup(FROM_XML_CHAR(Attribute->children->content));
+      xmlNewProp(OriginalNode, TO_XML_CHAR(NameCopy), TO_XML_CHAR(ContentCopy));
+    }
+  }
+#endif
+  return Error::success();
+}
+
+Error treeMerge(XMLNodeImpl OriginalRoot, XMLNodeImpl AdditionalRoot) {
+#if LLVM_LIBXML2_ENABLED
+  XMLNodeImpl AdditionalFirstChild = AdditionalRoot->children;
+  for (XMLNodeImpl Child = AdditionalFirstChild; Child; Child = Child->next) {
+    XMLNodeImpl OriginalChildWithName;
+    if (!isMergeableElement(Child->name) ||
+        !(OriginalChildWithName =
+              getChildWithName(OriginalRoot, Child->name))) {
+      XMLNodeImpl NewChild = xmlCopyNode(Child, 1);
+      if (!NewChild)
+        return make_error<WindowsManifestError>(Twine("error when copying ") +
+                                                FROM_XML_CHAR(Child->name));
+      if (NewChild->ns)
+        xmlFreeNs(NewChild->ns); // xmlCopyNode explicitly defines default
+                                 // namespace, undo this here.
+      if (!xmlAddChild(OriginalRoot, NewChild))
+        return make_error<WindowsManifestError>(Twine("could not merge ") +
+                                                FROM_XML_CHAR(NewChild->name));
+    } else if (auto E = treeMerge(OriginalChildWithName, Child)) {
+      return E;
+    }
+  }
+  if (auto E = mergeAttributes(OriginalRoot, AdditionalRoot))
+    return E;
+#endif
+  return Error::success();
+}
+
+void stripCommentsAndText(XMLNodeImpl Root) {
+#if LLVM_LIBXML2_ENABLED
+  xmlNode StoreNext;
+  for (XMLNodeImpl Child = Root->children; Child; Child = Child->next) {
+    if (!xmlStringsEqual(Child->name, TO_XML_CHAR("text")) &&
+        !xmlStringsEqual(Child->name, TO_XML_CHAR("comment"))) {
+      stripCommentsAndText(Child);
+    } else {
+      StoreNext.next = Child->next;
+      XMLNodeImpl Remove = Child;
+      Child = &StoreNext;
+      xmlUnlinkNode(Remove);
+      xmlFreeNode(Remove);
+    }
+  }
+#endif
+}
+
+WindowsManifestMerger::~WindowsManifestMerger() {
+#if LLVM_LIBXML2_ENABLED
+  for (auto &Doc : MergedDocs)
+    xmlFreeDoc(Doc);
+#endif
+}
+
 Error WindowsManifestMerger::merge(const MemoryBuffer &Manifest) {
 #if LLVM_LIBXML2_ENABLED
+  if (Manifest.getBufferSize() == 0)
+    return make_error<WindowsManifestError>(
+        "attempted to merge empty manifest");
   xmlSetGenericErrorFunc((void *)this, WindowsManifestMerger::errorCallback);
   XMLDocumentImpl ManifestXML =
       xmlReadMemory(Manifest.getBufferStart(), Manifest.getBufferSize(),
-                    "manifest.xml", nullptr, 0);
+                    "manifest.xml", nullptr, XML_PARSE_NOBLANKS);
   xmlSetGenericErrorFunc(nullptr, nullptr);
   if (auto E = getParseError())
     return E;
-  CombinedRoot = xmlDocGetRootElement(ManifestXML);
+  XMLNodeImpl AdditionalRoot = xmlDocGetRootElement(ManifestXML);
+  stripCommentsAndText(AdditionalRoot);
+  if (CombinedDoc == nullptr) {
+    CombinedDoc = ManifestXML;
+  } else {
+    XMLNodeImpl CombinedRoot = xmlDocGetRootElement(CombinedDoc);
+    if (xmlStringsEqual(CombinedRoot->name, AdditionalRoot->name) &&
+        isMergeableElement(AdditionalRoot->name)) {
+      if (auto E = treeMerge(CombinedRoot, AdditionalRoot)) {
+        return E;
+      }
+    } else {
+      XMLNodeImpl NewChild = xmlCopyNode(AdditionalRoot, 1);
+      if (!NewChild)
+        return make_error<WindowsManifestError>("could not copy manifest");
+      if (!xmlAddChild(CombinedRoot, NewChild))
+        return make_error<WindowsManifestError>("could not append manifest");
+    }
+  }
+  MergedDocs.push_back(ManifestXML);
 #endif
   return Error::success();
 }
@@ -42,15 +183,16 @@ std::unique_ptr<MemoryBuffer> WindowsMan
 #if LLVM_LIBXML2_ENABLED
   unsigned char *XmlBuff;
   int BufferSize = 0;
-  if (CombinedRoot) {
+  if (CombinedDoc) {
     std::unique_ptr<xmlDoc> OutputDoc(xmlNewDoc((const unsigned char *)"1.0"));
-    xmlDocSetRootElement(OutputDoc.get(), CombinedRoot);
-    xmlDocDumpMemory(OutputDoc.get(), &XmlBuff, &BufferSize);
+    xmlDocSetRootElement(OutputDoc.get(), xmlDocGetRootElement(CombinedDoc));
+    xmlKeepBlanksDefault(0);
+    xmlDocDumpFormatMemory(OutputDoc.get(), &XmlBuff, &BufferSize, 1);
   }
   if (BufferSize == 0)
     return nullptr;
   return MemoryBuffer::getMemBuffer(
-      StringRef(reinterpret_cast<const char *>(XmlBuff), (size_t)BufferSize));
+      StringRef(FROM_XML_CHAR(XmlBuff), (size_t)BufferSize));
 #else
   return nullptr;
 #endif

Added: llvm/trunk/test/tools/llvm-mt/Inputs/additional.manifest
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-mt/Inputs/additional.manifest?rev=309064&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-mt/Inputs/additional.manifest (added)
+++ llvm/trunk/test/tools/llvm-mt/Inputs/additional.manifest Tue Jul 25 17:25:12 2017
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+  <trustInfo>
+    <security>
+      <requestedPrivileges>
+<!--Comment will be removed-->
+         <requestedExecutionLevel level="3" admin="false"/>
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+  <dependency>
+    <dependentAssembly>
+      <assemblyIdentity program="logDisplay"/>
+    </dependentAssembly>
+  </dependency>
+  <compatibility>
+    <dependency>
+      <assemblyIdentity program="compatibilityCheck2"/>
+    </dependency>
+    <application>
+      <supportedOS Id="BarOS"/>
+    </application>
+  </compatibility>
+</assembly>

Added: llvm/trunk/test/tools/llvm-mt/Inputs/conflicting.manifest
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-mt/Inputs/conflicting.manifest?rev=309064&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-mt/Inputs/conflicting.manifest (added)
+++ llvm/trunk/test/tools/llvm-mt/Inputs/conflicting.manifest Tue Jul 25 17:25:12 2017
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1">
+  <trustInfo>
+    <security>
+      <requestedPrivileges>
+        <requestedExecutionLevel level="2" uiAccess="1"/>
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+</assembly>

Modified: llvm/trunk/test/tools/llvm-mt/Inputs/test_manifest.manifest
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-mt/Inputs/test_manifest.manifest?rev=309064&r1=309063&r2=309064&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-mt/Inputs/test_manifest.manifest (original)
+++ llvm/trunk/test/tools/llvm-mt/Inputs/test_manifest.manifest Tue Jul 25 17:25:12 2017
@@ -1,9 +1,9 @@
 <?xml version="1.0"?>
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1">
   <trustInfo>
     <security>
       <requestedPrivileges>
-         <requestedExecutionLevel level="3" uiAccess="1"/>
+        <requestedExecutionLevel level="3" uiAccess="1"/>
       </requestedPrivileges>
     </security>
   </trustInfo>
@@ -12,4 +12,12 @@
       <assemblyIdentity program="displayDriver"/>
     </dependentAssembly>
   </dependency>
+  <compatibility>
+    <dependency>
+      <assemblyIdentity program="compatibilityCheck1"/>
+    </dependency>
+    <application>
+      <supportedOS Id="FooOS"/>
+    </application>
+  </compatibility>
 </assembly>

Added: llvm/trunk/test/tools/llvm-mt/conflicting.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-mt/conflicting.test?rev=309064&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-mt/conflicting.test (added)
+++ llvm/trunk/test/tools/llvm-mt/conflicting.test Tue Jul 25 17:25:12 2017
@@ -0,0 +1,7 @@
+REQUIRES: libxml2
+UNSUPPORTED: windows
+
+RUN: not llvm-mt /manifest %p/Inputs/test_manifest.manifest /manifest \
+RUN:   %p/Inputs/conflicting.manifest /out:%t 2>&1 >/dev/null | FileCheck %s
+
+CHECK: llvm-mt error: conflicting attributes for requestedExecutionLevel

Added: llvm/trunk/test/tools/llvm-mt/simple_merge.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-mt/simple_merge.test?rev=309064&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-mt/simple_merge.test (added)
+++ llvm/trunk/test/tools/llvm-mt/simple_merge.test Tue Jul 25 17:25:12 2017
@@ -0,0 +1,39 @@
+REQUIRES: libxml2
+UNSUPPORTED: windows
+
+RUN: llvm-mt /manifest %p/Inputs/test_manifest.manifest /manifest \
+RUN:   %p/Inputs/additional.manifest /out:%t
+RUN: FileCheck %s -input-file=%t
+
+CHECK:      <?xml version="1.0"?>
+CHECK-NEXT: <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+CHECK-NEXT:   <trustInfo>
+CHECK-NEXT:     <security>
+CHECK-NEXT:       <requestedPrivileges>
+CHECK-NEXT:         <requestedExecutionLevel level="3" uiAccess="1" admin="false"/>
+CHECK-NEXT:       </requestedPrivileges>
+CHECK-NEXT:     </security>
+CHECK-NEXT:   </trustInfo>
+CHECK-NEXT:   <dependency>
+CHECK-NEXT:     <dependentAssembly>
+CHECK-NEXT:       <assemblyIdentity program="displayDriver"/>
+CHECK-NEXT:     </dependentAssembly>
+CHECK-NEXT:   </dependency>
+CHECK-NEXT:   <compatibility>
+CHECK-NEXT:     <dependency>
+CHECK-NEXT:       <assemblyIdentity program="compatibilityCheck1"/>
+CHECK-NEXT:     </dependency>
+CHECK-NEXT:     <application>
+CHECK-NEXT:       <supportedOS Id="FooOS"/>
+CHECK-NEXT:       <supportedOS Id="BarOS"/>
+CHECK-NEXT:     </application>
+CHECK-NEXT:     <dependency>
+CHECK-NEXT:       <assemblyIdentity program="compatibilityCheck2"/>
+CHECK-NEXT:     </dependency>
+CHECK-NEXT:   </compatibility>
+CHECK-NEXT:   <dependency>
+CHECK-NEXT:     <dependentAssembly>
+CHECK-NEXT:       <assemblyIdentity program="logDisplay"/>
+CHECK-NEXT:     </dependentAssembly>
+CHECK-NEXT:   </dependency>
+CHECK-NEXT: </assembly>

Modified: llvm/trunk/tools/llvm-mt/llvm-mt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mt/llvm-mt.cpp?rev=309064&r1=309063&r2=309064&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mt/llvm-mt.cpp (original)
+++ llvm/trunk/tools/llvm-mt/llvm-mt.cpp Tue Jul 25 17:25:12 2017
@@ -95,7 +95,6 @@ int main(int argc, const char **argv) {
   SpecificBumpPtrAllocator<char> ArgAllocator;
   ExitOnErr(errorCodeToError(sys::Process::GetArgumentVector(
       argv_buf, makeArrayRef(argv, argc), ArgAllocator)));
-
   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
 
   CvtResOptTable T;




More information about the llvm-commits mailing list