├── CMakeLists.txt ├── LICENSE ├── README.md ├── config ├── modref.config ├── ptr.config └── taint.config ├── include ├── Annotation │ ├── ArgPosition.h │ ├── ModRef │ │ ├── ExternalModRefTable.h │ │ ├── ExternalModRefTablePrinter.h │ │ ├── ModRefEffect.h │ │ └── ModRefEffectSummary.h │ ├── Pointer │ │ ├── ExternalPointerTable.h │ │ ├── ExternalPointerTablePrinter.h │ │ ├── PointerEffect.h │ │ └── PointerEffectSummary.h │ └── Taint │ │ ├── ExternalTaintTable.h │ │ ├── TaintDescriptor.h │ │ ├── TaintEntry.h │ │ └── TaintSummary.h ├── Context │ ├── AdaptiveContext.h │ ├── Context.h │ ├── KLimitContext.h │ └── ProgramPoint.h ├── Dynamic │ ├── Analysis │ │ ├── DynamicContext.h │ │ ├── DynamicMemory.h │ │ ├── DynamicMemoryObject.h │ │ ├── DynamicPointer.h │ │ └── DynamicPointerAnalysis.h │ ├── Instrument │ │ ├── AllocType.h │ │ ├── DynamicHooks.h │ │ ├── FeatureCheck.h │ │ ├── IDAssigner.h │ │ └── MemoryInstrument.h │ └── Log │ │ ├── LogPrinter.h │ │ ├── LogProcessor.h │ │ ├── LogReader.h │ │ ├── LogRecord.h │ │ └── LogVisitor.h ├── PointerAnalysis │ ├── Analysis │ │ ├── GlobalPointerAnalysis.h │ │ ├── PointerAnalysis.h │ │ └── SemiSparsePointerAnalysis.h │ ├── Engine │ │ ├── EvalResult.h │ │ ├── EvalSuccessor.h │ │ ├── GlobalState.h │ │ ├── Initializer.h │ │ ├── SemiSparsePropagator.h │ │ ├── StorePruner.h │ │ ├── TransferFunction.h │ │ └── WorkList.h │ ├── FrontEnd │ │ ├── CFG │ │ │ ├── CFGBuilder.h │ │ │ ├── CFGSimplifier.h │ │ │ ├── FunctionTranslator.h │ │ │ ├── InstructionTranslator.h │ │ │ └── PriorityAssigner.h │ │ ├── ConstPointerMap.h │ │ ├── SemiSparseProgramBuilder.h │ │ └── Type │ │ │ ├── ArrayLayoutAnalysis.h │ │ │ ├── ArrayLayoutMap.h │ │ │ ├── CastMap.h │ │ │ ├── PointerLayoutAnalysis.h │ │ │ ├── PointerLayoutMap.h │ │ │ ├── StructCastAnalysis.h │ │ │ ├── TypeAnalysis.h │ │ │ ├── TypeCollector.h │ │ │ ├── TypeMap.h │ │ │ └── TypeSet.h │ ├── MemoryModel │ │ ├── AllocSite.h │ │ ├── MemoryBlock.h │ │ ├── MemoryManager.h │ │ ├── MemoryObject.h │ │ ├── Pointer.h │ │ ├── PointerManager.h │ │ └── Type │ │ │ ├── ArrayLayout.h │ │ │ ├── PointerLayout.h │ │ │ └── TypeLayout.h │ ├── Precision │ │ ├── PrecisionLossTracker.h │ │ ├── TrackerGlobalState.h │ │ └── ValueDependenceTracker.h │ ├── Program │ │ ├── CFG │ │ │ ├── CFG.h │ │ │ ├── CFGNode.h │ │ │ ├── NodeMixin.h │ │ │ └── NodeVisitor.h │ │ └── SemiSparseProgram.h │ └── Support │ │ ├── CallGraph.h │ │ ├── Env.h │ │ ├── FunctionContext.h │ │ ├── Memo.h │ │ ├── ProgramPoint.h │ │ ├── ProgramPointSet.h │ │ ├── PtsMap.h │ │ ├── PtsSet.h │ │ └── Store.h ├── TaintAnalysis │ ├── Analysis │ │ ├── TaintAnalysis.h │ │ └── TrackingTaintAnalysis.h │ ├── Engine │ │ ├── EvalResult.h │ │ ├── EvalSuccessor.h │ │ ├── Initializer.h │ │ ├── SinkViolationChecker.h │ │ ├── TaintGlobalState.h │ │ ├── TaintPropagator.h │ │ ├── TransferFunction.h │ │ └── WorkList.h │ ├── FrontEnd │ │ ├── DefUseModuleBuilder.h │ │ ├── ModRefFunctionSummary.h │ │ ├── ModRefModuleAnalysis.h │ │ ├── ModRefModuleSummary.h │ │ ├── ReachingDefMap.h │ │ └── ReachingDefModuleAnalysis.h │ ├── Lattice │ │ ├── Lattice.h │ │ └── TaintLattice.h │ ├── Precision │ │ ├── CallTracker.h │ │ ├── IndexVector.h │ │ ├── LocalTracker.h │ │ ├── PrecisionLossTracker.h │ │ ├── ReturnTracker.h │ │ ├── TrackerGlobalState.h │ │ ├── TrackerTransferFunction.h │ │ ├── TrackerWorkList.h │ │ └── VectorTransform.h │ ├── Program │ │ ├── DefUseFunction.h │ │ ├── DefUseInstruction.h │ │ └── DefUseModule.h │ └── Support │ │ ├── ProgramPoint.h │ │ ├── ProgramPointSet.h │ │ ├── SinkSignature.h │ │ ├── SinkViolationRecord.h │ │ ├── TaintEnv.h │ │ ├── TaintMap.h │ │ ├── TaintMemo.h │ │ ├── TaintStore.h │ │ └── TaintValue.h ├── Transforms │ ├── ExpandByVal.h │ ├── ExpandConstantExpr.h │ ├── ExpandGetElementPtr.h │ ├── ExpandIndirectBr.h │ ├── ExpandUtils.h │ ├── FoldIntToPtr.h │ ├── GlobalCleanup.h │ ├── LowerGlobalCtor.h │ └── RunPrepass.h └── Util │ ├── AnalysisEngine │ └── DataFlowAnalysis.h │ ├── CommandLine │ ├── CommandLineFlags.h │ ├── CommandLineParser.h │ └── TypedCommandLineParser.h │ ├── DataStructure │ ├── FIFOWorkList.h │ ├── PriorityWorkList.h │ ├── SortedVector.h │ ├── TwoLevelWorkList.h │ ├── VectorMap.h │ └── VectorSet.h │ ├── Hashing.h │ ├── IO │ ├── Context │ │ └── Printer.h │ ├── PointerAnalysis │ │ ├── NodePrinter.h │ │ ├── Printer.h │ │ └── WriteDotFile.h │ ├── ReadFile.h │ ├── ReadIR.h │ ├── TaintAnalysis │ │ ├── Printer.h │ │ └── WriteDotFile.h │ └── WriteIR.h │ ├── Iterator │ ├── DereferenceIterator.h │ ├── InfixOutputIterator.h │ ├── IteratorAdaptor.h │ ├── IteratorFacade.h │ ├── IteratorRange.h │ ├── IteratorTrait.h │ ├── MapValueIterator.h │ └── UniquePtrIterator.h │ ├── Testing │ └── DummyPointerAnalysis.h │ └── pcomb │ ├── Combinator │ ├── AltParser.h │ ├── LazyParser.h │ ├── LexemeParser.h │ ├── ManyParser.h │ ├── ParserAdapter.h │ ├── SeqParser.h │ └── TokenParser.h │ ├── InputStream │ └── InputStream.h │ ├── Parser │ ├── ParseResult.h │ ├── Parser.h │ ├── PredicateCharParser.h │ ├── RegexParser.h │ └── StringParser.h │ └── pcomb.h ├── lib ├── Annotation │ ├── CMakeLists.txt │ ├── ExternalModRefTable.cpp │ ├── ExternalModRefTablePrinter.cpp │ ├── ExternalPointerTable.cpp │ ├── ExternalPointerTablePrinter.cpp │ └── ExternalTaintTable.cpp ├── CMakeLists.txt ├── Dynamic │ ├── Analysis │ │ ├── CMakeLists.txt │ │ ├── DynamicContext.cpp │ │ ├── DynamicMemory.cpp │ │ └── DynamicPointerAnalysis.cpp │ ├── CMakeLists.txt │ ├── Instrument │ │ ├── CMakeLists.txt │ │ ├── DynamicHooks.cpp │ │ ├── FeatureCheck.cpp │ │ ├── IDAssigner.cpp │ │ └── MemoryInstrument.cpp │ ├── Log │ │ ├── CMakeLists.txt │ │ ├── LogPrinter.cpp │ │ └── LogReader.cpp │ └── Runtime │ │ ├── CMakeLists.txt │ │ └── MemoryHooks.c ├── PointerAnalysis │ ├── Analysis │ │ ├── GlobalPointerAnalysis.cpp │ │ └── SemiSparsePointerAnalysis.cpp │ ├── CMakeLists.txt │ ├── Context │ │ ├── AdaptiveContext.cpp │ │ ├── Context.cpp │ │ └── KLimitContext.cpp │ ├── Engine │ │ ├── ExternalCallAnalysis.cpp │ │ ├── Initializer.cpp │ │ ├── SemiSparsePropagator.cpp │ │ ├── StorePruner.cpp │ │ ├── Transfer │ │ │ ├── AllocTransfer.cpp │ │ │ ├── CallTransfer.cpp │ │ │ ├── CopyTransfer.cpp │ │ │ ├── EntryTransfer.cpp │ │ │ ├── LoadTransfer.cpp │ │ │ ├── OffsetTransfer.cpp │ │ │ ├── ReturnTransfer.cpp │ │ │ └── StoreTransfer.cpp │ │ └── TransferFunction.cpp │ ├── FrontEnd │ │ ├── ArrayLayoutAnalysis.cpp │ │ ├── CFGBuilder.cpp │ │ ├── CFGSimplifier.cpp │ │ ├── FunctionTranslator.cpp │ │ ├── InstructionTranslator.cpp │ │ ├── PointerLayoutAnalysis.cpp │ │ ├── PriorityAssigner.cpp │ │ ├── SemiSparseProgramBuilder.cpp │ │ ├── StructCastAnalysis.cpp │ │ ├── TypeAnalysis.cpp │ │ └── TypeCollector.cpp │ ├── MemoryModel │ │ ├── ArrayLayout.cpp │ │ ├── MemoryManager.cpp │ │ ├── PointerLayout.cpp │ │ ├── PointerManager.cpp │ │ └── TypeLayout.cpp │ ├── Output │ │ ├── CFGNodePrinter.cpp │ │ ├── ContextPrinter.cpp │ │ ├── MemoryPrinter.cpp │ │ ├── NodePrinter.cpp │ │ └── WriteDotFile.cpp │ ├── Precision │ │ ├── PrecisionLossTracker.cpp │ │ └── ValueDependenceTracker.cpp │ ├── Program │ │ ├── CFG.cpp │ │ └── SemiSparseProgram.cpp │ ├── StaticFields.cpp │ └── Support │ │ └── PtsSet.cpp ├── TaintAnalysis │ ├── Analysis │ │ ├── TaintAnalysis.cpp │ │ └── TrackingTaintAnalysis.cpp │ ├── CMakeLists.txt │ ├── Engine │ │ ├── ExternalCallAnalysis.cpp │ │ ├── Initializer.cpp │ │ ├── SinkViolationChecker.cpp │ │ ├── TaintPropagator.cpp │ │ └── TransferFunction.cpp │ ├── FrontEnd │ │ ├── DefUseModuleBuilder.cpp │ │ ├── ModRefModuleAnalysis.cpp │ │ └── ReachingDefModuleAnalysis.cpp │ ├── Output │ │ ├── TaintPrinter.cpp │ │ └── WriteDotFile.cpp │ ├── Precision │ │ ├── CallTracker.cpp │ │ ├── PrecisionLossTracker.cpp │ │ ├── ReturnTracker.cpp │ │ └── TrackerTransferFunction.cpp │ └── Program │ │ └── DefUseModule.cpp ├── Transforms │ ├── CMakeLists.txt │ ├── ExpandByVal.cpp │ ├── ExpandConstantExpr.cpp │ ├── ExpandGetElementPtr.cpp │ ├── ExpandIndirectBr.cpp │ ├── ExpandUtils.cpp │ ├── FoldIntToPtr.cpp │ ├── GlobalCleanup.cpp │ ├── LowerGlobalCtor.cpp │ └── RunPrepass.cpp └── Util │ ├── CMakeLists.txt │ ├── CommandLine │ ├── CommandLineParser.cpp │ └── TypedCommandLineParser.cpp │ └── IO │ ├── ReadIR.cpp │ └── WriteIR.cpp ├── tool ├── CMakeLists.txt ├── dot-du-module │ ├── CMakeLists.txt │ ├── CommandLineOptions.cpp │ ├── CommandLineOptions.h │ ├── RunAnalysis.cpp │ ├── RunAnalysis.h │ └── dot-du-module.cpp ├── dot-pointer-cfg │ ├── CMakeLists.txt │ ├── CommandLineOptions.cpp │ ├── CommandLineOptions.h │ ├── RunAnalysis.cpp │ ├── RunAnalysis.h │ └── dot-pointer-cfg.cpp ├── global-pts │ ├── CMakeLists.txt │ ├── CommandLineOptions.cpp │ ├── CommandLineOptions.h │ ├── RunAnalysis.cpp │ ├── RunAnalysis.h │ └── global-pts.cpp ├── pts-dump │ ├── CMakeLists.txt │ ├── CommandLineOptions.cpp │ ├── CommandLineOptions.h │ ├── RunAnalysis.cpp │ ├── RunAnalysis.h │ └── pts-dump.cpp ├── pts-inst │ ├── CMakeLists.txt │ ├── CommandLineOptions.cpp │ ├── CommandLineOptions.h │ └── pts-inst.cpp ├── pts-log-dump │ ├── CMakeLists.txt │ └── pts-log-dump.cpp ├── pts-verify │ ├── CMakeLists.txt │ ├── CommandLineOptions.cpp │ ├── CommandLineOptions.h │ ├── RunAnalysis.cpp │ ├── RunAnalysis.h │ └── pts-verify.cpp ├── scripts │ ├── CMakeLists.txt │ ├── clang-opt.py │ ├── compile-dot.py │ ├── extract-annotation.py │ └── pts-test.py ├── table-check │ ├── CMakeLists.txt │ ├── TableChecker.cpp │ ├── TableChecker.h │ └── table-check.cpp ├── table │ ├── CMakeLists.txt │ ├── CommandLineOptions.cpp │ ├── CommandLineOptions.h │ ├── ExternalModRefTablePrinter.cpp │ ├── ExternalPointerTablePrinter.cpp │ ├── ExternalTaintTablePrinter.cpp │ ├── TablePrinter │ │ ├── ExternalModRefTablePrinter.h │ │ ├── ExternalPointerTablePrinter.h │ │ └── ExternalTaintTablePrinter.h │ └── table.cpp ├── taint-check │ ├── CMakeLists.txt │ ├── CommandLineOptions.cpp │ ├── CommandLineOptions.h │ ├── RunAnalysis.cpp │ ├── RunAnalysis.h │ └── taint-check.cpp └── vkcfa-taint │ ├── CMakeLists.txt │ ├── CommandLineOptions.cpp │ ├── CommandLineOptions.h │ ├── RunAnalysis.cpp │ ├── RunAnalysis.h │ └── vkcfa-taint.cpp ├── unittest ├── CMakeLists.txt ├── ControlFlowUnitTest │ └── ControlFlowTest.cpp ├── GlobalAnalysisUnitTest │ └── GlobalAnalysisTest.cpp ├── InterpreterUnitTest │ ├── InterProcTest.cpp │ └── InterpreterTest.cpp ├── MemoryUnitTest │ ├── ContextTest.cpp │ ├── MemoryTest.cpp │ ├── PointerTest.cpp │ └── PtsSetTest.cpp └── TaintnessUnitTest │ ├── PrecisionTest.cpp │ └── TaintnessTest.cpp └── util └── googletest └── include └── gtest ├── gtest-death-test.h ├── gtest-message.h ├── gtest-param-test.h ├── gtest-printers.h ├── gtest-spi.h ├── gtest-test-part.h ├── gtest-typed-test.h ├── gtest.h ├── gtest_pred_impl.h ├── gtest_prod.h └── internal ├── gtest-death-test-internal.h ├── gtest-filepath.h ├── gtest-internal.h ├── gtest-linked_ptr.h ├── gtest-param-util-generated.h ├── gtest-param-util.h ├── gtest-port.h ├── gtest-string.h ├── gtest-tuple.h └── gtest-type-util.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.8) 2 | project(tpa) 3 | 4 | # Check for LLVM installation 5 | find_package(LLVM REQUIRED CONFIG) 6 | message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") 7 | message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") 8 | include_directories(${LLVM_INCLUDE_DIRS}) 9 | add_definitions(${LLVM_DEFINITIONS}) 10 | 11 | # Check for Python3 installation 12 | find_package(PythonInterp 3 REQUIRED) 13 | message(STATUS "Found Python ${PYTHON_VERSION_STRING}") 14 | message(STATUS "Using python interpreter in: ${PYTHON_EXECUTABLE}") 15 | 16 | # Check for C++14 support and set the compilation flag 17 | include(CheckCXXCompilerFlag) 18 | CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14) 19 | if(COMPILER_SUPPORTS_CXX14) 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fno-rtti -Wall -fPIC") 21 | else() 22 | message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++14 support. Please use a different C++ compiler.") 23 | endif() 24 | 25 | configure_file(config/ptr.config ptr.config COPYONLY) 26 | configure_file(config/modref.config modref.config COPYONLY) 27 | configure_file(config/taint.config taint.config COPYONLY) 28 | 29 | # Specify library and binary output dir 30 | set (EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 31 | 32 | add_subdirectory (lib) 33 | #add_subdirectory (unittest) 34 | add_subdirectory (tool) 35 | 36 | enable_testing () 37 | add_test (MemoryUnitTest ${PROJECT_BINARY_DIR}/unittest/MemoryTest) 38 | add_test (InterpreterUnitTest ${PROJECT_BINARY_DIR}/unittest/InterpreterTest) 39 | add_test (GlobalAnalysisUnitTest ${PROJECT_BINARY_DIR}/unittest/GlobalAnalysisTest) 40 | add_test (ControlFlowTest ${PROJECT_BINARY_DIR}/unittest/ControlFlowTest) 41 | add_test (TaintnessTest ${PROJECT_BINARY_DIR}/unittest/TaintnessTest) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jia Chen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Taint checker for LLVM 2 | This project implements an efficient flow-sensitive, context-sensitive, field-sensitive taint analyzer on top of LLVM. 3 | 4 | TODO: Add more description 5 | -------------------------------------------------------------------------------- /include/Annotation/ModRef/ExternalModRefTable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Annotation/ModRef/ModRefEffectSummary.h" 4 | 5 | #include 6 | 7 | namespace llvm 8 | { 9 | class StringRef; 10 | } 11 | 12 | namespace annotation 13 | { 14 | 15 | class ExternalModRefTable 16 | { 17 | private: 18 | using MapType = std::unordered_map; 19 | MapType table; 20 | 21 | static ExternalModRefTable buildTable(const llvm::StringRef&); 22 | public: 23 | using const_iterator = MapType::const_iterator; 24 | 25 | ExternalModRefTable() = default; 26 | 27 | const ModRefEffectSummary* lookup(const llvm::StringRef&) const; 28 | 29 | const_iterator begin() const { return table.begin(); } 30 | const_iterator end() const { return table.end(); } 31 | size_t size() const { return table.size(); } 32 | 33 | static ExternalModRefTable loadFromFile(const char* fileName); 34 | }; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /include/Annotation/ModRef/ExternalModRefTablePrinter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm 4 | { 5 | class raw_ostream; 6 | } 7 | 8 | namespace annotation 9 | { 10 | 11 | class ExternalModRefTable; 12 | 13 | class ExternalModRefTablePrinter 14 | { 15 | private: 16 | llvm::raw_ostream& os; 17 | public: 18 | ExternalModRefTablePrinter(llvm::raw_ostream& o): os(o) {} 19 | 20 | void printTable(const ExternalModRefTable&); 21 | }; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /include/Annotation/ModRef/ModRefEffect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Annotation/ArgPosition.h" 4 | 5 | namespace annotation 6 | { 7 | 8 | enum class ModRefType: bool 9 | { 10 | Mod, 11 | Ref 12 | }; 13 | 14 | enum class ModRefClass: bool 15 | { 16 | DirectMemory, 17 | ReachableMemory 18 | }; 19 | 20 | class ModRefEffect 21 | { 22 | private: 23 | ModRefType type; 24 | ModRefClass mClass; 25 | APosition pos; 26 | public: 27 | ModRefEffect(ModRefType t, ModRefClass c, const APosition& p): type(t), mClass(c), pos(p) {} 28 | 29 | ModRefType getType() const { return type; } 30 | ModRefClass getClass() const { return mClass; } 31 | APosition getPosition() const { return pos; } 32 | 33 | bool isModEffect() const { return type == ModRefType::Mod; } 34 | bool isRefEffect() const { return type == ModRefType::Ref; } 35 | bool onDirectMemory() const { return mClass == ModRefClass::DirectMemory; } 36 | bool onReachableMemory() const { return mClass == ModRefClass::ReachableMemory; } 37 | }; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /include/Annotation/ModRef/ModRefEffectSummary.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Annotation/ModRef/ModRefEffect.h" 4 | 5 | #include 6 | 7 | namespace annotation 8 | { 9 | 10 | class ModRefEffectSummary 11 | { 12 | private: 13 | using EffectList = std::vector; 14 | EffectList list; 15 | public: 16 | using const_iterator = EffectList::const_iterator; 17 | 18 | ModRefEffectSummary() = default; 19 | 20 | void addEffect(ModRefEffect&& e) 21 | { 22 | list.emplace_back(std::move(e)); 23 | } 24 | 25 | const_iterator begin() const { return list.begin(); } 26 | const_iterator end() const { return list.end(); } 27 | bool empty() const { return list.empty(); } 28 | }; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /include/Annotation/Pointer/ExternalPointerTable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Annotation/Pointer/PointerEffectSummary.h" 4 | 5 | #include 6 | 7 | namespace llvm 8 | { 9 | class StringRef; 10 | } 11 | 12 | namespace annotation 13 | { 14 | 15 | class ExternalPointerTable 16 | { 17 | private: 18 | using MapType = std::unordered_map; 19 | MapType table; 20 | 21 | static ExternalPointerTable buildTable(const llvm::StringRef&); 22 | public: 23 | using const_iterator = MapType::const_iterator; 24 | 25 | const PointerEffectSummary* lookup(const llvm::StringRef& name) const; 26 | 27 | // Note: this function should be used for testing only. The only sensible way of constructing an external table is calling loadFromFile() 28 | void addEffect(const llvm::StringRef& name, PointerEffect&& e); 29 | 30 | const_iterator begin() const { return table.begin(); } 31 | const_iterator end() const { return table.end(); } 32 | size_t size() const { return table.size(); } 33 | 34 | static ExternalPointerTable loadFromFile(const char* fileName); 35 | }; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /include/Annotation/Pointer/ExternalPointerTablePrinter.h: -------------------------------------------------------------------------------- 1 | #ifndef TPA_EXTERNAL_POINTER_TABLE_PRINTER_H 2 | #define TPA_EXTERNAL_POINTER_TABLE_PRINTER_H 3 | 4 | namespace llvm 5 | { 6 | class raw_ostream; 7 | } 8 | 9 | namespace annotation 10 | { 11 | 12 | class ExternalPointerTable; 13 | 14 | class ExternalPointerTablePrinter 15 | { 16 | private: 17 | llvm::raw_ostream& os; 18 | public: 19 | ExternalPointerTablePrinter(llvm::raw_ostream& o): os(o) {} 20 | 21 | void printTable(const ExternalPointerTable&); 22 | }; 23 | 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /include/Annotation/Pointer/PointerEffectSummary.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Annotation/Pointer/PointerEffect.h" 4 | 5 | #include 6 | 7 | namespace annotation 8 | { 9 | 10 | class PointerEffectSummary 11 | { 12 | private: 13 | using EffectList = std::vector; 14 | EffectList list; 15 | public: 16 | using const_iterator = EffectList::const_iterator; 17 | 18 | PointerEffectSummary() = default; 19 | 20 | void addEffect(PointerEffect&& e) 21 | { 22 | list.emplace_back(std::move(e)); 23 | } 24 | 25 | const_iterator begin() const { return list.begin(); } 26 | const_iterator end() const { return list.end(); } 27 | bool empty() const { return list.empty(); } 28 | }; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /include/Annotation/Taint/ExternalTaintTable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Annotation/Taint/TaintSummary.h" 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace annotation 10 | { 11 | 12 | class ExternalTaintTable 13 | { 14 | private: 15 | std::unordered_map summaryMap; 16 | 17 | static ExternalTaintTable buildTable(const llvm::StringRef&); 18 | public: 19 | using const_iterator = typename decltype(summaryMap)::const_iterator; 20 | 21 | ExternalTaintTable() = default; 22 | 23 | const TaintSummary* lookup(const std::string& name) const; 24 | 25 | const_iterator begin() const { return summaryMap.begin(); } 26 | const_iterator end() const { return summaryMap.end(); } 27 | size_t size() const { return summaryMap.size(); } 28 | 29 | static ExternalTaintTable loadFromFile(const char* fileName); 30 | }; 31 | 32 | } // end of taint 33 | -------------------------------------------------------------------------------- /include/Annotation/Taint/TaintDescriptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Annotation/ArgPosition.h" 4 | 5 | namespace annotation 6 | { 7 | 8 | // TClass specify whether the taintness is on the value, on the memory location pointed to by the value, or on all memory locations that can be obtained from dereferencing pointers that are results of doing pointer arithmetics on the value 9 | enum class TClass: uint8_t 10 | { 11 | ValueOnly, 12 | DirectMemory, 13 | ReachableMemory 14 | }; 15 | 16 | // TEnd specify whether the given record is a taint source, a taint sink, or a taint pipe (transfer taint from one end to another) 17 | enum class TEnd: uint8_t 18 | { 19 | Source, 20 | Sink, 21 | Pipe 22 | }; 23 | 24 | // TPosition specify where the position of the taintness is 25 | using TPosition = APosition; 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /include/Annotation/Taint/TaintSummary.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Annotation/Taint/TaintEntry.h" 4 | 5 | #include 6 | #include 7 | 8 | namespace annotation 9 | { 10 | 11 | class TaintSummary 12 | { 13 | private: 14 | using DeclList = std::vector; 15 | DeclList effects; 16 | public: 17 | using const_iterator = DeclList::const_iterator; 18 | 19 | TaintSummary() = default; 20 | 21 | void addEntry(TaintEntry entry) 22 | { 23 | effects.push_back(std::move(entry)); 24 | } 25 | 26 | std::size_t size() const { return effects.size(); } 27 | bool empty() const { return effects.empty(); } 28 | 29 | const_iterator begin() const { return effects.begin(); } 30 | const_iterator end() const { return effects.end(); } 31 | }; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /include/Context/AdaptiveContext.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Context/Context.h" 4 | #include "Context/ProgramPoint.h" 5 | 6 | #include 7 | 8 | namespace context 9 | { 10 | 11 | class AdaptiveContext 12 | { 13 | private: 14 | static std::unordered_set trackedCallsites; 15 | public: 16 | static void trackCallSite(const ProgramPoint&); 17 | 18 | static const Context* pushContext(const Context*, const llvm::Instruction*); 19 | static const Context* pushContext(const ProgramPoint&); 20 | }; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /include/Context/Context.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/Hashing.h" 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace context 10 | { 11 | 12 | class ProgramPoint; 13 | 14 | // This class represents a particualr calling context, which is represented by a stack of callsites 15 | class Context 16 | { 17 | private: 18 | // The call stack is implemented by a linked list 19 | const llvm::Instruction* callSite; 20 | const Context* predContext; 21 | size_t sz; 22 | 23 | static std::unordered_set ctxSet; 24 | 25 | Context(): callSite(nullptr), predContext(nullptr), sz(0) {} 26 | Context(const llvm::Instruction* c, const Context* p): callSite(c), predContext(p), sz(p == nullptr ? 1 : p->sz + 1) {} 27 | public: 28 | const llvm::Instruction* getCallSite() const { return callSite; } 29 | size_t size() const { return sz; } 30 | bool isGlobalContext() const { return sz == 0; } 31 | 32 | bool operator==(const Context& other) const 33 | { 34 | return callSite == other.callSite && predContext == other.predContext; 35 | } 36 | bool operator!=(const Context& other) const 37 | { 38 | return !(*this == other); 39 | } 40 | 41 | static const Context* pushContext(const Context* ctx, const llvm::Instruction* inst); 42 | static const Context* pushContext(const ProgramPoint&); 43 | static const Context* popContext(const Context* ctx); 44 | static const Context* getGlobalContext(); 45 | 46 | static std::vector getAllContexts(); 47 | friend struct std::hash; 48 | }; 49 | 50 | } 51 | 52 | namespace std 53 | { 54 | template<> struct hash 55 | { 56 | size_t operator()(const context::Context& c) const 57 | { 58 | return util::hashPair(c.callSite, c.predContext); 59 | } 60 | }; 61 | } 62 | -------------------------------------------------------------------------------- /include/Context/KLimitContext.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Context/Context.h" 4 | 5 | namespace llvm 6 | { 7 | class Instruction; 8 | } 9 | 10 | namespace context 11 | { 12 | 13 | class ProgramPoint; 14 | 15 | class KLimitContext 16 | { 17 | private: 18 | static unsigned defaultLimit; 19 | public: 20 | static void setLimit(unsigned k) { defaultLimit = k; } 21 | static unsigned getLimit() { return defaultLimit; } 22 | 23 | static const Context* pushContext(const Context*, const llvm::Instruction*); 24 | static const Context* pushContext(const ProgramPoint&); 25 | }; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /include/Dynamic/Analysis/DynamicContext.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/Hashing.h" 4 | 5 | #include 6 | 7 | namespace dynamic 8 | { 9 | 10 | // Dynamic version of Context 11 | class DynamicContext 12 | { 13 | private: 14 | using CallSiteType = unsigned; 15 | 16 | CallSiteType callSite; 17 | const DynamicContext* predContext; 18 | size_t depth; 19 | 20 | static std::unordered_set ctxSet; 21 | static const DynamicContext* globalCtx; 22 | 23 | DynamicContext(): callSite(0), predContext(nullptr), depth(0) {} 24 | DynamicContext(CallSiteType c, const DynamicContext* p): callSite(c), predContext(p), depth(p == nullptr ? 1 : p->depth + 1) {} 25 | public: 26 | CallSiteType getCallSite() const { return callSite; } 27 | size_t getDepth() const { return depth; } 28 | bool isGlobalContext() const { return depth == 0; } 29 | 30 | bool operator==(const DynamicContext& other) const 31 | { 32 | return callSite == other.callSite && predContext == other.predContext; 33 | } 34 | bool operator!=(const DynamicContext& other) const 35 | { 36 | return !(*this == other); 37 | } 38 | 39 | static const DynamicContext* pushContext(const DynamicContext* ctx, CallSiteType cs); 40 | static const DynamicContext* popContext(const DynamicContext* ctx); 41 | static const DynamicContext* getGlobalContext(); 42 | 43 | friend struct std::hash; 44 | }; 45 | 46 | } 47 | 48 | namespace std 49 | { 50 | 51 | template<> struct hash 52 | { 53 | size_t operator()(const dynamic::DynamicContext& c) const 54 | { 55 | return util::hashPair(c.callSite, c.predContext); 56 | } 57 | }; 58 | 59 | } 60 | -------------------------------------------------------------------------------- /include/Dynamic/Analysis/DynamicMemory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Dynamic/Analysis/DynamicMemoryObject.h" 4 | #include "Dynamic/Instrument/AllocType.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace dynamic 11 | { 12 | 13 | class DynamicMemory 14 | { 15 | private: 16 | using AllocMapType = std::map; 17 | AllocMapType allocMap; 18 | 19 | using ContextMapType = std::unordered_map>; 20 | ContextMapType stackCtxMap; 21 | 22 | DynamicMemoryObject insertAllocMap(const DynamicPointer&, const void*); 23 | DynamicMemoryObject allocateGlobal(const DynamicPointer&, const void*); 24 | DynamicMemoryObject allocateStack(const DynamicPointer&, const void*); 25 | DynamicMemoryObject allocateHeap(const DynamicPointer&, const void*); 26 | public: 27 | DynamicMemory() = default; 28 | 29 | DynamicMemoryObject allocate(AllocType type, const DynamicPointer&, const void*); 30 | DynamicMemoryObject getMemoryObject(const void*); 31 | void deallocateStack(const DynamicContext*); 32 | }; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /include/Dynamic/Analysis/DynamicMemoryObject.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Dynamic/Analysis/DynamicPointer.h" 4 | 5 | #include 6 | 7 | namespace dynamic 8 | { 9 | 10 | class DynamicMemoryObject 11 | { 12 | private: 13 | DynamicPointer allocSite; 14 | std::ptrdiff_t offset; 15 | public: 16 | DynamicMemoryObject(const DynamicPointer& a, std::ptrdiff_t o): allocSite(a), offset(o) {} 17 | 18 | const DynamicPointer& getAllocSite() const { return allocSite; } 19 | std::ptrdiff_t getOffset() const { return offset; } 20 | 21 | static DynamicMemoryObject getNullObject(); 22 | }; 23 | 24 | } -------------------------------------------------------------------------------- /include/Dynamic/Analysis/DynamicPointer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/Hashing.h" 4 | 5 | namespace dynamic 6 | { 7 | 8 | class DynamicContext; 9 | 10 | class DynamicPointer 11 | { 12 | private: 13 | const DynamicContext* ctx; 14 | unsigned ptrId; 15 | public: 16 | DynamicPointer(const DynamicContext* c, unsigned p): ctx(c), ptrId(p) {} 17 | 18 | bool operator==(const DynamicPointer& rhs) const 19 | { 20 | return ctx == rhs.ctx && ptrId == rhs.ptrId; 21 | } 22 | bool operator!=(const DynamicPointer& rhs) const 23 | { 24 | return !(*this == rhs); 25 | } 26 | 27 | const DynamicContext* getContext() const { return ctx; } 28 | unsigned getID() const { return ptrId; } 29 | }; 30 | 31 | } 32 | 33 | namespace std 34 | { 35 | 36 | template<> struct hash 37 | { 38 | size_t operator()(const dynamic::DynamicPointer& ptr) const 39 | { 40 | return util::hashPair(ptr.getContext(), ptr.getID()); 41 | } 42 | }; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /include/Dynamic/Analysis/DynamicPointerAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Dynamic/Analysis/DynamicMemory.h" 4 | #include "Dynamic/Log/LogProcessor.h" 5 | 6 | namespace dynamic 7 | { 8 | 9 | class DynamicContext; 10 | 11 | class DynamicPointerAnalysis: public LogProcessor 12 | { 13 | private: 14 | using MapType = std::unordered_map; 15 | MapType ptsMap; 16 | 17 | DynamicMemory memory; 18 | const DynamicContext* currCtx; 19 | unsigned callerId; 20 | 21 | void setPointsTo(const DynamicPointer&, const DynamicMemoryObject&); 22 | public: 23 | using const_iterator = MapType::const_iterator; 24 | 25 | DynamicPointerAnalysis(const char* fileName); 26 | 27 | void visitAllocRecord(const AllocRecord&); 28 | void visitPointerRecord(const PointerRecord&); 29 | void visitEnterRecord(const EnterRecord&); 30 | void visitExitRecord(const ExitRecord&); 31 | void visitCallRecord(const CallRecord&); 32 | 33 | const_iterator begin() const { return ptsMap.begin(); } 34 | const_iterator end() const { return ptsMap.end(); } 35 | }; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /include/Dynamic/Instrument/AllocType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace dynamic 6 | { 7 | 8 | enum AllocType: std::uint8_t 9 | { 10 | Global = 0, 11 | Stack, 12 | Heap 13 | }; 14 | 15 | } -------------------------------------------------------------------------------- /include/Dynamic/Instrument/DynamicHooks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm 4 | { 5 | class Function; 6 | class Module; 7 | class Type; 8 | } 9 | 10 | namespace dynamic 11 | { 12 | 13 | class DynamicHooks 14 | { 15 | private: 16 | llvm::Function* initHook; 17 | llvm::Function* allocHook; 18 | llvm::Function* pointerHook; 19 | llvm::Function* callHook; 20 | llvm::Function* enterHook; 21 | llvm::Function* exitHook; 22 | llvm::Function* globalHook; 23 | llvm::Function* mainHook; 24 | public: 25 | DynamicHooks(llvm::Module&); 26 | 27 | llvm::Function* getInitHook() { return initHook; } 28 | llvm::Function* getAllocHook() { return allocHook; } 29 | llvm::Function* getPointerHook() { return pointerHook; } 30 | llvm::Function* getCallHook() { return callHook; } 31 | llvm::Function* getEnterHook() { return enterHook; } 32 | llvm::Function* getExitHook() { return exitHook; } 33 | llvm::Function* getGlobalHook() { return globalHook; } 34 | llvm::Function* getMainHook() { return mainHook; } 35 | 36 | bool isHook(const llvm::Function*) const; 37 | }; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /include/Dynamic/Instrument/FeatureCheck.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm 4 | { 5 | class Function; 6 | class Module; 7 | class StringRef; 8 | class Value; 9 | } 10 | 11 | namespace dynamic 12 | { 13 | 14 | class FeatureCheck 15 | { 16 | private: 17 | void issueWarning(const llvm::Value&, const llvm::StringRef&); 18 | 19 | void checkIndirectLibraryCall(const llvm::Function& f); 20 | void checkArrayArgOrInst(const llvm::Function& f); 21 | public: 22 | FeatureCheck() = default; 23 | 24 | void runOnModule(const llvm::Module& module); 25 | }; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /include/Dynamic/Instrument/IDAssigner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace llvm 6 | { 7 | class Module; 8 | class Value; 9 | class User; 10 | } 11 | 12 | namespace dynamic 13 | { 14 | 15 | class IDAssigner 16 | { 17 | private: 18 | using IDType = unsigned; 19 | IDType nextID; 20 | 21 | using MapType = llvm::DenseMap; 22 | MapType idMap; 23 | using RevMapType = std::vector; 24 | RevMapType revIdMap; 25 | 26 | bool assignValueID(const llvm::Value*); 27 | bool assignUserID(const llvm::User*); 28 | public: 29 | IDAssigner(const llvm::Module&); 30 | 31 | const IDType* getID(const llvm::Value* v) const; 32 | const llvm::Value* getValue(IDType id) const; 33 | 34 | void dump() const; 35 | }; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /include/Dynamic/Instrument/MemoryInstrument.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Annotation/Pointer/ExternalPointerTable.h" 4 | 5 | namespace llvm 6 | { 7 | class Module; 8 | } 9 | 10 | namespace dynamic 11 | { 12 | 13 | class MemoryInstrument 14 | { 15 | private: 16 | annotation::ExternalPointerTable extTable; 17 | public: 18 | MemoryInstrument() = default; 19 | 20 | void loadExternalTable(const char* fileName) 21 | { 22 | extTable = annotation::ExternalPointerTable::loadFromFile(fileName); 23 | } 24 | 25 | void runOnModule(llvm::Module&); 26 | }; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /include/Dynamic/Log/LogPrinter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Dynamic/Log/LogProcessor.h" 4 | 5 | namespace dynamic 6 | { 7 | 8 | class LogPrinter: public LogProcessor 9 | { 10 | private: 11 | std::ostream& os; 12 | public: 13 | LogPrinter(const char*, std::ostream&); 14 | 15 | void visitAllocRecord(const AllocRecord&); 16 | void visitPointerRecord(const PointerRecord&); 17 | void visitEnterRecord(const EnterRecord&); 18 | void visitExitRecord(const ExitRecord&); 19 | void visitCallRecord(const CallRecord&); 20 | }; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /include/Dynamic/Log/LogProcessor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Dynamic/Log/LogReader.h" 4 | #include "Dynamic/Log/LogVisitor.h" 5 | 6 | namespace dynamic 7 | { 8 | 9 | template 10 | class LogProcessor: public LogConstVisitor 11 | { 12 | private: 13 | LazyLogReader reader; 14 | public: 15 | LogProcessor(const char* fileName): reader(fileName) {} 16 | 17 | void process() 18 | { 19 | while (auto rec = reader.readLogRecord()) 20 | this->visit(*rec); 21 | } 22 | }; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /include/Dynamic/Log/LogReader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Dynamic/Log/LogRecord.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace dynamic 10 | { 11 | 12 | class EagerLogReader 13 | { 14 | public: 15 | EagerLogReader() = delete; 16 | 17 | static std::vector readLogFromFile(const char* fileName); 18 | }; 19 | 20 | class LazyLogReader 21 | { 22 | private: 23 | std::ifstream ifs; 24 | public: 25 | LazyLogReader(const char* fileName); 26 | 27 | std::experimental::optional readLogRecord(); 28 | }; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /include/Dynamic/Log/LogRecord.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // We won't put the following structs into a namespace because of C compatibility 4 | 5 | struct AllocRecord 6 | { 7 | char type; 8 | unsigned id; 9 | void* address; 10 | }; 11 | 12 | struct PointerRecord 13 | { 14 | unsigned id; 15 | void* address; 16 | }; 17 | 18 | struct EnterRecord 19 | { 20 | unsigned id; 21 | }; 22 | 23 | struct ExitRecord 24 | { 25 | unsigned id; 26 | }; 27 | 28 | struct CallRecord 29 | { 30 | unsigned id; 31 | }; 32 | 33 | enum LogRecordType 34 | { 35 | TAllocRec, 36 | TPointerRec, 37 | TEnterRec, 38 | TExitRec, 39 | TCallRec 40 | }; 41 | 42 | struct LogRecord 43 | { 44 | enum LogRecordType type; 45 | union 46 | { 47 | struct AllocRecord allocRecord; 48 | struct PointerRecord ptrRecord; 49 | struct EnterRecord enterRecord; 50 | struct ExitRecord exitRecord; 51 | struct CallRecord callRecord; 52 | }; 53 | }; 54 | -------------------------------------------------------------------------------- /include/Dynamic/Log/LogVisitor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Dynamic/Log/LogRecord.h" 4 | 5 | namespace dynamic 6 | { 7 | 8 | template 9 | class LogConstVisitor 10 | { 11 | public: 12 | LogConstVisitor() = default; 13 | 14 | RetType visit(const LogRecord& rec) 15 | { 16 | switch (rec.type) 17 | { 18 | case LogRecordType::TAllocRec: 19 | return static_cast(this)->visitAllocRecord(rec.allocRecord); 20 | case LogRecordType::TPointerRec: 21 | return static_cast(this)->visitPointerRecord(rec.ptrRecord); 22 | case LogRecordType::TEnterRec: 23 | return static_cast(this)->visitEnterRecord(rec.enterRecord); 24 | case LogRecordType::TExitRec: 25 | return static_cast(this)->visitExitRecord(rec.exitRecord); 26 | case LogRecordType::TCallRec: 27 | return static_cast(this)->visitCallRecord(rec.callRecord); 28 | default: 29 | std::abort(); 30 | } 31 | } 32 | }; 33 | 34 | } -------------------------------------------------------------------------------- /include/PointerAnalysis/Analysis/SemiSparsePointerAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Analysis/PointerAnalysis.h" 4 | #include "PointerAnalysis/Support/Env.h" 5 | #include "PointerAnalysis/Support/Memo.h" 6 | 7 | namespace tpa 8 | { 9 | 10 | class SemiSparseProgram; 11 | 12 | class SemiSparsePointerAnalysis: public PointerAnalysis 13 | { 14 | private: 15 | Env env; 16 | Memo memo; 17 | public: 18 | SemiSparsePointerAnalysis() = default; 19 | 20 | void runOnProgram(const SemiSparseProgram&); 21 | 22 | PtsSet getPtsSetImpl(const Pointer*) const; 23 | }; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /include/PointerAnalysis/Engine/EvalResult.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Engine/EvalSuccessor.h" 4 | #include "PointerAnalysis/Support/Store.h" 5 | 6 | #include 7 | #include 8 | 9 | namespace tpa 10 | { 11 | 12 | class EvalResult 13 | { 14 | private: 15 | std::vector> storeVec; 16 | 17 | using SuccessorList = std::vector; 18 | SuccessorList succs; 19 | public: 20 | using const_iterator = typename SuccessorList::const_iterator; 21 | 22 | EvalResult() = default; 23 | 24 | EvalResult(const EvalResult&) = delete; 25 | EvalResult(EvalResult&&) noexcept = default; 26 | EvalResult& operator=(const EvalResult&) = delete; 27 | EvalResult& operator=(EvalResult&&) = delete; 28 | 29 | template 30 | Store& getNewStore(Args&& ...a) 31 | { 32 | storeVec.emplace_back(std::make_unique(std::forward(a)...)); 33 | return *storeVec.back(); 34 | } 35 | 36 | void addTopLevelProgramPoint(const ProgramPoint& pp) 37 | { 38 | succs.push_back(EvalSuccessor(pp, nullptr)); 39 | } 40 | 41 | void addMemLevelProgramPoint(const ProgramPoint& pp, const Store& store) 42 | { 43 | succs.push_back(EvalSuccessor(pp, &store)); 44 | } 45 | 46 | const_iterator begin() const { return succs.begin(); } 47 | const_iterator end() const { return succs.end(); } 48 | bool empty() const { return succs.empty(); } 49 | size_t size() const { return succs.size(); } 50 | }; 51 | 52 | } 53 | -------------------------------------------------------------------------------- /include/PointerAnalysis/Engine/EvalSuccessor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Support/ProgramPoint.h" 4 | #include "PointerAnalysis/Support/Store.h" 5 | 6 | namespace tpa 7 | { 8 | 9 | class EvalSuccessor 10 | { 11 | private: 12 | ProgramPoint pp; 13 | const Store* store; 14 | 15 | EvalSuccessor(const ProgramPoint& p, const Store* s): pp(p), store(s) {} 16 | public: 17 | bool isTopLevel() const { return store == nullptr; } 18 | const ProgramPoint& getProgramPoint() const { return pp; } 19 | const Store* getStore() const { return store; } 20 | 21 | friend class EvalResult; 22 | }; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /include/PointerAnalysis/Engine/GlobalState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Support/CallGraph.h" 4 | #include "PointerAnalysis/Support/Env.h" 5 | #include "PointerAnalysis/Support/FunctionContext.h" 6 | #include "PointerAnalysis/Support/ProgramPoint.h" 7 | 8 | namespace annotation 9 | { 10 | class ExternalPointerTable; 11 | } 12 | 13 | namespace tpa 14 | { 15 | 16 | class MemoryManager; 17 | class PointerManager; 18 | class SemiSparseProgram; 19 | 20 | class GlobalState 21 | { 22 | private: 23 | PointerManager& ptrManager; 24 | MemoryManager& memManager; 25 | 26 | const SemiSparseProgram& prog; 27 | const annotation::ExternalPointerTable& extTable; 28 | 29 | Env& env; 30 | CallGraph callGraph; 31 | public: 32 | GlobalState(PointerManager& p, MemoryManager& m, const SemiSparseProgram& s, const annotation::ExternalPointerTable& t, Env& e): ptrManager(p), memManager(m), prog(s), extTable(t), env(e) {} 33 | 34 | PointerManager& getPointerManager() { return ptrManager; } 35 | const PointerManager& getPointerManager() const { return ptrManager; } 36 | MemoryManager& getMemoryManager() { return memManager; } 37 | const MemoryManager& getMemoryManager() const { return memManager; } 38 | const SemiSparseProgram& getSemiSparseProgram() const { return prog; } 39 | const annotation::ExternalPointerTable& getExternalPointerTable() const { return extTable; } 40 | 41 | Env& getEnv() { return env; } 42 | const Env& getEnv() const { return env; } 43 | 44 | decltype(callGraph)& getCallGraph() { return callGraph; } 45 | const decltype(callGraph)& getCallGraph() const { return callGraph; } 46 | }; 47 | 48 | } 49 | -------------------------------------------------------------------------------- /include/PointerAnalysis/Engine/Initializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Engine/WorkList.h" 4 | #include "PointerAnalysis/Support/Store.h" 5 | 6 | namespace tpa 7 | { 8 | 9 | class GlobalState; 10 | class Memo; 11 | 12 | class Initializer 13 | { 14 | private: 15 | GlobalState& globalState; 16 | Memo& memo; 17 | public: 18 | Initializer(GlobalState& g, Memo& m): globalState(g), memo(m) {} 19 | 20 | ForwardWorkList runOnInitState(Store&& initStore); 21 | }; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /include/PointerAnalysis/Engine/SemiSparsePropagator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Engine/WorkList.h" 4 | 5 | namespace tpa 6 | { 7 | 8 | class EvalResult; 9 | class EvalSuccessor; 10 | class Memo; 11 | 12 | class SemiSparsePropagator 13 | { 14 | private: 15 | Memo& memo; 16 | ForwardWorkList& workList; 17 | 18 | void propagateTopLevel(const EvalSuccessor&); 19 | void propagateMemLevel(const EvalSuccessor&); 20 | bool enqueueIfMemoChange(const ProgramPoint&, const Store&); 21 | public: 22 | SemiSparsePropagator(Memo& m, ForwardWorkList& w): memo(m), workList(w) {} 23 | 24 | void propagate(const EvalResult&); 25 | }; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /include/PointerAnalysis/Engine/StorePruner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Support/ProgramPoint.h" 4 | #include "PointerAnalysis/Support/Env.h" 5 | #include "PointerAnalysis/Support/Store.h" 6 | #include "Util/DataStructure/VectorSet.h" 7 | 8 | #include 9 | #include 10 | 11 | namespace tpa 12 | { 13 | 14 | class MemoryManager; 15 | class PointerManager; 16 | 17 | class StorePruner 18 | { 19 | private: 20 | const Env& env; 21 | const PointerManager& ptrManager; 22 | const MemoryManager& memManager; 23 | 24 | using ObjectSet = std::unordered_set; 25 | ObjectSet getRootSet(const Store&, const ProgramPoint&); 26 | void findAllReachableObjects(const Store&, ObjectSet&); 27 | Store filterStore(const Store&, const ObjectSet&); 28 | public: 29 | StorePruner(const Env& e, const PointerManager& p, const MemoryManager& m): env(e), ptrManager(p), memManager(m) {} 30 | 31 | Store pruneStore(const Store&, const ProgramPoint&); 32 | }; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/CFG/CFGBuilder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/FrontEnd/Type/TypeMap.h" 4 | 5 | namespace llvm 6 | { 7 | class Function; 8 | class Instruction; 9 | } 10 | 11 | namespace tpa 12 | { 13 | 14 | class CFG; 15 | class CFGNode; 16 | 17 | class CFGBuilder 18 | { 19 | private: 20 | CFG& cfg; 21 | const TypeMap& typeMap; 22 | 23 | CFGNode* translateInstruction(const llvm::Instruction&); 24 | public: 25 | CFGBuilder(CFG& c, const TypeMap& t); 26 | 27 | void buildCFG(const llvm::Function&); 28 | }; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/CFG/CFGSimplifier.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/DataStructure/VectorSet.h" 4 | 5 | #include 6 | 7 | namespace llvm 8 | { 9 | class Value; 10 | } 11 | 12 | namespace tpa 13 | { 14 | 15 | class CFG; 16 | class CFGNode; 17 | 18 | class CFGSimplifier 19 | { 20 | private: 21 | llvm::DenseMap eqMap; 22 | 23 | std::vector findRedundantNodes(CFG&); 24 | void flattenEquivalentMap(); 25 | void adjustCFG(CFG&, const util::VectorSet&); 26 | void adjustDefUseChain(const util::VectorSet&); 27 | void removeNodes(CFG&, const util::VectorSet&); 28 | public: 29 | CFGSimplifier() {} 30 | 31 | void simplify(CFG&); 32 | }; 33 | 34 | } -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/CFG/FunctionTranslator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace llvm 6 | { 7 | class BasicBlock; 8 | class Function; 9 | class Instruction; 10 | class Value; 11 | } 12 | 13 | namespace tpa 14 | { 15 | 16 | class CFG; 17 | class CFGNode; 18 | class InstructionTranslator; 19 | 20 | class FunctionTranslator 21 | { 22 | private: 23 | CFG& cfg; 24 | InstructionTranslator& translator; 25 | 26 | // Map llvm basic block to the start/end CFGNode that corresponds to the block 27 | llvm::DenseMap> bbToNode; 28 | llvm::DenseMap> nonEmptySuccMap; 29 | 30 | // Map CFGNode to correponding llvm instruction 31 | llvm::DenseMap nodeToInst; 32 | // Map llvm instruction to correponding CFGNode 33 | llvm::DenseMap instToNode; 34 | 35 | void drawDefUseEdgeFromValue(const llvm::Value*, CFGNode*); 36 | 37 | void translateBasicBlock(const llvm::Function&); 38 | void processEmptyBlock(); 39 | void connectCFGNodes(const llvm::BasicBlock&); 40 | void constructDefUseChains(); 41 | void computeNodePriority(); 42 | void detachStorePreservingNodes(); 43 | public: 44 | FunctionTranslator(CFG& c, InstructionTranslator& t): cfg(c), translator(t) {} 45 | 46 | void translateFunction(const llvm::Function&); 47 | }; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/CFG/PriorityAssigner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace tpa 6 | { 7 | 8 | class CFG; 9 | class CFGNode; 10 | 11 | class PriorityAssigner 12 | { 13 | private: 14 | CFG& cfg; 15 | size_t currLabel; 16 | 17 | using NodeSet = llvm::SmallPtrSet; 18 | NodeSet visitedNodes; 19 | 20 | void visitNode(CFGNode*); 21 | public: 22 | PriorityAssigner(CFG& c): cfg(c), currLabel(1) {} 23 | 24 | void traverse(); 25 | }; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/ConstPointerMap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace tpa 6 | { 7 | 8 | template 9 | class ConstPointerMap 10 | { 11 | private: 12 | using MapType = llvm::DenseMap; 13 | MapType ptrMap; 14 | public: 15 | using const_iterator = typename MapType::const_iterator; 16 | 17 | ConstPointerMap() = default; 18 | 19 | // The insert() function here performs strong update 20 | void insert(const KeyType* key, const ValueType* val) 21 | { 22 | assert(val != nullptr); 23 | ptrMap[key] = val; 24 | } 25 | 26 | // Return nullptr if key not found 27 | const ValueType* lookup(const KeyType* key) const 28 | { 29 | auto itr = ptrMap.find(key); 30 | if (itr == ptrMap.end()) 31 | return nullptr; 32 | else 33 | { 34 | assert(itr->second != nullptr); 35 | return itr->second; 36 | } 37 | } 38 | 39 | const_iterator begin() const { return ptrMap.begin(); } 40 | const_iterator end() const { return ptrMap.end(); } 41 | }; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/SemiSparseProgramBuilder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/FrontEnd/Type/TypeMap.h" 4 | #include "PointerAnalysis/Program/SemiSparseProgram.h" 5 | 6 | namespace llvm 7 | { 8 | class Function; 9 | class Module; 10 | } 11 | 12 | namespace tpa 13 | { 14 | 15 | class SemiSparseProgramBuilder 16 | { 17 | private: 18 | void buildCFGForFunction(tpa::SemiSparseProgram&, const llvm::Function&, const TypeMap&); 19 | public: 20 | tpa::SemiSparseProgram runOnModule(const llvm::Module& module); 21 | }; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/Type/ArrayLayoutAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/FrontEnd/Type/ArrayLayoutMap.h" 4 | 5 | namespace tpa 6 | { 7 | 8 | class TypeSet; 9 | 10 | class ArrayLayoutAnalysis 11 | { 12 | public: 13 | ArrayLayoutAnalysis() = default; 14 | 15 | ArrayLayoutMap runOnTypes(const TypeSet&); 16 | }; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/Type/ArrayLayoutMap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/FrontEnd/ConstPointerMap.h" 4 | 5 | namespace llvm 6 | { 7 | class Type; 8 | } 9 | 10 | namespace tpa 11 | { 12 | 13 | class ArrayLayout; 14 | 15 | using ArrayLayoutMap = ConstPointerMap; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/Type/CastMap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/DataStructure/VectorSet.h" 4 | 5 | #include 6 | 7 | namespace llvm 8 | { 9 | class Type; 10 | } 11 | 12 | namespace tpa 13 | { 14 | 15 | class CastMap 16 | { 17 | private: 18 | using SetType = util::VectorSet; 19 | using MapType = std::unordered_map; 20 | MapType castMap; 21 | public: 22 | using iterator = MapType::iterator; 23 | using const_iterator = MapType::const_iterator; 24 | 25 | void insert(llvm::Type* src, llvm::Type* dst) 26 | { 27 | castMap[src].insert(dst); 28 | } 29 | 30 | iterator find(llvm::Type* src) 31 | { 32 | return castMap.find(src); 33 | } 34 | 35 | SetType& getOrCreateRHS(llvm::Type* src) 36 | { 37 | return castMap[src]; 38 | } 39 | 40 | iterator begin() { return castMap.begin(); } 41 | iterator end() { return castMap.end(); } 42 | const_iterator begin() const { return castMap.begin(); } 43 | const_iterator end() const { return castMap.end(); } 44 | }; 45 | 46 | } -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/Type/PointerLayoutAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/FrontEnd/Type/PointerLayoutMap.h" 4 | 5 | namespace tpa 6 | { 7 | 8 | class CastMap; 9 | class TypeSet; 10 | 11 | class PointerLayoutAnalysis 12 | { 13 | private: 14 | const CastMap& castMap; 15 | public: 16 | PointerLayoutAnalysis(const CastMap& c): castMap(c) {} 17 | 18 | PointerLayoutMap runOnTypes(const TypeSet&); 19 | }; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/Type/PointerLayoutMap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/FrontEnd/ConstPointerMap.h" 4 | 5 | namespace llvm 6 | { 7 | class Type; 8 | } 9 | 10 | namespace tpa 11 | { 12 | 13 | class PointerLayout; 14 | 15 | using PointerLayoutMap = ConstPointerMap; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/Type/StructCastAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/FrontEnd/Type/CastMap.h" 4 | 5 | namespace llvm 6 | { 7 | class Module; 8 | } 9 | 10 | namespace tpa 11 | { 12 | 13 | class StructCastAnalysis 14 | { 15 | public: 16 | CastMap runOnModule(const llvm::Module&); 17 | }; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/Type/TypeAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/FrontEnd/Type/TypeMap.h" 4 | 5 | namespace llvm 6 | { 7 | class Module; 8 | } 9 | 10 | namespace tpa 11 | { 12 | 13 | class TypeAnalysis 14 | { 15 | public: 16 | TypeAnalysis() = default; 17 | 18 | TypeMap runOnModule(const llvm::Module&); 19 | }; 20 | 21 | } -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/Type/TypeCollector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/FrontEnd/Type/TypeSet.h" 4 | 5 | namespace llvm 6 | { 7 | class Module; 8 | } 9 | 10 | namespace tpa 11 | { 12 | 13 | class TypeCollector 14 | { 15 | public: 16 | TypeCollector() = default; 17 | 18 | TypeSet runOnModule(const llvm::Module&); 19 | }; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/Type/TypeMap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/FrontEnd/ConstPointerMap.h" 4 | 5 | namespace llvm 6 | { 7 | class Type; 8 | } 9 | 10 | namespace tpa 11 | { 12 | 13 | class TypeLayout; 14 | 15 | using TypeMap = ConstPointerMap; 16 | 17 | } -------------------------------------------------------------------------------- /include/PointerAnalysis/FrontEnd/Type/TypeSet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace llvm 7 | { 8 | class Module; 9 | class Type; 10 | } 11 | 12 | namespace tpa 13 | { 14 | 15 | class TypeSet 16 | { 17 | private: 18 | using SetType = llvm::DenseSet; 19 | SetType typeSet; 20 | 21 | llvm::DataLayout dataLayout; 22 | public: 23 | using const_iterator = SetType::const_iterator; 24 | 25 | TypeSet(const llvm::Module& module): dataLayout(&module) {} 26 | 27 | bool insert(llvm::Type* ty) 28 | { 29 | return typeSet.insert(ty).second; 30 | } 31 | 32 | bool count(llvm::Type* ty) const 33 | { 34 | return typeSet.count(ty); 35 | } 36 | 37 | const llvm::DataLayout& getDataLayout() const { return dataLayout; } 38 | 39 | const_iterator begin() const { return typeSet.begin(); } 40 | const_iterator end() const { return typeSet.end(); } 41 | }; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /include/PointerAnalysis/MemoryModel/MemoryBlock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/MemoryModel/AllocSite.h" 4 | 5 | namespace tpa 6 | { 7 | 8 | class TypeLayout; 9 | 10 | // MemoryBlock is a block of memory consists of potentially many memory objects. It is the unit of memory allocation 11 | class MemoryBlock 12 | { 13 | private: 14 | AllocSite allocSite; 15 | const TypeLayout* type; 16 | 17 | MemoryBlock(const AllocSite& a, const TypeLayout* ty): allocSite(a), type(ty){} 18 | public: 19 | const AllocSite& getAllocSite() const { return allocSite; } 20 | const TypeLayout* getTypeLayout() const { return type; } 21 | 22 | bool isNullBlock() const { return allocSite.getAllocType() == AllocSiteTag::Null; } 23 | bool isUniversalBlock() const { return allocSite.getAllocType() == AllocSiteTag::Universal; } 24 | bool isGlobalBlock() const { return allocSite.getAllocType() == AllocSiteTag::Global || allocSite.getAllocType() == AllocSiteTag::Null || allocSite.getAllocType() == AllocSiteTag::Universal; } 25 | bool isFunctionBlock() const { return allocSite.getAllocType() == AllocSiteTag::Function; } 26 | bool isStackBlock() const { return allocSite.getAllocType() == AllocSiteTag::Stack; } 27 | bool isHeapBlock() const { return allocSite.getAllocType() == AllocSiteTag::Heap; } 28 | 29 | friend class MemoryManager; 30 | }; 31 | 32 | } -------------------------------------------------------------------------------- /include/PointerAnalysis/MemoryModel/Pointer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/Hashing.h" 4 | 5 | #include 6 | 7 | namespace context 8 | { 9 | class Context; 10 | } 11 | 12 | namespace llvm 13 | { 14 | class Value; 15 | } 16 | 17 | namespace tpa 18 | { 19 | 20 | // The Pointer class models SSA pointers 21 | class Pointer 22 | { 23 | private: 24 | const context::Context* ctx; 25 | const llvm::Value* value; 26 | 27 | using PairType = std::pair; 28 | 29 | Pointer(const context::Context* c, const llvm::Value* v): ctx(c), value(v) 30 | { 31 | assert(c != nullptr && v != nullptr); 32 | } 33 | public: 34 | const context::Context* getContext() const { return ctx; } 35 | const llvm::Value* getValue() const { return value; } 36 | 37 | bool operator==(const Pointer& rhs) const 38 | { 39 | return ctx == rhs.ctx && value == rhs.value; 40 | } 41 | bool operator!=(const Pointer& rhs) const 42 | { 43 | return !(*this == rhs); 44 | } 45 | 46 | operator PairType() const 47 | { 48 | return std::make_pair(ctx, value); 49 | } 50 | 51 | friend class PointerManager; 52 | }; 53 | 54 | } 55 | 56 | namespace std 57 | { 58 | 59 | template<> struct hash 60 | { 61 | size_t operator()(const tpa::Pointer& ptr) const 62 | { 63 | return util::hashPair(ptr.getContext(), ptr.getValue()); 64 | } 65 | }; 66 | 67 | } 68 | -------------------------------------------------------------------------------- /include/PointerAnalysis/Precision/PrecisionLossTracker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Support/ProgramPointSet.h" 4 | 5 | #include 6 | 7 | namespace tpa 8 | { 9 | 10 | class GlobalState; 11 | class Pointer; 12 | 13 | class PrecisionLossTracker 14 | { 15 | private: 16 | using PointerList = std::vector; 17 | using ProgramPointList = std::vector; 18 | 19 | const GlobalState& globalState; 20 | 21 | ProgramPointList getProgramPointsFromPointers(const PointerList&); 22 | public: 23 | PrecisionLossTracker(const GlobalState& g): globalState(g) {} 24 | 25 | ProgramPointSet trackImprecision(const PointerList&); 26 | }; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /include/PointerAnalysis/Precision/ValueDependenceTracker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Support/CallGraph.h" 4 | #include "PointerAnalysis/Support/FunctionContext.h" 5 | #include "PointerAnalysis/Support/ProgramPointSet.h" 6 | 7 | #include 8 | 9 | namespace tpa 10 | { 11 | 12 | class SemiSparseProgram; 13 | 14 | class ValueDependenceTracker 15 | { 16 | private: 17 | using CallGraphType = CallGraph; 18 | const CallGraphType& callGraph; 19 | 20 | const SemiSparseProgram& ssProg; 21 | public: 22 | ValueDependenceTracker(const CallGraphType& c, const SemiSparseProgram& s): callGraph(c), ssProg(s) {} 23 | 24 | ProgramPointSet getValueDependencies(const ProgramPoint&) const; 25 | }; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /include/PointerAnalysis/Program/SemiSparseProgram.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/FrontEnd/Type/TypeMap.h" 4 | #include "PointerAnalysis/Program/CFG/CFG.h" 5 | #include "Util/Iterator/IteratorRange.h" 6 | #include "Util/Iterator/MapValueIterator.h" 7 | 8 | #include 9 | #include 10 | 11 | namespace tpa 12 | { 13 | 14 | class SemiSparseProgram 15 | { 16 | private: 17 | const llvm::Module& module; 18 | TypeMap typeMap; 19 | 20 | using MapType = std::unordered_map; 21 | MapType cfgMap; 22 | 23 | using FunctionList = std::vector; 24 | FunctionList addrTakenFuncList; 25 | public: 26 | using const_iterator = util::MapValueConstIterator; 27 | using addr_taken_const_iterator = FunctionList::const_iterator; 28 | 29 | SemiSparseProgram(const llvm::Module& m); 30 | const llvm::Module& getModule() const { return module; } 31 | 32 | const TypeMap& getTypeMap() const { return typeMap; } 33 | void setTypeMap(TypeMap&& t) { typeMap = std::move(t); } 34 | 35 | CFG& getOrCreateCFGForFunction(const llvm::Function& f); 36 | const CFG* getCFGForFunction(const llvm::Function& f) const; 37 | const CFG* getEntryCFG() const; 38 | 39 | const_iterator begin() const { return const_iterator(cfgMap.begin()); } 40 | const_iterator end() const { return const_iterator(cfgMap.end()); } 41 | 42 | addr_taken_const_iterator addr_taken_func_begin() const { return addrTakenFuncList.begin(); } 43 | addr_taken_const_iterator addr_taken_func_end() const { return addrTakenFuncList.end(); } 44 | auto addr_taken_funcs() const 45 | { 46 | return util::iteratorRange(addrTakenFuncList.begin(), addrTakenFuncList.end()); 47 | } 48 | }; 49 | 50 | } -------------------------------------------------------------------------------- /include/PointerAnalysis/Support/Env.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Support/PtsMap.h" 4 | 5 | namespace tpa 6 | { 7 | 8 | class Pointer; 9 | using Env = PtsMap; 10 | 11 | } -------------------------------------------------------------------------------- /include/PointerAnalysis/Support/FunctionContext.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/Hashing.h" 4 | 5 | #include 6 | 7 | namespace context 8 | { 9 | class Context; 10 | } 11 | 12 | namespace llvm 13 | { 14 | class Function; 15 | } 16 | 17 | namespace tpa 18 | { 19 | 20 | class FunctionContext 21 | { 22 | private: 23 | const context::Context* ctx; 24 | const llvm::Function* func; 25 | public: 26 | FunctionContext(const context::Context* c, const llvm::Function* f): ctx(c), func(f) 27 | { 28 | assert(ctx != nullptr && func != nullptr); 29 | } 30 | 31 | const context::Context* getContext() const { return ctx; } 32 | const llvm::Function* getFunction() const { return func; } 33 | 34 | bool operator==(const FunctionContext& rhs) const 35 | { 36 | return ctx == rhs.ctx && func == rhs.func; 37 | } 38 | bool operator!=(const FunctionContext& rhs) const 39 | { 40 | return !(*this == rhs); 41 | } 42 | bool operator<(const FunctionContext& rhs) const 43 | { 44 | if (ctx < rhs.ctx) 45 | return true; 46 | else if (rhs.ctx < ctx) 47 | return false; 48 | else 49 | return func < rhs.func; 50 | } 51 | bool operator>(const FunctionContext& rhs) const 52 | { 53 | return rhs < *this; 54 | } 55 | bool operator<=(const FunctionContext& rhs) const 56 | { 57 | return !(rhs < *this); 58 | } 59 | bool operator>=(const FunctionContext& rhs) const 60 | { 61 | return !(*this < rhs); 62 | } 63 | }; 64 | 65 | } 66 | 67 | namespace std 68 | { 69 | template<> struct hash 70 | { 71 | size_t operator()(const tpa::FunctionContext& f) const 72 | { 73 | return util::hashPair(f.getContext(), f.getFunction()); 74 | } 75 | }; 76 | } 77 | -------------------------------------------------------------------------------- /include/PointerAnalysis/Support/ProgramPoint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/Hashing.h" 4 | 5 | #include 6 | 7 | namespace context 8 | { 9 | class Context; 10 | } 11 | 12 | namespace tpa 13 | { 14 | 15 | class CFGNode; 16 | 17 | class ProgramPoint 18 | { 19 | private: 20 | const context::Context* ctx; 21 | const CFGNode* node; 22 | public: 23 | ProgramPoint(const context::Context* c, const CFGNode* n): ctx(c), node(n) 24 | { 25 | assert(ctx != nullptr && node != nullptr); 26 | } 27 | 28 | const context::Context* getContext() const { return ctx; } 29 | const CFGNode* getCFGNode() const { return node; } 30 | 31 | bool operator==(const ProgramPoint& rhs) const 32 | { 33 | return ctx == rhs.ctx && node == rhs.node; 34 | } 35 | bool operator!=(const ProgramPoint& rhs) const 36 | { 37 | return !(*this == rhs); 38 | } 39 | bool operator<(const ProgramPoint& rhs) const 40 | { 41 | if (ctx < rhs.ctx) 42 | return true; 43 | else if (rhs.ctx < ctx) 44 | return false; 45 | else 46 | return node < rhs.node; 47 | } 48 | bool operator>(const ProgramPoint& rhs) const 49 | { 50 | return rhs < *this; 51 | } 52 | bool operator<=(const ProgramPoint& rhs) const 53 | { 54 | return !(rhs < *this); 55 | } 56 | bool operator>=(const ProgramPoint& rhs) const 57 | { 58 | return !(*this < rhs); 59 | } 60 | }; 61 | 62 | } 63 | 64 | namespace std 65 | { 66 | template<> struct hash 67 | { 68 | size_t operator()(const tpa::ProgramPoint& p) const 69 | { 70 | return util::hashPair(p.getContext(), p.getCFGNode()); 71 | } 72 | }; 73 | } 74 | -------------------------------------------------------------------------------- /include/PointerAnalysis/Support/ProgramPointSet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Support/ProgramPoint.h" 4 | 5 | #include 6 | 7 | namespace tpa 8 | { 9 | 10 | class ProgramPointSet 11 | { 12 | private: 13 | using SetType = std::unordered_set; 14 | SetType ppSet; 15 | public: 16 | using const_iterator = SetType::const_iterator; 17 | 18 | ProgramPointSet() = default; 19 | 20 | ProgramPointSet(const ProgramPointSet&) = delete; 21 | ProgramPointSet(ProgramPointSet&&) noexcept = default; 22 | ProgramPointSet& operator=(const ProgramPointSet&) = delete; 23 | ProgramPointSet& operator=(ProgramPointSet&&) = delete; 24 | 25 | bool insert(const ProgramPoint& pp) 26 | { 27 | return ppSet.insert(pp).second; 28 | } 29 | 30 | void swap(ProgramPointSet& rhs) 31 | { 32 | ppSet.swap(rhs.ppSet); 33 | } 34 | 35 | const_iterator begin() const { return ppSet.begin(); } 36 | const_iterator end() const { return ppSet.end(); } 37 | size_t size() const { return ppSet.size(); } 38 | bool empty() const { return ppSet.empty(); } 39 | }; 40 | 41 | 42 | } -------------------------------------------------------------------------------- /include/PointerAnalysis/Support/Store.h: -------------------------------------------------------------------------------- 1 | #include "PointerAnalysis/Support/PtsMap.h" 2 | 3 | namespace tpa 4 | { 5 | 6 | using Store = PtsMap; 7 | 8 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/Analysis/TaintAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Annotation/Taint/ExternalTaintTable.h" 4 | #include "TaintAnalysis/Support/TaintEnv.h" 5 | #include "TaintAnalysis/Support/TaintMemo.h" 6 | 7 | namespace tpa 8 | { 9 | class SemiSparsePointerAnalysis; 10 | } 11 | 12 | namespace taint 13 | { 14 | 15 | class DefUseModule; 16 | 17 | class TaintAnalysis 18 | { 19 | private: 20 | TaintEnv env; 21 | TaintMemo memo; 22 | 23 | annotation::ExternalTaintTable extTable; 24 | const tpa::SemiSparsePointerAnalysis& ptrAnalysis; 25 | public: 26 | TaintAnalysis(const tpa::SemiSparsePointerAnalysis& p): ptrAnalysis(p) {} 27 | 28 | void loadExternalTaintTable(const char* extFileName) 29 | { 30 | extTable = annotation::ExternalTaintTable::loadFromFile(extFileName); 31 | } 32 | 33 | bool runOnDefUseModule(const DefUseModule&); 34 | }; 35 | 36 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/Analysis/TrackingTaintAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Annotation/Taint/ExternalTaintTable.h" 4 | #include "TaintAnalysis/Support/ProgramPointSet.h" 5 | #include "TaintAnalysis/Support/TaintEnv.h" 6 | #include "TaintAnalysis/Support/TaintMemo.h" 7 | 8 | namespace tpa 9 | { 10 | class SemiSparsePointerAnalysis; 11 | } 12 | 13 | namespace taint 14 | { 15 | 16 | class DefUseModule; 17 | 18 | class TrackingTaintAnalysis 19 | { 20 | private: 21 | TaintEnv env; 22 | TaintMemo memo; 23 | 24 | annotation::ExternalTaintTable extTable; 25 | const tpa::SemiSparsePointerAnalysis& ptrAnalysis; 26 | public: 27 | TrackingTaintAnalysis(const tpa::SemiSparsePointerAnalysis& p): ptrAnalysis(p) {} 28 | 29 | void loadExternalTaintTable(const char* extFileName) 30 | { 31 | extTable = annotation::ExternalTaintTable::loadFromFile(extFileName); 32 | } 33 | 34 | std::pair runOnDefUseModule(const DefUseModule&); 35 | }; 36 | 37 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/Engine/EvalResult.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Engine/EvalSuccessor.h" 4 | #include "TaintAnalysis/Support/TaintStore.h" 5 | 6 | #include 7 | 8 | namespace taint 9 | { 10 | 11 | class EvalResult 12 | { 13 | private: 14 | TaintStore store; 15 | 16 | using SuccessorList = std::vector; 17 | SuccessorList succs; 18 | public: 19 | using const_iterator = typename SuccessorList::const_iterator; 20 | 21 | EvalResult() = default; 22 | 23 | EvalResult(const EvalResult&) = delete; 24 | EvalResult(EvalResult&&) noexcept = default; 25 | EvalResult& operator=(const EvalResult&) = delete; 26 | EvalResult& operator=(EvalResult&&) = delete; 27 | 28 | TaintStore& getStore() { return store; } 29 | const TaintStore& getStore() const { return store; } 30 | void setStore(const TaintStore& s) { store = s; } 31 | void setStore(TaintStore&& s) { store = std::move(s); } 32 | 33 | void addTopLevelSuccessor(const ProgramPoint& pp) 34 | { 35 | succs.push_back(EvalSuccessor(pp, nullptr)); 36 | } 37 | 38 | void addMemLevelSuccessor(const ProgramPoint& pp, const tpa::MemoryObject* obj) 39 | { 40 | succs.push_back(EvalSuccessor(pp, obj)); 41 | } 42 | 43 | const_iterator begin() const { return succs.begin(); } 44 | const_iterator end() const { return succs.end(); } 45 | bool empty() const { return succs.empty(); } 46 | size_t size() const { return succs.size(); } 47 | }; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Engine/EvalSuccessor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Support/ProgramPoint.h" 4 | 5 | namespace tpa 6 | { 7 | class MemoryObject; 8 | } 9 | 10 | namespace taint 11 | { 12 | 13 | class EvalSuccessor 14 | { 15 | private: 16 | ProgramPoint pp; 17 | const tpa::MemoryObject* obj; 18 | 19 | EvalSuccessor(const ProgramPoint& p, const tpa::MemoryObject* o): pp(p), obj(o) {} 20 | public: 21 | bool isTopLevel() const { return obj == nullptr; } 22 | const ProgramPoint& getProgramPoint() const { return pp; } 23 | 24 | const tpa::MemoryObject* getMemoryObject() const 25 | { 26 | assert(obj != nullptr); 27 | return obj; 28 | } 29 | 30 | friend class EvalResult; 31 | }; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Engine/Initializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Engine/WorkList.h" 4 | #include "TaintAnalysis/Support/TaintStore.h" 5 | 6 | namespace tpa 7 | { 8 | class SemiSparsePointerAnalysis; 9 | } 10 | 11 | namespace taint 12 | { 13 | 14 | class DefUseModule; 15 | class TaintEnv; 16 | class TaintGlobalState; 17 | class TaintMemo; 18 | 19 | class Initializer 20 | { 21 | private: 22 | const DefUseModule& duModule; 23 | TaintEnv& env; 24 | const tpa::SemiSparsePointerAnalysis& ptrAnalysis; 25 | TaintMemo& memo; 26 | 27 | void initializeMainArgs(TaintStore&); 28 | void initializeGlobalVariables(TaintStore&); 29 | public: 30 | Initializer(TaintGlobalState& g, TaintMemo& m); 31 | 32 | WorkList runOnInitState(TaintStore&& initStore); 33 | }; 34 | 35 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/Engine/SinkViolationChecker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Annotation/Taint/TaintDescriptor.h" 4 | #include "TaintAnalysis/Support/SinkViolationRecord.h" 5 | #include "TaintAnalysis/Support/TaintStore.h" 6 | 7 | namespace annotation 8 | { 9 | class ExternalTaintTable; 10 | class SinkTaintEntry; 11 | class TaintSummary; 12 | } 13 | 14 | namespace tpa 15 | { 16 | class SemiSparsePointerAnalysis; 17 | } 18 | 19 | namespace taint 20 | { 21 | 22 | class SinkSignature; 23 | class TaintEnv; 24 | class TaintMemo; 25 | class TaintValue; 26 | 27 | class SinkViolationChecker 28 | { 29 | private: 30 | const TaintEnv& env; 31 | const TaintMemo& memo; 32 | const annotation::ExternalTaintTable& table; 33 | const tpa::SemiSparsePointerAnalysis& ptrAnalysis; 34 | 35 | TaintLattice lookupTaint(const TaintValue&, annotation::TClass, const TaintStore*); 36 | void checkValueWithTClass(const TaintValue&, annotation::TClass, uint8_t, const TaintStore*, SinkViolationList&); 37 | void checkCallSiteWithEntry(const ProgramPoint&, const annotation::SinkTaintEntry&, SinkViolationList&); 38 | SinkViolationList checkCallSiteWithSummary(const ProgramPoint&, const annotation::TaintSummary&); 39 | 40 | void checkSinkViolation(const SinkSignature&, SinkViolationRecord&); 41 | public: 42 | SinkViolationChecker(const TaintEnv& e, const TaintMemo& m, const annotation::ExternalTaintTable& t, const tpa::SemiSparsePointerAnalysis& p): env(e), memo(m), table(t), ptrAnalysis(p) {} 43 | 44 | // Return all prog location whose sink policy is violated 45 | template 46 | SinkViolationRecord checkSinkViolation(const SigContainer& sinks) 47 | { 48 | SinkViolationRecord ret; 49 | for (auto const& sig: sinks) 50 | checkSinkViolation(sig, ret); 51 | return ret; 52 | } 53 | }; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Engine/TaintPropagator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Support/TaintStore.h" 4 | 5 | namespace taint 6 | { 7 | 8 | class EvalResult; 9 | class ProgramPoint; 10 | class TaintMemo; 11 | class WorkList; 12 | 13 | class TaintPropagator 14 | { 15 | private: 16 | TaintMemo& memo; 17 | WorkList& workList; 18 | 19 | void enqueueIfMemoChange(const ProgramPoint&, const tpa::MemoryObject*, const TaintStore&); 20 | public: 21 | TaintPropagator(TaintMemo& m, WorkList& w): memo(m), workList(w) {} 22 | 23 | void propagate(const EvalResult&); 24 | }; 25 | 26 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/Engine/WorkList.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Support/FunctionContext.h" 4 | #include "TaintAnalysis/Program/DefUseInstruction.h" 5 | #include "TaintAnalysis/Support/ProgramPoint.h" 6 | #include "Util/DataStructure/FIFOWorkList.h" 7 | #include "Util/DataStructure/PriorityWorkList.h" 8 | #include "Util/DataStructure/TwoLevelWorkList.h" 9 | 10 | namespace taint 11 | { 12 | 13 | class WorkList 14 | { 15 | private: 16 | struct NodeComparator 17 | { 18 | bool operator()(const DefUseInstruction* lhs, const DefUseInstruction* rhs) const 19 | { 20 | return lhs->getPriority() < rhs->getPriority(); 21 | } 22 | }; 23 | 24 | using GlobalWorkListType = util::FIFOWorkList; 25 | using LocalWorkListType = util::PriorityWorkList; 26 | using WorkListType = util::TwoLevelWorkList; 27 | WorkListType workList; 28 | public: 29 | using ElemType = ProgramPoint; 30 | 31 | WorkList() = default; 32 | 33 | void enqueue(const ProgramPoint& p) 34 | { 35 | workList.enqueue(std::make_pair(tpa::FunctionContext(p.getContext(), p.getDefUseInstruction()->getFunction()), p.getDefUseInstruction())); 36 | } 37 | 38 | ProgramPoint dequeue() 39 | { 40 | auto pair = workList.dequeue(); 41 | return ProgramPoint(pair.first.getContext(), pair.second); 42 | } 43 | 44 | ProgramPoint front() 45 | { 46 | auto pair = workList.front(); 47 | return ProgramPoint(pair.first.getContext(), pair.second); 48 | } 49 | 50 | bool empty() const { return workList.empty(); } 51 | }; 52 | 53 | 54 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/FrontEnd/DefUseModuleBuilder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Annotation/ModRef/ExternalModRefTable.h" 4 | #include "TaintAnalysis/Program/DefUseModule.h" 5 | 6 | namespace llvm 7 | { 8 | class Module; 9 | class Value; 10 | } 11 | 12 | namespace tpa 13 | { 14 | class SemiSparsePointerAnalysis; 15 | } 16 | 17 | namespace taint 18 | { 19 | 20 | class ModRefModuleSummary; 21 | 22 | class DefUseModuleBuilder 23 | { 24 | private: 25 | const tpa::SemiSparsePointerAnalysis& ptrAnalysis; 26 | annotation::ExternalModRefTable modRefTable; 27 | 28 | void buildDefUseFunction(DefUseFunction& f, const ModRefModuleSummary&); 29 | void buildMemLevelEdges(DefUseFunction& f, const ModRefModuleSummary&); 30 | public: 31 | DefUseModuleBuilder(const tpa::SemiSparsePointerAnalysis& p): ptrAnalysis(p) {} 32 | 33 | DefUseModule buildDefUseModule(const llvm::Module& module); 34 | 35 | void loadExternalModRefTable(const char* fileName) 36 | { 37 | modRefTable = annotation::ExternalModRefTable::loadFromFile(fileName); 38 | } 39 | }; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /include/TaintAnalysis/FrontEnd/ModRefModuleAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/FrontEnd/ModRefModuleSummary.h" 4 | 5 | namespace llvm 6 | { 7 | class Function; 8 | class Module; 9 | } 10 | 11 | namespace annotation 12 | { 13 | class ExternalModRefTable; 14 | } 15 | 16 | namespace tpa 17 | { 18 | class SemiSparsePointerAnalysis; 19 | } 20 | 21 | namespace taint 22 | { 23 | 24 | class ModRefModuleAnalysis 25 | { 26 | private: 27 | const tpa::SemiSparsePointerAnalysis& ptrAnalysis; 28 | const annotation::ExternalModRefTable& modRefTable; 29 | 30 | void collectProcedureSummary(const llvm::Function&, ModRefFunctionSummary&); 31 | public: 32 | ModRefModuleAnalysis(const tpa::SemiSparsePointerAnalysis& p, const annotation::ExternalModRefTable& t): ptrAnalysis(p), modRefTable(t) {} 33 | 34 | ModRefModuleSummary runOnModule(const llvm::Module& module); 35 | }; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /include/TaintAnalysis/FrontEnd/ModRefModuleSummary.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/FrontEnd/ModRefFunctionSummary.h" 4 | 5 | namespace llvm 6 | { 7 | class Function; 8 | class Module; 9 | } 10 | 11 | namespace taint 12 | { 13 | 14 | class ModRefModuleSummary 15 | { 16 | private: 17 | using MapType = std::unordered_map; 18 | MapType summaryMap; 19 | public: 20 | using const_iterator = MapType::const_iterator; 21 | 22 | ModRefFunctionSummary& getSummary(const llvm::Function* f) 23 | { 24 | return summaryMap[f]; 25 | } 26 | const ModRefFunctionSummary& getSummary(const llvm::Function* f) const 27 | { 28 | auto itr = summaryMap.find(f); 29 | assert(itr != summaryMap.end()); 30 | return itr->second; 31 | } 32 | 33 | const_iterator begin() const { return summaryMap.begin(); } 34 | const_iterator end() const { return summaryMap.end(); } 35 | }; 36 | 37 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/FrontEnd/ReachingDefModuleAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/FrontEnd/ReachingDefMap.h" 4 | 5 | namespace llvm 6 | { 7 | class Instruction; 8 | class Function; 9 | } 10 | 11 | namespace annotation 12 | { 13 | class ExternalModRefTable; 14 | } 15 | 16 | namespace tpa 17 | { 18 | class MemoryLocation; 19 | class SemiSparsePointerAnalysis; 20 | } 21 | 22 | namespace taint 23 | { 24 | 25 | class ModRefModuleSummary; 26 | 27 | using ReachingDefModuleMap = ReachingDefMap; 28 | 29 | class ReachingDefModuleAnalysis 30 | { 31 | private: 32 | const tpa::SemiSparsePointerAnalysis& ptrAnalysis; 33 | const ModRefModuleSummary& summaryMap; 34 | const annotation::ExternalModRefTable& modRefTable; 35 | public: 36 | ReachingDefModuleAnalysis(const tpa::SemiSparsePointerAnalysis& p, const ModRefModuleSummary& s, const annotation::ExternalModRefTable& t): ptrAnalysis(p), summaryMap(s), modRefTable(t) {} 37 | 38 | ReachingDefModuleMap runOnFunction(const llvm::Function& func); 39 | }; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Lattice/Lattice.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace taint 6 | { 7 | 8 | enum LatticeCompareResult: std::uint8_t 9 | { 10 | Equal, 11 | LessThan, 12 | GreaterThan, 13 | Incomparable, 14 | }; 15 | 16 | // Lattice is a generic trait template that should be specialize by classed that wants to be properly handled by the dataflow engine 17 | 18 | // The default specialization produces an error 19 | template 20 | struct Lattice 21 | { 22 | // Members to include: 23 | // static LatticeCompareResult compare(const LatticeType& lhs, const LatticeType& rhs); 24 | // static LatticeType merge(const LatticeType& lhs, const LatticeType& rhs); 25 | 26 | 27 | // If anyone tries to use this class without having an appropriate specialization, make an error. If you get this error, it's because you need to include the appropriate specialization of Lattice<> for your lattice, or you need to define it for a new lattice type. 28 | using UnknownLatticeType = typename LatticeType::UnknownLatticeTypeError; 29 | }; 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Lattice/TaintLattice.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Lattice/Lattice.h" 4 | 5 | namespace taint 6 | { 7 | 8 | enum class TaintLattice: uint8_t 9 | { 10 | Unknown, 11 | Untainted, 12 | Tainted, 13 | Either 14 | }; 15 | 16 | template<> struct Lattice 17 | { 18 | static LatticeCompareResult compare(TaintLattice lhs, TaintLattice rhs) 19 | { 20 | if (lhs == rhs) 21 | return LatticeCompareResult::Equal; 22 | else if (rhs == TaintLattice::Either || lhs == TaintLattice::Unknown) 23 | return LatticeCompareResult::LessThan; 24 | else if (lhs == TaintLattice::Either || rhs == TaintLattice::Unknown) 25 | return LatticeCompareResult::GreaterThan; 26 | else 27 | return LatticeCompareResult::Incomparable; 28 | } 29 | 30 | static TaintLattice merge(TaintLattice lhs, TaintLattice rhs) 31 | { 32 | auto cmpResult = compare(lhs, rhs); 33 | switch (cmpResult) 34 | { 35 | case LatticeCompareResult::Equal: 36 | case LatticeCompareResult::GreaterThan: 37 | return lhs; 38 | case LatticeCompareResult::LessThan: 39 | return rhs; 40 | case LatticeCompareResult::Incomparable: 41 | return TaintLattice::Either; 42 | } 43 | } 44 | 45 | static bool willMergeSmearTaintness(TaintLattice lhs, TaintLattice rhs) 46 | { 47 | if (lhs == TaintLattice::Either && rhs == TaintLattice::Either) 48 | return false; 49 | else if (lhs == TaintLattice::Unknown || rhs == TaintLattice::Unknown) 50 | return false; 51 | else 52 | return lhs != rhs; 53 | } 54 | }; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Precision/CallTracker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Precision/IndexVector.h" 4 | #include "TaintAnalysis/Support/ProgramPoint.h" 5 | 6 | #include 7 | 8 | namespace tpa 9 | { 10 | class MemoryObject; 11 | } 12 | 13 | namespace taint 14 | { 15 | 16 | class TrackerGlobalState; 17 | class TrackerWorkList; 18 | 19 | class CallTracker 20 | { 21 | private: 22 | TrackerGlobalState& trackerState; 23 | TrackerWorkList& workList; 24 | 25 | using CallerVector = std::vector; 26 | 27 | TaintVector getArgTaintValues(const CallerVector&, size_t); 28 | TaintVector getMemoryTaintValues(const CallerVector&, const tpa::MemoryObject*); 29 | 30 | void trackValue(const ProgramPoint&, const CallerVector&); 31 | void trackMemory(const ProgramPoint&, const CallerVector&); 32 | public: 33 | CallTracker(TrackerGlobalState& g, TrackerWorkList& w): trackerState(g), workList(w) {} 34 | 35 | void trackCall(const ProgramPoint&, const CallerVector&); 36 | }; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Precision/IndexVector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Lattice/TaintLattice.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace taint 10 | { 11 | 12 | using IndexVector = std::vector; 13 | using TaintVector = std::vector; 14 | 15 | inline IndexVector getDemandingIndices(const TaintVector& taints) 16 | { 17 | assert(!taints.empty()); 18 | IndexVector ret; 19 | 20 | auto mergeVal = TaintLattice::Unknown; 21 | for (auto t: taints) 22 | mergeVal = Lattice::merge(mergeVal, t); 23 | 24 | if (mergeVal == TaintLattice::Either) 25 | { 26 | for (std::size_t i = 0, e = taints.size(); i < e; ++i) 27 | if (taints[i] == TaintLattice::Tainted) 28 | ret.push_back(i); 29 | } 30 | 31 | return ret; 32 | } 33 | 34 | inline IndexVector getImpreciseIndices(const TaintVector& taints) 35 | { 36 | assert(!taints.empty()); 37 | IndexVector ret; 38 | 39 | for (std::size_t i = 0, e = taints.size(); i < e; ++i) 40 | if (taints[i] == TaintLattice::Either) 41 | ret.push_back(i); 42 | 43 | return ret; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/Precision/LocalTracker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Precision/TrackerWorkList.h" 4 | #include "TaintAnalysis/Program/DefUseInstruction.h" 5 | #include "TaintAnalysis/Support/ProgramPoint.h" 6 | 7 | namespace taint 8 | { 9 | 10 | class LocalTracker 11 | { 12 | private: 13 | TrackerWorkList& workList; 14 | public: 15 | LocalTracker(TrackerWorkList& w): workList(w) {} 16 | 17 | template 18 | void trackValue(const ProgramPoint& pp, const ValueSet& vSet) 19 | { 20 | auto ctx = pp.getContext(); 21 | auto duInst = pp.getDefUseInstruction(); 22 | assert(!duInst->isEntryInstruction()); 23 | 24 | // Enqueue all affected operands 25 | for (auto predDuInst: duInst->top_preds()) 26 | { 27 | if (predDuInst->isEntryInstruction() || vSet.count(predDuInst->getInstruction())) 28 | workList.enqueue(ProgramPoint(ctx, predDuInst)); 29 | } 30 | } 31 | 32 | template 33 | void trackMemory(const ProgramPoint& pp, const MemSet& mSet) 34 | { 35 | auto ctx = pp.getContext(); 36 | auto duInst = pp.getDefUseInstruction(); 37 | assert(!duInst->isEntryInstruction()); 38 | 39 | // Enqueue all affected operands 40 | for (auto const& mapping: duInst->mem_preds()) 41 | { 42 | if (!mSet.count(mapping.first)) 43 | continue; 44 | 45 | for (auto predDuInst: mapping.second) 46 | workList.enqueue(ProgramPoint(ctx, predDuInst)); 47 | } 48 | } 49 | }; 50 | 51 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/Precision/PrecisionLossTracker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Support/ProgramPointSet.h" 4 | #include "TaintAnalysis/Support/SinkViolationRecord.h" 5 | 6 | #include 7 | 8 | namespace taint 9 | { 10 | 11 | class TaintGlobalState; 12 | class TrackerWorkList; 13 | 14 | class PrecisionLossTracker 15 | { 16 | private: 17 | const TaintGlobalState& globalState; 18 | 19 | void initializeWorkList(TrackerWorkList&, const SinkViolationRecord&); 20 | public: 21 | PrecisionLossTracker(const TaintGlobalState& g): globalState(g) {} 22 | 23 | ProgramPointSet trackImprecision(const SinkViolationRecord&); 24 | }; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Precision/ReturnTracker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Support/FunctionContext.h" 4 | #include "TaintAnalysis/Precision/IndexVector.h" 5 | #include "TaintAnalysis/Support/ProgramPoint.h" 6 | 7 | namespace tpa 8 | { 9 | class MemoryObject; 10 | } 11 | 12 | namespace taint 13 | { 14 | 15 | class ProgramPoint; 16 | class TrackerGlobalState; 17 | class TrackerWorkList; 18 | 19 | class ReturnTracker 20 | { 21 | private: 22 | TrackerGlobalState& trackerState; 23 | TrackerWorkList& workList; 24 | 25 | using CalleeVector = std::vector; 26 | using ReturnVector = std::vector; 27 | 28 | ReturnVector getReturnVector(const CalleeVector&); 29 | TaintVector getReturnTaintValues(const ReturnVector&); 30 | TaintVector getReturnTaintValues(const tpa::MemoryObject*, const ReturnVector&); 31 | void processReturns(const ProgramPoint&, const ReturnVector&, const TaintVector&); 32 | void propagateReturns(const ReturnVector&, const TaintVector&); 33 | 34 | void trackValue(const ProgramPoint&, const ReturnVector&); 35 | void trackMemory(const ProgramPoint&, const ReturnVector&); 36 | public: 37 | ReturnTracker(TrackerGlobalState& g, TrackerWorkList& w): trackerState(g), workList(w) {} 38 | 39 | void trackReturn(const ProgramPoint&, const CalleeVector&); 40 | }; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Precision/TrackerTransferFunction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Support/PtsSet.h" 4 | #include "TaintAnalysis/Support/TaintStore.h" 5 | 6 | #include 7 | 8 | namespace llvm 9 | { 10 | class Value; 11 | } 12 | 13 | namespace taint 14 | { 15 | 16 | class ProgramPoint; 17 | class TrackerGlobalState; 18 | class TrackerWorkList; 19 | 20 | class TrackerTransferFunction 21 | { 22 | private: 23 | TrackerGlobalState& trackerState; 24 | TrackerWorkList& workList; 25 | 26 | using ValueSet = std::unordered_set; 27 | using MemorySet = std::unordered_set; 28 | 29 | void evalExternalCallInst(const ProgramPoint&, const llvm::Function*); 30 | 31 | ValueSet evalAllOperands(const ProgramPoint&); 32 | MemorySet evalPtsSet(const ProgramPoint&, tpa::PtsSet, const TaintStore&); 33 | ValueSet evalStore(const ProgramPoint&); 34 | MemorySet evalLoad(const ProgramPoint&, const TaintStore&); 35 | void evalCallInst(const ProgramPoint&); 36 | 37 | void evalEntryInst(const ProgramPoint&); 38 | void evalInst(const ProgramPoint&, const TaintStore*); 39 | public: 40 | TrackerTransferFunction(TrackerGlobalState& g, TrackerWorkList& w): trackerState(g), workList(w) {} 41 | 42 | void eval(const ProgramPoint&); 43 | }; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Precision/TrackerWorkList.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Support/FunctionContext.h" 4 | #include "TaintAnalysis/Program/DefUseInstruction.h" 5 | #include "TaintAnalysis/Support/ProgramPoint.h" 6 | #include "Util/DataStructure/FIFOWorkList.h" 7 | #include "Util/DataStructure/PriorityWorkList.h" 8 | #include "Util/DataStructure/TwoLevelWorkList.h" 9 | 10 | namespace taint 11 | { 12 | 13 | class TrackerWorkList 14 | { 15 | private: 16 | struct NodeComparator 17 | { 18 | bool operator()(const DefUseInstruction* lhs, const DefUseInstruction* rhs) const 19 | { 20 | return lhs->getPriority() > rhs->getPriority(); 21 | } 22 | }; 23 | 24 | using GlobalWorkListType = util::FIFOWorkList; 25 | using LocalWorkListType = util::PriorityWorkList; 26 | using WorkListType = util::TwoLevelWorkList; 27 | WorkListType workList; 28 | public: 29 | using ElemType = ProgramPoint; 30 | 31 | TrackerWorkList() = default; 32 | 33 | void enqueue(const ProgramPoint& p) 34 | { 35 | workList.enqueue(std::make_pair(tpa::FunctionContext(p.getContext(), p.getDefUseInstruction()->getFunction()), p.getDefUseInstruction())); 36 | } 37 | 38 | ProgramPoint dequeue() 39 | { 40 | auto pair = workList.dequeue(); 41 | return ProgramPoint(pair.first.getContext(), pair.second); 42 | } 43 | 44 | ProgramPoint front() 45 | { 46 | auto pair = workList.front(); 47 | return ProgramPoint(pair.first.getContext(), pair.second); 48 | } 49 | 50 | bool empty() const { return workList.empty(); } 51 | }; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Precision/VectorTransform.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace taint 7 | { 8 | 9 | template ()(std::declval()))>>> 10 | OutputVector vectorTransform(const InputVector& input, UnaryOperator&& op) 11 | { 12 | OutputVector output; 13 | output.reserve(input.size()); 14 | 15 | std::transform(input.begin(), input.end(), std::back_inserter(output), std::forward(op)); 16 | 17 | return output; 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/Program/DefUseFunction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Program/DefUseInstruction.h" 4 | 5 | namespace taint 6 | { 7 | 8 | class DefUseFunction 9 | { 10 | private: 11 | const llvm::Function& function; 12 | std::unordered_map instMap; 13 | 14 | DefUseInstruction entryInst; 15 | DefUseInstruction* exitInst; 16 | public: 17 | using NodeType = DefUseInstruction; 18 | 19 | DefUseFunction(const llvm::Function& f); 20 | DefUseFunction(const DefUseFunction&) = delete; 21 | DefUseFunction& operator=(const DefUseFunction&) = delete; 22 | const llvm::Function& getFunction() const { return function; } 23 | 24 | DefUseInstruction* getDefUseInstruction(const llvm::Instruction*); 25 | const DefUseInstruction* getDefUseInstruction(const llvm::Instruction*) const; 26 | 27 | DefUseInstruction* getEntryInst() 28 | { 29 | return &entryInst; 30 | } 31 | const DefUseInstruction* getEntryInst() const 32 | { 33 | return &entryInst; 34 | } 35 | DefUseInstruction* getExitInst() 36 | { 37 | return exitInst; 38 | } 39 | const DefUseInstruction* getExitInst() const 40 | { 41 | return exitInst; 42 | } 43 | }; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Program/DefUseModule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Program/DefUseFunction.h" 4 | #include "Util/Iterator/MapValueIterator.h" 5 | 6 | namespace llvm 7 | { 8 | class Module; 9 | } 10 | 11 | namespace taint 12 | { 13 | 14 | class DefUseModule 15 | { 16 | private: 17 | const llvm::Module& module; 18 | using FunctionMap = std::unordered_map; 19 | FunctionMap funMap; 20 | const DefUseFunction* entryFunc; 21 | public: 22 | using iterator = util::MapValueIterator; 23 | using const_iterator = util::MapValueConstIterator; 24 | 25 | DefUseModule(const llvm::Module& m); 26 | const llvm::Module& getModule() const { return module; } 27 | 28 | const DefUseFunction& getEntryFunction() const 29 | { 30 | assert(entryFunc != nullptr); 31 | return *entryFunc; 32 | }; 33 | const DefUseFunction& getDefUseFunction(const llvm::Function* f) const; 34 | 35 | iterator begin() { return iterator(funMap.begin()); } 36 | iterator end() { return iterator(funMap.end()); } 37 | const_iterator begin() const { return const_iterator(funMap.begin()); } 38 | const_iterator end() const { return const_iterator(funMap.end()); } 39 | }; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Support/ProgramPoint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/Hashing.h" 4 | 5 | #include 6 | 7 | namespace context 8 | { 9 | class Context; 10 | } 11 | 12 | namespace taint 13 | { 14 | 15 | class DefUseInstruction; 16 | 17 | class ProgramPoint 18 | { 19 | private: 20 | const context::Context* ctx; 21 | const DefUseInstruction* node; 22 | public: 23 | ProgramPoint(const context::Context* c, const DefUseInstruction* n): ctx(c), node(n) 24 | { 25 | assert(ctx != nullptr && node != nullptr); 26 | } 27 | 28 | const context::Context* getContext() const { return ctx; } 29 | const DefUseInstruction* getDefUseInstruction() const { return node; } 30 | 31 | bool operator==(const ProgramPoint& rhs) const 32 | { 33 | return ctx == rhs.ctx && node == rhs.node; 34 | } 35 | bool operator!=(const ProgramPoint& rhs) const 36 | { 37 | return !(*this == rhs); 38 | } 39 | bool operator<(const ProgramPoint& rhs) const 40 | { 41 | if (ctx < rhs.ctx) 42 | return true; 43 | else if (rhs.ctx < ctx) 44 | return false; 45 | else 46 | return node < rhs.node; 47 | } 48 | bool operator>(const ProgramPoint& rhs) const 49 | { 50 | return rhs < *this; 51 | } 52 | bool operator<=(const ProgramPoint& rhs) const 53 | { 54 | return !(rhs < *this); 55 | } 56 | bool operator>=(const ProgramPoint& rhs) const 57 | { 58 | return !(*this < rhs); 59 | } 60 | }; 61 | 62 | } 63 | 64 | namespace std 65 | { 66 | template<> struct hash 67 | { 68 | size_t operator()(const taint::ProgramPoint& p) const 69 | { 70 | return util::hashPair(p.getContext(), p.getDefUseInstruction()); 71 | } 72 | }; 73 | } 74 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Support/ProgramPointSet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Support/ProgramPoint.h" 4 | 5 | #include 6 | 7 | namespace taint 8 | { 9 | 10 | class ProgramPointSet 11 | { 12 | private: 13 | using SetType = std::unordered_set; 14 | SetType ppSet; 15 | public: 16 | using const_iterator = SetType::const_iterator; 17 | 18 | ProgramPointSet() = default; 19 | 20 | ProgramPointSet(const ProgramPointSet&) = delete; 21 | ProgramPointSet(ProgramPointSet&&) noexcept = default; 22 | ProgramPointSet& operator=(const ProgramPointSet&) = delete; 23 | ProgramPointSet& operator=(ProgramPointSet&&) = delete; 24 | 25 | bool insert(const ProgramPoint& pp) 26 | { 27 | return ppSet.insert(pp).second; 28 | } 29 | 30 | const_iterator begin() const { return ppSet.begin(); } 31 | const_iterator end() const { return ppSet.end(); } 32 | size_t size() const { return ppSet.size(); } 33 | bool empty() const { return ppSet.empty(); } 34 | }; 35 | 36 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/Support/SinkSignature.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Support/ProgramPoint.h" 4 | #include "Util/Hashing.h" 5 | 6 | namespace llvm 7 | { 8 | class Function; 9 | } 10 | 11 | namespace taint 12 | { 13 | 14 | class SinkSignature 15 | { 16 | private: 17 | ProgramPoint callsite; 18 | const llvm::Function* callee; 19 | public: 20 | SinkSignature(const ProgramPoint& p, const llvm::Function* f): callsite(p), callee(f) {} 21 | 22 | const ProgramPoint& getCallSite() const 23 | { 24 | return callsite; 25 | } 26 | 27 | const llvm::Function* getCallee() const 28 | { 29 | return callee; 30 | } 31 | 32 | bool operator==(const SinkSignature& rhs) const 33 | { 34 | return callee == rhs.callee && callsite == rhs.callsite; 35 | } 36 | bool operator!=(const SinkSignature& rhs) const 37 | { 38 | return !(*this == rhs); 39 | } 40 | }; 41 | 42 | } 43 | 44 | namespace std 45 | { 46 | template<> struct hash 47 | { 48 | size_t operator()(const taint::SinkSignature& s) const 49 | { 50 | return util::hashPair(s.getCallSite(), s.getCallee()); 51 | } 52 | }; 53 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/Support/SinkViolationRecord.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Annotation/Taint/TaintDescriptor.h" 4 | #include "TaintAnalysis/Lattice/TaintLattice.h" 5 | #include "TaintAnalysis/Support/ProgramPoint.h" 6 | 7 | #include 8 | #include 9 | 10 | namespace taint 11 | { 12 | 13 | struct SinkViolation 14 | { 15 | uint8_t argPos; 16 | annotation::TClass what; 17 | TaintLattice expectVal; 18 | TaintLattice actualVal; 19 | }; 20 | 21 | using SinkViolationList = std::vector; 22 | using SinkViolationRecord = std::unordered_map; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /include/TaintAnalysis/Support/TaintEnv.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Support/TaintMap.h" 4 | #include "TaintAnalysis/Support/TaintValue.h" 5 | 6 | #include 7 | 8 | namespace taint 9 | { 10 | 11 | class TaintEnv 12 | { 13 | private: 14 | TaintMap env; 15 | public: 16 | using const_iterator = typename decltype(env)::const_iterator; 17 | 18 | TaintEnv() = default; 19 | 20 | TaintLattice lookup(const TaintValue& pLoc) const 21 | { 22 | if (llvm::isa(pLoc.getValue())) 23 | return TaintLattice::Untainted; 24 | else 25 | return env.lookup(pLoc); 26 | } 27 | 28 | bool weakUpdate(const TaintValue& pLoc, TaintLattice l) 29 | { 30 | assert(!llvm::isa(pLoc.getValue())); 31 | return env.weakUpdate(pLoc, l); 32 | } 33 | 34 | bool strongUpdate(const TaintValue& pLoc, TaintLattice l) 35 | { 36 | assert(!llvm::isa(pLoc.getValue())); 37 | return env.strongUpdate(pLoc, l); 38 | } 39 | 40 | bool mergeWith(const TaintEnv& rhs) 41 | { 42 | return env.mergeWith(rhs.env); 43 | } 44 | 45 | const_iterator begin() const { return env.begin(); } 46 | const_iterator end() const { return env.end(); } 47 | size_t size() const { return env.size(); } 48 | }; 49 | 50 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/Support/TaintMap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Lattice/TaintLattice.h" 4 | 5 | #include 6 | 7 | namespace taint 8 | { 9 | 10 | template 11 | class TaintMap 12 | { 13 | private: 14 | std::unordered_map taintMap; 15 | public: 16 | using const_iterator = typename decltype(taintMap)::const_iterator; 17 | 18 | TaintMap() = default; 19 | 20 | TaintLattice lookup(KeyType key) const 21 | { 22 | auto itr = taintMap.find(key); 23 | if (itr != taintMap.end()) 24 | return itr->second; 25 | else 26 | return TaintLattice::Unknown; 27 | } 28 | 29 | bool weakUpdate(KeyType key, TaintLattice l) 30 | { 31 | auto itr = taintMap.find(key); 32 | if (itr == taintMap.end()) 33 | { 34 | taintMap.insert(std::make_pair(key, l)); 35 | return true; 36 | } 37 | 38 | auto newVal = Lattice::merge(itr->second, l); 39 | if (itr->second == newVal) 40 | return false; 41 | itr->second = newVal; 42 | return true; 43 | } 44 | 45 | bool strongUpdate(KeyType key, TaintLattice l) 46 | { 47 | auto itr = taintMap.find(key); 48 | if (itr == taintMap.end()) 49 | { 50 | taintMap.insert(std::make_pair(key, l)); 51 | return true; 52 | } 53 | 54 | if (itr->second == l) 55 | return false; 56 | itr->second = l; 57 | return true; 58 | } 59 | 60 | bool mergeWith(const TaintMap& other) 61 | { 62 | auto ret = false; 63 | for (auto const& mapping: other) 64 | ret |= weakUpdate(mapping.first, mapping.second); 65 | return ret; 66 | } 67 | 68 | const_iterator begin() const { return taintMap.begin(); } 69 | const_iterator end() const { return taintMap.end(); } 70 | size_t size() const { return taintMap.size(); } 71 | }; 72 | 73 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/Support/TaintMemo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Support/ProgramPoint.h" 4 | #include "TaintAnalysis/Support/TaintStore.h" 5 | 6 | namespace taint 7 | { 8 | 9 | class TaintMemo 10 | { 11 | private: 12 | std::unordered_map memo; 13 | public: 14 | using const_iterator = decltype(memo)::const_iterator; 15 | 16 | TaintMemo() = default; 17 | 18 | // Return NULL if key not found 19 | const TaintStore* lookup(const ProgramPoint& pLoc) const 20 | { 21 | auto itr = memo.find(pLoc); 22 | if (itr == memo.end()) 23 | return nullptr; 24 | else 25 | return &itr->second; 26 | } 27 | 28 | bool insert(const ProgramPoint& pp, const tpa::MemoryObject* obj, TaintLattice tVal) 29 | { 30 | auto itr = memo.find(pp); 31 | if (itr == memo.end()) 32 | { 33 | itr = memo.insert(std::make_pair(pp, TaintStore())).first; 34 | } 35 | 36 | return itr->second.weakUpdate(obj, tVal); 37 | } 38 | 39 | void update(const ProgramPoint& pp, TaintStore&& store) 40 | { 41 | memo[pp] = std::move(store); 42 | } 43 | 44 | const_iterator begin() const { return memo.begin(); } 45 | const_iterator end() const { return memo.end(); } 46 | }; 47 | 48 | } -------------------------------------------------------------------------------- /include/TaintAnalysis/Support/TaintStore.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Support/TaintMap.h" 4 | 5 | namespace tpa 6 | { 7 | class MemoryObject; 8 | } 9 | 10 | namespace taint 11 | { 12 | 13 | using TaintStore = TaintMap; 14 | 15 | } -------------------------------------------------------------------------------- /include/Transforms/ExpandByVal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llvm/Pass.h" 4 | 5 | namespace transform 6 | { 7 | 8 | class ExpandByValPass: public llvm::ModulePass 9 | { 10 | public: 11 | static char ID; // Pass identification, replacement for typeid 12 | ExpandByValPass(): llvm::ModulePass(ID) {} 13 | 14 | bool runOnModule(llvm::Module &M) override; 15 | }; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /include/Transforms/ExpandConstantExpr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llvm/Pass.h" 4 | 5 | namespace transform 6 | { 7 | 8 | // This is a FunctionPass because our handling of PHI nodes means that our modifications may cross BasicBlocks. 9 | class ExpandConstantExprPass: public llvm::FunctionPass 10 | { 11 | public: 12 | static char ID; // Pass identification, replacement for typeid 13 | ExpandConstantExprPass() : llvm::FunctionPass(ID) {} 14 | 15 | bool runOnFunction(llvm::Function& F) override; 16 | }; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /include/Transforms/ExpandGetElementPtr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llvm/Pass.h" 4 | 5 | namespace transform 6 | { 7 | 8 | class ExpandGetElementPtrPass: public llvm::BasicBlockPass 9 | { 10 | public: 11 | static char ID; // Pass identification, replacement for typeid 12 | ExpandGetElementPtrPass(): llvm::BasicBlockPass(ID) {} 13 | 14 | bool runOnBasicBlock(llvm::BasicBlock& BB) override; 15 | }; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /include/Transforms/ExpandIndirectBr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llvm/Pass.h" 4 | 5 | namespace transform 6 | { 7 | 8 | // This is a ModulePass so that it can expand out blockaddress 9 | // ConstantExprs inside global variable initializers. 10 | class ExpandIndirectBr: public llvm::ModulePass { 11 | public: 12 | static char ID; 13 | ExpandIndirectBr(): llvm::ModulePass(ID) {} 14 | 15 | bool runOnModule(llvm::Module &M) override; 16 | }; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /include/Transforms/ExpandUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llvm/IR/Function.h" 4 | #include "llvm/IR/Instructions.h" 5 | 6 | namespace transform 7 | { 8 | 9 | llvm::Instruction* phiSafeInsertPt(llvm::Use* use); 10 | void phiSafeReplaceUses(llvm::Use* use, llvm::Value* newVal); 11 | llvm::Function* recreateFunction(llvm::Function* func, llvm::FunctionType* newType); 12 | llvm::Instruction* copyDebug(llvm::Instruction* newInst, llvm::Instruction* original); 13 | 14 | template 15 | static void copyLoadOrStoreAttrs(InstType* dest, InstType* src) 16 | { 17 | dest->setVolatile(src->isVolatile()); 18 | dest->setAlignment(src->getAlignment()); 19 | dest->setOrdering(src->getOrdering()); 20 | dest->setSynchScope(src->getSynchScope()); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /include/Transforms/FoldIntToPtr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llvm/Pass.h" 4 | 5 | namespace transform 6 | { 7 | 8 | class FoldIntToPtrPass: public llvm::BasicBlockPass { 9 | public: 10 | static char ID; 11 | FoldIntToPtrPass(): llvm::BasicBlockPass(ID) {} 12 | 13 | bool runOnBasicBlock(llvm::BasicBlock&) override; 14 | }; 15 | 16 | } -------------------------------------------------------------------------------- /include/Transforms/GlobalCleanup.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llvm/Pass.h" 4 | 5 | namespace transform 6 | { 7 | 8 | class GlobalCleanup: public llvm::ModulePass 9 | { 10 | public: 11 | static char ID; 12 | GlobalCleanup(): ModulePass(ID) {} 13 | 14 | bool runOnModule(llvm::Module &M) override; 15 | }; 16 | 17 | class ResolveAliases: public llvm::ModulePass 18 | { 19 | public: 20 | static char ID; 21 | ResolveAliases(): ModulePass(ID) {} 22 | 23 | bool runOnModule(llvm::Module &M) override; 24 | }; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /include/Transforms/LowerGlobalCtor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llvm/Pass.h" 4 | 5 | namespace transform 6 | { 7 | 8 | // This is a ModulePass so that it can expand out blockaddress 9 | // ConstantExprs inside global variable initializers. 10 | class LowerGlobalCtorPass: public llvm::ModulePass { 11 | public: 12 | static char ID; 13 | LowerGlobalCtorPass(): llvm::ModulePass(ID) {} 14 | 15 | bool runOnModule(llvm::Module &M) override; 16 | }; 17 | 18 | } -------------------------------------------------------------------------------- /include/Transforms/RunPrepass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace transform 4 | { 5 | 6 | void runPrepassOn(llvm::Module&); 7 | 8 | } 9 | -------------------------------------------------------------------------------- /include/Util/AnalysisEngine/DataFlowAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace util 4 | { 5 | 6 | template 7 | class DataFlowAnalysis 8 | { 9 | private: 10 | GlobalState& globalState; 11 | Memo& memo; 12 | public: 13 | DataFlowAnalysis(GlobalState& g, Memo& m): globalState(g), memo(m) {} 14 | 15 | DataFlowAnalysis(const DataFlowAnalysis&) = delete; 16 | DataFlowAnalysis(DataFlowAnalysis&&) noexcept = default; 17 | DataFlowAnalysis& operator=(const DataFlowAnalysis&) = delete; 18 | DataFlowAnalysis& operator=(DataFlowAnalysis&&) = delete; 19 | 20 | template 21 | void runOnWorkList(WorkList workList) 22 | { 23 | while (!workList.empty()) 24 | { 25 | auto item = workList.dequeue(); 26 | auto localState = memo.lookup(item); 27 | auto evalResult = TransferFunction(globalState, localState).eval(item); 28 | Propagator(memo, workList).propagate(evalResult); 29 | } 30 | } 31 | 32 | template 33 | void runOnInitialState(InitialState&& initState) 34 | { 35 | auto workList = Initializer(globalState, memo).runOnInitState(std::forward(initState)); 36 | runOnWorkList(std::move(workList)); 37 | } 38 | }; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /include/Util/CommandLine/CommandLineFlags.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/DataStructure/VectorMap.h" 4 | 5 | #include 6 | 7 | namespace util 8 | { 9 | 10 | class CommandLineFlags 11 | { 12 | private: 13 | using MapType = VectorMap; 14 | 15 | MapType flagMap; 16 | 17 | // Return true if insertion took place, false if override took place 18 | bool addFlag(const llvm::StringRef& key, const llvm::StringRef& value) 19 | { 20 | return flagMap.insert_or_assign(key, value).second; 21 | } 22 | public: 23 | using const_iterator = MapType::const_iterator; 24 | 25 | CommandLineFlags() = default; 26 | 27 | const llvm::StringRef* lookup(const llvm::StringRef& key) const 28 | { 29 | auto itr = flagMap.find(key); 30 | if (itr == flagMap.end()) 31 | return nullptr; 32 | else 33 | return &itr->second; 34 | } 35 | 36 | bool count(const llvm::StringRef& key) const 37 | { 38 | return lookup(key) != nullptr; 39 | } 40 | 41 | const_iterator begin() const { return flagMap.begin(); } 42 | const_iterator end() const { return flagMap.end(); } 43 | 44 | friend class CommandLineParser; 45 | }; 46 | 47 | } -------------------------------------------------------------------------------- /include/Util/CommandLine/CommandLineParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/CommandLine/CommandLineFlags.h" 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace util 10 | { 11 | 12 | class CommandLineParser 13 | { 14 | private: 15 | struct PositionalFlagEntry 16 | { 17 | llvm::StringRef desc; 18 | }; 19 | 20 | struct OptionalFlagEntry 21 | { 22 | llvm::StringRef desc; 23 | std::experimental::optional defaultValue; 24 | }; 25 | 26 | using OptionalFlagMap = VectorMap; 27 | OptionalFlagMap optFlagMap; 28 | using PositionalFlagMap = std::vector>; 29 | PositionalFlagMap posFlagMap; 30 | 31 | llvm::StringRef helpMsg; 32 | 33 | void addOptionalFlagEntry(const llvm::StringRef& name, OptionalFlagEntry&& entry); 34 | void addPositionalFlagEntry(const llvm::StringRef& name, PositionalFlagEntry&& entry); 35 | void parseArgs(const std::vector& args, CommandLineFlags& result) const; 36 | public: 37 | CommandLineParser(const llvm::StringRef& h = ""): helpMsg(h) {} 38 | 39 | void addPositionalFlag(const llvm::StringRef& name, const llvm::StringRef& desc); 40 | void addOptionalFlag(const llvm::StringRef& name, const llvm::StringRef& desc); 41 | void addOptionalFlag(const llvm::StringRef& name, const llvm::StringRef& desc, const llvm::StringRef& init); 42 | 43 | void printUsage(const llvm::StringRef& progName) const; 44 | 45 | CommandLineFlags parseCommandLineOptions(int, char**) const; 46 | }; 47 | 48 | } 49 | -------------------------------------------------------------------------------- /include/Util/CommandLine/TypedCommandLineParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/CommandLine/CommandLineParser.h" 4 | 5 | namespace util 6 | { 7 | 8 | class TypedCommandLineParser 9 | { 10 | private: 11 | enum class OptionType 12 | { 13 | String, 14 | Bool, 15 | UInt, 16 | }; 17 | 18 | struct OptionEntry 19 | { 20 | OptionType type; 21 | void* data; 22 | }; 23 | 24 | VectorMap optionMap; 25 | 26 | CommandLineParser parser; 27 | 28 | void updateOptionMap(const llvm::StringRef&, OptionType, void*); 29 | public: 30 | TypedCommandLineParser(const llvm::StringRef& h = ""): parser(h) {} 31 | 32 | void addBooleanOptionalFlag(const llvm::StringRef&, const llvm::StringRef&, bool&); 33 | void addStringOptionalFlag(const llvm::StringRef&, const llvm::StringRef&, llvm::StringRef&); 34 | void addUIntOptionalFlag(const llvm::StringRef&, const llvm::StringRef&, unsigned&); 35 | void addStringPositionalFlag(const llvm::StringRef&, const llvm::StringRef&, llvm::StringRef&); 36 | void parseCommandLineOptions(int argc, char** argv); 37 | }; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /include/Util/DataStructure/FIFOWorkList.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace util 8 | { 9 | 10 | // This worklist implementation is a simple FIFO queue with an additional set to help remove duplicate entries 11 | template > 12 | class FIFOWorkList 13 | { 14 | public: 15 | using ElemType = T; 16 | private: 17 | // The FIFO queue 18 | std::queue list; 19 | // Avoid duplicate entries in FIFO queue 20 | std::unordered_set set; 21 | public: 22 | FIFOWorkList() {} 23 | bool enqueue(ElemType elem) 24 | { 25 | if (!set.count(elem)) 26 | { 27 | list.push(elem); 28 | set.insert(elem); 29 | return true; 30 | } 31 | else 32 | return false; 33 | } 34 | 35 | ElemType dequeue() 36 | { 37 | assert(!list.empty() && "Trying to dequeue an empty queue!"); 38 | ElemType ret = list.front(); 39 | list.pop(); 40 | set.erase(ret); 41 | return ret; 42 | } 43 | 44 | ElemType front() 45 | { 46 | assert(!list.empty() && "Trying to dequeue an empty queue!"); 47 | return list.front(); 48 | } 49 | 50 | bool empty() const { return list.empty(); } 51 | }; 52 | 53 | } 54 | 55 | -------------------------------------------------------------------------------- /include/Util/DataStructure/PriorityWorkList.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace util 8 | { 9 | 10 | // This worklist implementation is a priority queue with an additional set to help remove duplicate entries 11 | template , typename Hasher = std::hash> 12 | class PriorityWorkList 13 | { 14 | public: 15 | using ElemType = T; 16 | private: 17 | // The FIFO queue 18 | std::priority_queue, Compare> list; 19 | // Avoid duplicate entries in FIFO queue 20 | std::unordered_set set; 21 | public: 22 | PriorityWorkList() {} 23 | PriorityWorkList(const Compare& cmp): list(cmp) {} 24 | 25 | bool enqueue(ElemType elem) 26 | { 27 | if (!set.count(elem)) 28 | { 29 | list.push(elem); 30 | set.insert(elem); 31 | return true; 32 | } 33 | else 34 | return false; 35 | } 36 | 37 | ElemType dequeue() 38 | { 39 | assert(!list.empty() && "Trying to dequeue an empty queue!"); 40 | ElemType ret = list.top(); 41 | list.pop(); 42 | set.erase(ret); 43 | return ret; 44 | } 45 | 46 | ElemType front() 47 | { 48 | assert(!list.empty() && "Trying to dequeue an empty queue!"); 49 | return list.top(); 50 | } 51 | 52 | bool empty() const { return list.empty(); } 53 | }; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /include/Util/DataStructure/VectorSet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/DataStructure/SortedVector.h" 4 | 5 | namespace util 6 | { 7 | 8 | template 9 | using VectorSet = SortedVector; 10 | 11 | } -------------------------------------------------------------------------------- /include/Util/IO/Context/Printer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace context 6 | { 7 | class Context; 8 | class ProgramPoint; 9 | } 10 | 11 | namespace util 12 | { 13 | namespace io 14 | { 15 | 16 | llvm::raw_ostream& operator<< (llvm::raw_ostream& os, const context::Context& c); 17 | llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const context::ProgramPoint& p); 18 | 19 | } 20 | } -------------------------------------------------------------------------------- /include/Util/IO/PointerAnalysis/NodePrinter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Program/CFG/NodeVisitor.h" 4 | 5 | namespace llvm 6 | { 7 | class raw_ostream; 8 | } 9 | 10 | namespace util 11 | { 12 | namespace io 13 | { 14 | 15 | template 16 | class NodePrinter: public tpa::ConstNodeVisitor> 17 | { 18 | private: 19 | llvm::raw_ostream& os; 20 | public: 21 | NodePrinter(llvm::raw_ostream&); 22 | 23 | void visitEntryNode(const tpa::EntryNodeMixin&); 24 | void visitAllocNode(const tpa::AllocNodeMixin&); 25 | void visitCopyNode(const tpa::CopyNodeMixin&); 26 | void visitOffsetNode(const tpa::OffsetNodeMixin&); 27 | void visitLoadNode(const tpa::LoadNodeMixin&); 28 | void visitStoreNode(const tpa::StoreNodeMixin&); 29 | void visitCallNode(const tpa::CallNodeMixin&); 30 | void visitReturnNode(const tpa::ReturnNodeMixin&); 31 | }; 32 | 33 | } 34 | } -------------------------------------------------------------------------------- /include/Util/IO/PointerAnalysis/Printer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/IO/Context/Printer.h" 4 | 5 | namespace llvm 6 | { 7 | class Value; 8 | } 9 | 10 | namespace tpa 11 | { 12 | class AllocSite; 13 | class Pointer; 14 | class MemoryObject; 15 | class PtsSet; 16 | 17 | class ArrayLayout; 18 | struct ArrayTriple; 19 | class PointerLayout; 20 | class TypeLayout; 21 | 22 | class CFGNode; 23 | class ProgramPoint; 24 | class FunctionContext; 25 | } 26 | 27 | namespace util 28 | { 29 | namespace io 30 | { 31 | 32 | void dumpValue(llvm::raw_ostream& os, const llvm::Value& value); 33 | 34 | llvm::raw_ostream& operator<< (llvm::raw_ostream& os, const tpa::AllocSite&); 35 | llvm::raw_ostream& operator<< (llvm::raw_ostream& os, const tpa::Pointer&); 36 | llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const tpa::MemoryObject&); 37 | llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const tpa::PtsSet&); 38 | 39 | llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const tpa::ArrayTriple&); 40 | llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const tpa::ArrayLayout&); 41 | llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const tpa::PointerLayout&); 42 | llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const tpa::TypeLayout&); 43 | 44 | llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const tpa::CFGNode&); 45 | llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const tpa::ProgramPoint&); 46 | llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const tpa::FunctionContext&); 47 | 48 | } 49 | } 50 | 51 | using namespace util::io; 52 | -------------------------------------------------------------------------------- /include/Util/IO/PointerAnalysis/WriteDotFile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace tpa 4 | { 5 | class CFG; 6 | } 7 | 8 | namespace util 9 | { 10 | namespace io 11 | { 12 | 13 | void writeDotFile(const char* filePath, const tpa::CFG& cfg); 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /include/Util/IO/ReadFile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace util 8 | { 9 | namespace io 10 | { 11 | 12 | inline std::unique_ptr readFileIntoBuffer(const char* fileName) 13 | { 14 | auto fileOrErr = llvm::MemoryBuffer::getFile(fileName); 15 | if (auto ec = fileOrErr.getError()) 16 | { 17 | auto errMsg = (llvm::Twine("Can't open file \'") + fileName + "\' :" + ec.message()).str(); 18 | llvm::report_fatal_error(errMsg); 19 | } 20 | 21 | return std::move(fileOrErr.get()); 22 | } 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /include/Util/IO/ReadIR.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace llvm 6 | { 7 | class Module; 8 | } 9 | 10 | namespace util 11 | { 12 | namespace io 13 | { 14 | 15 | std::unique_ptr readModuleFromFile(const char* fileName); 16 | std::unique_ptr readModuleFromString(const char *assembly); 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /include/Util/IO/TaintAnalysis/Printer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TaintAnalysis/Lattice/TaintLattice.h" 4 | #include "Util/IO/PointerAnalysis/Printer.h" 5 | 6 | namespace taint 7 | { 8 | class DefUseInstruction; 9 | class ProgramPoint; 10 | } 11 | 12 | namespace util 13 | { 14 | namespace io 15 | { 16 | 17 | llvm::raw_ostream& operator<< (llvm::raw_ostream& os, taint::TaintLattice l); 18 | llvm::raw_ostream& operator<< (llvm::raw_ostream& os, const taint::DefUseInstruction&); 19 | llvm::raw_ostream& operator<< (llvm::raw_ostream& os, const taint::ProgramPoint&); 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /include/Util/IO/TaintAnalysis/WriteDotFile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace taint 4 | { 5 | class DefUseFunction; 6 | } 7 | 8 | namespace util 9 | { 10 | namespace io 11 | { 12 | 13 | void writeDotFile(const char* filePath, const taint::DefUseFunction& duFunc); 14 | 15 | } 16 | } -------------------------------------------------------------------------------- /include/Util/IO/WriteIR.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm 4 | { 5 | class Module; 6 | } 7 | 8 | namespace util 9 | { 10 | namespace io 11 | { 12 | 13 | void writeModuleToText(const llvm::Module& module, const char* fileName); 14 | void writeModuleToBitCode(const llvm::Module& module, const char* fileName); 15 | void writeModuleToFile(const llvm::Module& module, const char* fileName, bool isText); 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /include/Util/Iterator/InfixOutputIterator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace util 7 | { 8 | namespace io 9 | { 10 | 11 | template 12 | class InfixOstreamIterator: public std::iterator 13 | { 14 | private: 15 | OStreamType& os; 16 | const char* delimiter; 17 | bool isFirstElem; 18 | public: 19 | InfixOstreamIterator(OStreamType& s): os(s), delimiter(0), isFirstElem(true) {} 20 | InfixOstreamIterator(OStreamType& s, const char* d): os(s), delimiter(d), isFirstElem(true) {} 21 | 22 | InfixOstreamIterator& operator=(const T& item) 23 | { 24 | if (delimiter != 0 && !isFirstElem) 25 | os << delimiter; 26 | os << item; 27 | isFirstElem = false; 28 | return *this; 29 | } 30 | 31 | InfixOstreamIterator& operator*() 32 | { 33 | return *this; 34 | } 35 | InfixOstreamIterator& operator++() 36 | { 37 | return *this; 38 | } 39 | InfixOstreamIterator& operator++(int) 40 | { 41 | return *this; 42 | } 43 | }; 44 | 45 | template 46 | InfixOstreamIterator infix_ostream_iterator(OStreamType& s, const char* d) 47 | { 48 | return InfixOstreamIterator(s, d); 49 | } 50 | 51 | } 52 | } -------------------------------------------------------------------------------- /include/Util/Iterator/IteratorRange.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace util 6 | { 7 | 8 | // A range adaptor for a pair of iterators 9 | template 10 | class IteratorRange 11 | { 12 | private: 13 | Iterator first, last; 14 | public: 15 | using value_type = typename std::iterator_traits::value_type; 16 | 17 | IteratorRange(Iterator s, Iterator e): first(std::move(s)), last(std::move(e)) {} 18 | 19 | Iterator begin() const { return first; } 20 | Iterator end() const { return last; } 21 | 22 | typename std::iterator_traits::difference_type size() const { return std::distance(first, last); } 23 | bool empty() const { return first == last; } 24 | }; 25 | 26 | template 27 | IteratorRange iteratorRange(T x, T y) 28 | { 29 | return IteratorRange(std::move(x), std::move(y)); 30 | } 31 | 32 | template 33 | IteratorRange iteratorRange(std::pair pair) 34 | { 35 | return IteratorRange(std::move(pair.first), std::move(pair.second)); 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /include/Util/Iterator/IteratorTrait.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Simple SFINAE struct to test for iterator type 6 | 7 | namespace util 8 | { 9 | 10 | template 11 | class is_iterator 12 | { 13 | private: 14 | template 15 | static std::enable_if_t::value, std::true_type> test(typename std::iterator_traits::value_type*); 16 | 17 | template 18 | static std::false_type test(...); 19 | public: 20 | static constexpr bool value = decltype(test(nullptr))::value; 21 | }; 22 | 23 | } -------------------------------------------------------------------------------- /include/Util/Iterator/UniquePtrIterator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/Iterator/IteratorAdaptor.h" 4 | 5 | namespace util 6 | { 7 | 8 | // An iterator adapter that takes an iterator over a container of unique_ptrs and returns the corresponding iterator that automatically invoke the get() method of the unique_ptr 9 | // Such an adapter is useful when we want to hide the ownership detail of a container when exposing its iterators 10 | template ::value_type::pointer> 11 | class UniquePtrIterator: public IteratorAdaptor, Iterator, typename std::iterator_traits::iterator_category, ValueT> 12 | { 13 | private: 14 | using BaseT = IteratorAdaptor, Iterator, typename std::iterator_traits::iterator_category, ValueT>; 15 | public: 16 | UniquePtrIterator() = default; 17 | UniquePtrIterator(const Iterator& i): BaseT(i) {} 18 | UniquePtrIterator(Iterator&& i): BaseT(std::move(i)) {} 19 | 20 | ValueT operator*() const { return this->itr->get(); } 21 | }; 22 | 23 | template ::value_type::pointer> 24 | class UniquePtrConstIterator: public IteratorAdaptor, Iterator, typename std::iterator_traits::iterator_category, ValueT> 25 | { 26 | private: 27 | using BaseT = IteratorAdaptor, Iterator, typename std::iterator_traits::iterator_category, ValueT>; 28 | public: 29 | UniquePtrConstIterator() = default; 30 | UniquePtrConstIterator(const Iterator& i): BaseT(i) {} 31 | UniquePtrConstIterator(Iterator&& i): BaseT(std::move(i)) {} 32 | 33 | ValueT operator*() const { return this->itr->get(); } 34 | }; 35 | 36 | } -------------------------------------------------------------------------------- /include/Util/Testing/DummyPointerAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerAnalysis/Analysis/PointerAnalysis.h" 4 | 5 | namespace util 6 | { 7 | 8 | // A dummy pointer analysis which is mostly useful for unit test 9 | class DummyPointerAnalysis: public PointerAnalysis 10 | { 11 | public: 12 | DummyPointerAnalysis(PointerManager& pm, MemoryManager& mm, const ExternalPointerTable& t): PointerAnalysis(pm, mm, t) {} 13 | 14 | void injectEnv(const Pointer* ptr, const MemoryLocation* loc) 15 | { 16 | env.insert(ptr, loc); 17 | } 18 | }; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /include/Util/pcomb/Combinator/LazyParser.h: -------------------------------------------------------------------------------- 1 | #ifndef PCOMB_LAZY_PARSER_H 2 | #define PCOMB_LAZY_PARSER_H 3 | 4 | #include "Util/pcomb/Parser/Parser.h" 5 | 6 | #include 7 | 8 | namespace pcomb 9 | { 10 | 11 | // LazyParser allows the user to declare a parser first before giving its full definitions. This is useful for recursive grammar definitions. 12 | // It is essentially a pointer to another parser. 13 | template 14 | class LazyParser: public Parser 15 | { 16 | private: 17 | const Parser* parser; 18 | public: 19 | using OutputType = O; 20 | using ResultType = typename Parser::ResultType; 21 | 22 | LazyParser(): parser(nullptr) {} 23 | 24 | LazyParser& setParser(const Parser& p) 25 | { 26 | parser = &p; 27 | return *this; 28 | } 29 | 30 | ResultType parse(const InputStream& input) const 31 | { 32 | assert(parser != nullptr); 33 | return parser->parse(input); 34 | } 35 | }; 36 | 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /include/Util/pcomb/Combinator/LexemeParser.h: -------------------------------------------------------------------------------- 1 | #ifndef PCOMB_LEXEME_PARSER_H 2 | #define PCOMB_LEXEME_PARSER_H 3 | 4 | #include "Util/pcomb/Combinator/ParserAdapter.h" 5 | #include "Util/pcomb/Combinator/TokenParser.h" 6 | #include "Util/pcomb/Parser/PredicateCharParser.h" 7 | 8 | namespace pcomb 9 | { 10 | 11 | // LexemeParser takes a parser p and returns a parser that parse an entire file using p. It tries to remove all preceding whitespaces first before sending the input to p, and after p succeeds it tries to remove trailing whitespaces and match an EOF. 12 | template 13 | auto lexeme(ParserA&& p, char finalChar, llvm::StringRef whitespaces = " \t\n\v\f\r") 14 | { 15 | return rule( 16 | seq( 17 | token(p, whitespaces), 18 | token(ch(finalChar), whitespaces) 19 | ), 20 | [] (auto&& pair) 21 | { 22 | using ParserType = std::remove_reference_t; 23 | return std::forward(std::get<0>(pair)); 24 | } 25 | ); 26 | } 27 | 28 | template 29 | auto file(ParserA&& p) 30 | { 31 | return lexeme(p, static_cast(std::char_traits::eof())); 32 | } 33 | 34 | template 35 | auto line(ParserA&& p) 36 | { 37 | return lexeme(p, '\n', " \t\r\v\f"); 38 | } 39 | 40 | template 41 | auto bigstr(ParserA&& p) 42 | { 43 | return lexeme(p, '\0'); 44 | } 45 | 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/Util/pcomb/Combinator/ParserAdapter.h: -------------------------------------------------------------------------------- 1 | #ifndef PCOMB_PARSER_ADAPTER_H 2 | #define PCOMB_PARSER_ADAPTER_H 3 | 4 | #include "Util/pcomb/Parser/Parser.h" 5 | 6 | namespace pcomb 7 | { 8 | 9 | // The ParserAdapter combinator takes another parser p0, fails if p0 fails, and convert p0's result to T using the function specified by the user if succeeds. 10 | template 11 | class ParserAdapter: public Parser> 12 | { 13 | private: 14 | ParserA pa; 15 | Converter conv; 16 | 17 | using AdapterInputType = typename ParserA::OutputType; 18 | using AdapterOutputType = std::result_of_t; 19 | public: 20 | using OutputType = AdapterOutputType; 21 | using ResultType = typename Parser::ResultType; 22 | 23 | template 24 | ParserAdapter(PA&& p, C&& c): pa(std::forward(p)), conv(std::forward(c)) {} 25 | 26 | ResultType parse(const InputStream& input) const override 27 | { 28 | auto pResult = pa.parse(input); 29 | auto ret = ResultType(pResult.getInputStream()); 30 | if (pResult.success()) 31 | ret.setOutput(conv(std::move(pResult).getOutput())); 32 | return ret; 33 | } 34 | }; 35 | 36 | template 37 | auto rule(ParserA&& p, Converter&& c) 38 | { 39 | using ParserType = std::remove_reference_t; 40 | return ParserAdapter(std::forward(p), std::forward(c)); 41 | } 42 | 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /include/Util/pcomb/InputStream/InputStream.h: -------------------------------------------------------------------------------- 1 | #ifndef PCOMB_INPUT_STREAM_H 2 | #define PCOMB_INPUT_STREAM_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace pcomb 9 | { 10 | 11 | class InputStream 12 | { 13 | private: 14 | struct Position 15 | { 16 | size_t row, col; 17 | }; 18 | 19 | llvm::StringRef str; 20 | Position pos; 21 | 22 | InputStream(const llvm::StringRef& s, const Position& p): str(s), pos(p) {} 23 | public: 24 | InputStream(llvm::StringRef s): str(s), pos({1, 1}) {} 25 | 26 | bool isEOF() const 27 | { 28 | return str.empty(); 29 | } 30 | 31 | const char* getRawBuffer() const 32 | { 33 | return str.data(); 34 | } 35 | 36 | InputStream consume(size_t n) const 37 | { 38 | assert(n <= str.size()); 39 | auto newPos = pos; 40 | for (auto i = 0u; i < n; ++i) 41 | { 42 | auto ch = str[i]; 43 | if (ch == '\n') 44 | { 45 | ++newPos.row; 46 | newPos.col = 1; 47 | } 48 | else 49 | ++newPos.col; 50 | } 51 | return InputStream(str.substr(n), newPos); 52 | } 53 | 54 | size_t getLineNumber() const { return pos.row; } 55 | size_t getColumnNumber() const { return pos.col; } 56 | }; 57 | 58 | } 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /include/Util/pcomb/Parser/ParseResult.h: -------------------------------------------------------------------------------- 1 | #ifndef PCOMB_PARSE_RESULT_H 2 | #define PCOMB_PARSE_RESULT_H 3 | 4 | #include "Util/pcomb/InputStream/InputStream.h" 5 | 6 | #include 7 | #include 8 | 9 | namespace pcomb 10 | { 11 | 12 | template 13 | class ParseResult 14 | { 15 | public: 16 | using OutputType = Out; 17 | private: 18 | InputStream input; 19 | std::experimental::optional attr; 20 | public: 21 | template 22 | ParseResult(I&& i): input(std::forward(i)) {} 23 | 24 | template 25 | ParseResult(I&& i, O&& o): input(std::forward(i)), attr(std::forward(o)) {} 26 | 27 | bool success() const { return static_cast(attr); } 28 | bool hasError() const { return !success(); } 29 | 30 | template 31 | void setOutput(O&& o) 32 | { 33 | attr = std::forward(o); 34 | } 35 | 36 | const OutputType& getOutput() const& 37 | { 38 | assert(success()); 39 | return (*attr); 40 | } 41 | OutputType&& getOutput() && 42 | { 43 | assert(success()); 44 | return std::move(*attr); 45 | } 46 | 47 | const InputStream& getInputStream() const& 48 | { 49 | return input; 50 | } 51 | InputStream&& getInputStream() && 52 | { 53 | return std::move(input); 54 | } 55 | }; 56 | 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /include/Util/pcomb/Parser/Parser.h: -------------------------------------------------------------------------------- 1 | #ifndef PCOMB_PARSER_H 2 | #define PCOMB_PARSER_H 3 | 4 | #include "Util/pcomb/InputStream/InputStream.h" 5 | #include "Util/pcomb/Parser/ParseResult.h" 6 | 7 | #include 8 | 9 | namespace pcomb 10 | { 11 | 12 | template 13 | class Parser 14 | { 15 | public: 16 | using OutputType = O; 17 | using ResultType = ParseResult; 18 | 19 | virtual ~Parser() {} 20 | 21 | virtual ResultType parse(const InputStream& input) const = 0; 22 | }; 23 | 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /include/Util/pcomb/Parser/RegexParser.h: -------------------------------------------------------------------------------- 1 | #ifndef PCOMB_REGEX_PARSER_H 2 | #define PCOMB_REGEX_PARSER_H 3 | 4 | #include "Util/pcomb/Parser/Parser.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace pcomb 11 | { 12 | 13 | // RegexParser takes a StringRef as regex and mathes the start of the input string against that regex. 14 | // RegexParser is strictly more powerful than StringParser. But I would expect that StringParser is cheaper. 15 | class RegexParser: public Parser 16 | { 17 | private: 18 | using StringView = llvm::StringRef; 19 | std::regex regex; 20 | public: 21 | using OutputType = StringView; 22 | using ResultType = typename Parser::ResultType; 23 | 24 | RegexParser(StringView r): regex(r.data()) {} 25 | 26 | ResultType parse(const InputStream& input) const override 27 | { 28 | auto ret = ResultType(input); 29 | 30 | auto res = std::cmatch(); 31 | auto rawStr = input.getRawBuffer(); 32 | if (std::regex_search(rawStr, res, regex, std::regex_constants::match_continuous)) 33 | { 34 | auto matchLen = res.length(0); 35 | ret = ResultType(input.consume(matchLen), StringView(rawStr, matchLen)); 36 | } 37 | 38 | return ret; 39 | } 40 | }; 41 | 42 | inline RegexParser regex(const llvm::StringRef& s) 43 | { 44 | return RegexParser(s); 45 | } 46 | 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /include/Util/pcomb/Parser/StringParser.h: -------------------------------------------------------------------------------- 1 | #ifndef PCOMB_STRING_PARSER_H 2 | #define PCOMB_STRING_PARSER_H 3 | 4 | #include "Util/pcomb/Parser/Parser.h" 5 | 6 | #include 7 | 8 | namespace pcomb 9 | { 10 | 11 | // StringParser matches a string and returns that string as its attribute 12 | class StringParser: public Parser 13 | { 14 | private: 15 | using StringView = llvm::StringRef; 16 | StringView pattern; 17 | public: 18 | using OutputType = StringView; 19 | using ResultType = typename Parser::ResultType; 20 | 21 | StringParser(StringView s): pattern(s) {} 22 | 23 | ResultType parse(const InputStream& input) const override 24 | { 25 | auto ret = ResultType(input); 26 | 27 | auto inputView = llvm::StringRef(input.getRawBuffer(), pattern.size()); 28 | if (pattern.compare(inputView) == 0) 29 | ret = ResultType(input.consume(pattern.size()), inputView); 30 | 31 | return ret; 32 | } 33 | }; 34 | 35 | inline StringParser str(const llvm::StringRef& s) 36 | { 37 | return StringParser(s); 38 | } 39 | 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/Util/pcomb/pcomb.h: -------------------------------------------------------------------------------- 1 | #ifndef PCOMB_MAIN_HEADER_H 2 | #define PCOMB_MAIN_HEADER_H 3 | 4 | // This is a header that pulls in all the headers for parsers and combinators 5 | #include "Util/pcomb/Parser/PredicateCharParser.h" 6 | #include "Util/pcomb/Parser/RegexParser.h" 7 | #include "Util/pcomb/Parser/StringParser.h" 8 | 9 | #include "Util/pcomb/Combinator/AltParser.h" 10 | #include "Util/pcomb/Combinator/SeqParser.h" 11 | #include "Util/pcomb/Combinator/ManyParser.h" 12 | #include "Util/pcomb/Combinator/TokenParser.h" 13 | #include "Util/pcomb/Combinator/ParserAdapter.h" 14 | #include "Util/pcomb/Combinator/LazyParser.h" 15 | #include "Util/pcomb/Combinator/LexemeParser.h" 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /lib/Annotation/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (AnnotationSourceCodes 2 | ExternalModRefTable.cpp 3 | ExternalPointerTable.cpp 4 | ExternalTaintTable.cpp 5 | ) 6 | add_library (Annotation STATIC ${AnnotationSourceCodes}) 7 | 8 | target_link_libraries (Annotation LLVMSupport) -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${tpa_SOURCE_DIR}/include) 2 | 3 | add_subdirectory(Transforms) 4 | add_subdirectory(Util) 5 | add_subdirectory(Annotation) 6 | add_subdirectory(PointerAnalysis) 7 | add_subdirectory(Dynamic) 8 | add_subdirectory(TaintAnalysis) -------------------------------------------------------------------------------- /lib/Dynamic/Analysis/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (DynamicAnalysisSourceCodes 2 | DynamicContext.cpp 3 | DynamicMemory.cpp 4 | DynamicPointerAnalysis.cpp 5 | ) 6 | add_library (DynamicAnalysis STATIC ${DynamicAnalysisSourceCodes}) 7 | target_link_libraries (DynamicAnalysis DynamicLog) -------------------------------------------------------------------------------- /lib/Dynamic/Analysis/DynamicContext.cpp: -------------------------------------------------------------------------------- 1 | #include "Dynamic/Analysis/DynamicContext.h" 2 | 3 | #include 4 | 5 | namespace dynamic 6 | { 7 | 8 | std::unordered_set DynamicContext::ctxSet; 9 | const DynamicContext* DynamicContext::globalCtx = &*(ctxSet.insert(DynamicContext()).first); 10 | 11 | const DynamicContext* DynamicContext::pushContext(const DynamicContext* ctx, CallSiteType cs) 12 | { 13 | auto newCtx = DynamicContext(cs, ctx); 14 | auto itr = ctxSet.insert(newCtx).first; 15 | return &(*itr); 16 | } 17 | 18 | const DynamicContext* DynamicContext::popContext(const DynamicContext* ctx) 19 | { 20 | assert(ctx->depth != 0 && "Trying to pop an empty context"); 21 | return ctx->predContext; 22 | } 23 | 24 | const DynamicContext* DynamicContext::getGlobalContext() 25 | { 26 | return globalCtx; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /lib/Dynamic/Analysis/DynamicPointerAnalysis.cpp: -------------------------------------------------------------------------------- 1 | #include "Dynamic/Analysis/DynamicContext.h" 2 | #include "Dynamic/Analysis/DynamicPointerAnalysis.h" 3 | 4 | #include 5 | 6 | namespace dynamic 7 | { 8 | 9 | DynamicPointerAnalysis::DynamicPointerAnalysis(const char* fileName): LogProcessor(fileName), currCtx(DynamicContext::getGlobalContext()), callerId(0) {} 10 | 11 | void DynamicPointerAnalysis::setPointsTo(const DynamicPointer& ptr, const DynamicMemoryObject& obj) 12 | { 13 | auto itr = ptsMap.find(ptr); 14 | if (itr == ptsMap.end()) 15 | ptsMap.insert(std::make_pair(ptr, obj)); 16 | else 17 | itr->second = obj; 18 | } 19 | 20 | void DynamicPointerAnalysis::visitAllocRecord(const AllocRecord& allocRecord) 21 | { 22 | auto ptr = DynamicPointer(currCtx, allocRecord.id); 23 | auto obj = memory.allocate(static_cast(allocRecord.type), ptr, allocRecord.address); 24 | setPointsTo(ptr, obj); 25 | } 26 | 27 | void DynamicPointerAnalysis::visitPointerRecord(const PointerRecord& ptrRecord) 28 | { 29 | auto ptr = DynamicPointer(currCtx, ptrRecord.id); 30 | auto obj = memory.getMemoryObject(ptrRecord.address); 31 | setPointsTo(ptr, obj); 32 | } 33 | 34 | void DynamicPointerAnalysis::visitEnterRecord(const EnterRecord& enterRecord) 35 | { 36 | assert(callerId != 0); 37 | currCtx = DynamicContext::pushContext(currCtx, callerId); 38 | callerId = 0; 39 | } 40 | 41 | void DynamicPointerAnalysis::visitExitRecord(const ExitRecord& exitRecord) 42 | { 43 | memory.deallocateStack(currCtx); 44 | currCtx = DynamicContext::popContext(currCtx); 45 | } 46 | 47 | void DynamicPointerAnalysis::visitCallRecord(const CallRecord& callRecord) 48 | { 49 | callerId = callRecord.id; 50 | } 51 | 52 | 53 | } -------------------------------------------------------------------------------- /lib/Dynamic/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(Analysis) 2 | add_subdirectory(Instrument) 3 | add_subdirectory(Log) 4 | add_subdirectory(Runtime) -------------------------------------------------------------------------------- /lib/Dynamic/Instrument/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (InstrumentersSourceCodes 2 | DynamicHooks.cpp 3 | FeatureCheck.cpp 4 | IDAssigner.cpp 5 | MemoryInstrument.cpp 6 | ) 7 | add_library (Instrument STATIC ${InstrumentersSourceCodes}) 8 | target_link_libraries (Instrument LLVMCore Annotation) -------------------------------------------------------------------------------- /lib/Dynamic/Instrument/FeatureCheck.cpp: -------------------------------------------------------------------------------- 1 | #include "Dynamic/Instrument/FeatureCheck.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace llvm; 8 | 9 | namespace dynamic 10 | { 11 | 12 | void FeatureCheck::issueWarning(const Value& v, const StringRef& msg) 13 | { 14 | errs().changeColor(raw_ostream::RED); 15 | errs() << v.getName() << ": " << msg << "\n"; 16 | errs().resetColor(); 17 | } 18 | 19 | void FeatureCheck::checkIndirectLibraryCall(const Function& f) 20 | { 21 | if (f.isDeclaration()) 22 | { 23 | for (auto user: f.users()) 24 | { 25 | ImmutableCallSite cs(user); 26 | if (!cs) 27 | continue; 28 | for (auto i = 0u; i < cs.arg_size(); ++i) 29 | if (cs.getArgument(i) == &f) 30 | issueWarning(f, "potential indirect external call found!"); 31 | } 32 | } 33 | } 34 | 35 | void FeatureCheck::checkArrayArgOrInst(const Function& f) 36 | { 37 | for (auto const& arg: f.args()) 38 | if (arg.getType()->isArrayTy()) 39 | issueWarning(arg, "param is an array"); 40 | 41 | for (auto const& bb: f) 42 | for (auto const& inst: bb) 43 | if (inst.getType()->isArrayTy()) 44 | issueWarning(inst, "inst is an array"); 45 | } 46 | 47 | void FeatureCheck::runOnModule(const Module& module) 48 | { 49 | for (auto const& f: module) 50 | { 51 | checkIndirectLibraryCall(f); 52 | checkArrayArgOrInst(f); 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /lib/Dynamic/Log/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (LogSourceCodes 2 | LogPrinter.cpp 3 | LogReader.cpp 4 | ) 5 | add_library (DynamicLog STATIC ${LogSourceCodes}) -------------------------------------------------------------------------------- /lib/Dynamic/Log/LogPrinter.cpp: -------------------------------------------------------------------------------- 1 | #include "Dynamic/Instrument/AllocType.h" 2 | #include "Dynamic/Log/LogPrinter.h" 3 | 4 | #include 5 | 6 | namespace dynamic 7 | { 8 | 9 | LogPrinter::LogPrinter(const char* fileName, std::ostream& o): LogProcessor(fileName), os(o) {} 10 | 11 | void LogPrinter::visitAllocRecord(const AllocRecord& allocRecord) 12 | { 13 | os << "[ALLOC] "; 14 | switch (allocRecord.type) 15 | { 16 | case AllocType::Global: 17 | os << "Global "; 18 | break; 19 | case AllocType::Stack: 20 | os << "Stack "; 21 | break; 22 | case AllocType::Heap: 23 | os << "Heap "; 24 | break; 25 | default: 26 | std::cerr << "Illegal alloc type. Log file must be broken\n"; 27 | std::exit(-1); 28 | } 29 | os << "Ptr# " << allocRecord.id << " = " << allocRecord.address << '\n'; 30 | } 31 | 32 | void LogPrinter::visitPointerRecord(const PointerRecord& ptrRecord) 33 | { 34 | os << "[POINTER] Ptr# " << ptrRecord.id << " = " << ptrRecord.address << '\n'; 35 | } 36 | 37 | void LogPrinter::visitEnterRecord(const EnterRecord& enterRecord) 38 | { 39 | os << "[ENTER] Function# " << enterRecord.id << '\n'; 40 | } 41 | 42 | void LogPrinter::visitExitRecord(const ExitRecord& exitRecord) 43 | { 44 | os << "[EXIT] Function# " << exitRecord.id << '\n'; 45 | } 46 | 47 | void LogPrinter::visitCallRecord(const CallRecord& callRecord) 48 | { 49 | os << "[CALL] Inst# " << callRecord.id << '\n'; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /lib/Dynamic/Runtime/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (DynamicRuntimeSourceCodes 2 | MemoryHooks.c 3 | ) 4 | 5 | add_library (DynamicRuntime STATIC ${DynamicRuntimeSourceCodes}) -------------------------------------------------------------------------------- /lib/PointerAnalysis/Analysis/SemiSparsePointerAnalysis.cpp: -------------------------------------------------------------------------------- 1 | #include "PointerAnalysis/Analysis/GlobalPointerAnalysis.h" 2 | #include "PointerAnalysis/Analysis/SemiSparsePointerAnalysis.h" 3 | #include "PointerAnalysis/Engine/GlobalState.h" 4 | #include "PointerAnalysis/Engine/Initializer.h" 5 | #include "PointerAnalysis/Engine/SemiSparsePropagator.h" 6 | #include "PointerAnalysis/Engine/TransferFunction.h" 7 | #include "PointerAnalysis/Program/SemiSparseProgram.h" 8 | #include "Util/AnalysisEngine/DataFlowAnalysis.h" 9 | 10 | namespace tpa 11 | { 12 | 13 | void SemiSparsePointerAnalysis::runOnProgram(const SemiSparseProgram& ssProg) 14 | { 15 | auto initStore = Store(); 16 | std::tie(env, initStore) = GlobalPointerAnalysis(ptrManager, memManager, ssProg.getTypeMap()).runOnModule(ssProg.getModule()); 17 | 18 | auto globalState = GlobalState(ptrManager, memManager, ssProg, extTable, env); 19 | auto dfa = util::DataFlowAnalysis(globalState, memo); 20 | dfa.runOnInitialState(std::move(initStore)); 21 | } 22 | 23 | PtsSet SemiSparsePointerAnalysis::getPtsSetImpl(const Pointer* ptr) const 24 | { 25 | return env.lookup(ptr); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /lib/PointerAnalysis/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set (PointerAnalysisSourceCodes 3 | Analysis/GlobalPointerAnalysis.cpp 4 | Analysis/SemiSparsePointerAnalysis.cpp 5 | Context/AdaptiveContext.cpp 6 | Context/Context.cpp 7 | Context/KLimitContext.cpp 8 | Engine/ExternalCallAnalysis.cpp 9 | Engine/Initializer.cpp 10 | Engine/SemiSparsePropagator.cpp 11 | Engine/StorePruner.cpp 12 | Engine/TransferFunction.cpp 13 | Engine/Transfer/AllocTransfer.cpp 14 | Engine/Transfer/CallTransfer.cpp 15 | Engine/Transfer/CopyTransfer.cpp 16 | Engine/Transfer/EntryTransfer.cpp 17 | Engine/Transfer/LoadTransfer.cpp 18 | Engine/Transfer/OffsetTransfer.cpp 19 | Engine/Transfer/ReturnTransfer.cpp 20 | Engine/Transfer/StoreTransfer.cpp 21 | FrontEnd/ArrayLayoutAnalysis.cpp 22 | FrontEnd/CFGBuilder.cpp 23 | FrontEnd/CFGSimplifier.cpp 24 | FrontEnd/FunctionTranslator.cpp 25 | FrontEnd/InstructionTranslator.cpp 26 | FrontEnd/PointerLayoutAnalysis.cpp 27 | FrontEnd/PriorityAssigner.cpp 28 | FrontEnd/SemiSparseProgramBuilder.cpp 29 | FrontEnd/StructCastAnalysis.cpp 30 | FrontEnd/TypeAnalysis.cpp 31 | FrontEnd/TypeCollector.cpp 32 | MemoryModel/ArrayLayout.cpp 33 | MemoryModel/MemoryManager.cpp 34 | MemoryModel/PointerLayout.cpp 35 | MemoryModel/PointerManager.cpp 36 | MemoryModel/TypeLayout.cpp 37 | Output/CFGNodePrinter.cpp 38 | Output/ContextPrinter.cpp 39 | Output/MemoryPrinter.cpp 40 | Output/NodePrinter.cpp 41 | Output/WriteDotFile.cpp 42 | Precision/PrecisionLossTracker.cpp 43 | Precision/ValueDependenceTracker.cpp 44 | Program/CFG.cpp 45 | Program/SemiSparseProgram.cpp 46 | Support/PtsSet.cpp 47 | StaticFields.cpp 48 | ) 49 | add_library (PointerAnalysis STATIC ${PointerAnalysisSourceCodes}) 50 | 51 | target_link_libraries (PointerAnalysis Annotation LLVMSupport LLVMCore) -------------------------------------------------------------------------------- /lib/PointerAnalysis/Context/AdaptiveContext.cpp: -------------------------------------------------------------------------------- 1 | #include "Context/AdaptiveContext.h" 2 | 3 | using namespace llvm; 4 | 5 | namespace context 6 | { 7 | 8 | void AdaptiveContext::trackCallSite(const ProgramPoint& pLoc) 9 | { 10 | trackedCallsites.insert(pLoc); 11 | } 12 | 13 | const Context* AdaptiveContext::pushContext(const Context* ctx, const llvm::Instruction* inst) 14 | { 15 | return pushContext(ProgramPoint(ctx, inst)); 16 | } 17 | 18 | const Context* AdaptiveContext::pushContext(const ProgramPoint& pp) 19 | { 20 | if (trackedCallsites.count(pp)) 21 | return Context::pushContext(pp); 22 | else 23 | return pp.getContext(); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /lib/PointerAnalysis/Context/Context.cpp: -------------------------------------------------------------------------------- 1 | #include "Context/Context.h" 2 | #include "Context/ProgramPoint.h" 3 | 4 | using namespace llvm; 5 | 6 | namespace context 7 | { 8 | 9 | const Context* Context::pushContext(const ProgramPoint& pp) 10 | { 11 | return pushContext(pp.getContext(), pp.getInstruction()); 12 | } 13 | 14 | const Context* Context::pushContext(const Context* ctx, const Instruction* inst) 15 | { 16 | auto newCtx = Context(inst, ctx); 17 | auto itr = ctxSet.insert(newCtx).first; 18 | return &(*itr); 19 | } 20 | 21 | const Context* Context::popContext(const Context* ctx) 22 | { 23 | assert(ctx->sz != 0 && "Trying to pop an empty context"); 24 | return ctx->predContext; 25 | } 26 | 27 | const Context* Context::getGlobalContext() 28 | { 29 | auto itr = ctxSet.insert(Context()).first; 30 | return &(*itr); 31 | } 32 | 33 | std::vector Context::getAllContexts() 34 | { 35 | std::vector ret; 36 | ret.reserve(ctxSet.size()); 37 | 38 | for (auto const& ctx: ctxSet) 39 | ret.push_back(&ctx); 40 | 41 | return ret; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /lib/PointerAnalysis/Context/KLimitContext.cpp: -------------------------------------------------------------------------------- 1 | #include "Context/KLimitContext.h" 2 | #include "Context/ProgramPoint.h" 3 | 4 | using namespace llvm; 5 | 6 | namespace context 7 | { 8 | 9 | const Context* KLimitContext::pushContext(const ProgramPoint& pp) 10 | { 11 | return pushContext(pp.getContext(), pp.getInstruction()); 12 | } 13 | 14 | const Context* KLimitContext::pushContext(const Context* ctx, const Instruction* inst) 15 | { 16 | size_t k = defaultLimit; 17 | 18 | assert(ctx->size() <= k); 19 | if (ctx->size() == k) 20 | return ctx; 21 | else 22 | return Context::pushContext(ctx, inst); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /lib/PointerAnalysis/Engine/Initializer.cpp: -------------------------------------------------------------------------------- 1 | #include "Context/Context.h" 2 | #include "PointerAnalysis/Engine/GlobalState.h" 3 | #include "PointerAnalysis/Engine/Initializer.h" 4 | #include "PointerAnalysis/MemoryModel/MemoryManager.h" 5 | #include "PointerAnalysis/MemoryModel/PointerManager.h" 6 | #include "PointerAnalysis/Program/SemiSparseProgram.h" 7 | #include "PointerAnalysis/Support/Memo.h" 8 | 9 | namespace tpa 10 | { 11 | 12 | ForwardWorkList Initializer::runOnInitState(Store&& initStore) 13 | { 14 | ForwardWorkList workList; 15 | 16 | auto entryCtx = context::Context::getGlobalContext(); 17 | auto entryCFG = globalState.getSemiSparseProgram().getEntryCFG(); 18 | assert(entryCFG != nullptr); 19 | auto entryNode = entryCFG->getEntryNode(); 20 | 21 | // Set up argv 22 | auto& entryFunc = entryCFG->getFunction(); 23 | if (entryFunc.arg_size() > 1) 24 | { 25 | auto argvValue = ++entryFunc.arg_begin(); 26 | auto argvPtr = globalState.getPointerManager().getOrCreatePointer(entryCtx, argvValue); 27 | auto argvObj = globalState.getMemoryManager().allocateArgv(argvValue); 28 | globalState.getEnv().insert(argvPtr, argvObj); 29 | initStore.insert(argvObj, argvObj); 30 | 31 | if (entryFunc.arg_size() > 2) 32 | { 33 | auto envpValue = ++argvValue; 34 | auto envpPtr = globalState.getPointerManager().getOrCreatePointer(entryCtx, envpValue); 35 | auto envpObj = globalState.getMemoryManager().allocateEnvp(envpValue); 36 | globalState.getEnv().insert(envpPtr, envpObj); 37 | initStore.insert(envpObj, envpObj); 38 | } 39 | } 40 | 41 | auto pp = ProgramPoint(entryCtx, entryNode); 42 | memo.update(pp, std::move(initStore)); 43 | workList.enqueue(pp); 44 | 45 | return workList; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /lib/PointerAnalysis/Engine/Transfer/AllocTransfer.cpp: -------------------------------------------------------------------------------- 1 | #include "PointerAnalysis/Engine/GlobalState.h" 2 | #include "PointerAnalysis/Engine/TransferFunction.h" 3 | #include "PointerAnalysis/MemoryModel/MemoryManager.h" 4 | #include "PointerAnalysis/MemoryModel/PointerManager.h" 5 | 6 | namespace tpa 7 | { 8 | 9 | bool TransferFunction::evalMemoryAllocation(const context::Context* ctx, const llvm::Instruction* inst, const TypeLayout* type, bool isHeap) 10 | { 11 | auto ptr = globalState.getPointerManager().getOrCreatePointer(ctx, inst); 12 | 13 | auto mem = 14 | isHeap? 15 | globalState.getMemoryManager().allocateHeapMemory(ctx, inst, type) : 16 | globalState.getMemoryManager().allocateStackMemory(ctx, inst, type); 17 | 18 | return globalState.getEnv().strongUpdate(ptr, PtsSet::getSingletonSet(mem)); 19 | } 20 | 21 | void TransferFunction::evalAllocNode(const ProgramPoint& pp, EvalResult& evalResult) 22 | { 23 | auto allocNode = static_cast(pp.getCFGNode()); 24 | auto envChanged = evalMemoryAllocation(pp.getContext(), allocNode->getDest(), allocNode->getAllocTypeLayout(), false); 25 | 26 | if (envChanged) 27 | addTopLevelSuccessors(pp, evalResult); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /lib/PointerAnalysis/Engine/Transfer/CopyTransfer.cpp: -------------------------------------------------------------------------------- 1 | #include "PointerAnalysis/Engine/GlobalState.h" 2 | #include "PointerAnalysis/Engine/TransferFunction.h" 3 | #include "PointerAnalysis/MemoryModel/MemoryManager.h" 4 | #include "PointerAnalysis/MemoryModel/PointerManager.h" 5 | 6 | namespace tpa 7 | { 8 | 9 | void TransferFunction::evalCopyNode(const ProgramPoint& pp, EvalResult& evalResult) 10 | { 11 | auto ctx = pp.getContext(); 12 | auto const& copyNode = static_cast(*pp.getCFGNode()); 13 | 14 | std::vector srcPtsSets; 15 | srcPtsSets.reserve(copyNode.getNumSrc()); 16 | 17 | auto& ptrManager = globalState.getPointerManager(); 18 | auto& env = globalState.getEnv(); 19 | for (auto src: copyNode) 20 | { 21 | auto srcPtr = ptrManager.getPointer(ctx, src); 22 | 23 | // This must happen in a PHI node, where one operand must be defined after the CopyNode itself. We need to proceed because the operand may depend on the rhs of this CopyNode and if we give up here, the analysis will reach an immature fixpoint 24 | if (srcPtr == nullptr) 25 | continue; 26 | 27 | auto pSet = env.lookup(srcPtr); 28 | if (pSet.empty()) 29 | // Operand not ready 30 | return; 31 | 32 | srcPtsSets.emplace_back(pSet); 33 | } 34 | 35 | auto dstPtr = ptrManager.getOrCreatePointer(ctx, copyNode.getDest()); 36 | auto dstSet = PtsSet::mergeAll(srcPtsSets); 37 | auto envChanged = globalState.getEnv().strongUpdate(dstPtr, dstSet); 38 | 39 | if (envChanged) 40 | addTopLevelSuccessors(pp, evalResult); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /lib/PointerAnalysis/Engine/Transfer/EntryTransfer.cpp: -------------------------------------------------------------------------------- 1 | #include "PointerAnalysis/Engine/GlobalState.h" 2 | #include "PointerAnalysis/Engine/TransferFunction.h" 3 | #include "PointerAnalysis/Program/CFG/CFG.h" 4 | 5 | namespace tpa 6 | { 7 | 8 | void TransferFunction::evalEntryNode(const ProgramPoint& pp, EvalResult& evalResult) 9 | { 10 | assert(localState != nullptr); 11 | 12 | addTopLevelSuccessors(pp, evalResult); 13 | addMemLevelSuccessors(pp, *localState, evalResult); 14 | 15 | // To prevent the analysis to converge before a newly added return edge is processed, we need to force the analysis to check the return targets whenever a function is entered 16 | auto& cfg = pp.getCFGNode()->getCFG(); 17 | if (!cfg.doesNotReturn()) 18 | evalResult.addTopLevelProgramPoint(ProgramPoint(pp.getContext(), cfg.getExitNode())); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /lib/PointerAnalysis/FrontEnd/CFGBuilder.cpp: -------------------------------------------------------------------------------- 1 | #include "PointerAnalysis/FrontEnd/CFG/CFGBuilder.h" 2 | #include "PointerAnalysis/FrontEnd/CFG/CFGSimplifier.h" 3 | #include "PointerAnalysis/FrontEnd/CFG/FunctionTranslator.h" 4 | #include "PointerAnalysis/FrontEnd/CFG/InstructionTranslator.h" 5 | #include "PointerAnalysis/Program/CFG/CFG.h" 6 | 7 | #include 8 | 9 | using namespace llvm; 10 | 11 | namespace tpa 12 | { 13 | 14 | CFGBuilder::CFGBuilder(CFG& c, const TypeMap& t): cfg(c), typeMap(t) 15 | { 16 | 17 | } 18 | 19 | void CFGBuilder::buildCFG(const Function& llvmFunc) 20 | { 21 | auto dataLayout = DataLayout(llvmFunc.getParent()); 22 | auto instTranslator = InstructionTranslator(cfg, typeMap, dataLayout); 23 | FunctionTranslator(cfg, instTranslator).translateFunction(llvmFunc); 24 | CFGSimplifier().simplify(cfg); 25 | cfg.buildValueMap(); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /lib/PointerAnalysis/FrontEnd/PriorityAssigner.cpp: -------------------------------------------------------------------------------- 1 | #include "PointerAnalysis/FrontEnd/CFG/PriorityAssigner.h" 2 | #include "PointerAnalysis/Program/CFG/CFG.h" 3 | 4 | namespace tpa 5 | { 6 | 7 | void PriorityAssigner::traverse() 8 | { 9 | currLabel = 1; 10 | for (auto node: cfg) 11 | if (node->getPriority() == 0u) 12 | visitNode(node); 13 | } 14 | 15 | void PriorityAssigner::visitNode(tpa::CFGNode* node) 16 | { 17 | if (!visitedNodes.insert(node).second) 18 | return; 19 | 20 | for (auto const& succ: node->succs()) 21 | visitNode(succ); 22 | 23 | node->setPriority(currLabel); 24 | ++currLabel; 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /lib/PointerAnalysis/FrontEnd/SemiSparseProgramBuilder.cpp: -------------------------------------------------------------------------------- 1 | #include "PointerAnalysis/FrontEnd/CFG/CFGBuilder.h" 2 | #include "PointerAnalysis/FrontEnd/SemiSparseProgramBuilder.h" 3 | #include "PointerAnalysis/FrontEnd/Type/TypeAnalysis.h" 4 | 5 | #include 6 | 7 | using namespace llvm; 8 | 9 | namespace tpa 10 | { 11 | 12 | void SemiSparseProgramBuilder::buildCFGForFunction(SemiSparseProgram& ssProg, const Function& f, const TypeMap& typeMap) 13 | { 14 | auto& cfg = ssProg.getOrCreateCFGForFunction(f); 15 | CFGBuilder(cfg, typeMap).buildCFG(f); 16 | } 17 | 18 | SemiSparseProgram SemiSparseProgramBuilder::runOnModule(const Module& module) 19 | { 20 | SemiSparseProgram ssProg(module); 21 | 22 | // Process types 23 | auto typeMap = TypeAnalysis().runOnModule(module); 24 | 25 | // Translate functions to CFG 26 | for (auto const& f: module) 27 | { 28 | if (f.isDeclaration()) 29 | continue; 30 | 31 | buildCFGForFunction(ssProg, f, typeMap); 32 | } 33 | 34 | ssProg.setTypeMap(std::move(typeMap)); 35 | return ssProg; 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /lib/PointerAnalysis/MemoryModel/PointerLayout.cpp: -------------------------------------------------------------------------------- 1 | #include "PointerAnalysis/MemoryModel/Type/PointerLayout.h" 2 | 3 | namespace tpa 4 | { 5 | 6 | const PointerLayout* PointerLayout::getEmptyLayout() 7 | { 8 | return emptyLayout; 9 | } 10 | 11 | const PointerLayout* PointerLayout::getSinglePointerLayout() 12 | { 13 | return singlePointerLayout; 14 | } 15 | 16 | const PointerLayout* PointerLayout::getLayout(SetType&& set) 17 | { 18 | auto itr = layoutSet.insert(PointerLayout(std::move(set))).first; 19 | return &(*itr); 20 | } 21 | 22 | const PointerLayout* PointerLayout::getLayout(std::initializer_list ilist) 23 | { 24 | SetType set(ilist); 25 | return getLayout(std::move(set)); 26 | } 27 | 28 | const PointerLayout* PointerLayout::merge(const PointerLayout* lhs, const PointerLayout* rhs) 29 | { 30 | assert(lhs != nullptr && rhs != nullptr); 31 | 32 | if (lhs == rhs) 33 | return lhs; 34 | if (lhs->empty()) 35 | return rhs; 36 | if (rhs->empty()) 37 | return lhs; 38 | 39 | SetType newSet(lhs->validOffsets); 40 | newSet.merge(rhs->validOffsets); 41 | return getLayout(std::move(newSet)); 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /lib/PointerAnalysis/Output/CFGNodePrinter.cpp: -------------------------------------------------------------------------------- 1 | #include "PointerAnalysis/Program/CFG/CFGNode.h" 2 | #include "PointerAnalysis/Support/FunctionContext.h" 3 | #include "PointerAnalysis/Support/ProgramPoint.h" 4 | #include "Util/IO/PointerAnalysis/Printer.h" 5 | #include "Util/IO/PointerAnalysis/NodePrinter.h" 6 | 7 | #include 8 | 9 | namespace util 10 | { 11 | namespace io 12 | { 13 | 14 | llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const tpa::CFGNode& node) 15 | { 16 | NodePrinter(os).visit(node); 17 | return os; 18 | } 19 | 20 | llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const tpa::ProgramPoint& pp) 21 | { 22 | os << "(" << *pp.getContext() << ", " << *pp.getCFGNode() << ")"; 23 | return os; 24 | } 25 | 26 | llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const tpa::FunctionContext& fc) 27 | { 28 | os << "(" << *fc.getContext() << ", " << fc.getFunction()->getName() << ")"; 29 | return os; 30 | } 31 | 32 | } 33 | } -------------------------------------------------------------------------------- /lib/PointerAnalysis/Output/ContextPrinter.cpp: -------------------------------------------------------------------------------- 1 | #include "Context/Context.h" 2 | #include "Context/ProgramPoint.h" 3 | #include "Util/IO/Context/Printer.h" 4 | 5 | #include 6 | 7 | namespace util 8 | { 9 | namespace io 10 | { 11 | 12 | llvm::raw_ostream& operator<< (llvm::raw_ostream& os, const context::Context& ctx) 13 | { 14 | if (ctx.isGlobalContext()) 15 | os << "[GLOBAL]"; 16 | else 17 | os << "[CTX(" << ctx.size() << ") " << &ctx << "]"; 18 | return os; 19 | } 20 | 21 | llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const context::ProgramPoint& p) 22 | { 23 | os << "(" << *p.getContext() << ", " << *p.getInstruction() << ")"; 24 | return os; 25 | } 26 | 27 | } 28 | } -------------------------------------------------------------------------------- /lib/PointerAnalysis/Output/WriteDotFile.cpp: -------------------------------------------------------------------------------- 1 | #include "PointerAnalysis/Program/CFG/CFG.h" 2 | #include "Util/IO/PointerAnalysis/Printer.h" 3 | #include "Util/IO/PointerAnalysis/WriteDotFile.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace llvm; 11 | 12 | namespace util 13 | { 14 | namespace io 15 | { 16 | 17 | static void writeCFG(raw_ostream& os, const tpa::CFG& cfg) 18 | { 19 | os << "digraph \"" << "PointerCFG with def-use edges for function " << cfg.getFunction().getName() << "\" {\n"; 20 | 21 | for (auto node: cfg) 22 | { 23 | os << "\tNode" << node << " [shape=record,"; 24 | os << "label=\"" << *node << "\"]\n"; 25 | for (auto succ: node->succs()) 26 | os << "\tNode" << node << " -> " << "Node" << succ << "\n"; 27 | for (auto succ: node->uses()) 28 | os << "\tNode" << node << " -> " << "Node" << succ << " [style=dotted]\n"; 29 | } 30 | os << "}\n"; 31 | } 32 | 33 | void writeDotFile(const char* filePath, const tpa::CFG& cfg) 34 | { 35 | std::error_code ec; 36 | tool_output_file out(filePath, ec, sys::fs::F_None); 37 | if (ec) 38 | { 39 | errs() << "Failed to open file " << filePath << ": " << ec.message() << "\n"; 40 | return; 41 | } 42 | 43 | writeCFG(out.os(), cfg); 44 | 45 | out.keep(); 46 | } 47 | 48 | } 49 | } -------------------------------------------------------------------------------- /lib/PointerAnalysis/Program/SemiSparseProgram.cpp: -------------------------------------------------------------------------------- 1 | #include "PointerAnalysis/Program/SemiSparseProgram.h" 2 | 3 | #include 4 | 5 | using namespace llvm; 6 | 7 | namespace tpa 8 | { 9 | 10 | SemiSparseProgram::SemiSparseProgram(const llvm::Module& m): module(m) 11 | { 12 | for (auto const& f: module) 13 | { 14 | if (f.hasAddressTaken()) 15 | addrTakenFuncList.push_back(&f); 16 | } 17 | } 18 | 19 | CFG& SemiSparseProgram::getOrCreateCFGForFunction(const llvm::Function& f) 20 | { 21 | auto itr = cfgMap.find(&f); 22 | if (itr == cfgMap.end()) 23 | itr = cfgMap.emplace(&f, f).first; 24 | return itr->second; 25 | } 26 | const CFG* SemiSparseProgram::getCFGForFunction(const llvm::Function& f) const 27 | { 28 | auto itr = cfgMap.find(&f); 29 | if (itr == cfgMap.end()) 30 | return nullptr; 31 | else 32 | return &itr->second; 33 | } 34 | const CFG* SemiSparseProgram::getEntryCFG() const 35 | { 36 | auto mainFunc = module.getFunction("main"); 37 | assert(mainFunc != nullptr && "Cannot find main function!"); 38 | return getCFGForFunction(*mainFunc); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /lib/TaintAnalysis/Analysis/TrackingTaintAnalysis.cpp: -------------------------------------------------------------------------------- 1 | #include "TaintAnalysis/Analysis/TrackingTaintAnalysis.h" 2 | #include "TaintAnalysis/Engine/Initializer.h" 3 | #include "TaintAnalysis/Engine/SinkViolationChecker.h" 4 | #include "TaintAnalysis/Engine/TaintPropagator.h" 5 | #include "TaintAnalysis/Engine/TaintGlobalState.h" 6 | #include "TaintAnalysis/Engine/TransferFunction.h" 7 | #include "TaintAnalysis/Precision/PrecisionLossTracker.h" 8 | #include "Util/AnalysisEngine/DataFlowAnalysis.h" 9 | 10 | namespace taint 11 | { 12 | 13 | std::pair TrackingTaintAnalysis::runOnDefUseModule(const DefUseModule& duModule) 14 | { 15 | auto globalState = TaintGlobalState(duModule, ptrAnalysis, extTable, env, memo); 16 | auto dfa = util::DataFlowAnalysis(globalState, memo); 17 | dfa.runOnInitialState(TaintStore()); 18 | 19 | auto violationRecord = SinkViolationChecker(env, memo, extTable, ptrAnalysis).checkSinkViolation(globalState.getSinks()); 20 | 21 | PrecisionLossTracker tracker(globalState); 22 | return std::make_pair(violationRecord.empty(), tracker.trackImprecision(violationRecord)); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /lib/TaintAnalysis/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set (TaintAnalysisSourceCodes 3 | Analysis/TrackingTaintAnalysis.cpp 4 | Analysis/TaintAnalysis.cpp 5 | Engine/ExternalCallAnalysis.cpp 6 | Engine/Initializer.cpp 7 | Engine/SinkViolationChecker.cpp 8 | Engine/TaintPropagator.cpp 9 | Engine/TransferFunction.cpp 10 | FrontEnd/DefUseModuleBuilder.cpp 11 | FrontEnd/ModRefModuleAnalysis.cpp 12 | FrontEnd/ReachingDefModuleAnalysis.cpp 13 | Output/TaintPrinter.cpp 14 | Output/WriteDotFile.cpp 15 | Precision/CallTracker.cpp 16 | Precision/PrecisionLossTracker.cpp 17 | Precision/ReturnTracker.cpp 18 | Precision/TrackerTransferFunction.cpp 19 | Program/DefUseModule.cpp 20 | ) 21 | add_library (TaintAnalysis STATIC ${TaintAnalysisSourceCodes}) 22 | 23 | target_link_libraries (TaintAnalysis PointerAnalysis) -------------------------------------------------------------------------------- /lib/TaintAnalysis/Engine/TaintPropagator.cpp: -------------------------------------------------------------------------------- 1 | #include "TaintAnalysis/Engine/EvalResult.h" 2 | #include "TaintAnalysis/Engine/TaintPropagator.h" 3 | #include "TaintAnalysis/Engine/WorkList.h" 4 | #include "TaintAnalysis/Support/TaintMemo.h" 5 | 6 | #include "Util/IO/TaintAnalysis/Printer.h" 7 | #include 8 | using namespace util::io; 9 | 10 | namespace taint 11 | { 12 | 13 | void TaintPropagator::enqueueIfMemoChange(const ProgramPoint& pp, const tpa::MemoryObject* obj, const TaintStore& store) 14 | { 15 | auto objVal = store.lookup(obj); 16 | if (objVal == TaintLattice::Unknown) 17 | return; 18 | if (memo.insert(pp, obj, objVal)) 19 | { 20 | //llvm::errs() << "\tenqueue mem " << pp << "\n"; 21 | workList.enqueue(pp); 22 | } 23 | } 24 | 25 | void TaintPropagator::propagate(const EvalResult& evalResult) 26 | { 27 | auto const& store = evalResult.getStore(); 28 | for (auto succ: evalResult) 29 | { 30 | if (succ.isTopLevel()) 31 | workList.enqueue(succ.getProgramPoint()); 32 | else 33 | enqueueIfMemoChange(succ.getProgramPoint(), succ.getMemoryObject(), store); 34 | } 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /lib/TaintAnalysis/Output/TaintPrinter.cpp: -------------------------------------------------------------------------------- 1 | #include "TaintAnalysis/Program/DefUseInstruction.h" 2 | #include "TaintAnalysis/Support/ProgramPoint.h" 3 | #include "Util/IO/TaintAnalysis/Printer.h" 4 | 5 | #include 6 | #include 7 | 8 | using namespace taint; 9 | 10 | namespace util 11 | { 12 | namespace io 13 | { 14 | 15 | llvm::raw_ostream& operator<< (llvm::raw_ostream& os, TaintLattice l) 16 | { 17 | switch (l) 18 | { 19 | case TaintLattice::Unknown: 20 | os << "Unknown"; 21 | break; 22 | case TaintLattice::Untainted: 23 | os << "Untainted"; 24 | break; 25 | case TaintLattice::Tainted: 26 | os << "Tainted"; 27 | break; 28 | case TaintLattice::Either: 29 | os << "Either"; 30 | break; 31 | } 32 | return os; 33 | } 34 | 35 | llvm::raw_ostream& operator<< (llvm::raw_ostream& os, const taint::DefUseInstruction& duInst) 36 | { 37 | if (duInst.isEntryInstruction()) 38 | os << "[entry duInst for " << duInst.getFunction()->getName() << "]"; 39 | else 40 | os << "[" << duInst.getFunction()->getName() << *duInst.getInstruction() << "]"; 41 | return os; 42 | } 43 | 44 | llvm::raw_ostream& operator<< (llvm::raw_ostream& os, const taint::ProgramPoint& pp) 45 | { 46 | os << "(" << *pp.getContext() << ", " << *pp.getDefUseInstruction() << ")"; 47 | return os; 48 | } 49 | 50 | } 51 | } -------------------------------------------------------------------------------- /lib/Transforms/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${tpa_SOURCE_DIR}/include/Transforms) 2 | 3 | set (TransformSourceCodes 4 | ExpandByVal.cpp 5 | ExpandConstantExpr.cpp 6 | ExpandGetElementPtr.cpp 7 | ExpandIndirectBr.cpp 8 | ExpandUtils.cpp 9 | FoldIntToPtr.cpp 10 | GlobalCleanup.cpp 11 | LowerGlobalCtor.cpp 12 | RunPrepass.cpp 13 | ) 14 | 15 | add_library (Transforms STATIC ${TransformSourceCodes}) 16 | target_link_libraries (Transforms LLVMTransformUtils LLVMipo LLVMSupport LLVMCore) 17 | -------------------------------------------------------------------------------- /lib/Transforms/FoldIntToPtr.cpp: -------------------------------------------------------------------------------- 1 | #include "Transforms/FoldIntToPtr.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace llvm; 8 | using namespace llvm::PatternMatch; 9 | 10 | namespace transform 11 | { 12 | 13 | static bool foldInstruction(IntToPtrInst* inst) 14 | { 15 | auto op = inst->getOperand(0)->stripPointerCasts(); 16 | 17 | // Pointer copy: Y = inttoptr (ptrtoint X) 18 | Value* src = nullptr; 19 | if (match(op, m_PtrToInt(m_Value(src)))) 20 | { 21 | inst->replaceAllUsesWith(src); 22 | inst->eraseFromParent(); 23 | return true; 24 | } 25 | 26 | // Pointer arithmetic 27 | Value* offsetValue = nullptr; 28 | if (match(op, m_Add(m_PtrToInt(m_Value(src)), m_Value(offsetValue)))) 29 | { 30 | if (src->getType() != inst->getType()) 31 | src = new BitCastInst(src, inst->getType(), "src.cast", inst); 32 | auto gepInst = GetElementPtrInst::Create(src, { ConstantInt::get(Type::getInt64Ty(inst->getContext()), 0), offsetValue}, inst->getName(), inst); 33 | inst->replaceAllUsesWith(gepInst); 34 | inst->eraseFromParent(); 35 | return true; 36 | } 37 | 38 | return false; 39 | } 40 | 41 | bool FoldIntToPtrPass::runOnBasicBlock(BasicBlock& bb) 42 | { 43 | bool modified = false; 44 | for (auto itr = bb.begin(); itr != bb.end(); ) 45 | { 46 | auto inst = itr++; 47 | if (auto itpInst = dyn_cast(inst)) 48 | modified |= foldInstruction(itpInst); 49 | } 50 | return modified; 51 | } 52 | 53 | char FoldIntToPtrPass::ID = 0; 54 | static RegisterPass X("fold-inttoptr", "Turn ptrtoint+arithmetic+inttoptr into gep", false, false); 55 | 56 | } 57 | -------------------------------------------------------------------------------- /lib/Util/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (UtilCodes 2 | CommandLine/CommandLineParser.cpp 3 | CommandLine/TypedCommandLineParser.cpp 4 | IO/ReadIR.cpp 5 | IO/WriteIR.cpp 6 | ) 7 | 8 | add_library (Util STATIC ${UtilCodes}) 9 | target_link_libraries (Util LLVMIRReader LLVMAsmParser LLVMBitWriter LLVMSupport LLVMCore) -------------------------------------------------------------------------------- /lib/Util/IO/ReadIR.cpp: -------------------------------------------------------------------------------- 1 | #include "Util/IO/ReadIR.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace llvm; 12 | 13 | namespace util 14 | { 15 | namespace io 16 | { 17 | 18 | std::unique_ptr readModuleFromFile(const char* fileName) 19 | { 20 | SMDiagnostic error; 21 | auto module = parseIRFile(fileName, error, getGlobalContext()); 22 | 23 | auto errMsg = std::string(); 24 | llvm::raw_string_ostream os(errMsg); 25 | error.print("", os); 26 | 27 | if (!module) 28 | { 29 | // A failure here means that the test itself is buggy. 30 | report_fatal_error(os.str().c_str()); 31 | } 32 | 33 | return std::move(module); 34 | } 35 | 36 | std::unique_ptr parseAssembly(const char *assembly) 37 | { 38 | SMDiagnostic error; 39 | auto module = parseAssemblyString(assembly, error, getGlobalContext()); 40 | 41 | auto errMsg = std::string(); 42 | llvm::raw_string_ostream os(errMsg); 43 | error.print("", os); 44 | 45 | if (!module) 46 | { 47 | // A failure here means that the test itself is buggy. 48 | report_fatal_error(os.str().c_str()); 49 | } 50 | 51 | return std::move(module); 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /lib/Util/IO/WriteIR.cpp: -------------------------------------------------------------------------------- 1 | #include "Util/IO/WriteIR.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace llvm; 9 | 10 | namespace util 11 | { 12 | namespace io 13 | { 14 | 15 | void writeModuleToText(const Module& module, const char* fileName) 16 | { 17 | std::error_code ec; 18 | tool_output_file out(fileName, ec, sys::fs::F_None); 19 | if (ec) 20 | { 21 | errs() << ec.message() << "\n"; 22 | std::exit(-3); 23 | } 24 | 25 | module.print(out.os(), nullptr); 26 | 27 | out.keep(); 28 | } 29 | 30 | void writeModuleToBitCode(const Module& module, const char* fileName) 31 | { 32 | std::error_code ec; 33 | tool_output_file out(fileName, ec, sys::fs::F_None); 34 | if (ec) 35 | { 36 | errs() << ec.message() << "\n"; 37 | std::exit(-3); 38 | } 39 | 40 | createBitcodeWriterPass(out.os())->runOnModule(const_cast(module)); 41 | 42 | out.keep(); 43 | } 44 | 45 | void writeModuleToFile(const Module& module, const char* fileName, bool isText) 46 | { 47 | if (isText) 48 | writeModuleToText(module, fileName); 49 | else 50 | writeModuleToBitCode(module, fileName); 51 | } 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tool/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${tpa_SOURCE_DIR}/include) 2 | 3 | add_subdirectory (global-pts) 4 | add_subdirectory (dot-pointer-cfg) 5 | add_subdirectory (pts-dump) 6 | add_subdirectory (table) 7 | add_subdirectory (table-check) 8 | add_subdirectory (pts-inst) 9 | add_subdirectory (pts-log-dump) 10 | add_subdirectory (pts-verify) 11 | add_subdirectory (dot-du-module) 12 | add_subdirectory (taint-check) 13 | add_subdirectory (vkcfa-taint) 14 | add_subdirectory (scripts) -------------------------------------------------------------------------------- /tool/dot-du-module/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${PROJECT_SOURCE_DIR}/tool/dot-du-module) 2 | 3 | set (dotDefUseModuleCode 4 | CommandLineOptions.cpp 5 | dot-du-module.cpp 6 | RunAnalysis.cpp 7 | ) 8 | 9 | add_executable (dot-du-module ${dotDefUseModuleCode}) 10 | target_link_libraries (dot-du-module Util Transforms TaintAnalysis) -------------------------------------------------------------------------------- /tool/dot-du-module/CommandLineOptions.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "Util/CommandLine/TypedCommandLineParser.h" 3 | 4 | using namespace util; 5 | 6 | CommandLineOptions::CommandLineOptions(int argc, char** argv): outputDirName("dot/"), ptrConfigFileName("ptr.config"), modRefConfigFileName("modref.config"), dryRunFlag(false), noPrepassFlag(false), k(0) 7 | { 8 | TypedCommandLineParser cmdParser("Pointer CFG to .dot drawer"); 9 | cmdParser.addStringPositionalFlag("inputFile", "Input LLVM bitcode file name", inputFileName); 10 | cmdParser.addStringOptionalFlag("o", "Output directory name (default: dot/)", outputDirName); 11 | cmdParser.addStringOptionalFlag("ptr-config", "Annotation file for external library points-to analysis (default = /ptr.config)", ptrConfigFileName); 12 | cmdParser.addStringOptionalFlag("modref-config", "Annotation file for external library mod/ref analysis (default = /modref.config)", modRefConfigFileName); 13 | cmdParser.addBooleanOptionalFlag("no-prepass", "Do no run IR cannonicalization before the analysis", noPrepassFlag); 14 | cmdParser.addBooleanOptionalFlag("dry-run", "Do no dump .dot file. Just run the front end", dryRunFlag); 15 | cmdParser.addUIntOptionalFlag("k", "Context sensitivity of the underlying pointer analysis", k); 16 | 17 | cmdParser.parseCommandLineOptions(argc, argv); 18 | } -------------------------------------------------------------------------------- /tool/dot-du-module/CommandLineOptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class CommandLineOptions 6 | { 7 | private: 8 | llvm::StringRef inputFileName; 9 | llvm::StringRef outputDirName; 10 | 11 | llvm::StringRef ptrConfigFileName; 12 | llvm::StringRef modRefConfigFileName; 13 | 14 | bool dryRunFlag; 15 | bool noPrepassFlag; 16 | unsigned k; 17 | public: 18 | CommandLineOptions(int argc, char** argv); 19 | 20 | const llvm::StringRef& getInputFileName() { return inputFileName; } 21 | const llvm::StringRef& getOutputDirName() const { return outputDirName; } 22 | 23 | const llvm::StringRef& getPtrConfigFileName() const { return ptrConfigFileName; } 24 | const llvm::StringRef& getModRefConfigFileName() const { return modRefConfigFileName; } 25 | 26 | bool isDryRun() const { return dryRunFlag; } 27 | bool isPrepassDisabled() const { return noPrepassFlag; } 28 | unsigned getContextSensitivity() const { return k; } 29 | }; -------------------------------------------------------------------------------- /tool/dot-du-module/RunAnalysis.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "RunAnalysis.h" 3 | 4 | #include "Context/KLimitContext.h" 5 | #include "PointerAnalysis/Analysis/SemiSparsePointerAnalysis.h" 6 | #include "PointerAnalysis/FrontEnd/SemiSparseProgramBuilder.h" 7 | #include "TaintAnalysis/FrontEnd/DefUseModuleBuilder.h" 8 | #include "Util/IO/TaintAnalysis/WriteDotFile.h" 9 | 10 | #include 11 | #include 12 | 13 | using namespace llvm; 14 | using namespace taint; 15 | using namespace tpa; 16 | 17 | void runAnalysisOnModule(const Module& module, const CommandLineOptions& opts) 18 | { 19 | SemiSparseProgramBuilder ssBuilder; 20 | auto ssProg = ssBuilder.runOnModule(module); 21 | 22 | context::KLimitContext::setLimit(opts.getContextSensitivity()); 23 | SemiSparsePointerAnalysis ptrAnalysis; 24 | ptrAnalysis.loadExternalPointerTable(opts.getPtrConfigFileName().data()); 25 | ptrAnalysis.runOnProgram(ssProg); 26 | 27 | DefUseModuleBuilder builder(ptrAnalysis); 28 | builder.loadExternalModRefTable(opts.getModRefConfigFileName().data()); 29 | auto duModule = builder.buildDefUseModule(module); 30 | 31 | for (auto const& duFunc: duModule) 32 | { 33 | auto funName = duFunc.getFunction().getName(); 34 | llvm::outs() << "Processing DefUseModule for function " << funName << "...\n"; 35 | 36 | if (!opts.isDryRun()) 37 | { 38 | auto fileName = opts.getOutputDirName() + funName + ".du_mod.dot"; 39 | llvm::outs() << "\tWriting output file " << fileName << "\n"; 40 | util::io::writeDotFile(fileName.str().data(), duFunc); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /tool/dot-du-module/RunAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm 4 | { 5 | class Module; 6 | class StringRef; 7 | } 8 | 9 | class CommandLineOptions; 10 | 11 | void runAnalysisOnModule(const llvm::Module&, const CommandLineOptions&); 12 | -------------------------------------------------------------------------------- /tool/dot-du-module/dot-du-module.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "RunAnalysis.h" 3 | 4 | #include "Transforms/RunPrepass.h" 5 | #include "Util/IO/ReadIR.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace llvm; 13 | 14 | int main(int argc, char** argv) 15 | { 16 | // Print full stack trace when crashed 17 | sys::PrintStackTraceOnErrorSignal(); 18 | PrettyStackTraceProgram X(argc, argv); 19 | 20 | // Parse command line options 21 | auto opts = CommandLineOptions(argc, argv); 22 | 23 | // Read module from file 24 | auto module = util::io::readModuleFromFile(opts.getInputFileName().data()); 25 | if (!module) 26 | { 27 | errs() << "Failed to read IR from " << opts.getInputFileName() << "\n"; 28 | std::exit(-2); 29 | } 30 | 31 | // Run prepasses to canonicalize the IR 32 | if (!opts.isPrepassDisabled()) 33 | transform::runPrepassOn(*module); 34 | 35 | // Run the analysis 36 | runAnalysisOnModule(*module, opts); 37 | 38 | return 0; 39 | } -------------------------------------------------------------------------------- /tool/dot-pointer-cfg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${PROJECT_SOURCE_DIR}/tool/dot-pointer-cfg) 2 | 3 | set (dotPointerCFGCode 4 | CommandLineOptions.cpp 5 | dot-pointer-cfg.cpp 6 | RunAnalysis.cpp 7 | ) 8 | 9 | add_executable (dot-pointer-cfg ${dotPointerCFGCode}) 10 | target_link_libraries (dot-pointer-cfg Util Transforms PointerAnalysis) -------------------------------------------------------------------------------- /tool/dot-pointer-cfg/CommandLineOptions.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "Util/CommandLine/TypedCommandLineParser.h" 3 | 4 | using namespace util; 5 | 6 | CommandLineOptions::CommandLineOptions(int argc, char** argv): outputDirName("dot/"), dryRunFlag(false), noPrepassFlag(false) 7 | { 8 | TypedCommandLineParser cmdParser("Pointer CFG to .dot drawer"); 9 | cmdParser.addStringPositionalFlag("inputFile", "Input LLVM bitcode file name", inputFileName); 10 | cmdParser.addStringOptionalFlag("o", "Output directory name (default: dot/)", outputDirName); 11 | cmdParser.addBooleanOptionalFlag("no-prepass", "Do no run IR cannonicalization before the analysis", noPrepassFlag); 12 | cmdParser.addBooleanOptionalFlag("dry-run", "Do no dump .dot file. Just run the front end", dryRunFlag); 13 | 14 | cmdParser.parseCommandLineOptions(argc, argv); 15 | } -------------------------------------------------------------------------------- /tool/dot-pointer-cfg/CommandLineOptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class CommandLineOptions 6 | { 7 | private: 8 | llvm::StringRef inputFileName; 9 | llvm::StringRef outputDirName; 10 | 11 | bool dryRunFlag; 12 | bool noPrepassFlag; 13 | public: 14 | CommandLineOptions(int argc, char** argv); 15 | 16 | const llvm::StringRef& getInputFileName() { return inputFileName; } 17 | const llvm::StringRef& getOutputDirName() const { return outputDirName; } 18 | 19 | bool isDryRun() const { return dryRunFlag; } 20 | bool isPrepassDisabled() const { return noPrepassFlag; } 21 | }; -------------------------------------------------------------------------------- /tool/dot-pointer-cfg/RunAnalysis.cpp: -------------------------------------------------------------------------------- 1 | #include "RunAnalysis.h" 2 | 3 | #include "PointerAnalysis/FrontEnd/SemiSparseProgramBuilder.h" 4 | #include "Util/IO/PointerAnalysis/WriteDotFile.h" 5 | 6 | #include 7 | #include 8 | 9 | void runAnalysisOnModule(const llvm::Module& module, const llvm::StringRef& dirName, bool writeFile) 10 | { 11 | tpa::SemiSparseProgramBuilder builder; 12 | auto ssProg = builder.runOnModule(module); 13 | 14 | for (auto const& cfg: ssProg) 15 | { 16 | auto funName = cfg.getFunction().getName(); 17 | llvm::outs() << "Processing PointerCFG for function " << funName << "...\n"; 18 | 19 | if (writeFile) 20 | { 21 | auto fileName = dirName + funName + ".dot"; 22 | llvm::outs() << "\tWriting output file " << fileName << "\n"; 23 | util::io::writeDotFile(fileName.str().data(), cfg); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /tool/dot-pointer-cfg/RunAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm 4 | { 5 | class Module; 6 | class StringRef; 7 | } 8 | 9 | void runAnalysisOnModule(const llvm::Module&, const llvm::StringRef&, bool); 10 | -------------------------------------------------------------------------------- /tool/dot-pointer-cfg/dot-pointer-cfg.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "RunAnalysis.h" 3 | 4 | #include "Transforms/RunPrepass.h" 5 | #include "Util/IO/ReadIR.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace llvm; 13 | 14 | int main(int argc, char** argv) 15 | { 16 | // Print full stack trace when crashed 17 | sys::PrintStackTraceOnErrorSignal(); 18 | PrettyStackTraceProgram X(argc, argv); 19 | 20 | // Parse command line options 21 | auto opts = CommandLineOptions(argc, argv); 22 | 23 | // Read module from file 24 | auto module = util::io::readModuleFromFile(opts.getInputFileName().data()); 25 | if (!module) 26 | { 27 | errs() << "Failed to read IR from " << opts.getInputFileName() << "\n"; 28 | std::exit(-2); 29 | } 30 | 31 | // Run prepasses to canonicalize the IR 32 | if (!opts.isPrepassDisabled()) 33 | transform::runPrepassOn(*module); 34 | 35 | // Run the analysis 36 | runAnalysisOnModule(*module, opts.getOutputDirName(), !opts.isDryRun()); 37 | 38 | return 0; 39 | } -------------------------------------------------------------------------------- /tool/global-pts/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${PROJECT_SOURCE_DIR}/tool/global-pts) 2 | 3 | set (llvmGlobalPtsSourceCode 4 | CommandLineOptions.cpp 5 | global-pts.cpp 6 | RunAnalysis.cpp 7 | ) 8 | 9 | add_executable (global-pts ${llvmGlobalPtsSourceCode}) 10 | target_link_libraries (global-pts Util Transforms PointerAnalysis) -------------------------------------------------------------------------------- /tool/global-pts/CommandLineOptions.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "Util/CommandLine/TypedCommandLineParser.h" 3 | 4 | using namespace util; 5 | 6 | CommandLineOptions::CommandLineOptions(int argc, char** argv): outputFileName(""), noPrepassFlag(false), dumpTypeFlag(false) 7 | { 8 | TypedCommandLineParser cmdParser("Global pointer analysis for LLVM IR"); 9 | cmdParser.addStringPositionalFlag("inputFile", "Input LLVM bitcode file name", inputFileName); 10 | cmdParser.addStringOptionalFlag("o", "Output LLVM bitcode file name", outputFileName); 11 | cmdParser.addBooleanOptionalFlag("no-prepass", "Do no run IR cannonicalization before the analysis", noPrepassFlag); 12 | cmdParser.addBooleanOptionalFlag("print-type", "Dump the internal type of the translated values", dumpTypeFlag); 13 | 14 | cmdParser.parseCommandLineOptions(argc, argv); 15 | } -------------------------------------------------------------------------------- /tool/global-pts/CommandLineOptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class CommandLineOptions 6 | { 7 | private: 8 | llvm::StringRef inputFileName; 9 | llvm::StringRef outputFileName; 10 | 11 | bool noPrepassFlag; 12 | bool dumpTypeFlag; 13 | public: 14 | CommandLineOptions(int argc, char** argv); 15 | 16 | const llvm::StringRef& getInputFileName() { return inputFileName; } 17 | const llvm::StringRef& getOutputFileName() const { return outputFileName; } 18 | 19 | bool isPrepassDisabled() const { return noPrepassFlag; } 20 | bool shouldPrintType() const { return dumpTypeFlag; } 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /tool/global-pts/RunAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm 4 | { 5 | class Module; 6 | } 7 | 8 | class CommandLineOptions; 9 | 10 | void runAnalysisOnModule(const llvm::Module&, const CommandLineOptions&); 11 | -------------------------------------------------------------------------------- /tool/global-pts/global-pts.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "RunAnalysis.h" 3 | 4 | #include "Transforms/RunPrepass.h" 5 | #include "Util/IO/ReadIR.h" 6 | #include "Util/IO/WriteIR.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace llvm; 14 | 15 | int main(int argc, char** argv) 16 | { 17 | // Print full stack trace when crashed 18 | sys::PrintStackTraceOnErrorSignal(); 19 | PrettyStackTraceProgram X(argc, argv); 20 | 21 | // Unsync iostream with C I/O libraries to accelerate standard iostreams 22 | std::ios::sync_with_stdio(false); 23 | 24 | // Parse command line options 25 | auto opts = CommandLineOptions(argc, argv); 26 | 27 | // Read module from file 28 | auto module = util::io::readModuleFromFile(opts.getInputFileName().data()); 29 | if (!module) 30 | { 31 | errs() << "Failed to read IR from " << opts.getInputFileName() << "\n"; 32 | std::exit(-2); 33 | } 34 | 35 | // Run prepasses to canonicalize the IR 36 | if (!opts.isPrepassDisabled()) 37 | transform::runPrepassOn(*module); 38 | 39 | // Run the analysis 40 | runAnalysisOnModule(*module, opts); 41 | 42 | // Output the IR if told to do so 43 | if (!opts.getOutputFileName().empty()) 44 | util::io::writeModuleToText(*module, opts.getOutputFileName().data()); 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /tool/pts-dump/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${PROJECT_SOURCE_DIR}/tool/pts-dump) 2 | 3 | set (ptsDumpSourceCode 4 | pts-dump.cpp 5 | CommandLineOptions.cpp 6 | RunAnalysis.cpp 7 | ) 8 | 9 | add_executable (pts-dump ${ptsDumpSourceCode}) 10 | target_link_libraries (pts-dump Util Transforms PointerAnalysis) -------------------------------------------------------------------------------- /tool/pts-dump/CommandLineOptions.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "Util/CommandLine/TypedCommandLineParser.h" 3 | 4 | using namespace util; 5 | 6 | CommandLineOptions::CommandLineOptions(int argc, char** argv): ptrConfigFileName("ptr.config"), noPrepassFlag(false), k(0) 7 | { 8 | TypedCommandLineParser cmdParser("Points-to set dumper"); 9 | cmdParser.addStringPositionalFlag("inputFile", "Input LLVM bitcode file name", inputFileName); 10 | cmdParser.addStringOptionalFlag("ptr-config", "Annotation file for external library points-to analysis (default = /ptr.config)", ptrConfigFileName); 11 | cmdParser.addUIntOptionalFlag("k", "The size limit of the stack for k-CFA", k); 12 | cmdParser.addBooleanOptionalFlag("no-prepass", "Do no run IR cannonicalization before the analysis", noPrepassFlag); 13 | 14 | cmdParser.parseCommandLineOptions(argc, argv); 15 | } -------------------------------------------------------------------------------- /tool/pts-dump/CommandLineOptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class CommandLineOptions 6 | { 7 | private: 8 | llvm::StringRef inputFileName; 9 | llvm::StringRef ptrConfigFileName; 10 | 11 | bool noPrepassFlag; 12 | unsigned k; 13 | public: 14 | CommandLineOptions(int argc, char** argv); 15 | 16 | const llvm::StringRef& getInputFileName() const { return inputFileName; } 17 | const llvm::StringRef& getPtrConfigFileName() const { return ptrConfigFileName; } 18 | 19 | bool isPrepassDisabled() const { return noPrepassFlag; } 20 | unsigned getContextSensitivity() const { return k; } 21 | }; 22 | -------------------------------------------------------------------------------- /tool/pts-dump/RunAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm 4 | { 5 | class Module; 6 | } 7 | 8 | class CommandLineOptions; 9 | 10 | void runAnalysisOnModule(const llvm::Module&, const CommandLineOptions&); -------------------------------------------------------------------------------- /tool/pts-dump/pts-dump.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "RunAnalysis.h" 3 | 4 | #include "Transforms/RunPrepass.h" 5 | #include "Util/IO/ReadIR.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace llvm; 13 | 14 | int main(int argc, char** argv) 15 | { 16 | // Print full stack trace when crashed 17 | sys::PrintStackTraceOnErrorSignal(); 18 | PrettyStackTraceProgram X(argc, argv); 19 | 20 | // Unsync iostream with C I/O libraries to accelerate standard iostreams 21 | std::ios::sync_with_stdio(false); 22 | 23 | // Parse command line options 24 | auto opts = CommandLineOptions(argc, argv); 25 | 26 | // Read module from file 27 | auto module = util::io::readModuleFromFile(opts.getInputFileName().data()); 28 | if (!module) 29 | { 30 | errs() << "Failed to read IR from " << opts.getInputFileName() << "\n"; 31 | std::exit(-2); 32 | } 33 | 34 | // Run prepasses to canonicalize the IR 35 | if (!opts.isPrepassDisabled()) 36 | transform::runPrepassOn(*module); 37 | 38 | // Run the analysis 39 | runAnalysisOnModule(*module, opts); 40 | 41 | return 0; 42 | } -------------------------------------------------------------------------------- /tool/pts-inst/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${PROJECT_SOURCE_DIR}/tool/pts-inst) 2 | 3 | set (ptsInstSourceCode 4 | pts-inst.cpp 5 | CommandLineOptions.cpp 6 | ) 7 | 8 | add_executable (pts-inst ${ptsInstSourceCode}) 9 | target_link_libraries (pts-inst Instrument Util Transforms) -------------------------------------------------------------------------------- /tool/pts-inst/CommandLineOptions.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "Util/CommandLine/TypedCommandLineParser.h" 3 | 4 | using namespace util; 5 | 6 | CommandLineOptions::CommandLineOptions(int argc, char** argv): outputFileName("-"), ptrConfigFileName("ptr.config"), noPrepassFlag(false), outputTextFlag(false) 7 | { 8 | TypedCommandLineParser cmdParser("Program instrumentation for dynamic pointer analysis"); 9 | cmdParser.addStringPositionalFlag("inputFile", "Input LLVM bitcode file name", inputFileName); 10 | cmdParser.addStringOptionalFlag("o", "Output LLVM bitcode file name", outputFileName); 11 | cmdParser.addStringOptionalFlag("ptr-config", "Annotation file for external library points-to analysis (default = /ptr.config)", ptrConfigFileName); 12 | cmdParser.addBooleanOptionalFlag("no-prepass", "Do no run IR cannonicalization before the analysis", noPrepassFlag); 13 | cmdParser.addBooleanOptionalFlag("S", "Output IR in text format rather than bitcode format", outputTextFlag); 14 | 15 | cmdParser.parseCommandLineOptions(argc, argv); 16 | } -------------------------------------------------------------------------------- /tool/pts-inst/CommandLineOptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class CommandLineOptions 6 | { 7 | private: 8 | llvm::StringRef inputFileName; 9 | llvm::StringRef outputFileName; 10 | llvm::StringRef ptrConfigFileName; 11 | 12 | bool noPrepassFlag; 13 | bool outputTextFlag; 14 | public: 15 | CommandLineOptions(int argc, char** argv); 16 | 17 | const llvm::StringRef& getInputFileName() { return inputFileName; } 18 | const llvm::StringRef& getOutputFileName() const { return outputFileName; } 19 | const llvm::StringRef& getPtrConfigFileName() { return ptrConfigFileName; } 20 | 21 | bool isPrepassDisabled() const { return noPrepassFlag; } 22 | bool isTextOutput() const { return outputTextFlag || outputFileName == "-"; } 23 | }; -------------------------------------------------------------------------------- /tool/pts-inst/pts-inst.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | 3 | #include "Dynamic/Instrument/MemoryInstrument.h" 4 | #include "Transforms/RunPrepass.h" 5 | #include "Util/IO/ReadIR.h" 6 | #include "Util/IO/WriteIR.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace llvm; 14 | 15 | int main(int argc, char** argv) 16 | { 17 | // Print full stack trace when crashed 18 | sys::PrintStackTraceOnErrorSignal(); 19 | PrettyStackTraceProgram X(argc, argv); 20 | 21 | // Parse command line options 22 | auto opts = CommandLineOptions(argc, argv); 23 | 24 | // Read module from file 25 | auto module = util::io::readModuleFromFile(opts.getInputFileName().data()); 26 | if (!module) 27 | { 28 | llvm::errs() << "Failed to read IR from " << opts.getInputFileName().data() << "\n"; 29 | std::exit(-2); 30 | } 31 | 32 | // Run prepasses to canonicalize the IR 33 | if (!opts.isPrepassDisabled()) 34 | transform::runPrepassOn(*module); 35 | 36 | // Instrument the module 37 | auto instrumenter = dynamic::MemoryInstrument(); 38 | instrumenter.loadExternalTable(opts.getPtrConfigFileName().data()); 39 | instrumenter.runOnModule(*module); 40 | 41 | // Output the instrumented program 42 | util::io::writeModuleToFile(*module, opts.getOutputFileName().data(), opts.isTextOutput()); 43 | 44 | return 0; 45 | } -------------------------------------------------------------------------------- /tool/pts-log-dump/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${PROJECT_SOURCE_DIR}/tool/pts-log-dump) 2 | 3 | set (ptsLogDumpSourceCode 4 | pts-log-dump.cpp 5 | ) 6 | 7 | add_executable (pts-log-dump ${ptsLogDumpSourceCode}) 8 | target_link_libraries (pts-log-dump DynamicLog Util) -------------------------------------------------------------------------------- /tool/pts-log-dump/pts-log-dump.cpp: -------------------------------------------------------------------------------- 1 | #include "Dynamic/Log/LogPrinter.h" 2 | 3 | #include 4 | 5 | int main(int argc, char** argv) 6 | { 7 | // Unsync iostream with C I/O libraries to accelerate standard iostreams 8 | std::ios::sync_with_stdio(false); 9 | 10 | if (argc != 2) 11 | { 12 | std::cout << "Usage: " << argv[0] << " \n\n"; 13 | std::exit(-1); 14 | } 15 | 16 | dynamic::LogPrinter(argv[1], std::cout).process(); 17 | } -------------------------------------------------------------------------------- /tool/pts-verify/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${PROJECT_SOURCE_DIR}/tool/pts-verify) 2 | 3 | set (ptsVerifySourceCode 4 | pts-verify.cpp 5 | CommandLineOptions.cpp 6 | RunAnalysis.cpp 7 | ) 8 | 9 | add_executable (pts-verify ${ptsVerifySourceCode}) 10 | target_link_libraries (pts-verify DynamicAnalysis Instrument Util PointerAnalysis) -------------------------------------------------------------------------------- /tool/pts-verify/CommandLineOptions.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "Util/CommandLine/TypedCommandLineParser.h" 3 | 4 | using namespace util; 5 | 6 | CommandLineOptions::CommandLineOptions(int argc, char** argv): ptrConfigFileName("ptr.config"), k(0) 7 | { 8 | TypedCommandLineParser cmdParser("Points-to analysis verifier"); 9 | cmdParser.addStringPositionalFlag("irFile", "Input LLVM bitcode file name", inputFileName); 10 | cmdParser.addStringPositionalFlag("logFile", "Input dynamic log file name", inputLogName); 11 | cmdParser.addStringOptionalFlag("ptr-config", "Annotation file for external library points-to analysis (default = /ptr.config)", ptrConfigFileName); 12 | cmdParser.addUIntOptionalFlag("k", "The size limit of the stack for k-CFA", k); 13 | 14 | cmdParser.parseCommandLineOptions(argc, argv); 15 | } -------------------------------------------------------------------------------- /tool/pts-verify/CommandLineOptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class CommandLineOptions 6 | { 7 | private: 8 | llvm::StringRef inputFileName; 9 | llvm::StringRef inputLogName; 10 | 11 | llvm::StringRef ptrConfigFileName; 12 | unsigned k; 13 | public: 14 | CommandLineOptions(int argc, char** argv); 15 | 16 | const llvm::StringRef& getInputFileName() { return inputFileName; } 17 | const llvm::StringRef& getInputLogName() { return inputLogName; } 18 | 19 | const llvm::StringRef& getPtrConfigFileName() { return ptrConfigFileName; } 20 | unsigned getContextSensitivity() const { return k; } 21 | }; -------------------------------------------------------------------------------- /tool/pts-verify/RunAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm 4 | { 5 | class Module; 6 | } 7 | 8 | // Return true if all test passed 9 | bool runAnalysisOnModule(const llvm::Module&, const char*, const char*, unsigned); -------------------------------------------------------------------------------- /tool/pts-verify/pts-verify.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "RunAnalysis.h" 3 | 4 | #include "Util/IO/ReadIR.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace llvm; 12 | 13 | int main(int argc, char** argv) 14 | { 15 | // Print full stack trace when crashed 16 | sys::PrintStackTraceOnErrorSignal(); 17 | PrettyStackTraceProgram X(argc, argv); 18 | 19 | // Parse command line options 20 | auto opts = CommandLineOptions(argc, argv); 21 | 22 | // Read module from file 23 | auto module = util::io::readModuleFromFile(opts.getInputFileName().data()); 24 | if (!module) 25 | { 26 | errs() << "Failed to read IR from " << opts.getInputFileName() << "\n"; 27 | std::exit(-2); 28 | } 29 | 30 | // Run the analysis 31 | bool succ = runAnalysisOnModule(*module, opts.getInputLogName().data(), opts.getPtrConfigFileName().data(), opts.getContextSensitivity()); 32 | 33 | if (succ) 34 | outs() << "Congratulations! All tests passed.\n"; 35 | 36 | return succ ? 0: -3; 37 | } -------------------------------------------------------------------------------- /tool/scripts/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | function (add_script script_name) 2 | get_filename_component(exec_name ${script_name} NAME_WE) 3 | file(INSTALL ${script_name} 4 | DESTINATION ${EXECUTABLE_OUTPUT_PATH} 5 | RENAME ${exec_name} 6 | FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE 7 | ) 8 | endfunction() 9 | 10 | add_script(compile-dot.py) 11 | add_script(extract-annotation.py) 12 | add_script(pts-test.py) 13 | add_script(clang-opt.py) -------------------------------------------------------------------------------- /tool/scripts/compile-dot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os, sys, argparse 4 | from pathlib import Path 5 | 6 | if __name__ == "__main__": 7 | optionParser = argparse.ArgumentParser(description='Compile all .dot files under a given directory to PNG files') 8 | optionParser.add_argument('dir', help='specify the directory containing .dot files') 9 | arg = optionParser.parse_args() 10 | 11 | filePath = Path(arg.dir) 12 | if not filePath.is_dir(): 13 | print('%s is not a valid path name!' % arg.dir) 14 | sys.exit(-1) 15 | 16 | for dotFile in filePath.glob('*.dot'): 17 | print('Compiling %s' % dotFile.name) 18 | 19 | cmd = 'dot -Tpng ' + str(dotFile) + ' -o ' + str(dotFile.with_suffix('.png')) 20 | os.system(cmd) 21 | 22 | sys.exit(0) -------------------------------------------------------------------------------- /tool/scripts/extract-annotation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse, sys 4 | 5 | def getFunName(line): 6 | words = line.split() 7 | assert len(words) > 1 8 | 9 | if words[0] in ['IGNORE', 'SOURCE', 'PIPE', 'SINK']: 10 | return words[1] 11 | else: 12 | return words[0] 13 | 14 | if __name__ == "__main__": 15 | optionParser = argparse.ArgumentParser(description='Extract external annotations for specified functions from a given file') 16 | optionParser.add_argument('annot_file', help='specify the name of the annotation file') 17 | optionParser.add_argument('-f', '--func_file', help='specify the name of the file containing all function names (default: stdin)', default='-') 18 | args = optionParser.parse_args() 19 | 20 | funDict = dict() 21 | with open(args.annot_file, 'r') as annotFile: 22 | for line in annotFile: 23 | line = line.strip() 24 | if len(line) == 0 or line.startswith('#'): 25 | continue 26 | 27 | funName = getFunName(line) 28 | if funName in funDict: 29 | funDict[funName].append(line) 30 | else: 31 | funDict[funName] = [line] 32 | 33 | funFile = sys.stdin if args.func_file == '-' else open(args.func_file) 34 | missingFuncs = [] 35 | for line in funFile: 36 | line = line.strip() 37 | if line in funDict: 38 | for entry in funDict[line]: 39 | print(entry) 40 | else: 41 | missingFuncs.append(line) 42 | if funFile is not sys.stdin: 43 | funFile.close() 44 | 45 | if len(missingFuncs) > 0: 46 | print('\nMissing functions:', file=sys.stderr) 47 | for entry in missingFuncs: 48 | print(entry, file=sys.stderr) -------------------------------------------------------------------------------- /tool/table-check/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${tpa_SOURCE_DIR}/tool/table-check) 2 | 3 | set (tableCheckSourceCode 4 | table-check.cpp 5 | TableChecker.cpp 6 | ) 7 | 8 | add_executable (table-check ${tableCheckSourceCode}) 9 | target_link_libraries (table-check Util Annotation) -------------------------------------------------------------------------------- /tool/table-check/TableChecker.h: -------------------------------------------------------------------------------- 1 | #ifndef TPA_TOOL_TABLECHECKER_H 2 | #define TPA_TOOL_TABLECHECKER_H 3 | 4 | namespace llvm 5 | { 6 | class Module; 7 | class StringRef; 8 | } 9 | 10 | template 11 | class TableChecker 12 | { 13 | private: 14 | Table table; 15 | public: 16 | TableChecker(const llvm::StringRef& fileName); 17 | 18 | void check(const llvm::Module& module); 19 | }; 20 | 21 | void checkPtrEffectTable(const llvm::Module&, const llvm::StringRef&); 22 | void checkModRefEffectTable(const llvm::Module&, const llvm::StringRef&); 23 | void checkTaintTable(const llvm::Module&, const llvm::StringRef&); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /tool/table/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${tpa_SOURCE_DIR}/tool/table) 2 | 3 | set (tableSourceCode 4 | CommandLineOptions.cpp 5 | ExternalModRefTablePrinter.cpp 6 | ExternalPointerTablePrinter.cpp 7 | ExternalTaintTablePrinter.cpp 8 | table.cpp 9 | ) 10 | 11 | add_executable (table ${tableSourceCode}) 12 | target_link_libraries (table Util Annotation) -------------------------------------------------------------------------------- /tool/table/CommandLineOptions.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "Util/CommandLine/TypedCommandLineParser.h" 3 | 4 | using namespace util; 5 | 6 | CommandLineOptions::CommandLineOptions(int argc, char** argv) 7 | { 8 | TypedCommandLineParser cmdParser("Annotation pretty printer"); 9 | cmdParser.addStringPositionalFlag("inputType", "Type of the input annotation (choices: ptr, modref, taint)", inputFileType); 10 | cmdParser.addStringPositionalFlag("inputFile", "Input annotation file name", inputFileName); 11 | 12 | cmdParser.parseCommandLineOptions(argc, argv); 13 | } -------------------------------------------------------------------------------- /tool/table/CommandLineOptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class CommandLineOptions 6 | { 7 | private: 8 | llvm::StringRef inputFileType; 9 | llvm::StringRef inputFileName; 10 | public: 11 | CommandLineOptions(int argc, char** argv); 12 | 13 | const llvm::StringRef& getInputFileType() const { return inputFileType; } 14 | const llvm::StringRef& getInputFileName() const { return inputFileName; } 15 | }; 16 | -------------------------------------------------------------------------------- /tool/table/TablePrinter/ExternalModRefTablePrinter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm 4 | { 5 | class raw_ostream; 6 | } 7 | 8 | namespace annotation 9 | { 10 | 11 | class ExternalModRefTable; 12 | 13 | class ExternalModRefTablePrinter 14 | { 15 | private: 16 | llvm::raw_ostream& os; 17 | public: 18 | using TableType = ExternalModRefTable; 19 | 20 | ExternalModRefTablePrinter(llvm::raw_ostream& o): os(o) {} 21 | 22 | void printTable(const ExternalModRefTable&); 23 | }; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /tool/table/TablePrinter/ExternalPointerTablePrinter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm 4 | { 5 | class raw_ostream; 6 | } 7 | 8 | namespace annotation 9 | { 10 | 11 | class ExternalPointerTable; 12 | 13 | class ExternalPointerTablePrinter 14 | { 15 | private: 16 | llvm::raw_ostream& os; 17 | public: 18 | using TableType = ExternalPointerTable; 19 | 20 | ExternalPointerTablePrinter(llvm::raw_ostream& o): os(o) {} 21 | 22 | void printTable(const ExternalPointerTable&); 23 | }; 24 | 25 | } -------------------------------------------------------------------------------- /tool/table/TablePrinter/ExternalTaintTablePrinter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm 4 | { 5 | class raw_ostream; 6 | } 7 | 8 | namespace annotation 9 | { 10 | 11 | class ExternalTaintTable; 12 | 13 | class ExternalTaintTablePrinter 14 | { 15 | private: 16 | llvm::raw_ostream& os; 17 | public: 18 | using TableType = ExternalTaintTable; 19 | 20 | ExternalTaintTablePrinter(llvm::raw_ostream& o): os(o) {} 21 | 22 | void printTable(const ExternalTaintTable&) const; 23 | }; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /tool/table/table.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "TablePrinter/ExternalModRefTablePrinter.h" 3 | #include "TablePrinter/ExternalPointerTablePrinter.h" 4 | #include "TablePrinter/ExternalTaintTablePrinter.h" 5 | 6 | #include "Annotation/Pointer/ExternalPointerTable.h" 7 | #include "Annotation/ModRef/ExternalModRefTable.h" 8 | #include "Annotation/Taint/ExternalTaintTable.h" 9 | 10 | #include 11 | 12 | using namespace annotation; 13 | using namespace llvm; 14 | 15 | template 16 | void printTable(const StringRef& fileName) 17 | { 18 | using TableType = typename PrinterType::TableType; 19 | auto table = TableType::loadFromFile(fileName.data()); 20 | PrinterType(outs()).printTable(table); 21 | } 22 | 23 | int main(int argc, char** argv) 24 | { 25 | // Parse command line options 26 | auto opts = CommandLineOptions(argc, argv); 27 | 28 | auto typeStr = opts.getInputFileType(); 29 | if (typeStr == "ptr") 30 | printTable(opts.getInputFileName()); 31 | else if (typeStr == "modref") 32 | printTable(opts.getInputFileName()); 33 | else if (typeStr == "taint") 34 | printTable(opts.getInputFileName()); 35 | else 36 | { 37 | outs() << "Unknown annotation file type: " << typeStr << "\n"; 38 | std::exit(-1); 39 | } 40 | 41 | return 0; 42 | } -------------------------------------------------------------------------------- /tool/taint-check/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${PROJECT_SOURCE_DIR}/tool/taint-check) 2 | 3 | set (taintCheckSourceCode 4 | taint-check.cpp 5 | CommandLineOptions.cpp 6 | RunAnalysis.cpp 7 | ) 8 | 9 | add_executable (taint-check ${taintCheckSourceCode}) 10 | target_link_libraries (taint-check Util Transforms TaintAnalysis) -------------------------------------------------------------------------------- /tool/taint-check/CommandLineOptions.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "Util/CommandLine/TypedCommandLineParser.h" 3 | 4 | using namespace util; 5 | 6 | CommandLineOptions::CommandLineOptions(int argc, char** argv): ptrConfigFileName("ptr.config"), modRefConfigFileName("modref.config"), taintConfigFileName("taint.config"), k(0) 7 | { 8 | TypedCommandLineParser cmdParser("Points-to analysis verifier"); 9 | cmdParser.addStringPositionalFlag("irFile", "Input LLVM bitcode file name", inputFileName); 10 | cmdParser.addStringOptionalFlag("ptr-config", "Annotation file for external library points-to analysis (default = /ptr.config)", ptrConfigFileName); 11 | cmdParser.addStringOptionalFlag("modref-config", "Annotation file for external library mod/ref analysis (default = /modref.config)", modRefConfigFileName); 12 | cmdParser.addStringOptionalFlag("taint-config", "Annotation file for external library taint analysis (default = /taint.config)", taintConfigFileName); 13 | cmdParser.addUIntOptionalFlag("k", "The size limit of the stack for k-CFA", k); 14 | cmdParser.addBooleanOptionalFlag("no-prepass", "Do no run IR cannonicalization before the analysis", noPrepassFlag); 15 | 16 | cmdParser.parseCommandLineOptions(argc, argv); 17 | } -------------------------------------------------------------------------------- /tool/taint-check/CommandLineOptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class CommandLineOptions 6 | { 7 | private: 8 | llvm::StringRef inputFileName; 9 | 10 | llvm::StringRef ptrConfigFileName; 11 | llvm::StringRef modRefConfigFileName; 12 | llvm::StringRef taintConfigFileName; 13 | bool noPrepassFlag; 14 | unsigned k; 15 | public: 16 | CommandLineOptions(int argc, char** argv); 17 | 18 | const llvm::StringRef& getInputFileName() const { return inputFileName; } 19 | 20 | const llvm::StringRef& getPtrConfigFileName() const { return ptrConfigFileName; } 21 | const llvm::StringRef& getModRefConfigFileName() const { return modRefConfigFileName; } 22 | const llvm::StringRef& getTaintConfigFileName() const { return taintConfigFileName; } 23 | bool isPrepassDisabled() const { return noPrepassFlag; } 24 | unsigned getContextSensitivity() const { return k; } 25 | }; 26 | -------------------------------------------------------------------------------- /tool/taint-check/RunAnalysis.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "RunAnalysis.h" 3 | 4 | #include "Context/KLimitContext.h" 5 | #include "PointerAnalysis/Analysis/SemiSparsePointerAnalysis.h" 6 | #include "PointerAnalysis/FrontEnd/SemiSparseProgramBuilder.h" 7 | #include "TaintAnalysis/Analysis/TaintAnalysis.h" 8 | #include "TaintAnalysis/FrontEnd/DefUseModuleBuilder.h" 9 | 10 | #include 11 | #include 12 | 13 | using namespace context; 14 | using namespace llvm; 15 | using namespace tpa; 16 | using namespace taint; 17 | 18 | bool runAnalysisOnModule(const Module& module, const CommandLineOptions& opts) 19 | { 20 | KLimitContext::setLimit(opts.getContextSensitivity()); 21 | 22 | SemiSparseProgramBuilder ssProgBuilder; 23 | auto ssProg = ssProgBuilder.runOnModule(module); 24 | 25 | SemiSparsePointerAnalysis ptrAnalysis; 26 | ptrAnalysis.loadExternalPointerTable(opts.getPtrConfigFileName().data()); 27 | ptrAnalysis.runOnProgram(ssProg); 28 | 29 | DefUseModuleBuilder builder(ptrAnalysis); 30 | builder.loadExternalModRefTable(opts.getModRefConfigFileName().data()); 31 | auto duModule = builder.buildDefUseModule(module); 32 | 33 | TaintAnalysis taintAnalysis(ptrAnalysis); 34 | taintAnalysis.loadExternalTaintTable(opts.getTaintConfigFileName().data()); 35 | return taintAnalysis.runOnDefUseModule(duModule); 36 | } -------------------------------------------------------------------------------- /tool/taint-check/RunAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm 4 | { 5 | class Module; 6 | } 7 | 8 | class CommandLineOptions; 9 | 10 | // Return true if all test passed 11 | bool runAnalysisOnModule(const llvm::Module&, const CommandLineOptions&); -------------------------------------------------------------------------------- /tool/taint-check/taint-check.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "RunAnalysis.h" 3 | 4 | #include "Transforms/RunPrepass.h" 5 | #include "Util/IO/ReadIR.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace llvm; 13 | 14 | int main(int argc, char** argv) 15 | { 16 | // Print full stack trace when crashed 17 | sys::PrintStackTraceOnErrorSignal(); 18 | PrettyStackTraceProgram X(argc, argv); 19 | 20 | // Parse command line options 21 | auto opts = CommandLineOptions(argc, argv); 22 | 23 | // Read module from file 24 | auto module = util::io::readModuleFromFile(opts.getInputFileName().data()); 25 | if (!module) 26 | { 27 | errs() << "Failed to read IR from " << opts.getInputFileName().data() << "\n"; 28 | std::exit(-2); 29 | } 30 | 31 | // Run prepasses to canonicalize the IR 32 | if (!opts.isPrepassDisabled()) 33 | transform::runPrepassOn(*module); 34 | 35 | // Run the analysis 36 | bool succ = runAnalysisOnModule(*module, opts); 37 | 38 | if (succ) 39 | outs() << "Congratulations! Taint check passed.\n"; 40 | else 41 | outs() << "Taint check failed\n"; 42 | 43 | return succ ? 0: -3; 44 | } -------------------------------------------------------------------------------- /tool/vkcfa-taint/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${PROJECT_SOURCE_DIR}/tool/vkcfa-taint) 2 | 3 | set (vkcfaSourceCode 4 | vkcfa-taint.cpp 5 | CommandLineOptions.cpp 6 | RunAnalysis.cpp 7 | ) 8 | 9 | add_executable (vkcfa-taint ${vkcfaSourceCode}) 10 | target_link_libraries (vkcfa-taint Util Transforms TaintAnalysis) -------------------------------------------------------------------------------- /tool/vkcfa-taint/CommandLineOptions.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "Util/CommandLine/TypedCommandLineParser.h" 3 | 4 | using namespace util; 5 | 6 | CommandLineOptions::CommandLineOptions(int argc, char** argv): ptrConfigFileName("ptr.config"), modRefConfigFileName("modref.config"), taintConfigFileName("taint.config") 7 | { 8 | TypedCommandLineParser cmdParser("Points-to analysis verifier"); 9 | cmdParser.addStringPositionalFlag("irFile", "Input LLVM bitcode file name", inputFileName); 10 | cmdParser.addStringOptionalFlag("ptr-config", "Annotation file for external library points-to analysis (default = /ptr.config)", ptrConfigFileName); 11 | cmdParser.addStringOptionalFlag("modref-config", "Annotation file for external library mod/ref analysis (default = /modref.config)", modRefConfigFileName); 12 | cmdParser.addStringOptionalFlag("taint-config", "Annotation file for external library taint analysis (default = /taint.config)", taintConfigFileName); 13 | cmdParser.addBooleanOptionalFlag("no-prepass", "Do no run IR cannonicalization before the analysis", noPrepassFlag); 14 | 15 | cmdParser.parseCommandLineOptions(argc, argv); 16 | } -------------------------------------------------------------------------------- /tool/vkcfa-taint/CommandLineOptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class CommandLineOptions 6 | { 7 | private: 8 | llvm::StringRef inputFileName; 9 | 10 | llvm::StringRef ptrConfigFileName; 11 | llvm::StringRef modRefConfigFileName; 12 | llvm::StringRef taintConfigFileName; 13 | bool noPrepassFlag; 14 | public: 15 | CommandLineOptions(int argc, char** argv); 16 | 17 | const llvm::StringRef& getInputFileName() const { return inputFileName; } 18 | 19 | const llvm::StringRef& getPtrConfigFileName() const { return ptrConfigFileName; } 20 | const llvm::StringRef& getModRefConfigFileName() const { return modRefConfigFileName; } 21 | const llvm::StringRef& getTaintConfigFileName() const { return taintConfigFileName; } 22 | bool isPrepassDisabled() const { return noPrepassFlag; } 23 | }; 24 | -------------------------------------------------------------------------------- /tool/vkcfa-taint/RunAnalysis.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "RunAnalysis.h" 3 | 4 | #include "Context/KLimitContext.h" 5 | #include "PointerAnalysis/Analysis/SemiSparsePointerAnalysis.h" 6 | #include "PointerAnalysis/FrontEnd/SemiSparseProgramBuilder.h" 7 | #include "TaintAnalysis/Analysis/TrackingTaintAnalysis.h" 8 | #include "TaintAnalysis/FrontEnd/DefUseModuleBuilder.h" 9 | #include "Util/IO/TaintAnalysis/Printer.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace context; 16 | using namespace llvm; 17 | using namespace tpa; 18 | using namespace taint; 19 | using namespace util::io; 20 | 21 | bool runAnalysisOnModule(const Module& module, const CommandLineOptions& opts) 22 | { 23 | KLimitContext::setLimit(0); 24 | 25 | SemiSparseProgramBuilder ssProgBuilder; 26 | auto ssProg = ssProgBuilder.runOnModule(module); 27 | 28 | SemiSparsePointerAnalysis ptrAnalysis; 29 | ptrAnalysis.loadExternalPointerTable(opts.getPtrConfigFileName().data()); 30 | ptrAnalysis.runOnProgram(ssProg); 31 | 32 | DefUseModuleBuilder builder(ptrAnalysis); 33 | builder.loadExternalModRefTable(opts.getModRefConfigFileName().data()); 34 | auto duModule = builder.buildDefUseModule(module); 35 | 36 | TrackingTaintAnalysis taintAnalysis(ptrAnalysis); 37 | taintAnalysis.loadExternalTaintTable(opts.getTaintConfigFileName().data()); 38 | auto ret = taintAnalysis.runOnDefUseModule(duModule); 39 | 40 | for (auto const& pp: ret.second) 41 | errs() << "Find loss site " << pp << "\n"; 42 | 43 | return ret.first; 44 | } -------------------------------------------------------------------------------- /tool/vkcfa-taint/RunAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm 4 | { 5 | class Module; 6 | } 7 | 8 | class CommandLineOptions; 9 | 10 | // Return true if all test passed 11 | bool runAnalysisOnModule(const llvm::Module&, const CommandLineOptions&); -------------------------------------------------------------------------------- /tool/vkcfa-taint/vkcfa-taint.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandLineOptions.h" 2 | #include "RunAnalysis.h" 3 | 4 | #include "Transforms/RunPrepass.h" 5 | #include "Util/IO/ReadIR.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace llvm; 13 | 14 | int main(int argc, char** argv) 15 | { 16 | // Print full stack trace when crashed 17 | sys::PrintStackTraceOnErrorSignal(); 18 | PrettyStackTraceProgram X(argc, argv); 19 | 20 | // Parse command line options 21 | auto opts = CommandLineOptions(argc, argv); 22 | 23 | // Read module from file 24 | auto module = util::io::readModuleFromFile(opts.getInputFileName().data()); 25 | if (!module) 26 | { 27 | errs() << "Failed to read IR from " << opts.getInputFileName().data() << "\n"; 28 | std::exit(-2); 29 | } 30 | 31 | // Run prepasses to canonicalize the IR 32 | if (!opts.isPrepassDisabled()) 33 | transform::runPrepassOn(*module); 34 | 35 | // Run the analysis 36 | bool succ = runAnalysisOnModule(*module, opts); 37 | 38 | if (succ) 39 | outs() << "Congratulations! Taint check passed.\n"; 40 | else 41 | outs() << "Taint check failed\n"; 42 | 43 | return succ ? 0: -3; 44 | } -------------------------------------------------------------------------------- /unittest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories( 2 | ${tpa_SOURCE_DIR}/util/googletest/include 3 | ${tpa_SOURCE_DIR}/include) 4 | 5 | link_directories (${tpa_BINARY_DIR}/lib) 6 | 7 | set (EXECUTABLE_OUTPUT_PATH ${tpa_BINARY_DIR}/unittest) 8 | add_definitions(-DGTEST_HAS_RTTI=0) 9 | 10 | add_executable(MemoryTest MemoryUnitTest/ContextTest.cpp MemoryUnitTest/PointerTest.cpp MemoryUnitTest/MemoryTest.cpp MemoryUnitTest/PtsSetTest.cpp) 11 | target_link_libraries(MemoryTest MemoryModelStatic LLVMAsmParser gtest_main) 12 | 13 | add_executable(ControlFlowTest ControlFlowUnitTest/ControlFlowTest.cpp) 14 | target_link_libraries(ControlFlowTest PointerAnalysisStatic LLVMAsmParser gtest_main) 15 | 16 | add_executable(InterpreterTest InterpreterUnitTest/InterpreterTest.cpp InterpreterUnitTest/InterProcTest.cpp) 17 | target_link_libraries(InterpreterTest TPAStatic LLVMAsmParser gtest_main) 18 | 19 | add_executable(GlobalAnalysisTest GlobalAnalysisUnitTest/GlobalAnalysisTest.cpp) 20 | target_link_libraries(GlobalAnalysisTest PointerAnalysisStatic LLVMAsmParser gtest_main) 21 | 22 | add_executable(TaintnessTest TaintnessUnitTest/TaintnessTest.cpp TaintnessUnitTest/PrecisionTest.cpp) 23 | target_link_libraries(TaintnessTest ClientsStatic LLVMAsmParser gtest_main) -------------------------------------------------------------------------------- /unittest/TaintnessUnitTest/PrecisionTest.cpp: -------------------------------------------------------------------------------- 1 | #include "Utils/ParseLLVMAssembly.h" 2 | 3 | #include "gtest/gtest.h" 4 | 5 | using namespace llvm; 6 | //using namespace tpa; 7 | //using namespace client; 8 | //using namespace client::taint; 9 | 10 | namespace 11 | { 12 | } --------------------------------------------------------------------------------