From a103cd5291f311db6640fadebf849268b685bac7 Mon Sep 17 00:00:00 2001 From: Mark Mankins Date: Wed, 2 Oct 2024 04:53:13 -0600 Subject: [PATCH] Reduce memory usage when LLVM is enabled. Function pass manager objects were being created, but never destroyed. When a function pass manager object is destroyed, it destroys all pass objects that have been registered. Previously pass objects were being reused, which is why the pass managers were never being freed, but this results in a large memory leak. This commit shuffles things around so the pass managers can be freed. a891 --- panda/include/panda/tcg-llvm.h | 5 +- panda/llvm/helper_runtime.cpp | 6 +- panda/llvm/tcg-llvm.cpp | 13 +- panda/plugins/taint2/llvm_taint_lib.cpp | 209 ++++++++++++------------ panda/plugins/taint2/llvm_taint_lib.h | 41 ++--- panda/plugins/taint2/taint2.cpp | 19 ++- 6 files changed, 141 insertions(+), 152 deletions(-) diff --git a/panda/include/panda/tcg-llvm.h b/panda/include/panda/tcg-llvm.h index 9572ea2ab0b..ce36b3eb7f5 100644 --- a/panda/include/panda/tcg-llvm.h +++ b/panda/include/panda/tcg-llvm.h @@ -163,7 +163,8 @@ class TCGLLVMTranslator { llvm::Value* getEnvOffsetPtr(int64_t offset, TCGTemp &temp); /* Function pass manager (used for optimizing the code) */ - llvm::legacy::FunctionPassManager *m_functionPassManager; + std::unique_ptr m_functionPassManager = + nullptr; /* Count of generated translation blocks */ int m_tbCount; @@ -300,7 +301,7 @@ class TCGLLVMTranslator { } llvm::legacy::FunctionPassManager* getFunctionPassManager() const { - return m_functionPassManager; + return m_functionPassManager.get(); } /* Code generation */ diff --git a/panda/llvm/helper_runtime.cpp b/panda/llvm/helper_runtime.cpp index c57ae7e1d76..f3af3da8da3 100644 --- a/panda/llvm/helper_runtime.cpp +++ b/panda/llvm/helper_runtime.cpp @@ -55,7 +55,6 @@ namespace llvm { ***/ char PandaCallMorphFunctionPass::ID = 0; -static FunctionPass *cmfp; static RegisterPass Y("PandaCallMorph", "Change helper function calls to the the LLVM version"); @@ -138,6 +137,7 @@ void PandaHelperCallVisitor::visitCallInst(CallInst &I) { static void llvmCallMorphNewModuleCallback(Module *module, legacy::FunctionPassManager *functionPassManager) { + auto cmfp = new llvm::PandaCallMorphFunctionPass(); functionPassManager->add(cmfp); } @@ -196,8 +196,8 @@ void init_llvm_helpers() { tcg_llvm_translator->writeModule(mod_file.str().c_str());*/ // Create call morph pass and add to function pass manager - llvm::cmfp = new llvm::PandaCallMorphFunctionPass(); - fpm->add(llvm::cmfp); + auto cmfp = new llvm::PandaCallMorphFunctionPass(); + fpm->add(cmfp); tcg_llvm_translator->addNewModuleCallback( &llvm::llvmCallMorphNewModuleCallback); helpers_initialized = true; diff --git a/panda/llvm/tcg-llvm.cpp b/panda/llvm/tcg-llvm.cpp index 520f7db4f3d..d61d0026632 100644 --- a/panda/llvm/tcg-llvm.cpp +++ b/panda/llvm/tcg-llvm.cpp @@ -159,7 +159,8 @@ TCGLLVMTranslator::TCGLLVMTranslator() m_eip = NULL; m_ccop = NULL; - m_functionPassManager = new legacy::FunctionPassManager(m_module.get()); + m_functionPassManager = std::make_unique( + m_module.get()); /* Note: if we want to use any of these, they also need to get added to the @@ -1310,9 +1311,10 @@ void TCGLLVMTranslator::jitPendingModule() m_module = std::make_unique(("tcg-llvm" + std::to_string(m_tbCount)).c_str(), *m_context); - m_functionPassManager = new legacy::FunctionPassManager(m_module.get()); + m_functionPassManager = std::make_unique( + m_module.get()); for(auto cb : newModuleCallbacks) { - cb(m_module.get(), m_functionPassManager); + cb(m_module.get(), m_functionPassManager.get()); } } @@ -1511,10 +1513,7 @@ void TCGLLVMTranslator::generateCode(TCGContext *s, TranslationBlock *tb) */ TCGLLVMTranslator::~TCGLLVMTranslator() { - if (m_functionPassManager) { - delete m_functionPassManager; - m_functionPassManager = nullptr; - } + m_functionPassManager = nullptr; /*if (llvm::llvm_is_multithreaded()) { LLVMStopMultithreaded(); diff --git a/panda/plugins/taint2/llvm_taint_lib.cpp b/panda/plugins/taint2/llvm_taint_lib.cpp index 918bf2960e2..3567eb8fb8e 100644 --- a/panda/plugins/taint2/llvm_taint_lib.cpp +++ b/panda/plugins/taint2/llvm_taint_lib.cpp @@ -95,7 +95,6 @@ using std::pair; ***/ char PandaTaintFunctionPass::ID = 0; -static PandaTaintFunctionPass *ptfp; extern TCGLLVMTranslator *tcg_llvm_translator; //static RegisterPass @@ -205,165 +204,159 @@ void taint_copyRegToPc_run(Shad *shad, uint64_t src, uint64_t size, PPP_RUN_CB(on_indirect_jump, a, size, from_helper, &tainted); } -static void llvmTaintLibNewModuleCallback(Module *module, - legacy::FunctionPassManager *functionPassManager) { - functionPassManager->add(ptfp); -} +PandaTaintVisitor::PandaTaintVisitor(ShadowState *shad, + taint2_memlog *taint_memlog) : shad(shad), taint_memlog(taint_memlog) { -bool PandaTaintFunctionPass::doInitialization(Module &M) { std::cout << "taint2: Initializing taint ops" << std::endl; - ptfp = this; - tcg_llvm_translator->addNewModuleCallback( - &llvmTaintLibNewModuleCallback); auto &ES = tcg_llvm_translator->getExecutionSession(); - PTV->ctx = tcg_llvm_translator->getContext(); + ctx = tcg_llvm_translator->getContext(); - Type *shadT = StructType::create(*PTV->ctx, "class.Shad"); + Type *shadT = StructType::create(*ctx, "class.Shad"); assert(shadT && "Can't resolve class.Shad"); - PTV->shadP = PointerType::getUnqual(shadT); + shadP = PointerType::getUnqual(shadT); - Type *memlogT = StructType::create(*PTV->ctx, "struct.taint2_memlog"); + Type *memlogT = StructType::create(*ctx, "struct.taint2_memlog"); assert(memlogT && "Can't resolve struct.taint2_memlog"); - PTV->memlogP = PointerType::getUnqual(memlogT); - - PTV->int1T = Type::getInt1Ty(*PTV->ctx); - PTV->int64T = Type::getInt64Ty(*PTV->ctx); - PTV->int128T = Type::getInt128Ty(*PTV->ctx); - PTV->int64P = Type::getInt64PtrTy(*PTV->ctx); - PTV->voidT = Type::getVoidTy(*PTV->ctx); - - PTV->llvConst = PTV->const_struct_ptr(PTV->shadP, &shad->llv); - PTV->memConst = PTV->const_struct_ptr(PTV->shadP, &shad->ram); - PTV->grvConst = PTV->const_struct_ptr(PTV->shadP, &shad->grv); - PTV->gsvConst = PTV->const_struct_ptr(PTV->shadP, &shad->gsv); - PTV->retConst = PTV->const_struct_ptr(PTV->shadP, &shad->ret); - PTV->prevBbConst = PTV->const_i64p(&shad->prev_bb); - PTV->memlogConst = PTV->const_struct_ptr(PTV->memlogP, taint_memlog); - PTV->zeroConst = ConstantInt::get(PTV->int64T, 0); - PTV->oneConst = ConstantInt::get(PTV->int64T, 1); - PTV->maxConst = ConstantInt::get(PTV->int64T, UINT64_C(~0)); - PTV->i64Of128Const = ConstantInt::get(PTV->int128T, 64); - - PTV->dataLayout = tcg_llvm_translator->getDataLayout(); + memlogP = PointerType::getUnqual(memlogT); + + int1T = Type::getInt1Ty(*ctx); + int64T = Type::getInt64Ty(*ctx); + int128T = Type::getInt128Ty(*ctx); + int64P = Type::getInt64PtrTy(*ctx); + voidT = Type::getVoidTy(*ctx); + + llvConst = const_struct_ptr(shadP, &shad->llv); + memConst = const_struct_ptr(shadP, &shad->ram); + grvConst = const_struct_ptr(shadP, &shad->grv); + gsvConst = const_struct_ptr(shadP, &shad->gsv); + retConst = const_struct_ptr(shadP, &shad->ret); + prevBbConst = const_i64p(&shad->prev_bb); + memlogConst = const_struct_ptr(memlogP, taint_memlog); + zeroConst = ConstantInt::get(int64T, 0); + oneConst = ConstantInt::get(int64T, 1); + maxConst = ConstantInt::get(int64T, UINT64_C(~0)); + i64Of128Const = ConstantInt::get(int128T, 64); + + dataLayout = tcg_llvm_translator->getDataLayout(); orc::SymbolMap symbols; - vector argTys { PTV->int64P, PTV->int64T }; + vector argTys { int64P, int64T }; - PTV->breadcrumbF = TaintOpsFunction("taint_breadcrumb", - (void *) &taint_breadcrumb, argTys, PTV->voidT, false, ES, symbols); + breadcrumbF = TaintOpsFunction("taint_breadcrumb", + (void *) &taint_breadcrumb, argTys, voidT, false, ES, symbols); - argTys = { PTV->shadP, PTV->int64T, PTV->int64T, PTV->int64T, - PTV->int64T, PTV->int64T, PTV->int64T, PTV->int64T, - PTV->int64T, PTV->int64T }; + argTys = { shadP, int64T, int64T, int64T, + int64T, int64T, int64T, int64T, + int64T, int64T }; - PTV->mixF = TaintOpsFunction("taint_mix", (void *) &taint_mix, - argTys, PTV->voidT, true, ES, symbols); + mixF = TaintOpsFunction("taint_mix", (void *) &taint_mix, + argTys, voidT, true, ES, symbols); - argTys = { PTV->shadP, PTV->int64T, PTV->shadP, PTV->int64T, - PTV->int64T, PTV->shadP, PTV->int64T, PTV->int64T, PTV->int64T }; + argTys = { shadP, int64T, shadP, int64T, + int64T, shadP, int64T, int64T, int64T }; - PTV->pointerF = TaintOpsFunction("taint_pointer", - (void *) &taint_pointer, argTys, PTV->voidT, false, ES, symbols); + pointerF = TaintOpsFunction("taint_pointer", + (void *) &taint_pointer, argTys, voidT, false, ES, symbols); - argTys = { PTV->shadP, PTV->int64T, PTV->int64T, PTV->int64T, - PTV->int64T, PTV->int64T, PTV->int64T, PTV->int64T, - PTV->int64T, PTV->int64T, PTV->int64T }; + argTys = { shadP, int64T, int64T, int64T, + int64T, int64T, int64T, int64T, + int64T, int64T, int64T }; - PTV->mix_computeF = TaintOpsFunction("taint_mix_compute", - (void *) &taint_mix_compute, argTys, PTV->voidT, false, ES, + mix_computeF = TaintOpsFunction("taint_mix_compute", + (void *) &taint_mix_compute, argTys, voidT, false, ES, symbols); - PTV->parallel_computeF = TaintOpsFunction("taint_parallel_compute", - (void *) &taint_parallel_compute, argTys, PTV->voidT, false, ES, + parallel_computeF = TaintOpsFunction("taint_parallel_compute", + (void *) &taint_parallel_compute, argTys, voidT, false, ES, symbols); - argTys = { PTV->shadP, PTV->int64T, PTV->int64T, PTV->int64T, - PTV->int64T, PTV->int64T, PTV->int64T, PTV->int64T, - PTV->int64T, PTV->int64T, PTV->int64T, PTV->int64T }; + argTys = { shadP, int64T, int64T, int64T, + int64T, int64T, int64T, int64T, + int64T, int64T, int64T, int64T }; - PTV->mul_computeF = TaintOpsFunction("taint_mul_compute", - (void *) &taint_mul_compute, argTys, PTV->voidT, false, ES, + mul_computeF = TaintOpsFunction("taint_mul_compute", + (void *) &taint_mul_compute, argTys, voidT, false, ES, symbols); - argTys = { PTV->shadP, PTV->int64T, PTV->shadP, PTV->int64T, - PTV->int64T, PTV->int64T, PTV->int64T, PTV->int64T }; + argTys = { shadP, int64T, shadP, int64T, + int64T, int64T, int64T, int64T }; - PTV->copyF = TaintOpsFunction("taint_copy", (void *) &taint_copy, - argTys, PTV->voidT, true, ES, symbols); + copyF = TaintOpsFunction("taint_copy", (void *) &taint_copy, + argTys, voidT, true, ES, symbols); - argTys = { PTV->shadP, PTV->int64T, PTV->int64T, PTV->int64T, - PTV->int64T, PTV->int64T }; + argTys = { shadP, int64T, int64T, int64T, + int64T, int64T }; - PTV->sextF = TaintOpsFunction("taint_sext", (void *) &taint_sext, - argTys, PTV->voidT, false, ES, symbols); + sextF = TaintOpsFunction("taint_sext", (void *) &taint_sext, + argTys, voidT, false, ES, symbols); - argTys = { PTV->shadP, PTV->int64T, PTV->int64T, PTV->int64T }; + argTys = { shadP, int64T, int64T, int64T }; - PTV->selectF = TaintOpsFunction("taint_select", (void *) &taint_select, - argTys, PTV->voidT, true, ES, symbols); + selectF = TaintOpsFunction("taint_select", (void *) &taint_select, + argTys, voidT, true, ES, symbols); - argTys = { PTV->int64T, PTV->int64T, PTV->shadP, PTV->int64T, - PTV->shadP, PTV->shadP, PTV->shadP, PTV->int64T, PTV->int64T, - PTV->int1T }; + argTys = { int64T, int64T, shadP, int64T, + shadP, shadP, shadP, int64T, int64T, + int1T }; - PTV->host_copyF = TaintOpsFunction("taint_host_copy", - (void *) &taint_host_copy, argTys, PTV->voidT, false, ES, symbols); + host_copyF = TaintOpsFunction("taint_host_copy", + (void *) &taint_host_copy, argTys, voidT, false, ES, symbols); - argTys = { PTV->int64T, PTV->int64T, PTV->int64T, PTV->shadP, - PTV->shadP, PTV->int64T, PTV->int64T }; + argTys = { int64T, int64T, int64T, shadP, + shadP, int64T, int64T }; - PTV->host_memcpyF = TaintOpsFunction("taint_host_memcpy", - (void *) &taint_host_memcpy, argTys, PTV->voidT, false, ES, + host_memcpyF = TaintOpsFunction("taint_host_memcpy", + (void *) &taint_host_memcpy, argTys, voidT, false, ES, symbols); - argTys = { PTV->int64T, PTV->int64T, PTV->shadP, PTV->shadP, - PTV->int64T, PTV->int64T }; + argTys = { int64T, int64T, shadP, shadP, + int64T, int64T }; - PTV->host_deleteF = TaintOpsFunction("taint_host_delete", - (void *) &taint_host_delete, argTys, PTV->voidT, false, ES, + host_deleteF = TaintOpsFunction("taint_host_delete", + (void *) &taint_host_delete, argTys, voidT, false, ES, symbols); - argTys = { PTV->shadP }; + argTys = { shadP }; - PTV->push_frameF = TaintOpsFunction("taint_push_frame", - (void *) &taint_push_frame, argTys, PTV->voidT, false, ES, symbols); + push_frameF = TaintOpsFunction("taint_push_frame", + (void *) &taint_push_frame, argTys, voidT, false, ES, symbols); - PTV->pop_frameF = TaintOpsFunction("taint_pop_frame", - (void *) &taint_pop_frame, argTys, PTV->voidT, false, ES, symbols); + pop_frameF = TaintOpsFunction("taint_pop_frame", + (void *) &taint_pop_frame, argTys, voidT, false, ES, symbols); - PTV->reset_frameF = TaintOpsFunction("taint_reset_frame", - (void *) &taint_reset_frame, argTys, PTV->voidT, false, ES, + reset_frameF = TaintOpsFunction("taint_reset_frame", + (void *) &taint_reset_frame, argTys, voidT, false, ES, symbols); - argTys = { PTV->memlogP }; + argTys = { memlogP }; - PTV->memlog_popF = TaintOpsFunction("taint_memlog_pop", - (void *) &taint_memlog_pop, argTys, PTV->int64T, false, ES, + memlog_popF = TaintOpsFunction("taint_memlog_pop", + (void *) &taint_memlog_pop, argTys, int64T, false, ES, symbols); - argTys = { PTV->shadP, PTV->int64T, PTV->int64T }; + argTys = { shadP, int64T, int64T }; - PTV->deleteF = TaintOpsFunction("taint_delete", - (void *) &taint_delete, argTys, PTV->voidT, false, ES, symbols); + deleteF = TaintOpsFunction("taint_delete", + (void *) &taint_delete, argTys, voidT, false, ES, symbols); - argTys = { PTV->shadP, PTV->int64T, PTV->int64T, PTV->int64T, - PTV->int64T, PTV->int1T }; + argTys = { shadP, int64T, int64T, int64T, + int64T, int1T }; - PTV->branch_runF = TaintOpsFunction("taint_branch_run", - (void *) &taint_branch_run, argTys, PTV->voidT, false, ES, symbols); + branch_runF = TaintOpsFunction("taint_branch_run", + (void *) &taint_branch_run, argTys, voidT, false, ES, symbols); - argTys = { PTV->shadP, PTV->int64T, PTV->int64T, PTV->int1T }; + argTys = { shadP, int64T, int64T, int1T }; - PTV->copyRegToPc_runF = TaintOpsFunction("taint_copyRegToPc_run", - (void *) &taint_copyRegToPc_run, argTys, PTV->voidT, false, ES, + copyRegToPc_runF = TaintOpsFunction("taint_copyRegToPc_run", + (void *) &taint_copyRegToPc_run, argTys, voidT, false, ES, symbols); - argTys = { PTV->int64T, PTV->int64T, PTV->int64T }; + argTys = { int64T, int64T, int64T }; - PTV->afterLdF = TaintOpsFunction("taint_after_ld_run", - (void *) &taint_after_ld_run, argTys, PTV->voidT, false, ES, symbols); + afterLdF = TaintOpsFunction("taint_after_ld_run", + (void *) &taint_after_ld_run, argTys, voidT, false, ES, symbols); if(tcg_llvm_translator->getJit()->getMainJITDylib().define( orc::absoluteSymbols(std::move(symbols)))) { @@ -372,8 +365,6 @@ bool PandaTaintFunctionPass::doInitialization(Module &M) { std::cout << "taint2: Done initializing taint transformation." << std::endl; - - return true; } bool PandaTaintFunctionPass::runOnFunction(Function &F) { @@ -1106,7 +1097,7 @@ void PandaTaintVisitor::insertTaintBranch(Instruction &I, Value *cond) { vector args { llvConst, constSlot(cond), const_uint64(getValueSize(cond)), Cast, const_uint64(I.getOpcode()), - ConstantInt::get(int1T, ptfp->processingHelper()) }; + ConstantInt::get(int1T, processing_helper) }; insertCallBefore(I, branch_runF, args); } @@ -1120,7 +1111,7 @@ void PandaTaintVisitor::insertTaintQueryNonConstPc(Instruction &I, vector args { llvConst, constSlot(new_pc), const_uint64(getValueSize(new_pc)), - ConstantInt::get(int1T, ptfp->processingHelper()) + ConstantInt::get(int1T, processing_helper) }; insertCallBefore(I, copyRegToPc_runF, args); diff --git a/panda/plugins/taint2/llvm_taint_lib.h b/panda/plugins/taint2/llvm_taint_lib.h index 8eb747d1fe4..244209f173b 100644 --- a/panda/plugins/taint2/llvm_taint_lib.h +++ b/panda/plugins/taint2/llvm_taint_lib.h @@ -127,6 +127,7 @@ class Instruction; */ class PandaTaintVisitor : public InstVisitor { private: + bool processing_helper = false; std::unique_ptr PST; ShadowState *shad; // no ownership. weak ptr. taint2_memlog *taint_memlog; // same. @@ -234,8 +235,7 @@ class PandaTaintVisitor : public InstVisitor { IntegerType *int128T; PointerType *int64P; - PandaTaintVisitor(ShadowState *shad, taint2_memlog *taint_memlog) - : shad(shad), taint_memlog(taint_memlog) {} + PandaTaintVisitor(ShadowState *shad, taint2_memlog *taint_memlog); ~PandaTaintVisitor() {} @@ -276,6 +276,16 @@ class PandaTaintVisitor : public InstVisitor { void visitMemCpyInst(MemTransferInst &I); void visitMemMoveInst(MemTransferInst &I); void visitMemSetInst(MemSetInst &I); + + // the processing_helper flag is used to tweak some taint op arguments based + // on whether or not instrumenting a helper function + void setProcessingHelper() { + processing_helper = true; + } + + void clearProcessingHelper() { + processing_helper = false; + } }; /* PandaTaintFunctionPass class @@ -286,23 +296,16 @@ class PandaTaintVisitor : public InstVisitor { */ class PandaTaintFunctionPass : public FunctionPass { private: - ShadowState *shad; - taint2_memlog *taint_memlog; - bool processing_helper; + PandaTaintVisitor *PTV; public: static char ID; - PandaTaintVisitor *PTV; // Our LLVM instruction visitor - PandaTaintFunctionPass(ShadowState *shad, taint2_memlog *taint_memlog) - : FunctionPass(ID), shad(shad), taint_memlog(taint_memlog), - processing_helper(false), - PTV(new PandaTaintVisitor(shad, taint_memlog)) {} + explicit PandaTaintFunctionPass(PandaTaintVisitor *PTV) : + FunctionPass(ID), PTV(PTV) { } ~PandaTaintFunctionPass() { } - bool doInitialization(Module &M); - // runOnFunction - Our custom function pass implementation bool runOnFunction(Function &F); @@ -312,20 +315,6 @@ class PandaTaintFunctionPass : public FunctionPass { virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); } - - // the processing_helper flag is used to tweak some taint op arguments based - // on whether or not instrumenting a helper function - void setProcessingHelper() { - processing_helper = true; - } - - void clearProcessingHelper() { - processing_helper = false; - } - - bool processingHelper() { - return processing_helper; - } }; } // End llvm namespace diff --git a/panda/plugins/taint2/taint2.cpp b/panda/plugins/taint2/taint2.cpp index 6f5e4893c3a..74be17a1e7f 100644 --- a/panda/plugins/taint2/taint2.cpp +++ b/panda/plugins/taint2/taint2.cpp @@ -125,8 +125,7 @@ void *taint2_plugin = nullptr; // Our pass manager to derive taint ops llvm::legacy::FunctionPassManager *FPM = nullptr; -// Taint function pass. -llvm::PandaTaintFunctionPass *PTFP = nullptr; +llvm::PandaTaintVisitor* PTV = nullptr; // For now, taint becomes enabled when a label operation first occurs, and // becomes disabled when a query operation subsequently occurs @@ -299,6 +298,12 @@ void taint2_enable_tainted_pointer(void) { tainted_pointer = true; } +void taint2_new_module_callback(llvm::Module *module, + llvm::legacy::FunctionPassManager *functionPassManager) { + auto ptfp = new llvm::PandaTaintFunctionPass(PTV); + functionPassManager->add(ptfp); +} + void taint2_enable_taint(void) { if(taintEnabled) {return;} std::cerr << PANDA_MSG << __FUNCTION__ << std::endl; @@ -347,18 +352,22 @@ void taint2_enable_taint(void) { Builder.populateFunctionPassManager(*FPM); } + PTV = new llvm::PandaTaintVisitor(shadow, &taint_memlog); + + tcg_llvm_translator->addNewModuleCallback(&taint2_new_module_callback); + // Add the taint analysis pass to our taint pass manager - PTFP = new llvm::PandaTaintFunctionPass(shadow, &taint_memlog); + auto PTFP = new llvm::PandaTaintFunctionPass(PTV); FPM->add(PTFP); FPM->doInitialization(); // Populate module with helper function taint ops - PTFP->setProcessingHelper(); + PTV->setProcessingHelper(); for (auto i = mod->begin(); i != mod->end(); i++){ if (!i->isDeclaration()) PTFP->runOnFunction(*i); } - PTFP->clearProcessingHelper(); + PTV->clearProcessingHelper(); std::cerr << PANDA_MSG "Done processing helper functions for taint." << std::endl;