about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
authorMartin Nowack <m.nowack@imperial.ac.uk>2019-03-16 14:06:56 +0000
committerCristian Cadar <c.cadar@imperial.ac.uk>2019-03-19 15:37:46 +0000
commit51597914293ac0080f984efcca0e702cff35605f (patch)
treea287b279a8e06e365b228b77f2deeea436010af1
parent2558d3e34b4e0a47a1fe224683604ddaec96f69c (diff)
downloadklee-51597914293ac0080f984efcca0e702cff35605f.tar.gz
Add support to assign debug instructions to optimised code
-rw-r--r--lib/Core/Executor.cpp4
-rw-r--r--lib/Module/InstructionInfoTable.cpp110
-rw-r--r--lib/Module/IntrinsicCleaner.cpp10
3 files changed, 83 insertions, 41 deletions
diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp
index 82fe2356..7a676cc3 100644
--- a/lib/Core/Executor.cpp
+++ b/lib/Core/Executor.cpp
@@ -597,7 +597,11 @@ void Executor::initializeGlobalObject(ExecutionState &state, ObjectState *os,
     for (unsigned i=0, e=cds->getNumElements(); i != e; ++i)
       initializeGlobalObject(state, os, cds->getElementAsConstant(i),
                              offset + i*elementSize);
+#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 8)
   } else if (!isa<UndefValue>(c) && !isa<MetadataAsValue>(c)) {
+#else
+  } else if (!isa<UndefValue>(c)) {
+#endif
     unsigned StoreBits = targetData->getTypeStoreSizeInBits(c->getType());
     ref<ConstantExpr> C = evalConstant(c);
 
diff --git a/lib/Module/InstructionInfoTable.cpp b/lib/Module/InstructionInfoTable.cpp
index a1896831..6ff49669 100644
--- a/lib/Module/InstructionInfoTable.cpp
+++ b/lib/Module/InstructionInfoTable.cpp
@@ -34,6 +34,13 @@
 #else
 #include "llvm/DebugInfo.h"
 #endif
+#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 7)
+#include "llvm/IR/DebugInfoMetadata.h"
+#endif
+
+#if LLVM_VERSION_CODE == LLVM_VERSION(3, 6)
+#include "llvm/Support/Debug.h"
+#endif
 
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -105,7 +112,9 @@ static std::string getFullPath(llvm::StringRef Directory,
 class DebugInfoExtractor {
   std::vector<std::unique_ptr<std::string>> &internedStrings;
   std::map<uintptr_t, uint64_t> lineTable;
+#if LLVM_VERSION_CODE < LLVM_VERSION(3, 8)
   llvm::DebugInfoFinder DIF;
+#endif
 
   const llvm::Module &module;
 
@@ -114,7 +123,9 @@ public:
       std::vector<std::unique_ptr<std::string>> &_internedStrings,
       const llvm::Module &_module)
       : internedStrings(_internedStrings), module(_module) {
+#if LLVM_VERSION_CODE < LLVM_VERSION(3, 8)
     DIF.processModule(module);
+#endif
     lineTable = buildInstructionToLineMap(module);
   }
 
@@ -136,68 +147,105 @@ public:
   std::unique_ptr<FunctionInfo> getFunctionInfo(const llvm::Function &Func) {
     auto asmLine = lineTable.at(reinterpret_cast<std::uintptr_t>(&Func));
 #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 8)
-#if LLVM_VERSION_CODE >= LLVM_VERSION(6, 0)
+
+#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 9)
     auto dsub = Func.getSubprogram();
 #else
     auto dsub = llvm::getDISubprogram(&Func);
 #endif
-    if (dsub == nullptr)
-      return std::unique_ptr<FunctionInfo>(
-          new FunctionInfo(0, getInternedString(""), 0, asmLine));
-    auto path = getFullPath(dsub->getDirectory(), dsub->getFilename());
-    return std::unique_ptr<FunctionInfo>(
-        new FunctionInfo(0, getInternedString(path), dsub->getLine(), asmLine));
+    if (dsub != nullptr) {
+      auto path = getFullPath(dsub->getDirectory(), dsub->getFilename());
+      return std::unique_ptr<FunctionInfo>(new FunctionInfo(
+          0, getInternedString(path), dsub->getLine(), asmLine));
+    }
 
-#else
-    // Acquire function debug information
-#if LLVM_VERSION_CODE < LLVM_VERSION(3, 5)
-    for (auto subIt = DIF.subprogram_begin(), subItE = DIF.subprogram_end();
-         subIt != subItE; ++subIt) {
-      llvm::DISubprogram SubProgram(*subIt);
-#else
-    for (const auto &SubProgram : DIF.subprograms()) {
-#endif
+#elif LLVM_VERSION_CODE == LLVM_VERSION(3, 7)
+    for (const auto SP : DIF.subprograms()) {
+      auto &SubProgram = *SP;
       if (SubProgram.getFunction() != &Func)
         continue;
-
       auto path =
           getFullPath(SubProgram.getDirectory(), SubProgram.getFilename());
+      return std::unique_ptr<FunctionInfo>(new FunctionInfo(
+          0, getInternedString(path), SubProgram.getLine(), asmLine));
+    }
+#endif
 
+#if LLVM_VERSION_CODE <= LLVM_VERSION(3, 6)
+    // Workaround missing debug information for older LLVM versions
+    // Search for any instructions inside this function with debug information
+    // and assume it's part of this function in the source code as well.
+    for (auto it = llvm::inst_begin(&Func), ie = llvm::inst_end(&Func);
+         it != ie; ++it) {
+      auto iInfo = getInstructionInfo(*it, nullptr);
+      if (iInfo->file.empty())
+        continue;
+      // Found an instruction
       return std::unique_ptr<FunctionInfo>(new FunctionInfo(
-          0, getInternedString(path), SubProgram.getLineNumber(), asmLine));
+          0, getInternedString(iInfo->file), iInfo->line, asmLine));
     }
 
+#endif
+    // Fallback: Mark as unknown
     return std::unique_ptr<FunctionInfo>(
         new FunctionInfo(0, getInternedString(""), 0, asmLine));
-#endif
   }
 
   std::unique_ptr<InstructionInfo>
-  getInstructionInfo(const llvm::Instruction &Inst, const FunctionInfo &f) {
+  getInstructionInfo(const llvm::Instruction &Inst, const FunctionInfo *f) {
     auto asmLine = lineTable.at(reinterpret_cast<std::uintptr_t>(&Inst));
 
 #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 8)
+    // Retrieve debug information associated with instruction
     auto dl = Inst.getDebugLoc();
-    auto dil = dl.get();
-    if (dil != nullptr) {
-      auto full_path = getFullPath(dil->getDirectory(), dil->getFilename());
 
+    // Check if a valid debug location is assigned to the instruction.
+    if (dl.get() != nullptr) {
+      auto full_path = dl.get()->getFilename();
+      auto line = dl.getLine();
+      auto column = dl.getCol();
+
+      // Still, if the line is unknown, take the context of the instruction to
+      // narrow it down
+      if (line == 0) {
+        if (auto LexicalBlock =
+                llvm::dyn_cast<llvm::DILexicalBlock>(dl.getScope())) {
+          line = LexicalBlock->getLine();
+          column = LexicalBlock->getColumn();
+        }
+      }
       return std::unique_ptr<InstructionInfo>(new InstructionInfo(
-          0, getInternedString(full_path), dl.getLine(), dl.getCol(), asmLine));
+          0, getInternedString(full_path), line, column, asmLine));
     }
-#else
+#elif LLVM_VERSION_CODE == LLVM_VERSION(3, 7)
+    // Retrieve debug information
     llvm::DebugLoc Loc(Inst.getDebugLoc());
-    if (!Loc.isUnknown()) {
-      llvm::DIScope Scope(Loc.getScope(module.getContext()));
-      auto full_path = getFullPath(Scope.getDirectory(), Scope.getFilename());
+    // Check if valid
+    if (Loc.get() != nullptr) {
+      auto subProg = getDISubprogram(Loc.getScope());
+      auto full_path =
+          getFullPath(subProg->getDirectory(), subProg->getFilename());
       return std::unique_ptr<InstructionInfo>(
           new InstructionInfo(0, getInternedString(full_path), Loc.getLine(),
                               Loc.getCol(), asmLine));
     }
+#elif LLVM_VERSION_CODE <= LLVM_VERSION(3, 6)
+    if (llvm::MDNode *N = Inst.getMetadata("dbg")) {
+      llvm::DILocation Loc(N);
+      auto path = getFullPath(Loc.getDirectory(), Loc.getFilename());
+      auto Line = Loc.getLineNumber();
+      return std::unique_ptr<InstructionInfo>(
+          new InstructionInfo(0, getInternedString(path), Line, 0, asmLine));
+    }
 #endif
+
+    if (f != nullptr)
+      // If nothing found, use the surrounding function
+      return std::unique_ptr<InstructionInfo>(
+          new InstructionInfo(0, f->file, f->line, 0, asmLine));
     // If nothing found, use the surrounding function
     return std::unique_ptr<InstructionInfo>(
-        new InstructionInfo(0, f.file, f.line, 0, asmLine));
+        new InstructionInfo(0, getInternedString(""), 0, 0, asmLine));
   }
 };
 
@@ -206,13 +254,13 @@ InstructionInfoTable::InstructionInfoTable(const llvm::Module &m) {
   DebugInfoExtractor DI(internedStrings, m);
   for (const auto &Func : m) {
     auto F = DI.getFunctionInfo(Func);
-    auto FD = F.get();
+    auto FR = F.get();
     functionInfos.insert(std::make_pair(&Func, std::move(F)));
 
     for (auto it = llvm::inst_begin(Func), ie = llvm::inst_end(Func); it != ie;
          ++it) {
       auto instr = &*it;
-      infos.insert(std::make_pair(instr, DI.getInstructionInfo(*instr, *FD)));
+      infos.insert(std::make_pair(instr, DI.getInstructionInfo(*instr, FR)));
     }
   }
 
diff --git a/lib/Module/IntrinsicCleaner.cpp b/lib/Module/IntrinsicCleaner.cpp
index b757faa1..cb006799 100644
--- a/lib/Module/IntrinsicCleaner.cpp
+++ b/lib/Module/IntrinsicCleaner.cpp
@@ -199,16 +199,6 @@ bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b, Module &M) {
         break;
       }
 
-      case Intrinsic::dbg_value:
-      case Intrinsic::dbg_declare: {
-        //        // Remove these regardless of lower intrinsics flag. This can
-        //        // be removed once IntrinsicLowering is fixed to not have bad
-        //        // caches.
-        //        ii->eraseFromParent();
-        //        dirty = true;
-        break;
-      }
-
       case Intrinsic::trap: {
         // Intrinsic instruction "llvm.trap" found. Directly lower it to
         // a call of the abort() function.