From db5538308eb043112ad2ba61480309fb05d25707 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Thu, 8 Aug 2024 16:52:27 +0300 Subject: [PATCH 01/22] feat: Add simple metrics --- tools/klee/main.cpp | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index 9cd06abbf7..d96526ce99 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -50,8 +50,10 @@ #include "llvm/Support/TargetSelect.h" #include +#include #include #include +#include #include #include #include @@ -1557,8 +1559,8 @@ static int run_klee_on_function(int pArgc, char **pArgv, char **pEnvp, KTest *out = *it; interpreter->setReplayKTest(out); llvm::errs() << "KLEE: replaying: " << *it << " (" << kTest_numBytes(out) - << " bytes)" - << " (" << ++i << "/" << kTestFiles.size() << ")\n"; + << " bytes)" << " (" << ++i << "/" << kTestFiles.size() + << ")\n"; // XXX should put envp in .ktest ? interpreter->runFunctionAsMain(mainFn, out->numArgs, out->args, pEnvp); if (interrupted) @@ -2451,6 +2453,21 @@ int main(int argc, char **argv, char **envp) { uint64_t instructions = *theStatisticManager->getStatisticByName("Instructions"); uint64_t forks = *theStatisticManager->getStatisticByName("Forks"); + uint64_t solverTime = + (*theStatisticManager->getStatisticByName("SolverTime")) / 1000000000; + uint64_t uncoverageInstructions = + *theStatisticManager->getStatisticByName("UncoveredInstructions"); + + std::uint32_t solverH; + std::uint8_t solverM, solverS; + std::tie(solverH, solverM, solverS) = time::seconds(solverTime).toHMS(); + + std::stringstream ss; + ss << std::setw(2) << std::setfill('0') << solverH << ':'; + ss << std::setw(2) << std::setfill('0') << +solverM << ':'; + ss << std::setw(2) << std::setfill('0') << +solverS; + + handler->getInfoStream() << "KLEE: done: solver time = " << ss.str() << "\n"; handler->getInfoStream() << "KLEE: done: explored paths = " << 1 + forks << "\n"; @@ -2477,7 +2494,13 @@ int main(int argc, char **argv, char **envp) { << handler->getNumPathsExplored() - handler->getNumPathsCompleted() << '\n' << "KLEE: done: generated tests = " << handler->getNumTestCases() - << '\n'; + << '\n' + << "KLEE: done: forks = " << forks << '\n' + << "KLEE: done: coverage = " + << (static_cast(instructions - uncoverageInstructions) / + instructions) * + 100 + << "%" << '\n'; bool useColors = llvm::errs().is_displayed(); if (useColors) From c3bc233bc3c74532c239f88d78c09f348f6e845c Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Thu, 15 Aug 2024 15:32:37 +0300 Subject: [PATCH 02/22] feat: Add viewing statistics for individual functions --- lib/Core/Executor.cpp | 40 +++++++++++++++++++++++++++++----------- tools/klee/main.cpp | 10 +++++----- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 9c37230634..adf1df9433 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -11,6 +11,7 @@ #include "AddressSpace.h" #include "CXXTypeSystem/CXXTypeManager.h" +#include "CallPathManager.h" #include "ConstructStorage.h" #include "CoreStats.h" #include "DistanceCalculator.h" @@ -103,6 +104,7 @@ #include #include #include +#include #include #include #include @@ -489,9 +491,9 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, InterpreterHandler *ih) : Interpreter(opts), interpreterHandler(ih), searcher(nullptr), externalDispatcher(new ExternalDispatcher(ctx)), statsTracker(0), - pathWriter(0), symPathWriter(0), - specialFunctionHandler(0), timers{time::Span(TimerInterval)}, - guidanceKind(opts.Guidance), codeGraphInfo(new CodeGraphInfo()), + pathWriter(0), symPathWriter(0), specialFunctionHandler(0), + timers{time::Span(TimerInterval)}, guidanceKind(opts.Guidance), + codeGraphInfo(new CodeGraphInfo()), distanceCalculator(new DistanceCalculator(*codeGraphInfo)), targetCalculator(new TargetCalculator(*codeGraphInfo)), targetManager(new TargetManager(guidanceKind, *distanceCalculator, @@ -6829,8 +6831,7 @@ void Executor::executeMakeSymbolic(ExecutionState &state, (!AllowSeedTruncation && obj->numBytes > moSize))) { std::stringstream msg; msg << "replace size mismatch: " << mo->name << "[" << moSize - << "]" - << " vs " << obj->name << "[" << obj->numBytes << "]" + << "]" << " vs " << obj->name << "[" << obj->numBytes << "]" << " in test\n"; terminateStateOnUserError(state, msg.str()); @@ -7252,8 +7253,7 @@ void Executor::logState(const ExecutionState &state, int id, object.first->getSizeExpr()->print(*f); *f << "\n"; } - *f << state.symbolics.size() << " symbolics total. " - << "Symbolics:\n"; + *f << state.symbolics.size() << " symbolics total. " << "Symbolics:\n"; size_t sc = 0; for (const auto &symbolic : state.symbolics) { *f << "Symbolic number " << sc++ << "\n"; @@ -7455,6 +7455,24 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { solver->setTimeout(coreSolverTimeout); PathConstraints extendedConstraints(state.constraints); + std::map StatisticMap{}; + + for (ExecutionState *es : objectManager->getStates()) { + InfoStackFrame &sf = es->stack.infoStack().back(); + CallPathNode *pn = sf.callPathNode; + if (StatisticMap.find(pn->function->getName().str()) == + StatisticMap.end()) { + StatisticMap[pn->function->getName().str()] = pn->statistics; + } + } + + for (const auto &pair : StatisticMap) { + auto name = pair.first; + auto instr = pair.second.getValue(stats::instructions); + auto forks = pair.second.getValue(stats::forks); + std::cout << "Instructions " << name << " = " << instr << std::endl; + std::cout << "Forks " << name << " = " << forks << std::endl; + } // Go through each byte in every test case and attempt to restrict // it to the constraints contained in cexPreferences. (Note: @@ -7503,8 +7521,8 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { std::back_inserter(symbolics), isReproducible); } - // we cannot be sure that an irreproducible state proves the presence of an - // error + // we cannot be sure that an irreproducible state proves the presence of + // an error if (uninitObjects.size() > 0 || state.symbolics.size() != symbolics.size()) { state.error = ReachWithError::None; } else if (FunctionCallReproduce != "" && @@ -7586,8 +7604,8 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { ref symcretizedAddress = sizeSymcrete->addressSymcrete.symcretized; - /* Receive address array linked with this size array to request address - * concretization. */ + /* Receive address array linked with this size array to request + * address concretization. */ ref condcretized = concretizations.at(symcrete->symcretized); uint64_t newSize = cast(condcretized)->getZExtValue(); diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index d96526ce99..957e74f27d 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -2463,9 +2464,9 @@ int main(int argc, char **argv, char **envp) { std::tie(solverH, solverM, solverS) = time::seconds(solverTime).toHMS(); std::stringstream ss; - ss << std::setw(2) << std::setfill('0') << solverH << ':'; - ss << std::setw(2) << std::setfill('0') << +solverM << ':'; - ss << std::setw(2) << std::setfill('0') << +solverS; + ss << std::setw(2) << std::setfill('0') << solverH << ':' << std::setw(2) + << std::setfill('0') << +solverM << ':' << std::setw(2) + << std::setfill('0') << +solverS; handler->getInfoStream() << "KLEE: done: solver time = " << ss.str() << "\n"; @@ -2499,8 +2500,7 @@ int main(int argc, char **argv, char **envp) { << "KLEE: done: coverage = " << (static_cast(instructions - uncoverageInstructions) / instructions) * - 100 - << "%" << '\n'; + 100; bool useColors = llvm::errs().is_displayed(); if (useColors) From ecd344ebb46ac80cd9caa4aec6532e17702b5be6 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Tue, 27 Aug 2024 17:16:47 +0300 Subject: [PATCH 03/22] feat: Add a separate statistics function Signed-off-by: YazoonDinalt --- include/klee/Core/Interpreter.h | 2 ++ lib/Core/Executor.cpp | 23 +++++++++++++++++++++++ lib/Core/Executor.h | 2 ++ 3 files changed, 27 insertions(+) diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index aceb78dcfc..d2212e393c 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -237,6 +237,8 @@ class Interpreter { virtual void getConstraintLog(const ExecutionState &state, std::string &res, LogType logFormat = STP) = 0; + virtual void getFunctionStatistic() = 0; + virtual bool getSymbolicSolution(const ExecutionState &state, KTest &res) = 0; virtual void addSARIFReport(const ExecutionState &state) = 0; diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index adf1df9433..7314c18d22 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -7451,6 +7451,29 @@ bool isMakeSymbolic(const klee::Symbolic &symb) { return good; } +void Executor::getFunctionStatistic() { + + std::map StatisticMap{}; + + for (ExecutionState *es : objectManager->getStates()) { + InfoStackFrame &sf = es->stack.infoStack().back(); + CallPathNode *pn = sf.callPathNode; + if (StatisticMap.find(pn->function->getName().str()) == + StatisticMap.end()) { + StatisticMap[pn->function->getName().str()] = pn->statistics; + } + } + + for (const auto &pair : StatisticMap) { + auto name = pair.first; + auto instr = pair.second.getValue(stats::instructions); + auto forks = pair.second.getValue(stats::forks); + std::cout << "Instructions " << name << " = " << instr << std::endl; + std::cout << "Forks " << name << " = " << forks << std::endl; + } + +}; + bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { solver->setTimeout(coreSolverTimeout); diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index e990524a45..dde35ed997 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -844,6 +844,8 @@ class Executor : public Interpreter { void logState(const ExecutionState &state, int id, std::unique_ptr &f) override; + void getFunctionStatistic() override; + bool getSymbolicSolution(const ExecutionState &state, KTest &res) override; void getCoveredLines(const ExecutionState &state, From f3fb9d38e50ffde60d13d8246f88ad473f93edaf Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Fri, 6 Sep 2024 13:59:33 +0300 Subject: [PATCH 04/22] feat: Add print statistics in delta time Signed-off-by: YazoonDinalt --- include/klee/Core/Interpreter.h | 2 +- lib/Core/CMakeLists.txt | 1 + lib/Core/Delta.cpp | 30 ++++++++++ lib/Core/Delta.h | 32 +++++++++++ lib/Core/Executor.cpp | 97 +++++++++++++++++++++------------ lib/Core/Executor.h | 8 ++- 6 files changed, 134 insertions(+), 36 deletions(-) create mode 100644 lib/Core/Delta.cpp create mode 100644 lib/Core/Delta.h diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index d2212e393c..5f06ce4d24 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -237,7 +237,7 @@ class Interpreter { virtual void getConstraintLog(const ExecutionState &state, std::string &res, LogType logFormat = STP) = 0; - virtual void getFunctionStatistic() = 0; + virtual void getFunctionStatistic(std::map deltaMap) = 0; virtual bool getSymbolicSolution(const ExecutionState &state, KTest &res) = 0; diff --git a/lib/Core/CMakeLists.txt b/lib/Core/CMakeLists.txt index 9f654afc0f..3b715c8e0f 100644 --- a/lib/Core/CMakeLists.txt +++ b/lib/Core/CMakeLists.txt @@ -14,6 +14,7 @@ add_library(kleeCore Context.cpp CoreStats.cpp CXXTypeSystem/CXXTypeManager.cpp + Delta.cpp DistanceCalculator.cpp EventRecorder.cpp ExecutionState.cpp diff --git a/lib/Core/Delta.cpp b/lib/Core/Delta.cpp new file mode 100644 index 0000000000..9a47e24097 --- /dev/null +++ b/lib/Core/Delta.cpp @@ -0,0 +1,30 @@ +//===-- Delta.cpp -----------------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Delta.h" +#include + +using namespace klee; + +namespace klee { + + + +std::map +Delta::CalculateDelta(std::map statisticMap) { + + for (const auto &pair : statisticMap) { + deltaMap[pair.first] = pair.second - previousMap[pair.first]; + } + + previousMap = statisticMap; + + return deltaMap; +} +} // namespace klee diff --git a/lib/Core/Delta.h b/lib/Core/Delta.h new file mode 100644 index 0000000000..2eb6759b3f --- /dev/null +++ b/lib/Core/Delta.h @@ -0,0 +1,32 @@ +//===-- Delta.h--- ----------------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_GETDELTA_H +#define KLEE_GETDELTA_H + +#include +#include + +namespace klee { + +/// TimingSolver - A simple class that collects delta statistics +class Delta { +public: + std::map deltaMap; + std::map previousMap{{"Instructions", 0}, {"Forks", 0}}; + ; + +public: + void initPrevious(); + std::map + CalculateDelta(std::map statisticMap); +}; +} // namespace klee + +#endif /* KLEE_DELTA_H */ diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 7314c18d22..dccfbc00db 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -14,6 +14,7 @@ #include "CallPathManager.h" #include "ConstructStorage.h" #include "CoreStats.h" +#include "Delta.h" #include "DistanceCalculator.h" #include "ExecutionState.h" #include "ExternalDispatcher.h" @@ -4699,8 +4700,32 @@ void Executor::run(ExecutionState *initialState) { objectManager->initialUpdate(); + // std::atomic running = true; + + auto lastExecutionTime = std::chrono::steady_clock::now(); + + Delta dt; + // main interpreter loop while (!haltExecution && !searcher->empty()) { + + auto currentTime = std::chrono::steady_clock::now(); + + if (std::chrono::duration_cast(currentTime - + lastExecutionTime) + .count() >= 1) { + + std::map statisticsMap = { + {"Instructions", + *theStatisticManager->getStatisticByName("Instructions")}, + {"Forks", *theStatisticManager->getStatisticByName("Forks")}}; + + std::thread thread = this->spawn(dt.CalculateDelta(statisticsMap)); + + lastExecutionTime = currentTime; + thread.join(); + } + auto action = searcher->selectAction(); executeAction(action); objectManager->updateSubscribers(); @@ -7451,51 +7476,55 @@ bool isMakeSymbolic(const klee::Symbolic &symb) { return good; } -void Executor::getFunctionStatistic() { +void Executor::getFunctionStatistic(std::map deltaMap) { - std::map StatisticMap{}; + std::cout << "==== Current delta ====" << std::endl; - for (ExecutionState *es : objectManager->getStates()) { - InfoStackFrame &sf = es->stack.infoStack().back(); - CallPathNode *pn = sf.callPathNode; - if (StatisticMap.find(pn->function->getName().str()) == - StatisticMap.end()) { - StatisticMap[pn->function->getName().str()] = pn->statistics; - } + for (const auto &pair : deltaMap) { + std::cout << pair.first << " = " << pair.second << std::endl; } - for (const auto &pair : StatisticMap) { - auto name = pair.first; - auto instr = pair.second.getValue(stats::instructions); - auto forks = pair.second.getValue(stats::forks); - std::cout << "Instructions " << name << " = " << instr << std::endl; - std::cout << "Forks " << name << " = " << forks << std::endl; - } + // std::map StatisticMap{}; + // for (ExecutionState *es : objectManager->getStates()) { + // InfoStackFrame &sf = es->stack.infoStack().back(); + // CallPathNode *pn = sf.callPathNode; + // if (StatisticMap.find(pn->function->getName().str()) == + // StatisticMap.end()) { + // StatisticMap[pn->function->getName().str()] = pn->statistics; + // } + // } + + // std::cout << "==== Current statistic ====" << std::endl; + + // for (const auto &pair : StatisticMap) { + // auto name = pair.first; + // auto instr = pair.second.getValue(stats::instructions); + // auto forks = pair.second.getValue(stats::forks); + // std::cout << "===== Current function is " << name << " =====" << '\n' + // << "Instructions = " << instr << '\n' + // << "Forks = " << forks << std::endl; + // } + + // std::this_thread::sleep_for(std::chrono::milliseconds(5)); + + // std::cout << "==== Current statistic ====" << std::endl; + + // std::stringstream stats; + + // stats << '\n' + // << "KLEE: done: total instructions = " + // << *theStatisticManager->getStatisticByName("Instructions") << '\n' + // << "KLEE: done: forks = " + // << *theStatisticManager->getStatisticByName("Forks") << '\n'; + // std::cout << stats.str() << std::endl; + // std::this_thread::sleep_for(std::chrono::milliseconds(10)); }; bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { solver->setTimeout(coreSolverTimeout); PathConstraints extendedConstraints(state.constraints); - std::map StatisticMap{}; - - for (ExecutionState *es : objectManager->getStates()) { - InfoStackFrame &sf = es->stack.infoStack().back(); - CallPathNode *pn = sf.callPathNode; - if (StatisticMap.find(pn->function->getName().str()) == - StatisticMap.end()) { - StatisticMap[pn->function->getName().str()] = pn->statistics; - } - } - - for (const auto &pair : StatisticMap) { - auto name = pair.first; - auto instr = pair.second.getValue(stats::instructions); - auto forks = pair.second.getValue(stats::forks); - std::cout << "Instructions " << name << " = " << instr << std::endl; - std::cout << "Forks " << name << " = " << forks << std::endl; - } // Go through each byte in every test case and attempt to restrict // it to the constraints contained in cexPreferences. (Note: diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index dde35ed997..04f49eff34 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -92,6 +92,7 @@ class MemoryManager; class MemoryObject; class ObjectState; class PForest; +class Delta; class Searcher; class SeedInfo; class SpecialFunctionHandler; @@ -844,7 +845,12 @@ class Executor : public Interpreter { void logState(const ExecutionState &state, int id, std::unique_ptr &f) override; - void getFunctionStatistic() override; + void getFunctionStatistic(std::map deltaMap) override; + + std::thread spawn(std::map deltaMap) { + return std::thread( + [this, deltaMap]() { this->getFunctionStatistic(deltaMap); }); + } bool getSymbolicSolution(const ExecutionState &state, KTest &res) override; From 049ab9806efece43efc808e592350726f0bd0102 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Fri, 6 Sep 2024 15:05:13 +0300 Subject: [PATCH 05/22] feat: Change type Calculate Delta function Signed-off-by: YazoonDinalt --- include/klee/Core/Interpreter.h | 3 +- lib/Core/Delta.cpp | 19 +++++---- lib/Core/Delta.h | 9 +++-- lib/Core/Executor.cpp | 70 ++++++++++++--------------------- lib/Core/Executor.h | 6 ++- 5 files changed, 48 insertions(+), 59 deletions(-) diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index 5f06ce4d24..c856106a78 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -237,7 +237,8 @@ class Interpreter { virtual void getConstraintLog(const ExecutionState &state, std::string &res, LogType logFormat = STP) = 0; - virtual void getFunctionStatistic(std::map deltaMap) = 0; + virtual void getFunctionStatistic( + std::map> deltaMap) = 0; virtual bool getSymbolicSolution(const ExecutionState &state, KTest &res) = 0; diff --git a/lib/Core/Delta.cpp b/lib/Core/Delta.cpp index 9a47e24097..fd2435a009 100644 --- a/lib/Core/Delta.cpp +++ b/lib/Core/Delta.cpp @@ -8,23 +8,26 @@ //===----------------------------------------------------------------------===// #include "Delta.h" -#include +#include "CoreStats.h" using namespace klee; namespace klee { +std::map> +Delta::CalculateDelta(std::map StatMap) { + std::map> DelMap; -std::map -Delta::CalculateDelta(std::map statisticMap) { + for (const auto &pair : StatMap) { + auto name = pair.first; - for (const auto &pair : statisticMap) { - deltaMap[pair.first] = pair.second - previousMap[pair.first]; + DelMap[pair.first]["Instructions"] = + pair.second.getValue(stats::instructions); + DelMap[pair.first]["Forks"] = pair.second.getValue(stats::forks); } - previousMap = statisticMap; - - return deltaMap; + return DelMap; } + } // namespace klee diff --git a/lib/Core/Delta.h b/lib/Core/Delta.h index 2eb6759b3f..f7ee495719 100644 --- a/lib/Core/Delta.h +++ b/lib/Core/Delta.h @@ -13,6 +13,8 @@ #include #include +#include + namespace klee { /// TimingSolver - A simple class that collects delta statistics @@ -20,12 +22,13 @@ class Delta { public: std::map deltaMap; std::map previousMap{{"Instructions", 0}, {"Forks", 0}}; + std::map> newDelta; ; public: - void initPrevious(); - std::map - CalculateDelta(std::map statisticMap); + + std::map> + CalculateDelta(std::map StatMap); }; } // namespace klee diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index dccfbc00db..99f1b3ac67 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -4703,9 +4703,17 @@ void Executor::run(ExecutionState *initialState) { // std::atomic running = true; auto lastExecutionTime = std::chrono::steady_clock::now(); - + std::map StatisticMap{}; + for (const auto &pair : StatisticMap) { + auto name = pair.first; + auto instr = pair.second.getValue(stats::instructions); + auto forks = pair.second.getValue(stats::forks); + std::cout << "===== Current function is " << name << " =====" << '\n' + << "Instructions = " << instr << '\n' + << "Forks = " << forks << std::endl; + } Delta dt; - + // main interpreter loop while (!haltExecution && !searcher->empty()) { @@ -4715,12 +4723,14 @@ void Executor::run(ExecutionState *initialState) { lastExecutionTime) .count() >= 1) { - std::map statisticsMap = { - {"Instructions", - *theStatisticManager->getStatisticByName("Instructions")}, - {"Forks", *theStatisticManager->getStatisticByName("Forks")}}; - std::thread thread = this->spawn(dt.CalculateDelta(statisticsMap)); + for (ExecutionState *es : objectManager->getStates()) { + InfoStackFrame &sf = es->stack.infoStack().back(); + CallPathNode *pn = sf.callPathNode; + StatisticMap[pn->function->getName().str()] = pn->statistics; + } + + std::thread thread = this->spawn(dt.CalculateDelta(StatisticMap)); lastExecutionTime = currentTime; thread.join(); @@ -7476,49 +7486,19 @@ bool isMakeSymbolic(const klee::Symbolic &symb) { return good; } -void Executor::getFunctionStatistic(std::map deltaMap) { +void Executor::getFunctionStatistic( + std::map> deltaMap) { std::cout << "==== Current delta ====" << std::endl; - for (const auto &pair : deltaMap) { - std::cout << pair.first << " = " << pair.second << std::endl; + for (const auto &[key1, map2] : deltaMap) { + std::cout << " Имя функции: " << key1 << std::endl; + for (const auto &[key2, value] : map2) { + std::cout << " Имя статистики: " << key2 << ", Изменение: " << value + << std::endl; + } } - // std::map StatisticMap{}; - - // for (ExecutionState *es : objectManager->getStates()) { - // InfoStackFrame &sf = es->stack.infoStack().back(); - // CallPathNode *pn = sf.callPathNode; - // if (StatisticMap.find(pn->function->getName().str()) == - // StatisticMap.end()) { - // StatisticMap[pn->function->getName().str()] = pn->statistics; - // } - // } - - // std::cout << "==== Current statistic ====" << std::endl; - - // for (const auto &pair : StatisticMap) { - // auto name = pair.first; - // auto instr = pair.second.getValue(stats::instructions); - // auto forks = pair.second.getValue(stats::forks); - // std::cout << "===== Current function is " << name << " =====" << '\n' - // << "Instructions = " << instr << '\n' - // << "Forks = " << forks << std::endl; - // } - - // std::this_thread::sleep_for(std::chrono::milliseconds(5)); - - // std::cout << "==== Current statistic ====" << std::endl; - - // std::stringstream stats; - - // stats << '\n' - // << "KLEE: done: total instructions = " - // << *theStatisticManager->getStatisticByName("Instructions") << '\n' - // << "KLEE: done: forks = " - // << *theStatisticManager->getStatisticByName("Forks") << '\n'; - // std::cout << stats.str() << std::endl; - // std::this_thread::sleep_for(std::chrono::milliseconds(10)); }; bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index 04f49eff34..62c1488522 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -845,9 +845,11 @@ class Executor : public Interpreter { void logState(const ExecutionState &state, int id, std::unique_ptr &f) override; - void getFunctionStatistic(std::map deltaMap) override; + void getFunctionStatistic( + std::map> deltaMap) override; - std::thread spawn(std::map deltaMap) { + std::thread + spawn(std::map> deltaMap) { return std::thread( [this, deltaMap]() { this->getFunctionStatistic(deltaMap); }); } From 11fb1fc2da909af0f6542ba9e09262527d3256c1 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Tue, 17 Sep 2024 03:37:02 +0300 Subject: [PATCH 06/22] feat: Add output of statistics for each function by time delta Signed-off-by: YazoonDinalt --- lib/Core/Delta.cpp | 47 +++++++++++++++++++++++++++++++++++++++++-- lib/Core/Delta.h | 13 +++++++----- lib/Core/Executor.cpp | 44 +++++++++++++++++++++++++++++++++------- 3 files changed, 90 insertions(+), 14 deletions(-) diff --git a/lib/Core/Delta.cpp b/lib/Core/Delta.cpp index fd2435a009..19fae4a03a 100644 --- a/lib/Core/Delta.cpp +++ b/lib/Core/Delta.cpp @@ -23,11 +23,54 @@ Delta::CalculateDelta(std::map StatMap) { auto name = pair.first; DelMap[pair.first]["Instructions"] = - pair.second.getValue(stats::instructions); - DelMap[pair.first]["Forks"] = pair.second.getValue(stats::forks); + pair.second.getValue(stats::instructions) - + previousMap[pair.first].getValue(stats::instructions); + DelMap[pair.first]["Forks"] = + pair.second.getValue(stats::forks) - + previousMap[pair.first].getValue(stats::forks); } + previousMap = StatMap; + + // SerializeDelMap(DelMap); + return DelMap; } +std::vector Delta::SerializeDelMap( + const std::map> &DelMap) { + + std::vector jsonArray; + + for (const auto &funPair : DelMap) { + const std::string &funName = funPair.first; + const auto &metricsMap = funPair.second; + + for (const auto &metricPair : metricsMap) { + const std::string &metricName = metricPair.first; + int count = metricPair.second; + + if (count != 0) { + jsonArray.push_back({{"name", metricName}, + {"params", + {{"funName", funName}, + {"type", "int"}, + {"value", count}, + {"transitive", false}}}}); + } + } + } + + // for (const auto &jsonObj : jsonArray) { + // std::cout << jsonObj.dump(4) + // << std::endl; // 4 - количество пробелов для отступа + // } + // std::cout << "\n\n\n" << std::endl; + return jsonArray; +} + +void Delta::initPrevDelta(std::map StatMap) { + previousMap = StatMap; +} + } // namespace klee diff --git a/lib/Core/Delta.h b/lib/Core/Delta.h index f7ee495719..ad5f6483e6 100644 --- a/lib/Core/Delta.h +++ b/lib/Core/Delta.h @@ -10,6 +10,7 @@ #ifndef KLEE_GETDELTA_H #define KLEE_GETDELTA_H +#include "nlohmann/json.hpp" #include #include @@ -20,15 +21,17 @@ namespace klee { /// TimingSolver - A simple class that collects delta statistics class Delta { public: - std::map deltaMap; - std::map previousMap{{"Instructions", 0}, {"Forks", 0}}; - std::map> newDelta; - ; + std::map previousMap; + std::map> Delta; public: - std::map> CalculateDelta(std::map StatMap); + + std::vector SerializeDelMap( + const std::map> &DelMap); + + void initPrevDelta(std::map StatMap); }; } // namespace klee diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 99f1b3ac67..8f35509f1a 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -4703,7 +4703,7 @@ void Executor::run(ExecutionState *initialState) { // std::atomic running = true; auto lastExecutionTime = std::chrono::steady_clock::now(); - std::map StatisticMap{}; + std::map StatisticMap; for (const auto &pair : StatisticMap) { auto name = pair.first; auto instr = pair.second.getValue(stats::instructions); @@ -4714,6 +4714,8 @@ void Executor::run(ExecutionState *initialState) { } Delta dt; + dt.initPrevDelta(StatisticMap); + // main interpreter loop while (!haltExecution && !searcher->empty()) { @@ -4723,17 +4725,19 @@ void Executor::run(ExecutionState *initialState) { lastExecutionTime) .count() >= 1) { - for (ExecutionState *es : objectManager->getStates()) { InfoStackFrame &sf = es->stack.infoStack().back(); CallPathNode *pn = sf.callPathNode; StatisticMap[pn->function->getName().str()] = pn->statistics; } +// llvm::Function* + auto deltaMap = dt.CalculateDelta(StatisticMap); + getFunctionStatistic(deltaMap); - std::thread thread = this->spawn(dt.CalculateDelta(StatisticMap)); + // std::thread thread = this->spawn(deltaMap); lastExecutionTime = currentTime; - thread.join(); + // thread.join(); } auto action = searcher->selectAction(); @@ -7492,15 +7496,41 @@ void Executor::getFunctionStatistic( std::cout << "==== Current delta ====" << std::endl; for (const auto &[key1, map2] : deltaMap) { - std::cout << " Имя функции: " << key1 << std::endl; + std::cout << " Fun name: " << key1 << std::endl; for (const auto &[key2, value] : map2) { - std::cout << " Имя статистики: " << key2 << ", Изменение: " << value + std::cout << " Metrics name: " << key2 << ", delta: " << value << std::endl; } } - }; +// void sendPostRequest(const std::string& url, const std::vector& metrics) { +// CURL *curl; +// CURLcode res; + +// curl_global_init(CURL_GLOBAL_ALL); +// curl = curl_easy_init(); + +// if (curl) { + +// json jsonData = metrics; +// std::string jsonString = jsonData.dump(); + +// curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); +// curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonString.c_str()); +// res = curl_easy_perform(curl); + +// if (res != CURLE_OK) +// fprintf(stderr, "curl_easy_perform() failed: %s\n", +// curl_easy_strerror(res)); + + +// curl_easy_cleanup(curl); +// } +// curl_global_cleanup(); +// return 0; +// } + bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { solver->setTimeout(coreSolverTimeout); From 2e7c104e8f2a346b531a448dbd394743b7b9c91c Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Tue, 17 Sep 2024 04:21:53 +0300 Subject: [PATCH 07/22] fix: Fix bug with incorrect metrics calculation Signed-off-by: YazoonDinalt --- include/klee/Core/Interpreter.h | 3 ++- lib/Core/Delta.cpp | 12 ++++++------ lib/Core/Delta.h | 14 +++++++++----- lib/Core/Executor.cpp | 23 ++++++++++------------- lib/Core/Executor.h | 5 +++-- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index c856106a78..47d2c1f314 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -238,7 +238,8 @@ class Interpreter { LogType logFormat = STP) = 0; virtual void getFunctionStatistic( - std::map> deltaMap) = 0; + std::map> + deltaMap) = 0; virtual bool getSymbolicSolution(const ExecutionState &state, KTest &res) = 0; diff --git a/lib/Core/Delta.cpp b/lib/Core/Delta.cpp index 19fae4a03a..65c5667acc 100644 --- a/lib/Core/Delta.cpp +++ b/lib/Core/Delta.cpp @@ -14,14 +14,13 @@ using namespace klee; namespace klee { -std::map> -Delta::CalculateDelta(std::map StatMap) { +std::map> +Delta::CalculateDelta( + std::map StatMap) { - std::map> DelMap; + std::map> DelMap; for (const auto &pair : StatMap) { - auto name = pair.first; - DelMap[pair.first]["Instructions"] = pair.second.getValue(stats::instructions) - previousMap[pair.first].getValue(stats::instructions); @@ -69,7 +68,8 @@ std::vector Delta::SerializeDelMap( return jsonArray; } -void Delta::initPrevDelta(std::map StatMap) { +void Delta::initPrevDelta( + std::map StatMap) { previousMap = StatMap; } diff --git a/lib/Core/Delta.h b/lib/Core/Delta.h index ad5f6483e6..d69521fc82 100644 --- a/lib/Core/Delta.h +++ b/lib/Core/Delta.h @@ -11,6 +11,10 @@ #define KLEE_GETDELTA_H #include "nlohmann/json.hpp" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h" #include #include @@ -21,17 +25,17 @@ namespace klee { /// TimingSolver - A simple class that collects delta statistics class Delta { public: - std::map previousMap; - std::map> Delta; + std::map previousMap; + std::map> Delta; public: - std::map> - CalculateDelta(std::map StatMap); + std::map> + CalculateDelta(std::map StatMap); std::vector SerializeDelMap( const std::map> &DelMap); - void initPrevDelta(std::map StatMap); + void initPrevDelta(std::map StatMap); }; } // namespace klee diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 8f35509f1a..9f311c38c7 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -4703,9 +4703,9 @@ void Executor::run(ExecutionState *initialState) { // std::atomic running = true; auto lastExecutionTime = std::chrono::steady_clock::now(); - std::map StatisticMap; + std::map StatisticMap; for (const auto &pair : StatisticMap) { - auto name = pair.first; + auto name = pair.first->getName().str(); auto instr = pair.second.getValue(stats::instructions); auto forks = pair.second.getValue(stats::forks); std::cout << "===== Current function is " << name << " =====" << '\n' @@ -4720,7 +4720,6 @@ void Executor::run(ExecutionState *initialState) { while (!haltExecution && !searcher->empty()) { auto currentTime = std::chrono::steady_clock::now(); - if (std::chrono::duration_cast(currentTime - lastExecutionTime) .count() >= 1) { @@ -4728,14 +4727,12 @@ void Executor::run(ExecutionState *initialState) { for (ExecutionState *es : objectManager->getStates()) { InfoStackFrame &sf = es->stack.infoStack().back(); CallPathNode *pn = sf.callPathNode; - StatisticMap[pn->function->getName().str()] = pn->statistics; + const llvm::Function *funcPtr = pn->function; + StatisticMap[funcPtr] = pn->statistics; } -// llvm::Function* - auto deltaMap = dt.CalculateDelta(StatisticMap); - getFunctionStatistic(deltaMap); + getFunctionStatistic(dt.CalculateDelta(StatisticMap)); // std::thread thread = this->spawn(deltaMap); - lastExecutionTime = currentTime; // thread.join(); } @@ -7491,12 +7488,12 @@ bool isMakeSymbolic(const klee::Symbolic &symb) { } void Executor::getFunctionStatistic( - std::map> deltaMap) { + std::map> deltaMap) { std::cout << "==== Current delta ====" << std::endl; for (const auto &[key1, map2] : deltaMap) { - std::cout << " Fun name: " << key1 << std::endl; + std::cout << " Fun name: " << key1->getName().str() << std::endl; for (const auto &[key2, value] : map2) { std::cout << " Metrics name: " << key2 << ", delta: " << value << std::endl; @@ -7504,7 +7501,8 @@ void Executor::getFunctionStatistic( } }; -// void sendPostRequest(const std::string& url, const std::vector& metrics) { +// void sendPostRequest(const std::string& url, const std::vector& +// metrics) { // CURL *curl; // CURLcode res; @@ -7513,7 +7511,7 @@ void Executor::getFunctionStatistic( // if (curl) { -// json jsonData = metrics; +// json jsonData = metrics; // std::string jsonString = jsonData.dump(); // curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); @@ -7524,7 +7522,6 @@ void Executor::getFunctionStatistic( // fprintf(stderr, "curl_easy_perform() failed: %s\n", // curl_easy_strerror(res)); - // curl_easy_cleanup(curl); // } // curl_global_cleanup(); diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index 62c1488522..caa0cccdb9 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -846,10 +846,11 @@ class Executor : public Interpreter { std::unique_ptr &f) override; void getFunctionStatistic( - std::map> deltaMap) override; + std::map> deltaMap) + override; std::thread - spawn(std::map> deltaMap) { + spawn(std::map> deltaMap) { return std::thread( [this, deltaMap]() { this->getFunctionStatistic(deltaMap); }); } From 67dd22e8889f54926964f89d03f342a33ae34819 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Wed, 9 Oct 2024 22:00:33 +0300 Subject: [PATCH 08/22] feat: Add save metrics on server Signed-off-by: YazoonDinalt --- include/klee/Core/Interpreter.h | 3 ++ lib/Core/CMakeLists.txt | 5 ++++ lib/Core/Delta.cpp | 9 ++++-- lib/Core/Delta.h | 4 +-- lib/Core/Executor.cpp | 52 ++++++++++++++++++++------------- lib/Core/Executor.h | 3 ++ 6 files changed, 51 insertions(+), 25 deletions(-) diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index 47d2c1f314..f7a5b57736 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -237,6 +237,9 @@ class Interpreter { virtual void getConstraintLog(const ExecutionState &state, std::string &res, LogType logFormat = STP) = 0; + virtual void sendPostRequest(const std::string &url, + const std::vector &metrics) = 0; + virtual void getFunctionStatistic( std::map> deltaMap) = 0; diff --git a/lib/Core/CMakeLists.txt b/lib/Core/CMakeLists.txt index 3b715c8e0f..f0d2cc491b 100644 --- a/lib/Core/CMakeLists.txt +++ b/lib/Core/CMakeLists.txt @@ -53,7 +53,12 @@ target_link_libraries(kleeCore PRIVATE llvm_config(kleeCore "${USE_LLVM_SHARED}" core executionengine mcjit native support) target_link_libraries(kleeCore PRIVATE ${SQLite3_LIBRARIES}) + +find_package(CURL REQUIRED) + target_include_directories(kleeCore SYSTEM PRIVATE ${LLVM_INCLUDE_DIRS} ${SQLite3_INCLUDE_DIRS}) target_include_directories(kleeCore PRIVATE ${KLEE_INCLUDE_DIRS}) target_compile_options(kleeCore PRIVATE ${KLEE_COMPONENT_CXX_FLAGS}) target_compile_definitions(kleeCore PRIVATE ${KLEE_COMPONENT_CXX_DEFINES}) +target_include_directories(kleeCore SYSTEM PRIVATE ${CURL_INCLUDE_DIRS}) +target_link_libraries(kleeCore PRIVATE CURL::libcurl) diff --git a/lib/Core/Delta.cpp b/lib/Core/Delta.cpp index 65c5667acc..3c5b8d964a 100644 --- a/lib/Core/Delta.cpp +++ b/lib/Core/Delta.cpp @@ -9,6 +9,7 @@ #include "Delta.h" #include "CoreStats.h" +#include using namespace klee; @@ -37,17 +38,20 @@ Delta::CalculateDelta( } std::vector Delta::SerializeDelMap( - const std::map> &DelMap) { + std::map> &DelMap) { std::vector jsonArray; for (const auto &funPair : DelMap) { - const std::string &funName = funPair.first; + auto funName = funPair.first->getName(); const auto &metricsMap = funPair.second; for (const auto &metricPair : metricsMap) { + std::cout << &funName << std::endl; const std::string &metricName = metricPair.first; int count = metricPair.second; + std::cout << metricName << std::endl; + std::cout << count << std::endl; if (count != 0) { jsonArray.push_back({{"name", metricName}, @@ -65,6 +69,7 @@ std::vector Delta::SerializeDelMap( // << std::endl; // 4 - количество пробелов для отступа // } // std::cout << "\n\n\n" << std::endl; + return jsonArray; } diff --git a/lib/Core/Delta.h b/lib/Core/Delta.h index d69521fc82..8b274cae98 100644 --- a/lib/Core/Delta.h +++ b/lib/Core/Delta.h @@ -33,9 +33,9 @@ class Delta { CalculateDelta(std::map StatMap); std::vector SerializeDelMap( - const std::map> &DelMap); + std::map> &DelMap); - void initPrevDelta(std::map StatMap); + void initPrevDelta(std::map StatMap); }; } // namespace klee diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 9f311c38c7..f2d60b1358 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -102,6 +102,7 @@ #include #include +#include #include #include #include @@ -4730,8 +4731,13 @@ void Executor::run(ExecutionState *initialState) { const llvm::Function *funcPtr = pn->function; StatisticMap[funcPtr] = pn->statistics; } - getFunctionStatistic(dt.CalculateDelta(StatisticMap)); + // getFunctionStatistic(dt.CalculateDelta(StatisticMap)); + + auto a = dt.CalculateDelta(StatisticMap); + + sendPostRequest("http://localhost:8080/server/save-metric", + dt.SerializeDelMap(a)); // std::thread thread = this->spawn(deltaMap); lastExecutionTime = currentTime; // thread.join(); @@ -7501,32 +7507,36 @@ void Executor::getFunctionStatistic( } }; -// void sendPostRequest(const std::string& url, const std::vector& -// metrics) { -// CURL *curl; -// CURLcode res; +void Executor::sendPostRequest(const std::string &url, + const std::vector &metrics) { + CURL *curl; + CURLcode res; -// curl_global_init(CURL_GLOBAL_ALL); -// curl = curl_easy_init(); + curl_global_init(CURL_GLOBAL_ALL); + curl = curl_easy_init(); -// if (curl) { + if (curl) { + json jsonData = metrics; + std::string jsonString = jsonData.dump(); -// json jsonData = metrics; -// std::string jsonString = jsonData.dump(); + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonString.c_str()); -// curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); -// curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonString.c_str()); -// res = curl_easy_perform(curl); + struct curl_slist *headers = nullptr; + headers = curl_slist_append(headers, "Content-Type: application/json"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); -// if (res != CURLE_OK) -// fprintf(stderr, "curl_easy_perform() failed: %s\n", -// curl_easy_strerror(res)); + res = curl_easy_perform(curl); + std::cout << jsonString << std::endl; + + if (res != CURLE_OK) + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); -// curl_easy_cleanup(curl); -// } -// curl_global_cleanup(); -// return 0; -// } + curl_easy_cleanup(curl); + } + curl_global_cleanup(); +} bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { solver->setTimeout(coreSolverTimeout); diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index caa0cccdb9..d9fbc4d841 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -845,6 +845,9 @@ class Executor : public Interpreter { void logState(const ExecutionState &state, int id, std::unique_ptr &f) override; + void sendPostRequest(const std::string &url, + const std::vector &metrics) override; + void getFunctionStatistic( std::map> deltaMap) override; From d7a9128e496f3c2aa9a74df7284985f2d9c35286 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Mon, 14 Oct 2024 20:32:03 +0300 Subject: [PATCH 09/22] feat: Moving network interaction into a separate class Signed-off-by: YazoonDinalt --- include/klee/Core/Interpreter.h | 3 --- lib/Core/CMakeLists.txt | 1 + lib/Core/Delta.cpp | 31 ++++++++++++---------- lib/Core/Delta.h | 5 +++- lib/Core/Executor.cpp | 46 +++++++-------------------------- lib/Core/Executor.h | 3 --- lib/Core/ServerConnection.cpp | 45 ++++++++++++++++++++++++++++++++ lib/Core/ServerConnection.h | 30 +++++++++++++++++++++ 8 files changed, 107 insertions(+), 57 deletions(-) create mode 100644 lib/Core/ServerConnection.cpp create mode 100644 lib/Core/ServerConnection.h diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index f7a5b57736..47d2c1f314 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -237,9 +237,6 @@ class Interpreter { virtual void getConstraintLog(const ExecutionState &state, std::string &res, LogType logFormat = STP) = 0; - virtual void sendPostRequest(const std::string &url, - const std::vector &metrics) = 0; - virtual void getFunctionStatistic( std::map> deltaMap) = 0; diff --git a/lib/Core/CMakeLists.txt b/lib/Core/CMakeLists.txt index f0d2cc491b..26b0398446 100644 --- a/lib/Core/CMakeLists.txt +++ b/lib/Core/CMakeLists.txt @@ -40,6 +40,7 @@ add_library(kleeCore TimingSolver.cpp TypeManager.cpp UserSearcher.cpp + ServerConnection.cpp ) target_link_libraries(kleeCore PRIVATE diff --git a/lib/Core/Delta.cpp b/lib/Core/Delta.cpp index 3c5b8d964a..441a61c3fe 100644 --- a/lib/Core/Delta.cpp +++ b/lib/Core/Delta.cpp @@ -1,4 +1,4 @@ -//===-- Delta.cpp -----------------------------------------------*- C++ -*-===// +//===-- Delta.cpp------------------------------------------------*- C++ -*-===// // // The KLEE Symbolic Virtual Machine // @@ -9,7 +9,6 @@ #include "Delta.h" #include "CoreStats.h" -#include using namespace klee; @@ -32,8 +31,6 @@ Delta::CalculateDelta( previousMap = StatMap; - // SerializeDelMap(DelMap); - return DelMap; } @@ -47,11 +44,8 @@ std::vector Delta::SerializeDelMap( const auto &metricsMap = funPair.second; for (const auto &metricPair : metricsMap) { - std::cout << &funName << std::endl; const std::string &metricName = metricPair.first; int count = metricPair.second; - std::cout << metricName << std::endl; - std::cout << count << std::endl; if (count != 0) { jsonArray.push_back({{"name", metricName}, @@ -64,15 +58,26 @@ std::vector Delta::SerializeDelMap( } } - // for (const auto &jsonObj : jsonArray) { - // std::cout << jsonObj.dump(4) - // << std::endl; // 4 - количество пробелов для отступа - // } - // std::cout << "\n\n\n" << std::endl; - return jsonArray; } +std::map> +Delta::getCurrentMetric( + std::map StatMap) { + + std::map> DelMap; + + for (const auto &pair : StatMap) { + DelMap[pair.first]["Instructions"] = + pair.second.getValue(stats::instructions); + DelMap[pair.first]["Forks"] = pair.second.getValue(stats::forks); + } + + previousMap = StatMap; + + return DelMap; +} + void Delta::initPrevDelta( std::map StatMap) { previousMap = StatMap; diff --git a/lib/Core/Delta.h b/lib/Core/Delta.h index 8b274cae98..b8724f3f97 100644 --- a/lib/Core/Delta.h +++ b/lib/Core/Delta.h @@ -1,4 +1,4 @@ -//===-- Delta.h--- ----------------------------------------------*- C++ -*-===// +//===-- Delta.h--------------------------------------------------*- C++ -*-===// // // The KLEE Symbolic Virtual Machine // @@ -35,6 +35,9 @@ class Delta { std::vector SerializeDelMap( std::map> &DelMap); + std::map> + getCurrentMetric(std::map StatMap); + void initPrevDelta(std::map StatMap); }; } // namespace klee diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index f2d60b1358..c80a6f4dba 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -26,6 +26,7 @@ #include "PTree.h" #include "Searcher.h" #include "SeedInfo.h" +#include "ServerConnection.h" #include "SpecialFunctionHandler.h" #include "StatsTracker.h" #include "TargetCalculator.h" @@ -4717,13 +4718,15 @@ void Executor::run(ExecutionState *initialState) { dt.initPrevDelta(StatisticMap); + ServerConnection sc; + sc.url = "http://localhost:8080/server/save-metric"; // main interpreter loop while (!haltExecution && !searcher->empty()) { auto currentTime = std::chrono::steady_clock::now(); - if (std::chrono::duration_cast(currentTime - - lastExecutionTime) - .count() >= 1) { + if (std::chrono::duration_cast(currentTime - + lastExecutionTime) + .count() >= 330) { for (ExecutionState *es : objectManager->getStates()) { InfoStackFrame &sf = es->stack.infoStack().back(); @@ -4734,10 +4737,10 @@ void Executor::run(ExecutionState *initialState) { // getFunctionStatistic(dt.CalculateDelta(StatisticMap)); - auto a = dt.CalculateDelta(StatisticMap); + auto a = dt.getCurrentMetric(StatisticMap); + + sc.PostRequest(dt.SerializeDelMap(a)); - sendPostRequest("http://localhost:8080/server/save-metric", - dt.SerializeDelMap(a)); // std::thread thread = this->spawn(deltaMap); lastExecutionTime = currentTime; // thread.join(); @@ -7507,37 +7510,6 @@ void Executor::getFunctionStatistic( } }; -void Executor::sendPostRequest(const std::string &url, - const std::vector &metrics) { - CURL *curl; - CURLcode res; - - curl_global_init(CURL_GLOBAL_ALL); - curl = curl_easy_init(); - - if (curl) { - json jsonData = metrics; - std::string jsonString = jsonData.dump(); - - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonString.c_str()); - - struct curl_slist *headers = nullptr; - headers = curl_slist_append(headers, "Content-Type: application/json"); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); - - res = curl_easy_perform(curl); - std::cout << jsonString << std::endl; - - if (res != CURLE_OK) - fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); - - curl_easy_cleanup(curl); - } - curl_global_cleanup(); -} - bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { solver->setTimeout(coreSolverTimeout); diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index d9fbc4d841..caa0cccdb9 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -845,9 +845,6 @@ class Executor : public Interpreter { void logState(const ExecutionState &state, int id, std::unique_ptr &f) override; - void sendPostRequest(const std::string &url, - const std::vector &metrics) override; - void getFunctionStatistic( std::map> deltaMap) override; diff --git a/lib/Core/ServerConnection.cpp b/lib/Core/ServerConnection.cpp new file mode 100644 index 0000000000..e0d0f90635 --- /dev/null +++ b/lib/Core/ServerConnection.cpp @@ -0,0 +1,45 @@ +//===-- ServerConnection.cpp-------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ServerConnection.h" +#include + +using namespace klee; + +namespace klee { + +void ServerConnection::PostRequest(const std::vector &metrics) { + CURL *curl; + CURLcode res; + + curl_global_init(CURL_GLOBAL_ALL); + curl = curl_easy_init(); + + if (curl) { + nlohmann::json jsonData = metrics; + std::string jsonString = jsonData.dump(); + + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonString.c_str()); + + struct curl_slist *headers = nullptr; + headers = curl_slist_append(headers, "Content-Type: application/json"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + res = curl_easy_perform(curl); + + if (res != CURLE_OK) + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + + curl_easy_cleanup(curl); + } + curl_global_cleanup(); +}; +} // namespace klee \ No newline at end of file diff --git a/lib/Core/ServerConnection.h b/lib/Core/ServerConnection.h new file mode 100644 index 0000000000..8c84fbc1ca --- /dev/null +++ b/lib/Core/ServerConnection.h @@ -0,0 +1,30 @@ +//===-- ServerConnection.h---------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef KLEE_SERVERCONNECTION_H +#define KLEE_SERVERCONNECTION_H + +#include "nlohmann/json.hpp" +#include +#include + +namespace klee { + +/// TimingSolver - A simple class that collects delta statistics + class ServerConnection { + public: + std::string url; + + public: + void PostRequest(const std::vector &metrics); + }; +} // namespace klee + +#endif \ No newline at end of file From 58eb576a8239ce1fe35cec90449e8a9d5a7dbe2b Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Wed, 23 Oct 2024 03:03:48 +0300 Subject: [PATCH 10/22] feat: Remove check all states Signed-off-by: YazoonDinalt --- lib/Core/Delta.cpp | 44 +++++++++++++++++++++++--------------- lib/Core/Delta.h | 22 ++++++++++++------- lib/Core/Executor.cpp | 27 ++++------------------- lib/Core/ObjectManager.cpp | 5 +++++ lib/Core/ObjectManager.h | 2 ++ 5 files changed, 52 insertions(+), 48 deletions(-) diff --git a/lib/Core/Delta.cpp b/lib/Core/Delta.cpp index 441a61c3fe..efe4567a8c 100644 --- a/lib/Core/Delta.cpp +++ b/lib/Core/Delta.cpp @@ -14,19 +14,21 @@ using namespace klee; namespace klee { -std::map> +std::unordered_map> Delta::CalculateDelta( - std::map StatMap) { + std::unordered_map StatMap) { - std::map> DelMap; + std::unordered_map> + DelMap; for (const auto &pair : StatMap) { DelMap[pair.first]["Instructions"] = - pair.second.getValue(stats::instructions) - - previousMap[pair.first].getValue(stats::instructions); + pair.second->getValue(stats::instructions) - + previousMap[pair.first]->getValue(stats::instructions); DelMap[pair.first]["Forks"] = - pair.second.getValue(stats::forks) - - previousMap[pair.first].getValue(stats::forks); + pair.second->getValue(stats::forks) - + previousMap[pair.first]->getValue(stats::forks); } previousMap = StatMap; @@ -35,7 +37,8 @@ Delta::CalculateDelta( } std::vector Delta::SerializeDelMap( - std::map> &DelMap) { + std::unordered_map> &DelMap) { std::vector jsonArray; @@ -45,7 +48,14 @@ std::vector Delta::SerializeDelMap( for (const auto &metricPair : metricsMap) { const std::string &metricName = metricPair.first; - int count = metricPair.second; + int prev = 0; + if (metricName == "Instructions") { + prev = previousMap[funPair.first]->getValue(stats::instructions); + } else if (metricName == "Forks") { + prev = previousMap[funPair.first]->getValue(stats::forks); + } + + int count = metricPair.second - prev; if (count != 0) { jsonArray.push_back({{"name", metricName}, @@ -61,25 +71,25 @@ std::vector Delta::SerializeDelMap( return jsonArray; } -std::map> +std::unordered_map> Delta::getCurrentMetric( - std::map StatMap) { + std::unordered_map StatMap) { - std::map> DelMap; + std::unordered_map> + DelMap; for (const auto &pair : StatMap) { DelMap[pair.first]["Instructions"] = - pair.second.getValue(stats::instructions); - DelMap[pair.first]["Forks"] = pair.second.getValue(stats::forks); + pair.second->getValue(stats::instructions); + DelMap[pair.first]["Forks"] = pair.second->getValue(stats::forks); } - previousMap = StatMap; - return DelMap; } void Delta::initPrevDelta( - std::map StatMap) { + std::unordered_map StatMap) { previousMap = StatMap; } diff --git a/lib/Core/Delta.h b/lib/Core/Delta.h index b8724f3f97..8749a7feaf 100644 --- a/lib/Core/Delta.h +++ b/lib/Core/Delta.h @@ -25,20 +25,26 @@ namespace klee { /// TimingSolver - A simple class that collects delta statistics class Delta { public: - std::map previousMap; - std::map> Delta; + std::unordered_map previousMap; + std::unordered_map> Delta; public: - std::map> - CalculateDelta(std::map StatMap); + std::unordered_map> + CalculateDelta( + std::unordered_map StatMap); std::vector SerializeDelMap( - std::map> &DelMap); + std::unordered_map> &DelMap); - std::map> - getCurrentMetric(std::map StatMap); + std::unordered_map> + getCurrentMetric( + std::unordered_map StatMap); - void initPrevDelta(std::map StatMap); + void initPrevDelta( + std::unordered_map StatMap); }; } // namespace klee diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index c80a6f4dba..ab72741ce9 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -4705,18 +4705,9 @@ void Executor::run(ExecutionState *initialState) { // std::atomic running = true; auto lastExecutionTime = std::chrono::steady_clock::now(); - std::map StatisticMap; - for (const auto &pair : StatisticMap) { - auto name = pair.first->getName().str(); - auto instr = pair.second.getValue(stats::instructions); - auto forks = pair.second.getValue(stats::forks); - std::cout << "===== Current function is " << name << " =====" << '\n' - << "Instructions = " << instr << '\n' - << "Forks = " << forks << std::endl; - } Delta dt; - dt.initPrevDelta(StatisticMap); + dt.initPrevDelta(objectManager->StatisticMap); ServerConnection sc; sc.url = "http://localhost:8080/server/save-metric"; @@ -4726,21 +4717,11 @@ void Executor::run(ExecutionState *initialState) { auto currentTime = std::chrono::steady_clock::now(); if (std::chrono::duration_cast(currentTime - lastExecutionTime) - .count() >= 330) { - - for (ExecutionState *es : objectManager->getStates()) { - InfoStackFrame &sf = es->stack.infoStack().back(); - CallPathNode *pn = sf.callPathNode; - const llvm::Function *funcPtr = pn->function; - StatisticMap[funcPtr] = pn->statistics; - } - - // getFunctionStatistic(dt.CalculateDelta(StatisticMap)); - - auto a = dt.getCurrentMetric(StatisticMap); + .count() >= 33) { + dt.previousMap = objectManager->StatisticMap; + auto a = dt.getCurrentMetric(objectManager->StatisticMap); sc.PostRequest(dt.SerializeDelMap(a)); - // std::thread thread = this->spawn(deltaMap); lastExecutionTime = currentTime; // thread.join(); diff --git a/lib/Core/ObjectManager.cpp b/lib/Core/ObjectManager.cpp index 40a66eee23..7618a5dc6b 100644 --- a/lib/Core/ObjectManager.cpp +++ b/lib/Core/ObjectManager.cpp @@ -1,5 +1,6 @@ #include "ObjectManager.h" +#include "CallPathManager.h" #include "CoreStats.h" #include "PForest.h" #include "TargetManager.h" @@ -26,6 +27,10 @@ void ObjectManager::setCurrentState(ExecutionState *_current) { assert(current == nullptr); current = _current; statesUpdated = true; + InfoStackFrame &sf = current->stack.infoStack().back(); + const llvm::Function *funcPtr = sf.callPathNode->function; + StatisticMap[funcPtr] = &sf.callPathNode->statistics; + // StatisticMap.emplace(funcPtr, &pn->statistics); } ExecutionState *ObjectManager::branchState(ExecutionState *state, diff --git a/lib/Core/ObjectManager.h b/lib/Core/ObjectManager.h index 4d3acd78f6..79698b2509 100644 --- a/lib/Core/ObjectManager.h +++ b/lib/Core/ObjectManager.h @@ -6,6 +6,7 @@ #include "klee/ADT/Ref.h" #include "klee/Core/BranchTypes.h" #include "klee/Module/KModule.h" +#include #include @@ -49,6 +50,7 @@ class ObjectManager { ObjectManager(); ~ObjectManager(); + std::unordered_map StatisticMap; void addSubscriber(Subscriber *); void addProcessForest(PForest *); From b3b1ec7ec69253e2a0eb60904992b26cefa12ac1 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Wed, 6 Nov 2024 08:28:56 +0300 Subject: [PATCH 11/22] feat: Add data queue and remove useless function Signed-off-by: YazoonDinalt --- include/klee/Core/Interpreter.h | 4 ---- lib/Core/CMakeLists.txt | 1 + lib/Core/Delta.cpp | 31 +++++++++++++++---------- lib/Core/Delta.h | 3 ++- lib/Core/Executor.cpp | 40 ++++++++++++++++----------------- lib/Core/Executor.h | 10 --------- lib/Core/ServerConnection.cpp | 21 +++++++++++++++++ lib/Core/ServerConnection.h | 15 +++++++------ lib/Core/StatisticQueue.cpp | 33 +++++++++++++++++++++++++++ lib/Core/StatisticQueue.h | 35 +++++++++++++++++++++++++++++ 10 files changed, 139 insertions(+), 54 deletions(-) create mode 100644 lib/Core/StatisticQueue.cpp create mode 100644 lib/Core/StatisticQueue.h diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index 47d2c1f314..aceb78dcfc 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -237,10 +237,6 @@ class Interpreter { virtual void getConstraintLog(const ExecutionState &state, std::string &res, LogType logFormat = STP) = 0; - virtual void getFunctionStatistic( - std::map> - deltaMap) = 0; - virtual bool getSymbolicSolution(const ExecutionState &state, KTest &res) = 0; virtual void addSARIFReport(const ExecutionState &state) = 0; diff --git a/lib/Core/CMakeLists.txt b/lib/Core/CMakeLists.txt index 26b0398446..0de4966f75 100644 --- a/lib/Core/CMakeLists.txt +++ b/lib/Core/CMakeLists.txt @@ -41,6 +41,7 @@ add_library(kleeCore TypeManager.cpp UserSearcher.cpp ServerConnection.cpp + StatisticQueue.cpp ) target_link_libraries(kleeCore PRIVATE diff --git a/lib/Core/Delta.cpp b/lib/Core/Delta.cpp index efe4567a8c..7bd1d15039 100644 --- a/lib/Core/Delta.cpp +++ b/lib/Core/Delta.cpp @@ -38,7 +38,7 @@ Delta::CalculateDelta( std::vector Delta::SerializeDelMap( std::unordered_map> &DelMap) { + std::unordered_map> &DelMap, std::string UID) { std::vector jsonArray; @@ -48,17 +48,24 @@ std::vector Delta::SerializeDelMap( for (const auto &metricPair : metricsMap) { const std::string &metricName = metricPair.first; - int prev = 0; - if (metricName == "Instructions") { - prev = previousMap[funPair.first]->getValue(stats::instructions); - } else if (metricName == "Forks") { - prev = previousMap[funPair.first]->getValue(stats::forks); - } - - int count = metricPair.second - prev; - - if (count != 0) { - jsonArray.push_back({{"name", metricName}, + uint64_t prev = 0; + // if (metricName == "Instructions") { + // std::optional prev = + // previousMap[funPair.first]->getValue(stats::instructions); + // if (!prev) + // prev = 0; + // } else if (metricName == "Forks") { + // std::optional prev = + // previousMap[funPair.first]->getValue(stats::forks); + // if (!prev) + // prev = 0; + // } + + int count = metricPair.second; + + if (count - prev != 0) { + jsonArray.push_back({{"guid", UID}, + {"name", metricName}, {"params", {{"funName", funName}, {"type", "int"}, diff --git a/lib/Core/Delta.h b/lib/Core/Delta.h index 8749a7feaf..dfde6a1e0d 100644 --- a/lib/Core/Delta.h +++ b/lib/Core/Delta.h @@ -36,7 +36,8 @@ class Delta { std::vector SerializeDelMap( std::unordered_map> &DelMap); + std::unordered_map> &DelMap, + std::string UID); std::unordered_map> diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index ab72741ce9..aea6b14bb7 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -28,6 +28,7 @@ #include "SeedInfo.h" #include "ServerConnection.h" #include "SpecialFunctionHandler.h" +#include "StatisticQueue.h" #include "StatsTracker.h" #include "TargetCalculator.h" #include "TargetManager.h" @@ -4706,25 +4707,35 @@ void Executor::run(ExecutionState *initialState) { auto lastExecutionTime = std::chrono::steady_clock::now(); Delta dt; + StatisticQueue StatQ; dt.initPrevDelta(objectManager->StatisticMap); - ServerConnection sc; - sc.url = "http://localhost:8080/server/save-metric"; + sc.url = "http://localhost:8080/metrics"; + sc.getUID(); + std::atomic shouldStop = false; + + std::thread consumer([&StatQ, &dt, &sc, &shouldStop]() { + while (!shouldStop) { + if (!StatQ.empty()) { + auto data = StatQ.pop(); + sc.PostRequest(dt.SerializeDelMap(data, sc.UID)); + } + } + }); + // main interpreter loop while (!haltExecution && !searcher->empty()) { auto currentTime = std::chrono::steady_clock::now(); if (std::chrono::duration_cast(currentTime - lastExecutionTime) - .count() >= 33) { + .count() >= 100) { dt.previousMap = objectManager->StatisticMap; auto a = dt.getCurrentMetric(objectManager->StatisticMap); - sc.PostRequest(dt.SerializeDelMap(a)); - // std::thread thread = this->spawn(deltaMap); + StatQ.push(a); lastExecutionTime = currentTime; - // thread.join(); } auto action = searcher->selectAction(); @@ -4736,6 +4747,9 @@ void Executor::run(ExecutionState *initialState) { } } + shouldStop = true; // Сигнализируем о необходимости остановки + consumer.join(); + if (guidanceKind == GuidanceKind::ErrorGuidance) { reportProgressTowardsTargets(); decreaseConfidenceFromStoppedStates(objectManager->getStates(), @@ -7477,20 +7491,6 @@ bool isMakeSymbolic(const klee::Symbolic &symb) { return good; } -void Executor::getFunctionStatistic( - std::map> deltaMap) { - - std::cout << "==== Current delta ====" << std::endl; - - for (const auto &[key1, map2] : deltaMap) { - std::cout << " Fun name: " << key1->getName().str() << std::endl; - for (const auto &[key2, value] : map2) { - std::cout << " Metrics name: " << key2 << ", delta: " << value - << std::endl; - } - } -}; - bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { solver->setTimeout(coreSolverTimeout); diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index caa0cccdb9..9a2bd5ac91 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -845,16 +845,6 @@ class Executor : public Interpreter { void logState(const ExecutionState &state, int id, std::unique_ptr &f) override; - void getFunctionStatistic( - std::map> deltaMap) - override; - - std::thread - spawn(std::map> deltaMap) { - return std::thread( - [this, deltaMap]() { this->getFunctionStatistic(deltaMap); }); - } - bool getSymbolicSolution(const ExecutionState &state, KTest &res) override; void getCoveredLines(const ExecutionState &state, diff --git a/lib/Core/ServerConnection.cpp b/lib/Core/ServerConnection.cpp index e0d0f90635..9f6efa448a 100644 --- a/lib/Core/ServerConnection.cpp +++ b/lib/Core/ServerConnection.cpp @@ -42,4 +42,25 @@ void ServerConnection::PostRequest(const std::vector &metrics) { } curl_global_cleanup(); }; + +size_t write_data(void *ptr, size_t size, size_t nmemb, void *userdata) { + std::string *buffer = static_cast(userdata); + buffer->append(static_cast(ptr), size * nmemb); + return size * nmemb; +} + +void ServerConnection::getUID() { + + CURL *curl = curl_easy_init(); + + curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:8080/new-session"); + + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &UID); + + // Выполняем запрос + curl_easy_perform(curl); + curl_easy_cleanup(curl); +} + } // namespace klee \ No newline at end of file diff --git a/lib/Core/ServerConnection.h b/lib/Core/ServerConnection.h index 8c84fbc1ca..2f223d0735 100644 --- a/lib/Core/ServerConnection.h +++ b/lib/Core/ServerConnection.h @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #ifndef KLEE_SERVERCONNECTION_H #define KLEE_SERVERCONNECTION_H @@ -18,13 +17,15 @@ namespace klee { /// TimingSolver - A simple class that collects delta statistics - class ServerConnection { - public: - std::string url; +class ServerConnection { +public: + std::string url; + std::string UID; - public: - void PostRequest(const std::vector &metrics); - }; +public: + void PostRequest(const std::vector &metrics); + void getUID(); +}; } // namespace klee #endif \ No newline at end of file diff --git a/lib/Core/StatisticQueue.cpp b/lib/Core/StatisticQueue.cpp new file mode 100644 index 0000000000..a086009477 --- /dev/null +++ b/lib/Core/StatisticQueue.cpp @@ -0,0 +1,33 @@ +#include "StatisticQueue.h" +#include "llvm/IR/Function.h" +#include +#include +#include +#include + +using namespace klee; + +void StatisticQueue::push( + const std::unordered_map> &value) { + std::unique_lock lock(mutex); + StatQueue.push(value); + cond_var.notify_one(); +} + +std::unordered_map> +StatisticQueue::pop() { + std::unique_lock lock(mutex); + cond_var.wait(lock, [this] { return !StatQueue.empty(); }); + std::unordered_map> + value = StatQueue.front(); + StatQueue.pop(); + return value; +} + +bool StatisticQueue::empty() { + + std::unique_lock lock(mutex); + return StatQueue.empty(); +} diff --git a/lib/Core/StatisticQueue.h b/lib/Core/StatisticQueue.h new file mode 100644 index 0000000000..88a4f23499 --- /dev/null +++ b/lib/Core/StatisticQueue.h @@ -0,0 +1,35 @@ + +#include "llvm/IR/Function.h" +#include +#include +#include +#include + +#ifndef KLEE_STATISTICQUEUE_H +#define KLEE_STATISTICQUEUE_H + +namespace klee { + +class StatisticQueue { + +private: + std::mutex mutex; + std::condition_variable cond_var; + std::queue>> + StatQueue; + +public: + void + push(const std::unordered_map> &value); + + std::unordered_map> + pop(); + bool empty(); +}; + +} // namespace klee + +#endif \ No newline at end of file From 0d322b34cc44c8046fd67aded7118099623551c6 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Wed, 6 Nov 2024 08:31:32 +0300 Subject: [PATCH 12/22] feat: Add desription in StatisticQueue Signed-off-by: YazoonDinalt --- lib/Core/StatisticQueue.cpp | 14 +++++++++----- lib/Core/StatisticQueue.h | 8 ++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/Core/StatisticQueue.cpp b/lib/Core/StatisticQueue.cpp index a086009477..aabac1c910 100644 --- a/lib/Core/StatisticQueue.cpp +++ b/lib/Core/StatisticQueue.cpp @@ -1,9 +1,13 @@ +//===-- StatisticQueue.cpp---------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + #include "StatisticQueue.h" -#include "llvm/IR/Function.h" -#include -#include -#include -#include using namespace klee; diff --git a/lib/Core/StatisticQueue.h b/lib/Core/StatisticQueue.h index 88a4f23499..5d7d3c316f 100644 --- a/lib/Core/StatisticQueue.h +++ b/lib/Core/StatisticQueue.h @@ -1,3 +1,11 @@ +//===-- StatisticQueue.h-----------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// #include "llvm/IR/Function.h" #include From 70f42b4e562abcbff2215a23190c57965256a197 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Wed, 13 Nov 2024 06:18:30 +0300 Subject: [PATCH 13/22] feat: Remove useless function and fix bug with collect metrics Signed-off-by: YazoonDinalt --- lib/Core/Delta.cpp | 64 ++++++++++++----------------------- lib/Core/Delta.h | 19 ++++------- lib/Core/Executor.cpp | 55 +++++++++++++++++------------- lib/Core/ObjectManager.cpp | 7 ++-- lib/Core/ObjectManager.h | 3 +- lib/Core/ServerConnection.cpp | 18 ++++++++-- lib/Core/ServerConnection.h | 1 - 7 files changed, 80 insertions(+), 87 deletions(-) diff --git a/lib/Core/Delta.cpp b/lib/Core/Delta.cpp index 7bd1d15039..93aef7babf 100644 --- a/lib/Core/Delta.cpp +++ b/lib/Core/Delta.cpp @@ -14,31 +14,10 @@ using namespace klee; namespace klee { -std::unordered_map> -Delta::CalculateDelta( - std::unordered_map StatMap) { - - std::unordered_map> - DelMap; - - for (const auto &pair : StatMap) { - DelMap[pair.first]["Instructions"] = - pair.second->getValue(stats::instructions) - - previousMap[pair.first]->getValue(stats::instructions); - DelMap[pair.first]["Forks"] = - pair.second->getValue(stats::forks) - - previousMap[pair.first]->getValue(stats::forks); - } - - previousMap = StatMap; - - return DelMap; -} - std::vector Delta::SerializeDelMap( std::unordered_map> &DelMap, std::string UID) { + std::unordered_map> &DelMap, + std::string UID) { std::vector jsonArray; @@ -48,19 +27,7 @@ std::vector Delta::SerializeDelMap( for (const auto &metricPair : metricsMap) { const std::string &metricName = metricPair.first; - uint64_t prev = 0; - // if (metricName == "Instructions") { - // std::optional prev = - // previousMap[funPair.first]->getValue(stats::instructions); - // if (!prev) - // prev = 0; - // } else if (metricName == "Forks") { - // std::optional prev = - // previousMap[funPair.first]->getValue(stats::forks); - // if (!prev) - // prev = 0; - // } - + uint64_t prev = previousMap[funPair.first][metricName]; int count = metricPair.second; if (count - prev != 0) { @@ -80,24 +47,37 @@ std::vector Delta::SerializeDelMap( std::unordered_map> Delta::getCurrentMetric( - std::unordered_map StatMap) { + std::unordered_map StatMap) { std::unordered_map> DelMap; for (const auto &pair : StatMap) { - DelMap[pair.first]["Instructions"] = - pair.second->getValue(stats::instructions); - DelMap[pair.first]["Forks"] = pair.second->getValue(stats::forks); + CallPathNode *cpn = pair.first; + if (DelMap.count(cpn->function) > 0) { + DelMap[cpn->function]["Instructions"] += + pair.second->getValue(stats::instructions); + DelMap[cpn->function]["Forks"] += pair.second->getValue(stats::forks); + } else { + DelMap[cpn->function]["Instructions"] = + pair.second->getValue(stats::instructions); + DelMap[cpn->function]["Forks"] = pair.second->getValue(stats::forks); + } } return DelMap; } void Delta::initPrevDelta( - std::unordered_map StatMap) { - previousMap = StatMap; + std::unordered_map StatMap) { + + for (const auto &pair : StatMap) { + previousMap[pair.first->function]["Instructions"] = + pair.second->getValue(stats::instructions); + previousMap[pair.first->function]["Forks"] = + pair.second->getValue(stats::forks); + } } } // namespace klee diff --git a/lib/Core/Delta.h b/lib/Core/Delta.h index dfde6a1e0d..3cb8d9916d 100644 --- a/lib/Core/Delta.h +++ b/lib/Core/Delta.h @@ -10,11 +10,9 @@ #ifndef KLEE_GETDELTA_H #define KLEE_GETDELTA_H +#include "CallPathManager.h" #include "nlohmann/json.hpp" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/BasicBlock.h" #include "llvm/IR/Function.h" -#include "llvm/IR/LLVMContext.h" #include #include @@ -22,18 +20,14 @@ namespace klee { -/// TimingSolver - A simple class that collects delta statistics class Delta { -public: - std::unordered_map previousMap; - std::unordered_map> Delta; - public: std::unordered_map> - CalculateDelta( - std::unordered_map StatMap); + previousMap; + std::unordered_map> Delta; +public: std::vector SerializeDelMap( std::unordered_map> &DelMap, @@ -41,11 +35,10 @@ class Delta { std::unordered_map> - getCurrentMetric( - std::unordered_map StatMap); + getCurrentMetric(std::unordered_map); void initPrevDelta( - std::unordered_map StatMap); + std::unordered_map StatMap); }; } // namespace klee diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index aea6b14bb7..089f6adca6 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -4703,10 +4703,10 @@ void Executor::run(ExecutionState *initialState) { objectManager->initialUpdate(); - // std::atomic running = true; - auto lastExecutionTime = std::chrono::steady_clock::now(); Delta dt; + std::thread consumer; + std::thread producer; StatisticQueue StatQ; dt.initPrevDelta(objectManager->StatisticMap); @@ -4714,30 +4714,34 @@ void Executor::run(ExecutionState *initialState) { sc.url = "http://localhost:8080/metrics"; sc.getUID(); std::atomic shouldStop = false; - - std::thread consumer([&StatQ, &dt, &sc, &shouldStop]() { - while (!shouldStop) { - if (!StatQ.empty()) { - auto data = StatQ.pop(); - sc.PostRequest(dt.SerializeDelMap(data, sc.UID)); + if (sc.UID != "ServerNotValid") { + consumer = std::thread([&StatQ, &dt, &sc, &shouldStop]() { + while (!shouldStop) { + if (!StatQ.empty()) { + auto data = StatQ.pop(); + sc.PostRequest(dt.SerializeDelMap(data, sc.UID)); + } } - } - }); + }); + + producer = + std::thread([&lastExecutionTime, &dt, &StatQ, &shouldStop, this]() { + while (!shouldStop) { + auto currentTime = std::chrono::steady_clock::now(); + if (std::chrono::duration_cast( + currentTime - lastExecutionTime) + .count() >= 100) { + + StatQ.push(dt.getCurrentMetric(objectManager->StatisticMap)); + lastExecutionTime = currentTime; + } + } + }); + } // main interpreter loop while (!haltExecution && !searcher->empty()) { - auto currentTime = std::chrono::steady_clock::now(); - if (std::chrono::duration_cast(currentTime - - lastExecutionTime) - .count() >= 100) { - - dt.previousMap = objectManager->StatisticMap; - auto a = dt.getCurrentMetric(objectManager->StatisticMap); - StatQ.push(a); - lastExecutionTime = currentTime; - } - auto action = searcher->selectAction(); executeAction(action); objectManager->updateSubscribers(); @@ -4746,9 +4750,14 @@ void Executor::run(ExecutionState *initialState) { objectManager->updateSubscribers(); } } + auto a = dt.getCurrentMetric(objectManager->StatisticMap); + StatQ.push(a); - shouldStop = true; // Сигнализируем о необходимости остановки - consumer.join(); + shouldStop = true; + if (sc.UID != "ServerNotValid") { + consumer.join(); + producer.join(); + } if (guidanceKind == GuidanceKind::ErrorGuidance) { reportProgressTowardsTargets(); diff --git a/lib/Core/ObjectManager.cpp b/lib/Core/ObjectManager.cpp index 7618a5dc6b..8e4a053b97 100644 --- a/lib/Core/ObjectManager.cpp +++ b/lib/Core/ObjectManager.cpp @@ -4,8 +4,8 @@ #include "CoreStats.h" #include "PForest.h" #include "TargetManager.h" - #include "klee/Module/KModule.h" +#include using namespace llvm; using namespace klee; @@ -28,9 +28,8 @@ void ObjectManager::setCurrentState(ExecutionState *_current) { current = _current; statesUpdated = true; InfoStackFrame &sf = current->stack.infoStack().back(); - const llvm::Function *funcPtr = sf.callPathNode->function; - StatisticMap[funcPtr] = &sf.callPathNode->statistics; - // StatisticMap.emplace(funcPtr, &pn->statistics); + StatisticMap[sf.callPathNode] = &sf.callPathNode->statistics; + auto funName = sf.callPathNode->function->getName().str(); } ExecutionState *ObjectManager::branchState(ExecutionState *state, diff --git a/lib/Core/ObjectManager.h b/lib/Core/ObjectManager.h index 79698b2509..4e32cffddd 100644 --- a/lib/Core/ObjectManager.h +++ b/lib/Core/ObjectManager.h @@ -1,6 +1,7 @@ #ifndef KLEE_OBJECTMANAGER_H #define KLEE_OBJECTMANAGER_H +#include "CallPathManager.h" #include "ExecutionState.h" #include "PForest.h" #include "klee/ADT/Ref.h" @@ -50,7 +51,7 @@ class ObjectManager { ObjectManager(); ~ObjectManager(); - std::unordered_map StatisticMap; + std::unordered_map StatisticMap; void addSubscriber(Subscriber *); void addProcessForest(PForest *); diff --git a/lib/Core/ServerConnection.cpp b/lib/Core/ServerConnection.cpp index 9f6efa448a..7d7dd64748 100644 --- a/lib/Core/ServerConnection.cpp +++ b/lib/Core/ServerConnection.cpp @@ -9,6 +9,7 @@ #include "ServerConnection.h" #include +#include using namespace klee; @@ -27,7 +28,13 @@ void ServerConnection::PostRequest(const std::vector &metrics) { curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonString.c_str()); - + // curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); + // curl_easy_setopt( + // curl, CURLOPT_WRITEFUNCTION, + // +[](void *, size_t size, size_t nmemb, void *) -> size_t { + // return size * nmemb; + // }); + // curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr); struct curl_slist *headers = nullptr; headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); @@ -58,8 +65,13 @@ void ServerConnection::getUID() { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &UID); - // Выполняем запрос - curl_easy_perform(curl); + CURLcode res = curl_easy_perform(curl); + if (res != CURLE_OK) { + UID = "ServerNotValid"; + std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) + << std::endl; + } + curl_easy_cleanup(curl); } diff --git a/lib/Core/ServerConnection.h b/lib/Core/ServerConnection.h index 2f223d0735..7eaf0a054d 100644 --- a/lib/Core/ServerConnection.h +++ b/lib/Core/ServerConnection.h @@ -16,7 +16,6 @@ namespace klee { -/// TimingSolver - A simple class that collects delta statistics class ServerConnection { public: std::string url; From 43a7fdd97da3f98909dd0d416900633b22c4bb6f Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Wed, 13 Nov 2024 06:24:29 +0300 Subject: [PATCH 14/22] refactor: Remove useless include Signed-off-by: YazoonDinalt --- lib/Core/Delta.h | 4 ++-- lib/Core/ObjectManager.cpp | 1 - lib/Core/ServerConnection.cpp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/Core/Delta.h b/lib/Core/Delta.h index 3cb8d9916d..d2b0b1223b 100644 --- a/lib/Core/Delta.h +++ b/lib/Core/Delta.h @@ -37,8 +37,8 @@ class Delta { std::unordered_map> getCurrentMetric(std::unordered_map); - void initPrevDelta( - std::unordered_map StatMap); + void + initPrevDelta(std::unordered_map StatMap); }; } // namespace klee diff --git a/lib/Core/ObjectManager.cpp b/lib/Core/ObjectManager.cpp index 8e4a053b97..759997926e 100644 --- a/lib/Core/ObjectManager.cpp +++ b/lib/Core/ObjectManager.cpp @@ -5,7 +5,6 @@ #include "PForest.h" #include "TargetManager.h" #include "klee/Module/KModule.h" -#include using namespace llvm; using namespace klee; diff --git a/lib/Core/ServerConnection.cpp b/lib/Core/ServerConnection.cpp index 7d7dd64748..69bf092bc6 100644 --- a/lib/Core/ServerConnection.cpp +++ b/lib/Core/ServerConnection.cpp @@ -71,7 +71,7 @@ void ServerConnection::getUID() { std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl; } - + curl_easy_cleanup(curl); } From 840c2db47b9c4dc8cc1311c5846faa8e42a3df02 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Wed, 13 Nov 2024 06:51:05 +0300 Subject: [PATCH 15/22] feat: Add sending only non-zero metrics and removed unnecessary logging Signed-off-by: YazoonDinalt --- lib/Core/Delta.cpp | 68 ++++++++++++++++++++--------------- lib/Core/Delta.h | 5 +-- lib/Core/ServerConnection.cpp | 14 ++++---- lib/Core/ServerConnection.h | 6 ++-- lib/Core/StatisticQueue.h | 2 -- 5 files changed, 50 insertions(+), 45 deletions(-) diff --git a/lib/Core/Delta.cpp b/lib/Core/Delta.cpp index 93aef7babf..67d1005637 100644 --- a/lib/Core/Delta.cpp +++ b/lib/Core/Delta.cpp @@ -27,9 +27,16 @@ std::vector Delta::SerializeDelMap( for (const auto &metricPair : metricsMap) { const std::string &metricName = metricPair.first; - uint64_t prev = previousMap[funPair.first][metricName]; + uint64_t prev; int count = metricPair.second; - + std::string targetFunName = "myFunction"; + for (const auto &jsonObject : newPrevMap) { + if (jsonObject["params"]["funName"] == funName && + jsonObject["name"] == metricName) { + prev = jsonObject["params"]["value"]; + break; + } + } if (count - prev != 0) { jsonArray.push_back({{"guid", UID}, {"name", metricName}, @@ -42,42 +49,45 @@ std::vector Delta::SerializeDelMap( } } - return jsonArray; -} + newPrevMap = jsonArray; -std::unordered_map> -Delta::getCurrentMetric( - std::unordered_map StatMap) { + return jsonArray; + } std::unordered_map> - DelMap; + Delta::getCurrentMetric( + std::unordered_map StatMap) { - for (const auto &pair : StatMap) { - CallPathNode *cpn = pair.first; - if (DelMap.count(cpn->function) > 0) { - DelMap[cpn->function]["Instructions"] += - pair.second->getValue(stats::instructions); - DelMap[cpn->function]["Forks"] += pair.second->getValue(stats::forks); - } else { - DelMap[cpn->function]["Instructions"] = - pair.second->getValue(stats::instructions); - DelMap[cpn->function]["Forks"] = pair.second->getValue(stats::forks); + std::unordered_map> + DelMap; + + for (const auto &pair : StatMap) { + CallPathNode *cpn = pair.first; + if (DelMap.count(cpn->function) > 0) { + DelMap[cpn->function]["Instructions"] += + pair.second->getValue(stats::instructions); + DelMap[cpn->function]["Forks"] += pair.second->getValue(stats::forks); + } else { + DelMap[cpn->function]["Instructions"] = + pair.second->getValue(stats::instructions); + DelMap[cpn->function]["Forks"] = pair.second->getValue(stats::forks); + } } - } - return DelMap; -} + return DelMap; + } -void Delta::initPrevDelta( - std::unordered_map StatMap) { + void Delta::initPrevDelta( + std::unordered_map StatMap) { - for (const auto &pair : StatMap) { - previousMap[pair.first->function]["Instructions"] = - pair.second->getValue(stats::instructions); - previousMap[pair.first->function]["Forks"] = - pair.second->getValue(stats::forks); + for (const auto &pair : StatMap) { + previousMap[pair.first->function]["Instructions"] = + pair.second->getValue(stats::instructions); + previousMap[pair.first->function]["Forks"] = + pair.second->getValue(stats::forks); + } } -} } // namespace klee diff --git a/lib/Core/Delta.h b/lib/Core/Delta.h index d2b0b1223b..5600fd1ca0 100644 --- a/lib/Core/Delta.h +++ b/lib/Core/Delta.h @@ -13,10 +13,6 @@ #include "CallPathManager.h" #include "nlohmann/json.hpp" #include "llvm/IR/Function.h" -#include -#include - -#include namespace klee { @@ -25,6 +21,7 @@ class Delta { std::unordered_map> previousMap; + std::vector newPrevMap; std::unordered_map> Delta; public: diff --git a/lib/Core/ServerConnection.cpp b/lib/Core/ServerConnection.cpp index 69bf092bc6..d133e2eac4 100644 --- a/lib/Core/ServerConnection.cpp +++ b/lib/Core/ServerConnection.cpp @@ -28,13 +28,13 @@ void ServerConnection::PostRequest(const std::vector &metrics) { curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonString.c_str()); - // curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); - // curl_easy_setopt( - // curl, CURLOPT_WRITEFUNCTION, - // +[](void *, size_t size, size_t nmemb, void *) -> size_t { - // return size * nmemb; - // }); - // curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); + curl_easy_setopt( + curl, CURLOPT_WRITEFUNCTION, + +[](void *, size_t size, size_t nmemb, void *) -> size_t { + return size * nmemb; + }); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr); struct curl_slist *headers = nullptr; headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); diff --git a/lib/Core/ServerConnection.h b/lib/Core/ServerConnection.h index 7eaf0a054d..63a5559d4b 100644 --- a/lib/Core/ServerConnection.h +++ b/lib/Core/ServerConnection.h @@ -11,8 +11,8 @@ #define KLEE_SERVERCONNECTION_H #include "nlohmann/json.hpp" -#include -#include + +using json = nlohmann::json; namespace klee { @@ -22,7 +22,7 @@ class ServerConnection { std::string UID; public: - void PostRequest(const std::vector &metrics); + void PostRequest(const std::vector &metrics); void getUID(); }; } // namespace klee diff --git a/lib/Core/StatisticQueue.h b/lib/Core/StatisticQueue.h index 5d7d3c316f..fe90f77c60 100644 --- a/lib/Core/StatisticQueue.h +++ b/lib/Core/StatisticQueue.h @@ -9,9 +9,7 @@ #include "llvm/IR/Function.h" #include -#include #include -#include #ifndef KLEE_STATISTICQUEUE_H #define KLEE_STATISTICQUEUE_H From 4cca3fb396390dfa7d4fd275db938fb8c0939b4d Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Wed, 13 Nov 2024 07:16:14 +0300 Subject: [PATCH 16/22] feat: Fix wrong calculate in main Signed-off-by: YazoonDinalt --- tools/klee/main.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index 957e74f27d..b466eb7154 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -649,7 +649,9 @@ static std::vector rules() { #define TTYPE(N, I, S) \ if ((I) > (unsigned int)StateTerminationType::SOLVERERR && \ (I) < (unsigned int)StateTerminationType::PROGERR) { \ - ret.push_back(RuleJson{#N, {"Program error"}, {}, {}}); \ + ret.push_back(RuleJson { \ + #N, {"Program error"}, {}, {} \ + }); \ } #define TTMARK(N, I) @@ -2456,8 +2458,6 @@ int main(int argc, char **argv, char **envp) { uint64_t forks = *theStatisticManager->getStatisticByName("Forks"); uint64_t solverTime = (*theStatisticManager->getStatisticByName("SolverTime")) / 1000000000; - uint64_t uncoverageInstructions = - *theStatisticManager->getStatisticByName("UncoveredInstructions"); std::uint32_t solverH; std::uint8_t solverM, solverS; @@ -2498,9 +2498,9 @@ int main(int argc, char **argv, char **envp) { << '\n' << "KLEE: done: forks = " << forks << '\n' << "KLEE: done: coverage = " - << (static_cast(instructions - uncoverageInstructions) / - instructions) * - 100; + << (static_cast(handler->getNumPathsCompleted()) / + static_cast(handler->getNumTestCases())) * + 100 << "%"; bool useColors = llvm::errs().is_displayed(); if (useColors) From 318462e992de3bb5ae78e13dac1c2715ce0f4df3 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Wed, 13 Nov 2024 08:12:53 +0300 Subject: [PATCH 17/22] feat: Add SolverTime in metrics Signed-off-by: YazoonDinalt --- lib/Core/Delta.cpp | 97 +++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 39 deletions(-) diff --git a/lib/Core/Delta.cpp b/lib/Core/Delta.cpp index 67d1005637..1bdce7b61f 100644 --- a/lib/Core/Delta.cpp +++ b/lib/Core/Delta.cpp @@ -28,8 +28,8 @@ std::vector Delta::SerializeDelMap( for (const auto &metricPair : metricsMap) { const std::string &metricName = metricPair.first; uint64_t prev; - int count = metricPair.second; - std::string targetFunName = "myFunction"; + auto count = metricPair.second; + std::string type_of_var = "int"; for (const auto &jsonObject : newPrevMap) { if (jsonObject["params"]["funName"] == funName && jsonObject["name"] == metricName) { @@ -37,57 +37,76 @@ std::vector Delta::SerializeDelMap( break; } } + if (count - prev != 0) { - jsonArray.push_back({{"guid", UID}, - {"name", metricName}, - {"params", - {{"funName", funName}, - {"type", "int"}, - {"value", count}, - {"transitive", false}}}}); + if (metricName == "SolverTime") { + type_of_var = "double"; + double solverCount = static_cast(count) / (double)1000000000; + solverCount = static_cast(round(solverCount * 100)) / 100; + jsonArray.push_back({{"guid", UID}, + {"name", metricName}, + {"params", + {{"funName", funName}, + {"type", type_of_var}, + {"value", solverCount}, + {"transitive", false}}}}); + } else { + jsonArray.push_back({{"guid", UID}, + {"name", metricName}, + {"params", + {{"funName", funName}, + {"type", type_of_var}, + {"value", count}, + {"transitive", false}}}}); + } } } } - newPrevMap = jsonArray; + newPrevMap = jsonArray; - return jsonArray; - } + return jsonArray; +} + +std::unordered_map> +Delta::getCurrentMetric( + std::unordered_map StatMap) { std::unordered_map> - Delta::getCurrentMetric( - std::unordered_map StatMap) { + DelMap; - std::unordered_map> - DelMap; - - for (const auto &pair : StatMap) { - CallPathNode *cpn = pair.first; - if (DelMap.count(cpn->function) > 0) { - DelMap[cpn->function]["Instructions"] += - pair.second->getValue(stats::instructions); - DelMap[cpn->function]["Forks"] += pair.second->getValue(stats::forks); - } else { - DelMap[cpn->function]["Instructions"] = - pair.second->getValue(stats::instructions); - DelMap[cpn->function]["Forks"] = pair.second->getValue(stats::forks); - } + for (const auto &pair : StatMap) { + CallPathNode *cpn = pair.first; + if (DelMap.count(cpn->function) > 0) { + DelMap[cpn->function]["Instructions"] += + pair.second->getValue(stats::instructions); + DelMap[cpn->function]["SolverTime"] += + pair.second->getValue(stats::solverTime); + DelMap[cpn->function]["Forks"] += pair.second->getValue(stats::forks); + } else { + DelMap[cpn->function]["Instructions"] = + pair.second->getValue(stats::instructions); + DelMap[cpn->function]["SolverTime"] += + pair.second->getValue(stats::solverTime); + DelMap[cpn->function]["Forks"] = pair.second->getValue(stats::forks); } - - return DelMap; } - void Delta::initPrevDelta( - std::unordered_map StatMap) { + return DelMap; +} - for (const auto &pair : StatMap) { - previousMap[pair.first->function]["Instructions"] = - pair.second->getValue(stats::instructions); - previousMap[pair.first->function]["Forks"] = - pair.second->getValue(stats::forks); - } +void Delta::initPrevDelta( + std::unordered_map StatMap) { + + for (const auto &pair : StatMap) { + previousMap[pair.first->function]["Instructions"] = + pair.second->getValue(stats::instructions); + previousMap[pair.first->function]["Forks"] = + pair.second->getValue(stats::forks); + previousMap[pair.first->function]["SolverTime"] = + pair.second->getValue(stats::solverTime); } +} } // namespace klee From ed63878f5b6056fb24df50798f44dd400139d0e7 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Thu, 21 Nov 2024 08:09:16 +0300 Subject: [PATCH 18/22] feat: Fix main problem with data race and init curl on every function invocation Signed-off-by: YazoonDinalt --- lib/Core/CMakeLists.txt | 4 ++-- lib/Core/Delta.cpp | 36 ++++++++++------------------ lib/Core/Delta.h | 9 ++++--- lib/Core/Executor.cpp | 16 ++++++------- lib/Core/ObjectManager.cpp | 1 - lib/Core/ServerConnection.cpp | 45 +++++++++++++++++------------------ lib/Core/ServerConnection.h | 19 +++++++++------ lib/Core/StatisticQueue.cpp | 2 +- lib/Core/StatisticQueue.h | 2 +- tools/klee/main.cpp | 5 +--- 10 files changed, 66 insertions(+), 73 deletions(-) diff --git a/lib/Core/CMakeLists.txt b/lib/Core/CMakeLists.txt index 0de4966f75..73427d7a31 100644 --- a/lib/Core/CMakeLists.txt +++ b/lib/Core/CMakeLists.txt @@ -31,7 +31,9 @@ add_library(kleeCore Searcher.cpp SeedInfo.cpp SeedMap.cpp + ServerConnection.cpp SpecialFunctionHandler.cpp + StatisticQueue.cpp StatsTracker.cpp TargetCalculator.cpp TargetedExecutionReporter.cpp @@ -40,8 +42,6 @@ add_library(kleeCore TimingSolver.cpp TypeManager.cpp UserSearcher.cpp - ServerConnection.cpp - StatisticQueue.cpp ) target_link_libraries(kleeCore PRIVATE diff --git a/lib/Core/Delta.cpp b/lib/Core/Delta.cpp index 1bdce7b61f..bb53e14cb0 100644 --- a/lib/Core/Delta.cpp +++ b/lib/Core/Delta.cpp @@ -12,11 +12,11 @@ using namespace klee; -namespace klee { +const double NANOSECONDS_PER_SECOND = 1000000000.0; std::vector Delta::SerializeDelMap( - std::unordered_map> &DelMap, + const std::unordered_map> &DelMap, std::string UID) { std::vector jsonArray; @@ -29,7 +29,6 @@ std::vector Delta::SerializeDelMap( const std::string &metricName = metricPair.first; uint64_t prev; auto count = metricPair.second; - std::string type_of_var = "int"; for (const auto &jsonObject : newPrevMap) { if (jsonObject["params"]["funName"] == funName && jsonObject["name"] == metricName) { @@ -40,14 +39,14 @@ std::vector Delta::SerializeDelMap( if (count - prev != 0) { if (metricName == "SolverTime") { - type_of_var = "double"; - double solverCount = static_cast(count) / (double)1000000000; + double solverCount = + static_cast(count) / NANOSECONDS_PER_SECOND; solverCount = static_cast(round(solverCount * 100)) / 100; jsonArray.push_back({{"guid", UID}, {"name", metricName}, {"params", {{"funName", funName}, - {"type", type_of_var}, + {"type", "double"}, {"value", solverCount}, {"transitive", false}}}}); } else { @@ -55,7 +54,7 @@ std::vector Delta::SerializeDelMap( {"name", metricName}, {"params", {{"funName", funName}, - {"type", type_of_var}, + {"type", "int"}, {"value", count}, {"transitive", false}}}}); } @@ -76,21 +75,14 @@ Delta::getCurrentMetric( std::unordered_map> DelMap; + std::lock_guard lock(StatisticMapMutex); for (const auto &pair : StatMap) { CallPathNode *cpn = pair.first; - if (DelMap.count(cpn->function) > 0) { - DelMap[cpn->function]["Instructions"] += - pair.second->getValue(stats::instructions); - DelMap[cpn->function]["SolverTime"] += - pair.second->getValue(stats::solverTime); - DelMap[cpn->function]["Forks"] += pair.second->getValue(stats::forks); - } else { - DelMap[cpn->function]["Instructions"] = - pair.second->getValue(stats::instructions); - DelMap[cpn->function]["SolverTime"] += - pair.second->getValue(stats::solverTime); - DelMap[cpn->function]["Forks"] = pair.second->getValue(stats::forks); - } + DelMap[cpn->function]["Instructions"] += + pair.second->getValue(stats::instructions); + DelMap[cpn->function]["SolverTime"] += + pair.second->getValue(stats::solverTime); + DelMap[cpn->function]["Forks"] += pair.second->getValue(stats::forks); } return DelMap; @@ -108,5 +100,3 @@ void Delta::initPrevDelta( pair.second->getValue(stats::solverTime); } } - -} // namespace klee diff --git a/lib/Core/Delta.h b/lib/Core/Delta.h index 5600fd1ca0..5df520a014 100644 --- a/lib/Core/Delta.h +++ b/lib/Core/Delta.h @@ -14,6 +14,8 @@ #include "nlohmann/json.hpp" #include "llvm/IR/Function.h" +#include + namespace klee { class Delta { @@ -22,13 +24,14 @@ class Delta { std::unordered_map> previousMap; std::vector newPrevMap; + std::mutex StatisticMapMutex; std::unordered_map> Delta; public: std::vector SerializeDelMap( - std::unordered_map> &DelMap, - std::string UID); + const std::unordered_map> &DelMap, + const std::string UID); std::unordered_map> diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 089f6adca6..68ef41e944 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -76,6 +76,7 @@ #include "klee/Support/RoundingModeUtil.h" #include "klee/System/MemoryUsage.h" #include "klee/System/Time.h" +#include #include "CodeEvent.h" #include "CodeLocation.h" @@ -108,7 +109,6 @@ #include #include #include -#include #include #include #include @@ -4710,16 +4710,17 @@ void Executor::run(ExecutionState *initialState) { StatisticQueue StatQ; dt.initPrevDelta(objectManager->StatisticMap); - ServerConnection sc; - sc.url = "http://localhost:8080/metrics"; - sc.getUID(); + ServerConnection scForUID("http://localhost:8080/new-session"); + scForUID.getUIDFromServer(); + ServerConnection sc("http://localhost:8080/metrics"); + sc.setUID(scForUID.getUID()); std::atomic shouldStop = false; - if (sc.UID != "ServerNotValid") { + if (sc.getUID() != "ServerNotValid") { consumer = std::thread([&StatQ, &dt, &sc, &shouldStop]() { while (!shouldStop) { if (!StatQ.empty()) { auto data = StatQ.pop(); - sc.PostRequest(dt.SerializeDelMap(data, sc.UID)); + sc.PostRequest(dt.SerializeDelMap(std::move(data), sc.getUID())); } } }); @@ -4741,7 +4742,6 @@ void Executor::run(ExecutionState *initialState) { // main interpreter loop while (!haltExecution && !searcher->empty()) { - auto action = searcher->selectAction(); executeAction(action); objectManager->updateSubscribers(); @@ -4754,7 +4754,7 @@ void Executor::run(ExecutionState *initialState) { StatQ.push(a); shouldStop = true; - if (sc.UID != "ServerNotValid") { + if (sc.getUID() != "ServerNotValid") { consumer.join(); producer.join(); } diff --git a/lib/Core/ObjectManager.cpp b/lib/Core/ObjectManager.cpp index 759997926e..d425ef1b42 100644 --- a/lib/Core/ObjectManager.cpp +++ b/lib/Core/ObjectManager.cpp @@ -28,7 +28,6 @@ void ObjectManager::setCurrentState(ExecutionState *_current) { statesUpdated = true; InfoStackFrame &sf = current->stack.infoStack().back(); StatisticMap[sf.callPathNode] = &sf.callPathNode->statistics; - auto funName = sf.callPathNode->function->getName().str(); } ExecutionState *ObjectManager::branchState(ExecutionState *state, diff --git a/lib/Core/ServerConnection.cpp b/lib/Core/ServerConnection.cpp index d133e2eac4..da9184c8dc 100644 --- a/lib/Core/ServerConnection.cpp +++ b/lib/Core/ServerConnection.cpp @@ -8,25 +8,31 @@ //===----------------------------------------------------------------------===// #include "ServerConnection.h" -#include -#include +#include using namespace klee; -namespace klee { +ServerConnection::ServerConnection(const std::string &serverUrl) + : url(serverUrl), curl(curl_easy_init()) { + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + if (!curl) { + llvm::errs() << "Failed to initialize curl" << "\n"; + } + curl_global_init(CURL_GLOBAL_ALL); +} + +ServerConnection::~ServerConnection() { + curl_easy_cleanup(curl); + curl_global_cleanup(); +} void ServerConnection::PostRequest(const std::vector &metrics) { - CURL *curl; CURLcode res; - curl_global_init(CURL_GLOBAL_ALL); - curl = curl_easy_init(); - if (curl) { nlohmann::json jsonData = metrics; std::string jsonString = jsonData.dump(); - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonString.c_str()); curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); curl_easy_setopt( @@ -42,12 +48,9 @@ void ServerConnection::PostRequest(const std::vector &metrics) { res = curl_easy_perform(curl); if (res != CURLE_OK) - fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); - - curl_easy_cleanup(curl); + llvm::errs() << "curl_easy_perform() failed: " << curl_easy_strerror(res) + << "\n"; } - curl_global_cleanup(); }; size_t write_data(void *ptr, size_t size, size_t nmemb, void *userdata) { @@ -56,11 +59,7 @@ size_t write_data(void *ptr, size_t size, size_t nmemb, void *userdata) { return size * nmemb; } -void ServerConnection::getUID() { - - CURL *curl = curl_easy_init(); - - curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:8080/new-session"); +void ServerConnection::getUIDFromServer() { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &UID); @@ -68,11 +67,11 @@ void ServerConnection::getUID() { CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { UID = "ServerNotValid"; - std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) - << std::endl; + llvm::errs() << "curl_easy_perform() failed: " << curl_easy_strerror(res) + << "\n"; } - - curl_easy_cleanup(curl); } -} // namespace klee \ No newline at end of file +std::string ServerConnection::getUID() { return UID; } + +void ServerConnection::setUID(const std::string &newUID) { UID = newUID; } diff --git a/lib/Core/ServerConnection.h b/lib/Core/ServerConnection.h index 63a5559d4b..4381e20bc0 100644 --- a/lib/Core/ServerConnection.h +++ b/lib/Core/ServerConnection.h @@ -11,20 +11,25 @@ #define KLEE_SERVERCONNECTION_H #include "nlohmann/json.hpp" - -using json = nlohmann::json; +#include namespace klee { class ServerConnection { + public: + ServerConnection(const std::string &serverUrl); + ~ServerConnection(); + void PostRequest(const std::vector &metrics); + void getUIDFromServer(); + std::string getUID(); + void setUID(const std::string &newUID); + +private: std::string url; + CURL *curl; std::string UID; - -public: - void PostRequest(const std::vector &metrics); - void getUID(); }; } // namespace klee -#endif \ No newline at end of file +#endif diff --git a/lib/Core/StatisticQueue.cpp b/lib/Core/StatisticQueue.cpp index aabac1c910..5901056b0b 100644 --- a/lib/Core/StatisticQueue.cpp +++ b/lib/Core/StatisticQueue.cpp @@ -25,7 +25,7 @@ StatisticQueue::pop() { cond_var.wait(lock, [this] { return !StatQueue.empty(); }); std::unordered_map> - value = StatQueue.front(); + value = std::move(StatQueue.front()); StatQueue.pop(); return value; } diff --git a/lib/Core/StatisticQueue.h b/lib/Core/StatisticQueue.h index fe90f77c60..b30f1c1dcd 100644 --- a/lib/Core/StatisticQueue.h +++ b/lib/Core/StatisticQueue.h @@ -38,4 +38,4 @@ class StatisticQueue { } // namespace klee -#endif \ No newline at end of file +#endif diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index b466eb7154..618366b12c 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -2459,10 +2459,7 @@ int main(int argc, char **argv, char **envp) { uint64_t solverTime = (*theStatisticManager->getStatisticByName("SolverTime")) / 1000000000; - std::uint32_t solverH; - std::uint8_t solverM, solverS; - std::tie(solverH, solverM, solverS) = time::seconds(solverTime).toHMS(); - + auto [solverH, solverM, solverS] = time::seconds(solverTime).toHMS(); std::stringstream ss; ss << std::setw(2) << std::setfill('0') << solverH << ':' << std::setw(2) << std::setfill('0') << +solverM << ':' << std::setw(2) From d385cb87eeff924e42825a9f418ed730db193847 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Thu, 21 Nov 2024 08:49:35 +0300 Subject: [PATCH 19/22] feat: Move some data to command line option Signed-off-by: YazoonDinalt --- include/klee/Support/OptionCategories.h | 1 + lib/Core/Executor.cpp | 31 ++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/include/klee/Support/OptionCategories.h b/include/klee/Support/OptionCategories.h index 773800edfe..e559e6effe 100644 --- a/include/klee/Support/OptionCategories.h +++ b/include/klee/Support/OptionCategories.h @@ -26,6 +26,7 @@ extern llvm::cl::OptionCategory SeedingCat; extern llvm::cl::OptionCategory SolvingCat; extern llvm::cl::OptionCategory TerminationCat; extern llvm::cl::OptionCategory TestGenCat; +extern llvm::cl::OptionCategory AgentCat; } // namespace klee #endif /* KLEE_OPTIONCATEGORIES_H */ diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 68ef41e944..16cb08f42e 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -142,6 +142,9 @@ cl::OptionCategory TestGenCat("Test generation options", cl::OptionCategory LazyInitCat("Lazy initialization option", "These options configure lazy initialization."); +cl::OptionCategory AgentCat("Agent options", + "These options specify agent settings."); + cl::opt UseAdvancedTypeSystem( "use-advanced-type-system", cl::desc("Use advanced information about type system from " @@ -344,6 +347,25 @@ cl::opt AllExternalWarnings( "as opposed to once per function (default=false)"), cl::cat(ExtCallsCat)); +/*** Agent options ***/ + +cl::opt UrlUID("url-uid", + cl::init("http://localhost:8080/new-session"), + cl::desc("The option allows to specify the url " + "from which can get the UID"), + cl::cat(AgentCat)); + +cl::opt MetricsUID( + "metrics-uid", cl::init("http://localhost:8080/metrics"), + cl::desc("The option allows to specify the url where can save metrics"), + cl::cat(AgentCat)); + +cl::opt + DeltaTime("delta-time", cl::init(100), + cl::desc("Using the option, you specify the time in milliseconds " + "at which statistics will be sent (default = 100)"), + cl::cat(AgentCat)); + /*** Seeding options ***/ cl::opt AlwaysOutputSeeds( @@ -4710,9 +4732,9 @@ void Executor::run(ExecutionState *initialState) { StatisticQueue StatQ; dt.initPrevDelta(objectManager->StatisticMap); - ServerConnection scForUID("http://localhost:8080/new-session"); + ServerConnection scForUID(UrlUID); scForUID.getUIDFromServer(); - ServerConnection sc("http://localhost:8080/metrics"); + ServerConnection sc(MetricsUID); sc.setUID(scForUID.getUID()); std::atomic shouldStop = false; if (sc.getUID() != "ServerNotValid") { @@ -4727,14 +4749,17 @@ void Executor::run(ExecutionState *initialState) { producer = std::thread([&lastExecutionTime, &dt, &StatQ, &shouldStop, this]() { + auto nextExecutionTime = std::chrono::steady_clock::now() + + std::chrono::milliseconds(DeltaTime); while (!shouldStop) { + std::this_thread::sleep_until(nextExecutionTime); auto currentTime = std::chrono::steady_clock::now(); if (std::chrono::duration_cast( currentTime - lastExecutionTime) .count() >= 100) { StatQ.push(dt.getCurrentMetric(objectManager->StatisticMap)); - lastExecutionTime = currentTime; + nextExecutionTime += std::chrono::milliseconds(DeltaTime); } } }); From 81a64f5c2f24b2c8053f56a5ba86e2f91dae00c7 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Thu, 21 Nov 2024 09:12:53 +0300 Subject: [PATCH 20/22] feat: Change serialize and rename delta class Signed-off-by: YazoonDinalt --- lib/Core/CMakeLists.txt | 2 +- lib/Core/Executor.cpp | 15 ++++---- ...a.cpp => MetricCollectorAndSerializer.cpp} | 37 +++++++++---------- ...Delta.h => MetricCollectorAndSerializer.h} | 21 +++++------ 4 files changed, 35 insertions(+), 40 deletions(-) rename lib/Core/{Delta.cpp => MetricCollectorAndSerializer.cpp} (79%) rename lib/Core/{Delta.h => MetricCollectorAndSerializer.h} (72%) diff --git a/lib/Core/CMakeLists.txt b/lib/Core/CMakeLists.txt index 73427d7a31..f92ac627bc 100644 --- a/lib/Core/CMakeLists.txt +++ b/lib/Core/CMakeLists.txt @@ -14,7 +14,6 @@ add_library(kleeCore Context.cpp CoreStats.cpp CXXTypeSystem/CXXTypeManager.cpp - Delta.cpp DistanceCalculator.cpp EventRecorder.cpp ExecutionState.cpp @@ -24,6 +23,7 @@ add_library(kleeCore ImpliedValue.cpp Memory.cpp MemoryManager.cpp + MetricCollectorAndSerializer.cpp ObjectManager.cpp PForest.cpp MockBuilder.cpp diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 16cb08f42e..2fd0ba7236 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -14,7 +14,6 @@ #include "CallPathManager.h" #include "ConstructStorage.h" #include "CoreStats.h" -#include "Delta.h" #include "DistanceCalculator.h" #include "ExecutionState.h" #include "ExternalDispatcher.h" @@ -22,6 +21,7 @@ #include "ImpliedValue.h" #include "Memory.h" #include "MemoryManager.h" +#include "MetricCollectorAndSerializer.h" #include "PForest.h" #include "PTree.h" #include "Searcher.h" @@ -4726,29 +4726,28 @@ void Executor::run(ExecutionState *initialState) { objectManager->initialUpdate(); auto lastExecutionTime = std::chrono::steady_clock::now(); - Delta dt; + MetricCollectorAndSerializer mc; std::thread consumer; std::thread producer; StatisticQueue StatQ; - dt.initPrevDelta(objectManager->StatisticMap); ServerConnection scForUID(UrlUID); scForUID.getUIDFromServer(); ServerConnection sc(MetricsUID); sc.setUID(scForUID.getUID()); std::atomic shouldStop = false; if (sc.getUID() != "ServerNotValid") { - consumer = std::thread([&StatQ, &dt, &sc, &shouldStop]() { + consumer = std::thread([&StatQ, &mc, &sc, &shouldStop]() { while (!shouldStop) { if (!StatQ.empty()) { auto data = StatQ.pop(); - sc.PostRequest(dt.SerializeDelMap(std::move(data), sc.getUID())); + sc.PostRequest(mc.GetJson(std::move(data), sc.getUID())); } } }); producer = - std::thread([&lastExecutionTime, &dt, &StatQ, &shouldStop, this]() { + std::thread([&lastExecutionTime, &mc, &StatQ, &shouldStop, this]() { auto nextExecutionTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(DeltaTime); while (!shouldStop) { @@ -4758,7 +4757,7 @@ void Executor::run(ExecutionState *initialState) { currentTime - lastExecutionTime) .count() >= 100) { - StatQ.push(dt.getCurrentMetric(objectManager->StatisticMap)); + StatQ.push(mc.getCurrentMetric(objectManager->StatisticMap)); nextExecutionTime += std::chrono::milliseconds(DeltaTime); } } @@ -4775,7 +4774,7 @@ void Executor::run(ExecutionState *initialState) { objectManager->updateSubscribers(); } } - auto a = dt.getCurrentMetric(objectManager->StatisticMap); + auto a = mc.getCurrentMetric(objectManager->StatisticMap); StatQ.push(a); shouldStop = true; diff --git a/lib/Core/Delta.cpp b/lib/Core/MetricCollectorAndSerializer.cpp similarity index 79% rename from lib/Core/Delta.cpp rename to lib/Core/MetricCollectorAndSerializer.cpp index bb53e14cb0..481e60a19d 100644 --- a/lib/Core/Delta.cpp +++ b/lib/Core/MetricCollectorAndSerializer.cpp @@ -1,4 +1,4 @@ -//===-- Delta.cpp------------------------------------------------*- C++ -*-===// +//===--MetricCollectorAndSerializer.cpp---------------------------*-C++ -*-===// // // The KLEE Symbolic Virtual Machine // @@ -7,18 +7,30 @@ // //===----------------------------------------------------------------------===// -#include "Delta.h" +#include "MetricCollectorAndSerializer.h" #include "CoreStats.h" using namespace klee; const double NANOSECONDS_PER_SECOND = 1000000000.0; -std::vector Delta::SerializeDelMap( +std::vector MetricCollectorAndSerializer::GetJson( const std::unordered_map> &DelMap, std::string UID) { + std::vector jsonArray = SerializeDelMap(DelMap, UID); + + previousMap = jsonArray; + + return jsonArray; +} + +std::vector MetricCollectorAndSerializer::SerializeDelMap( + const std::unordered_map> &DelMap, + const std::string UID) { + std::vector jsonArray; for (const auto &funPair : DelMap) { @@ -29,7 +41,7 @@ std::vector Delta::SerializeDelMap( const std::string &metricName = metricPair.first; uint64_t prev; auto count = metricPair.second; - for (const auto &jsonObject : newPrevMap) { + for (const auto &jsonObject : previousMap) { if (jsonObject["params"]["funName"] == funName && jsonObject["name"] == metricName) { prev = jsonObject["params"]["value"]; @@ -62,13 +74,11 @@ std::vector Delta::SerializeDelMap( } } - newPrevMap = jsonArray; - return jsonArray; } std::unordered_map> -Delta::getCurrentMetric( +MetricCollectorAndSerializer::getCurrentMetric( std::unordered_map StatMap) { std::unordered_map StatMap) { - - for (const auto &pair : StatMap) { - previousMap[pair.first->function]["Instructions"] = - pair.second->getValue(stats::instructions); - previousMap[pair.first->function]["Forks"] = - pair.second->getValue(stats::forks); - previousMap[pair.first->function]["SolverTime"] = - pair.second->getValue(stats::solverTime); - } -} diff --git a/lib/Core/Delta.h b/lib/Core/MetricCollectorAndSerializer.h similarity index 72% rename from lib/Core/Delta.h rename to lib/Core/MetricCollectorAndSerializer.h index 5df520a014..325ad42992 100644 --- a/lib/Core/Delta.h +++ b/lib/Core/MetricCollectorAndSerializer.h @@ -1,4 +1,4 @@ -//===-- Delta.h--------------------------------------------------*- C++ -*-===// +//===--MetricCollectorAndSerializer.h-----------------------------*-C++ -*-===// // // The KLEE Symbolic Virtual Machine // @@ -18,27 +18,26 @@ namespace klee { -class Delta { -public: - std::unordered_map> - previousMap; - std::vector newPrevMap; +class MetricCollectorAndSerializer { +private: + std::vector previousMap; std::mutex StatisticMapMutex; std::unordered_map> Delta; -public: std::vector SerializeDelMap( const std::unordered_map> &DelMap, const std::string UID); +public: + std::vector GetJson( + const std::unordered_map> &DelMap, + const std::string UID); + std::unordered_map> getCurrentMetric(std::unordered_map); - - void - initPrevDelta(std::unordered_map StatMap); }; } // namespace klee From a138d621d90f2ac25c71aa60916287a5d90d2812 Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Thu, 21 Nov 2024 09:53:48 +0300 Subject: [PATCH 21/22] fix: Add localStatisticMap to executor Signed-off-by: YazoonDinalt --- lib/Core/Executor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 2fd0ba7236..37d7fb2e60 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -4756,8 +4756,8 @@ void Executor::run(ExecutionState *initialState) { if (std::chrono::duration_cast( currentTime - lastExecutionTime) .count() >= 100) { - - StatQ.push(mc.getCurrentMetric(objectManager->StatisticMap)); + auto localStatisticMap = objectManager->StatisticMap; + StatQ.push(mc.getCurrentMetric(localStatisticMap)); nextExecutionTime += std::chrono::milliseconds(DeltaTime); } } From b816bebcd3e8f63ad3e15c637d0d37b9bc7a2efb Mon Sep 17 00:00:00 2001 From: YazoonDinalt Date: Thu, 21 Nov 2024 14:59:44 +0300 Subject: [PATCH 22/22] fix: Data race direct solution method Signed-off-by: YazoonDinalt --- lib/Core/Executor.cpp | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 37d7fb2e60..b2a152d333 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -4725,7 +4725,6 @@ void Executor::run(ExecutionState *initialState) { objectManager->initialUpdate(); - auto lastExecutionTime = std::chrono::steady_clock::now(); MetricCollectorAndSerializer mc; std::thread consumer; std::thread producer; @@ -4733,8 +4732,10 @@ void Executor::run(ExecutionState *initialState) { ServerConnection scForUID(UrlUID); scForUID.getUIDFromServer(); + ServerConnection sc(MetricsUID); sc.setUID(scForUID.getUID()); + std::atomic shouldStop = false; if (sc.getUID() != "ServerNotValid") { consumer = std::thread([&StatQ, &mc, &sc, &shouldStop]() { @@ -4745,27 +4746,24 @@ void Executor::run(ExecutionState *initialState) { } } }); - - producer = - std::thread([&lastExecutionTime, &mc, &StatQ, &shouldStop, this]() { - auto nextExecutionTime = std::chrono::steady_clock::now() + - std::chrono::milliseconds(DeltaTime); - while (!shouldStop) { - std::this_thread::sleep_until(nextExecutionTime); - auto currentTime = std::chrono::steady_clock::now(); - if (std::chrono::duration_cast( - currentTime - lastExecutionTime) - .count() >= 100) { - auto localStatisticMap = objectManager->StatisticMap; - StatQ.push(mc.getCurrentMetric(localStatisticMap)); - nextExecutionTime += std::chrono::milliseconds(DeltaTime); - } - } - }); } + auto startTime = std::chrono::high_resolution_clock::now(); // main interpreter loop while (!haltExecution && !searcher->empty()) { + + if (sc.getUID() != "ServerNotValid") { + auto currentTime = std::chrono::high_resolution_clock::now(); + auto elapsedTime = std::chrono::duration_cast( + currentTime - startTime) + .count(); + if (elapsedTime >= 100) { + auto localStatisticMap = objectManager->StatisticMap; + StatQ.push(mc.getCurrentMetric(localStatisticMap)); + startTime = currentTime; + } + } + auto action = searcher->selectAction(); executeAction(action); objectManager->updateSubscribers();