diff --git a/src/CTUApexConsumer.cpp b/src/CTUApexConsumer.cpp index 8da27a9630632d787c19df31c6bce02737f736da..30e6fa40117d0a64b13332c1fe51e4086083921d 100644 --- a/src/CTUApexConsumer.cpp +++ b/src/CTUApexConsumer.cpp @@ -150,6 +150,12 @@ void CTUApexConsumer::HandleTranslationUnit(clang::ASTContext &Context) { SPDLOG_INFO("Generate wrapper calls"); SPDLOG_CRITICAL("WRAPPER CALLS CAN NOT YET BE IMPLEMENTED"); + for(const auto& e : call_graph->getNodes()){ + std::cout<<e.second->getFunctionName()<<"\n"; + } + + assert(call_graph->getMain()); + if(auto md=call_graph->getMain()->checkAndGet<ExtractionMetadata>(); md.first && !md.second->isMarkedToExtract()){ //we have no main function and need to create or own outFile<<"\nint main(){return 0;}\n"; diff --git a/src/main.cpp b/src/main.cpp index ab16f9f64c766234d5e8e5579dc172ab3e72ca60..d3b54ff9b7b68e8af2129ec14d04ad0dfe725191 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -60,14 +60,15 @@ static cl::opt<bool> OnlyWrapper("generate-only-wrapper", cl::desc("Output only static cl::opt<bool> DumpAnalysisResult("dump-analysis-result", cl::desc("Dump the dependence analysis result to stdout"), cl::cat(CTUApex)); -class CTUApexFactory : clang::ASTFrontendAction { +class CTUApexFrontendAction : clang::ASTFrontendAction { public: - CTUApexFactory(metacg::Callgraph &cg) : cg(&cg) {} + CTUApexFrontendAction(metacg::Callgraph &cg) : cg(&cg) {} std::unique_ptr<clang::ASTConsumer> newASTConsumer() { return std::unique_ptr<clang::ASTConsumer>(new CTUApexConsumer(cg, includes, macros, pragmas)); } + std::unique_ptr<clang::ASTConsumer> CreateASTConsumer([[maybe_unused]] clang::CompilerInstance &compiler, [[maybe_unused]] llvm::StringRef sr) { return std::unique_ptr<clang::ASTConsumer>(new CTUApexConsumer(cg, includes, macros, pragmas)); @@ -98,6 +99,64 @@ void markFunctionsAlongCallpaths(metacg::Callgraph &cg) { } } +#include "clang/Basic/SourceManager.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Tooling/Tooling.h" + +using namespace clang; +using namespace clang::tooling; + +std::vector<std::string> clangIncludeBasedArgumentAdjustor(const CommandLineArguments & cla , StringRef sr){ + //call the compiler specified in cla[0] with -S and -v like so + std::string command = "clang"; + //command.append(" -S -v"); + command.append(" -W,p -v -fsyntax-only"); + for(int i=1;i<cla.size();i++){ + command.append(" "+cla[i]); + } + command.append(" 2>&1"); + std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(command.c_str(), "r"), pclose); + //then read the output of the command like so: + std::string txt; + std::array<char, 128> buffer{}; + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { + txt += buffer.data(); + } + //search for "include search starts here" string and add all the paths with -I to the tool invocation + txt=txt.substr(txt.rfind("search starts here:")+20,txt.rfind("End of search list.")-txt.rfind("search starts here:")-20); + std::vector<std::string> ret; + ret.assign(cla.begin(),cla.end()); + std::string::size_type pos; + std::string::size_type prev = 0; + while ((pos = txt.find('\n', prev)) != std::string::npos) + { + ret.push_back("-I"+txt.substr(prev, pos - prev)); + prev = pos + 2; + } + return ret; +} + +std::vector<std::string> clangResourceDirBasedAdjuster(const CommandLineArguments & cla , StringRef){ + //call the compiler specified in cla[0] with -S and -v like so + std::string command = "clang --print-resource-dir 2>1&"; + std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(command.c_str(), "r"), pclose); + //then read the output of the command like so: + std::string txt; + std::array<char, 128> buffer{}; + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { + txt += buffer.data(); + } + std::vector<std::string> ret; + ret.assign(cla.begin(),cla.end()); + trim(txt); + txt.pop_back(); + ret.push_back("-I"+txt+"/include"); + return ret; +} + int main(int argc, const char **argv) { auto ExpectedParser = CommonOptionsParser::create(argc, argv, CTUApex); @@ -131,7 +190,10 @@ int main(int argc, const char **argv) { CommonOptionsParser &OptionsParser = ExpectedParser.get(); + ClangTool tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList()); + tool.clearArgumentsAdjusters(); + tool.appendArgumentsAdjuster(clangResourceDirBasedAdjuster); metacg::io::FileSource fs(cg_file.getValue()); @@ -147,8 +209,14 @@ int main(int argc, const char **argv) { auto &mcgManager = metacg::graph::MCGManager::get(); mcgManager.addToManagedGraphs("emptyGraph", std::make_unique<metacg::Callgraph>()); + nlohmann::json j = fs.get().at("_CG"); + std::cout<<j.dump(4); + metacg::io::VersionTwoMetaCGReader::upgradeV2FormatToV3Format(j); + std::cout<<j.dump(4); mcgReader->read(); auto &cg = *mcgManager.getCallgraph(); + std::cout<<cg.size()<<"\n"; + //Add extraction point gotten via the CLI for(const auto& extractionFunc : extractionPoints){ if (cg.hasNode(extractionFunc)) { @@ -162,8 +230,10 @@ int main(int argc, const char **argv) { markFunctionsAlongCallpaths(cg); - tool.run(clang::tooling::newFrontendActionFactory<CTUApexFactory>( - new CTUApexFactory(*mcgManager.getCallgraph())).get()); + + + tool.run(clang::tooling::newFrontendActionFactory<CTUApexFrontendAction>( + new CTUApexFrontendAction(*mcgManager.getCallgraph())).get()); return 0; }