about summary refs log tree commit diff homepage
path: root/lib/Module
diff options
context:
space:
mode:
authorMartin Nowack <martin@se.inf.tu-dresden.de>2013-12-04 23:35:10 +0100
committerMartin Nowack <martin@se.inf.tu-dresden.de>2014-02-06 23:55:29 +0100
commit9e16c443aea9104609c5d5f4016ff41190c7dd24 (patch)
tree645cf06da601f93f0688a4ffb5dbc01fb5271724 /lib/Module
parentf629a6d1ec51b39334c78bce354b3efb245c35b3 (diff)
downloadklee-9e16c443aea9104609c5d5f4016ff41190c7dd24.tar.gz
Add support for archive and single bc file linking
With LLVM 3.3 the linker does not support reading of
archive files directly. This brings the support back
(based on llvm-mn).
Furthermore, linking single bc files or archives with
bc and object files mixed is supported as well.
Diffstat (limited to 'lib/Module')
-rw-r--r--lib/Module/ModuleUtil.cpp85
1 files changed, 76 insertions, 9 deletions
diff --git a/lib/Module/ModuleUtil.cpp b/lib/Module/ModuleUtil.cpp
index 9ae72936..c1ea274f 100644
--- a/lib/Module/ModuleUtil.cpp
+++ b/lib/Module/ModuleUtil.cpp
@@ -19,6 +19,9 @@
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IRReader/IRReader.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/DataStream.h"
 #else
@@ -49,15 +52,79 @@ using namespace klee;
 Module *klee::linkWithLibrary(Module *module, 
                               const std::string &libraryName) {
 #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3)
-  SMDiagnostic err;
-  std::string err_str;
-  sys::Path libraryPath(libraryName);
-  Module *new_mod = ParseIRFile(libraryPath.str(), err, 
-module->getContext());
-
-  if (Linker::LinkModules(module, new_mod, Linker::DestroySource, 
-&err_str)) {
-    klee_error("Linking library %s failed", libraryName.c_str());
+  if (!sys::fs::exists(libraryName)) {
+    klee_error("Link with library %s failed. No such file.",
+        libraryName.c_str());
+  }
+
+  OwningPtr<MemoryBuffer> Buffer;
+  if (error_code ec = MemoryBuffer::getFile(libraryName,Buffer)) {
+    klee_error("Link with library %s failed: %s", libraryName.c_str(),
+        ec.message().c_str());
+  }
+
+  sys::fs::file_magic magic = sys::fs::identify_magic(Buffer->getBuffer());
+
+  LLVMContext &Context = getGlobalContext();
+  std::string ErrorMessage;
+
+  if (magic == sys::fs::file_magic::bitcode) {
+    Module *Result = 0;
+    Result = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage);
+
+
+    if (!Result || Linker::LinkModules(module, Result, Linker::DestroySource,
+        &ErrorMessage))
+      klee_error("Link with library %s failed: %s", libraryName.c_str(),
+          ErrorMessage.c_str());
+
+    delete Result;
+
+  } else if (magic == sys::fs::file_magic::archive) {
+    OwningPtr<object::Binary> arch;
+    if (error_code ec = object::createBinary(Buffer.take(), arch))
+      klee_error("Link with library %s failed: %s", libraryName.c_str(),
+          ec.message().c_str());
+
+    if (object::Archive *a = dyn_cast<object::Archive>(arch.get())) {
+      for (object::Archive::child_iterator i = a->begin_children(),
+          e = a->end_children(); i != e; ++i) {
+        OwningPtr<object::Binary> child;
+        if (i->getAsBinary(child)) {
+          // Try opening it as a bitcode file.
+          OwningPtr<MemoryBuffer> buff;
+          if (error_code ec = i->getMemoryBuffer(buff))
+            klee_error("Link with library %s failed: %s", libraryName.c_str(),
+                ec.message().c_str());
+          Module *Result = 0;
+          if (buff)
+            Result = ParseBitcodeFile(buff.get(), Context, &ErrorMessage);
+
+          if (!Result || Linker::LinkModules(module, Result,
+              Linker::DestroySource, &ErrorMessage))
+            klee_error("Link with library %s failed: %s", libraryName.c_str(),
+                ErrorMessage.c_str());
+          delete Result;
+
+          continue;
+        }
+        if (object::ObjectFile *o = dyn_cast<object::ObjectFile>(child.get())) {
+          klee_warning("Link with library: Object file %s in archive %s found. "
+              "Currently not supported.",
+              o->getFileName().data(), libraryName.c_str());
+        }
+      }
+    }
+  } else if (magic.is_object()) {
+    OwningPtr<object::Binary> obj;
+    if (object::ObjectFile *o = dyn_cast<object::ObjectFile>(obj.get())) {
+      klee_warning("Link with library: Object file %s in archive %s found. "
+          "Currently not supported.",
+          o->getFileName().data(), libraryName.c_str());
+    }
+  } else {
+    klee_error("Link with library %s failed: Unrecognized file type.",
+        libraryName.c_str());
   }
 
   return module;