about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
authorMartin Nowack <m.nowack@imperial.ac.uk>2023-10-30 14:46:22 +0000
committerCristian Cadar <c.cadar@imperial.ac.uk>2024-02-08 13:17:19 +0000
commit657f9618023923f08adac11eee0a9566b808f805 (patch)
tree394afc2f0d073a0ecb3b1e4388882f1a2b2be1cb
parent44a38ba6f54046cb4a9f8b08a0b8711ad5d5ebaa (diff)
downloadklee-657f9618023923f08adac11eee0a9566b808f805.tar.gz
Add support for opaque pointers
-rw-r--r--lib/Core/Executor.cpp119
-rw-r--r--lib/Core/ExternalDispatcher.cpp20
-rw-r--r--lib/Core/GetElementPtrTypeIterator.h8
-rw-r--r--lib/Module/FunctionAlias.cpp8
-rw-r--r--lib/Module/IntrinsicCleaner.cpp11
5 files changed, 132 insertions, 34 deletions
diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp
index eccdf9eb..14951b7d 100644
--- a/lib/Core/Executor.cpp
+++ b/lib/Core/Executor.cpp
@@ -15,7 +15,9 @@
 #include "ExecutionState.h"
 #include "ExecutionTree.h"
 #include "ExternalDispatcher.h"
+#if LLVM_VERSION_CODE <= LLVM_VERSION(14, 0)
 #include "GetElementPtrTypeIterator.h"
+#endif
 #include "ImpliedValue.h"
 #include "Memory.h"
 #include "MemoryManager.h"
@@ -67,6 +69,9 @@
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Operator.h"
+#if LLVM_VERSION_CODE >= LLVM_VERSION(15, 0)
+#include "llvm/IR/GetElementPtrTypeIterator.h"
+#endif
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
@@ -1481,24 +1486,25 @@ MemoryObject *Executor::serializeLandingpad(ExecutionState &state,
   stateTerminated = false;
 
   std::vector<unsigned char> serialized;
-
   for (unsigned current_clause_id = 0; current_clause_id < lpi.getNumClauses();
        ++current_clause_id) {
-    llvm::Constant *current_clause = lpi.getClause(current_clause_id);
     if (lpi.isCatch(current_clause_id)) {
       // catch-clause
       serialized.push_back(0);
 
       std::uint64_t ti_addr = 0;
 
-      llvm::BitCastOperator *clause_bitcast =
-          dyn_cast<llvm::BitCastOperator>(current_clause);
-      if (clause_bitcast) {
-        llvm::GlobalValue *clause_type =
+      llvm::Constant *catchClause = lpi.getClause(current_clause_id);
+      llvm::Constant *typeInfo = catchClause->stripPointerCasts();
+      if (auto *gv = dyn_cast<llvm::GlobalVariable>(typeInfo)) {
+        ti_addr = globalAddresses[gv]->getZExtValue();
+      } else if (auto *clause_bitcast =
+                     dyn_cast<llvm::BitCastOperator>(catchClause)) {
+        auto *clause_type =
             dyn_cast<GlobalValue>(clause_bitcast->getOperand(0));
 
         ti_addr = globalAddresses[clause_type]->getZExtValue();
-      } else if (current_clause->isNullValue()) {
+      } else if (catchClause->isNullValue()) {
         ti_addr = 0;
       } else {
         terminateStateOnExecError(
@@ -1510,15 +1516,16 @@ MemoryObject *Executor::serializeLandingpad(ExecutionState &state,
       serialized.resize(old_size + 8);
       memcpy(serialized.data() + old_size, &ti_addr, sizeof(ti_addr));
     } else if (lpi.isFilter(current_clause_id)) {
-      if (current_clause->isNullValue()) {
+      llvm::Constant *filter_clause = lpi.getClause(current_clause_id);
+
+      if (filter_clause->isNullValue()) {
         // special handling for a catch-all filter clause, i.e., "[0 x i8*]"
         // for this case we serialize 1 element..
         serialized.push_back(1);
         // which is a 64bit-wide 0.
         serialized.resize(serialized.size() + 8, 0);
       } else {
-        llvm::ConstantArray const *ca =
-            cast<llvm::ConstantArray>(current_clause);
+        const auto *ca = cast<llvm::ConstantArray>(filter_clause);
 
         // serialize `num_elements+1` as unsigned char
         unsigned const num_elements = ca->getNumOperands();
@@ -1537,18 +1544,16 @@ MemoryObject *Executor::serializeLandingpad(ExecutionState &state,
 
         // serialize the exception-types occurring in this filter-clause
         for (llvm::Value const *v : ca->operands()) {
-          llvm::BitCastOperator const *bitcast =
-              dyn_cast<llvm::BitCastOperator>(v);
-          if (!bitcast) {
-            terminateStateOnExecError(state,
-                                      "Internal: expected value inside a "
-                                      "filter-clause to be a bitcast");
-            stateTerminated = true;
-            return nullptr;
+          llvm::GlobalValue const *clause_value = nullptr;
+
+          if (auto const *bitcast = dyn_cast<llvm::BitCastOperator>(v)) {
+            clause_value = dyn_cast<GlobalValue>(bitcast->getOperand(0));
+          }
+
+          if (auto *gv = dyn_cast<llvm::GlobalVariable>(v)) {
+            clause_value = gv;
           }
 
-          llvm::GlobalValue const *clause_value =
-              dyn_cast<GlobalValue>(bitcast->getOperand(0));
           if (!clause_value) {
             terminateStateOnExecError(state,
                                       "Internal: expected value inside a "
@@ -2167,7 +2172,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
           unwindToNextLandingpad(state);
         } else {
           // a clause (or a catch-all clause or filter clause) matches:
-          // remember the stack index and switch to cleanup phase
+          // remember the stack index and switch to clean-up phase
           state.unwindingInformation =
               std::make_unique<CleanupPhaseUnwindingInformation>(
                   sui->exceptionObject, cast<ConstantExpr>(result),
@@ -2474,8 +2479,12 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
 
     if (f) {
       const FunctionType *fType = f->getFunctionType();
+#if LLVM_VERSION_MAJOR >= 15
+      const FunctionType *fpType = cb.getFunctionType();
+#else
       const FunctionType *fpType =
           dyn_cast<FunctionType>(fp->getType()->getPointerElementType());
+#endif
 
       // special case the call with a bitcast case
       if (fType != fpType) {
@@ -3423,10 +3432,17 @@ template <typename TypeIt>
 void Executor::computeOffsetsSeqTy(KGEPInstruction *kgepi,
                                    ref<ConstantExpr> &constantOffset,
                                    uint64_t index, const TypeIt it) {
+#if LLVM_VERSION_CODE <= LLVM_VERSION(14, 0)
   assert(it->getNumContainedTypes() == 1 &&
          "Sequential type must contain one subtype");
   uint64_t elementSize =
       kmodule->targetData->getTypeStoreSize(it->getContainedType(0));
+#else
+  assert(it.isSequential() && "Called with non-sequential type");
+  // Get the size of a single element
+  uint64_t elementSize =
+      kmodule->targetData->getTypeStoreSize(it.getIndexedType());
+#endif
   const Value *operand = it.getOperand();
   if (const Constant *c = dyn_cast<Constant>(operand)) {
     ref<ConstantExpr> index =
@@ -3445,13 +3461,21 @@ void Executor::computeOffsets(KGEPInstruction *kgepi, TypeIt ib, TypeIt ie) {
     ConstantExpr::alloc(0, Context::get().getPointerWidth());
   uint64_t index = 1;
   for (TypeIt ii = ib; ii != ie; ++ii) {
+#if LLVM_VERSION_CODE <= LLVM_VERSION(14, 0)
     if (StructType *st = dyn_cast<StructType>(*ii)) {
+#else
+    if (StructType *st = ii.getStructTypeOrNull()) {
+#endif
       const StructLayout *sl = kmodule->targetData->getStructLayout(st);
       const ConstantInt *ci = cast<ConstantInt>(ii.getOperand());
       uint64_t addend = sl->getElementOffset((unsigned) ci->getZExtValue());
       constantOffset = constantOffset->Add(ConstantExpr::alloc(addend,
                                                                Context::get().getPointerWidth()));
+#if LLVM_VERSION_CODE <= LLVM_VERSION(14, 0)
     } else if (ii->isArrayTy() || ii->isVectorTy() || ii->isPointerTy()) {
+#else
+    } else if (ii.isSequential()) {
+#endif
       computeOffsetsSeqTy(kgepi, constantOffset, index, ii);
     } else
       assert("invalid type" && 0);
@@ -3463,15 +3487,66 @@ void Executor::computeOffsets(KGEPInstruction *kgepi, TypeIt ib, TypeIt ie) {
 void Executor::bindInstructionConstants(KInstruction *KI) {
   if (GetElementPtrInst *gepi = dyn_cast<GetElementPtrInst>(KI->inst)) {
     KGEPInstruction *kgepi = static_cast<KGEPInstruction *>(KI);
-    computeOffsets(kgepi, gep_type_begin(gepi), gep_type_end(gepi));
+#if LLVM_VERSION_CODE <= LLVM_VERSION(14, 0)
+    computeOffsets(kgepi, klee::gep_type_begin(gepi), klee::gep_type_end(gepi));
+#else
+    computeOffsets(kgepi, llvm::gep_type_begin(gepi), llvm::gep_type_end(gepi));
+#endif
   } else if (InsertValueInst *ivi = dyn_cast<InsertValueInst>(KI->inst)) {
     KGEPInstruction *kgepi = static_cast<KGEPInstruction *>(KI);
+#if LLVM_VERSION_CODE <= LLVM_VERSION(10, 0)
     computeOffsets(kgepi, iv_type_begin(ivi), iv_type_end(ivi));
     assert(kgepi->indices.empty() && "InsertValue constant offset expected");
+#else
+    llvm::Value *agg = ivi->getAggregateOperand();
+    llvm::Type *current_type = agg->getType();
+    uint64_t offset = 0;
+    for (auto index : ivi->indices()) {
+      if (StructType *st = dyn_cast<llvm::StructType>(current_type)) {
+        const StructLayout *sl = kmodule->targetData->getStructLayout(st);
+        uint64_t addend = sl->getElementOffset(index);
+        offset = offset + addend;
+      } else if (current_type->isArrayTy() || current_type->isVectorTy() ||
+                 current_type->isPointerTy()) {
+        uint64_t elementSize = kmodule->targetData->getTypeStoreSize(
+            current_type->getArrayElementType());
+        offset += elementSize * index;
+      } else {
+        assert(0 && "Unknown type");
+      }
+
+      current_type = GetElementPtrInst::getTypeAtIndex(current_type, index);
+    }
+    kgepi->offset = offset;
+#endif
   } else if (ExtractValueInst *evi = dyn_cast<ExtractValueInst>(KI->inst)) {
     KGEPInstruction *kgepi = static_cast<KGEPInstruction *>(KI);
+#if LLVM_VERSION_CODE <= LLVM_VERSION(10, 0)
     computeOffsets(kgepi, ev_type_begin(evi), ev_type_end(evi));
     assert(kgepi->indices.empty() && "ExtractValue constant offset expected");
+#else
+
+    llvm::Value *agg = evi->getAggregateOperand();
+    llvm::Type *current_type = agg->getType();
+    uint64_t offset = 0;
+    for (auto index : evi->indices()) {
+      if (StructType *st = dyn_cast<llvm::StructType>(current_type)) {
+        const StructLayout *sl = kmodule->targetData->getStructLayout(st);
+        uint64_t addend = sl->getElementOffset(index);
+        offset = offset + addend;
+      } else if (current_type->isArrayTy() || current_type->isVectorTy() ||
+                 current_type->isPointerTy()) {
+        uint64_t elementSize = kmodule->targetData->getTypeStoreSize(
+            current_type->getArrayElementType());
+        offset += elementSize * index;
+      } else {
+        assert(0 && "Unknown type");
+      }
+
+      current_type = GetElementPtrInst::getTypeAtIndex(current_type, index);
+    }
+    kgepi->offset = offset;
+#endif
   }
 }
 
diff --git a/lib/Core/ExternalDispatcher.cpp b/lib/Core/ExternalDispatcher.cpp
index 718b1c31..7b43218b 100644
--- a/lib/Core/ExternalDispatcher.cpp
+++ b/lib/Core/ExternalDispatcher.cpp
@@ -250,7 +250,7 @@ bool ExternalDispatcherImpl::runProtectedCall(Function *f, uint64_t *args) {
 }
 
 // FIXME: This might have been relevant for the old JIT but the MCJIT
-// has a completly different implementation so this comment below is
+// has a completely different implementation so this comment below is
 // likely irrelevant and misleading.
 //
 // For performance purposes we construct the stub in such a way that the
@@ -283,13 +283,20 @@ Function *ExternalDispatcherImpl::createDispatcher(KCallable *target,
 
   llvm::IRBuilder<> Builder(dBB);
   // Get a Value* for &gTheArgsP, as an i64**.
+#if LLVM_VERSION_CODE >= LLVM_VERSION(15, 0)
+  auto argI64sp = Builder.CreateIntToPtr(
+      ConstantInt::get(Type::getInt64Ty(ctx), (uintptr_t)&gTheArgsP),
+      PointerType::getUnqual(PointerType::getUnqual(Type::getInt64Ty(ctx))),
+      "argsp");
+  auto argI64s = Builder.CreateLoad(Builder.getPtrTy(), argI64sp, "args");
+#else
   auto argI64sp = Builder.CreateIntToPtr(
       ConstantInt::get(Type::getInt64Ty(ctx), (uintptr_t)(void *)&gTheArgsP),
       PointerType::getUnqual(PointerType::getUnqual(Type::getInt64Ty(ctx))),
       "argsp");
   auto argI64s = Builder.CreateLoad(
       argI64sp->getType()->getPointerElementType(), argI64sp, "args");
-
+#endif
   // Get the target function type.
   FunctionType *FTy = target->getFunctionType();
 
@@ -306,6 +313,14 @@ Function *ExternalDispatcherImpl::createDispatcher(KCallable *target,
     if (argTy->isX86_FP80Ty() && idx & 0x01)
       idx++;
 
+#if LLVM_VERSION_CODE >= LLVM_VERSION(15, 0)
+    auto argI64p =
+        Builder.CreateGEP(Builder.getPtrTy(), argI64s,
+                          ConstantInt::get(Type::getInt32Ty(ctx), idx));
+
+    auto argp = Builder.CreateBitCast(argI64p, PointerType::getUnqual(argTy));
+    args[i] = Builder.CreateLoad(argTy, argp);
+#else
     auto argI64p =
         Builder.CreateGEP(argI64s->getType()->getPointerElementType(), argI64s,
                           ConstantInt::get(Type::getInt32Ty(ctx), idx));
@@ -313,6 +328,7 @@ Function *ExternalDispatcherImpl::createDispatcher(KCallable *target,
     auto argp = Builder.CreateBitCast(argI64p, PointerType::getUnqual(argTy));
     args[i] =
         Builder.CreateLoad(argp->getType()->getPointerElementType(), argp);
+#endif
 
     unsigned argSize = argTy->getPrimitiveSizeInBits();
     idx += ((!!argSize ? argSize : 64) + 63) / 64;
diff --git a/lib/Core/GetElementPtrTypeIterator.h b/lib/Core/GetElementPtrTypeIterator.h
index d8b0e097..4e0314cb 100644
--- a/lib/Core/GetElementPtrTypeIterator.h
+++ b/lib/Core/GetElementPtrTypeIterator.h
@@ -144,14 +144,6 @@ public:
     return iv_type_iterator::end(IV->idx_end());
   }
 
-  inline vce_type_iterator vce_type_begin(const llvm::ConstantExpr *CE) {
-    return vce_type_iterator::begin(CE->getOperand(0)->getType(),
-                                    CE->getIndices().begin());
-  }
-  inline vce_type_iterator vce_type_end(const llvm::ConstantExpr *CE) {
-    return vce_type_iterator::end(CE->getIndices().end());
-  }
-
   template <typename ItTy>
   inline generic_gep_type_iterator<ItTy> gep_type_begin(llvm::Type *Op0, ItTy I,
                                                         ItTy E) {
diff --git a/lib/Module/FunctionAlias.cpp b/lib/Module/FunctionAlias.cpp
index aa80b35d..c00bde58 100644
--- a/lib/Module/FunctionAlias.cpp
+++ b/lib/Module/FunctionAlias.cpp
@@ -134,10 +134,16 @@ bool FunctionAliasPass::runOnModule(Module &M) {
 }
 
 const FunctionType *FunctionAliasPass::getFunctionType(const GlobalValue *gv) {
+#if LLVM_VERSION_CODE >= LLVM_VERSION(15, 0)
+  if (auto *ft = dyn_cast<FunctionType>(gv->getType()))
+    return ft;
+  return dyn_cast<FunctionType>(gv->getValueType());
+#else
   const Type *type = gv->getType();
   while (type->isPointerTy())
     type = type->getPointerElementType();
-  return cast<FunctionType>(type);
+  return dyn_cast<FunctionType>(type);
+#endif
 }
 
 bool FunctionAliasPass::checkType(const GlobalValue *match,
diff --git a/lib/Module/IntrinsicCleaner.cpp b/lib/Module/IntrinsicCleaner.cpp
index ad7c0631..40ff2874 100644
--- a/lib/Module/IntrinsicCleaner.cpp
+++ b/lib/Module/IntrinsicCleaner.cpp
@@ -100,9 +100,14 @@ bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b, Module &M) {
               Builder.CreatePointerCast(dst, i8pp, "vacopy.cast.dst");
           auto castedSrc =
               Builder.CreatePointerCast(src, i8pp, "vacopy.cast.src");
+#if LLVM_VERSION_CODE >= LLVM_VERSION(15, 0)
+          auto load = Builder.CreateLoad(Builder.getInt8PtrTy(), castedSrc,
+                                         "vacopy.read");
+#else
           auto load =
               Builder.CreateLoad(castedSrc->getType()->getPointerElementType(),
                                  castedSrc, "vacopy.read");
+#endif
           Builder.CreateStore(load, castedDst, false /* isVolatile */);
         } else {
           assert(WordSize == 8 && "Invalid word size!");
@@ -110,9 +115,13 @@ bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b, Module &M) {
           auto pDst = Builder.CreatePointerCast(dst, i64p, "vacopy.cast.dst");
           auto pSrc = Builder.CreatePointerCast(src, i64p, "vacopy.cast.src");
 
+#if LLVM_VERSION_CODE >= LLVM_VERSION(15, 0)
+          auto pSrcType = Builder.getPtrTy();
+          auto pDstType = Builder.getPtrTy();
+#else
           auto pSrcType = pSrc->getType()->getPointerElementType();
           auto pDstType = pDst->getType()->getPointerElementType();
-
+#endif
           auto val = Builder.CreateLoad(pSrcType, pSrc);
           Builder.CreateStore(val, pDst, ii);