├── ChangeLog ├── NEWS ├── docs ├── Makefile.am └── doxygen.intro ├── AUTHORS ├── tool ├── WrapperGcc.h ├── CommandPwd.h ├── CommandRun.h ├── CommandQuit.h ├── CommandStep.h ├── CommandBreak.h ├── CommandStart.h ├── CommandFinish.h ├── CommandContinue.h ├── Utils.h ├── CommandFile.h ├── CommandCd.h ├── CommandDump.h ├── CommandContinue.cpp ├── CommandHelp.h ├── Command.cpp ├── CommandFinish.cpp ├── IteratorCallback.cpp ├── CommandInfo.h ├── CommandShow.h ├── CommandRun.cpp ├── CommandSet.h ├── CommandPwd.cpp ├── CommandStart.cpp ├── CommandQuit.cpp ├── CommandBreak.cpp ├── CMakeLists.txt ├── CommandPrint.h ├── CommandStep.cpp ├── IteratorCallback.h ├── Makefile.am ├── Prereq.h ├── Commands.h ├── Command.h ├── Utils.cpp ├── State.h ├── CommandDump.cpp ├── CommandCd.cpp ├── CommandShow.cpp ├── CommandSet.cpp ├── Canal.cpp ├── State.cpp └── CommandHelp.cpp ├── tests ├── 3-pointer.c ├── atlocal.in ├── ArraySingleItemTest.cpp ├── 0-numeric.c ├── file_test.sh ├── 1-pointer.c ├── local.at ├── ArrayExactSizeTest.cpp ├── CMakeLists.txt ├── PointerTest.cpp ├── 2-string.c ├── ProductMessageTest.cpp ├── testsuite.at ├── Makefile.am ├── ProductVectorTest.cpp ├── FieldMinMaxTest.cpp └── FloatIntervalTest.cpp ├── canal.pc.in ├── .dir-locals.el ├── lib ├── ArrayUtils.h ├── FunctionModel.h ├── FunctionModelManager.h ├── PointerUtils.h ├── ProductMessage.h ├── FloatUtils.h ├── ConfigCMake.h.in ├── ProductMessage.cpp ├── WideningPointers.h ├── WideningDataIterationCount.cpp ├── WideningDataInterface.h ├── PointerUtils.cpp ├── WideningNumericalInfinity.h ├── FieldMinMax.h ├── Interpreter.cpp ├── FieldMinMax.cpp ├── ProductMessageField.h ├── WideningInterface.h ├── Environment.cpp ├── WideningDataIterationCount.h ├── WideningManager.h ├── OperationsCallback.h ├── InterpreterIteratorCallback.h ├── ArrayUtils.cpp ├── CMakeLists.txt ├── InterpreterOperationsCallback.h ├── WideningNumericalInfinity.cpp ├── InterpreterBasicBlock.h ├── VariableArguments.h ├── InterpreterBasicBlock.cpp ├── Environment.h ├── InterpreterModule.h ├── WideningPointers.cpp ├── StateMap.h ├── Makefile.am ├── StateMap.cpp ├── ArrayStringTrie.h ├── InterpreterFunction.h ├── Interpreter.h ├── WideningManager.cpp ├── Constructors.h ├── Structure.h ├── FloatUtils.cpp ├── InterpreterIterator.h ├── FloatInterval.h ├── SharedDataPointer.h ├── Prereq.h ├── SlotTracker.h ├── VariableArguments.cpp ├── PointerTarget.h ├── ProductVector.h ├── InterpreterIterator.cpp ├── Utils.cpp ├── IntegerUtils.h ├── ArrayStringPrefix.h └── InterpreterOperationsCallback.cpp ├── STYLE ├── .travis.yml ├── FindReadline.cmake ├── FindLibElf.cmake ├── Makefile.am ├── CMakeLists.txt ├── .gitignore ├── canal.spec.in ├── COPYING ├── README ├── FindClang.cmake ├── FindLLVM.cmake └── configure.ac /ChangeLog: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | == Canal 1 2 | Released 2012-11-07. 3 | 4 | - Initial release. -------------------------------------------------------------------------------- /docs/Makefile.am: -------------------------------------------------------------------------------- 1 | DIST = \ 2 | canal.tex \ 3 | doxygen.conf \ 4 | doxygen.intro \ 5 | Wishlist.rst 6 | 7 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Karel Klíč 2 | Tomáš Brukner 3 | Matej Šuta 4 | Jan Dupal 5 | -------------------------------------------------------------------------------- /tool/WrapperGcc.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_WRAPPER_GCC_H 2 | #define CANAL_WRAPPER_GCC_H 3 | 4 | #include "Prereq.h" 5 | 6 | int wrapGcc(int argc, char **argv); 7 | 8 | int wrapLd(int argc, char **argv); 9 | 10 | #endif // CANAL_WRAPPER_GCC_H 11 | -------------------------------------------------------------------------------- /tests/3-pointer.c: -------------------------------------------------------------------------------- 1 | struct munger 2 | { 3 | int f1; 4 | int f2; 5 | }; 6 | 7 | void munge(struct munger *p) 8 | { 9 | p[0].f1 = p[1].f1 + p[2].f2; 10 | } 11 | 12 | int main(void) 13 | { 14 | struct munger array[3]; 15 | munge(array); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /canal.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: canal 7 | Description: Abstract interpreter for real-world application programs 8 | Version: @PACKAGE_VERSION@ 9 | Libs: -L${libdir} -lcanal 10 | Cflags: -I${includedir} 11 | -------------------------------------------------------------------------------- /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ;; Emacs settings for canal 2 | ((c-mode . ((c-file-style . "BSD") 3 | (c-basic-offset . 4) 4 | (indent-tabs-mode . nil) 5 | (show-trailing-whitespace . t))) 6 | (c++-mode . ((c-file-style . "BSD") 7 | (c-basic-offset . 4) 8 | (indent-tabs-mode . nil) 9 | (show-trailing-whitespace . t)))) 10 | -------------------------------------------------------------------------------- /tool/CommandPwd.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_PWD_H 2 | #define CANAL_COMMAND_PWD_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandPwd : public Command 7 | { 8 | public: 9 | CommandPwd(Commands &commands); 10 | 11 | // Implementation of Command::run(). 12 | virtual void run(const std::vector &args); 13 | }; 14 | 15 | #endif // CANAL_COMMAND_PWD_H 16 | -------------------------------------------------------------------------------- /tool/CommandRun.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_RUN_H 2 | #define CANAL_COMMAND_RUN_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandRun : public Command 7 | { 8 | public: 9 | CommandRun(Commands &commands); 10 | 11 | // Implementation of Command::run(). 12 | virtual void run(const std::vector &args); 13 | }; 14 | 15 | #endif // CANAL_COMMAND_RUN_H 16 | -------------------------------------------------------------------------------- /lib/ArrayUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_ARRAY_UTILS_H 2 | #define LIBCANAL_ARRAY_UTILS_H 3 | 4 | #include "Prereq.h" 5 | 6 | namespace Canal { 7 | namespace Array { 8 | namespace Utils { 9 | 10 | void strcat(Domain &destination, const Domain &source); 11 | 12 | } // namespace Utils 13 | } // namespace Array 14 | } // namespace Canal 15 | 16 | #endif // LIBCANAL_ARRAY_UTILS_H 17 | -------------------------------------------------------------------------------- /tool/CommandQuit.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_QUIT_H 2 | #define CANAL_COMMAND_QUIT_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandQuit : public Command 7 | { 8 | public: 9 | CommandQuit(Commands &commands); 10 | 11 | // Implementation of Command::run(). 12 | virtual void run(const std::vector &args); 13 | }; 14 | 15 | #endif // CANAL_COMMAND_QUIT_H 16 | -------------------------------------------------------------------------------- /tool/CommandStep.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_STEP_H 2 | #define CANAL_COMMAND_STEP_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandStep : public Command 7 | { 8 | public: 9 | CommandStep(Commands &commands); 10 | 11 | // Implementation of Command::run(). 12 | virtual void run(const std::vector &args); 13 | }; 14 | 15 | #endif // CANAL_COMMAND_STEP_H 16 | -------------------------------------------------------------------------------- /tool/CommandBreak.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_BREAK_H 2 | #define CANAL_COMMAND_BREAK_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandBreak : public Command 7 | { 8 | public: 9 | CommandBreak(Commands &commands); 10 | 11 | // Implementation of Command::run(). 12 | virtual void run(const std::vector &args); 13 | }; 14 | 15 | #endif // CANAL_COMMAND_BREAK_H 16 | -------------------------------------------------------------------------------- /tool/CommandStart.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_START_H 2 | #define CANAL_COMMAND_START_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandStart : public Command 7 | { 8 | public: 9 | CommandStart(Commands &commands); 10 | 11 | // Implementation of Command::run(). 12 | virtual void run(const std::vector &args); 13 | }; 14 | 15 | #endif // CANAL_COMMAND_START_H 16 | -------------------------------------------------------------------------------- /tool/CommandFinish.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_FINISH_H 2 | #define CANAL_COMMAND_FINISH_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandFinish : public Command 7 | { 8 | public: 9 | CommandFinish(Commands &commands); 10 | 11 | // Implementation of Command::run(). 12 | virtual void run(const std::vector &args); 13 | }; 14 | 15 | #endif // CANAL_COMMAND_FINISH_H 16 | -------------------------------------------------------------------------------- /tool/CommandContinue.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_CONTINUE_H 2 | #define CANAL_COMMAND_CONTINUE_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandContinue : public Command 7 | { 8 | public: 9 | CommandContinue(Commands &commands); 10 | 11 | // Implementation of Command::run(). 12 | virtual void run(const std::vector &args); 13 | }; 14 | 15 | #endif // CANAL_COMMAND_CONTINUE_H 16 | -------------------------------------------------------------------------------- /docs/doxygen.intro: -------------------------------------------------------------------------------- 1 | // -*- c++ -*- 2 | 3 | /// @mainpage Canal 4 | /// 5 | /// @section main_intro Introduction 6 | /// Welcome to Canal. 7 | /// 8 | /// This documentation describes the Canal source code. There are no 9 | /// instructions here on how to use Canal, only the APIs that make up 10 | /// the software. 11 | /// 12 | /// This documentation is generated directly from the source code by 13 | /// Doxygen. 14 | -------------------------------------------------------------------------------- /STYLE: -------------------------------------------------------------------------------- 1 | This document describes coding standards that are being used in this 2 | project. It's based on LLVM Coding Standards[1]. 3 | 4 | == Commenting 5 | Comments are one critical part of readability and 6 | maintainability. Everyone knows they should comment, so should 7 | you. When writing comments, write them as English prose, which means 8 | they should use proper capitalization, punctuation, etc. 9 | 10 | [1] http://llvm.org/docs/CodingStandards.html 11 | -------------------------------------------------------------------------------- /lib/FunctionModel.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_FUNCTION_MODEL_H 2 | #define LIBCANAL_FUNCTION_MODEL_H 3 | 4 | #include "Prereq.h" 5 | 6 | namespace Canal { 7 | 8 | class FunctionModel 9 | { 10 | public: 11 | bool canHandle(llvm::Function *function, 12 | bool implementationAvailable); 13 | 14 | void handle(llvm::Function *function, 15 | State &state); 16 | }; 17 | 18 | } // namespace Canal 19 | 20 | #endif // LIBCANAL_CALLBACKS_H 21 | -------------------------------------------------------------------------------- /tests/atlocal.in: -------------------------------------------------------------------------------- 1 | # @configure_input@ -*- shell-script -*- 2 | # Configurable variable values for btparser test suite. 3 | 4 | # We need a C compiler. 5 | CC='@CC@' 6 | LIBTOOL="$abs_top_builddir/libtool" 7 | 8 | # We want no optimization. 9 | CFLAGS="@O0CFLAGS@ -I$abs_top_builddir -D_GNU_SOURCE" 10 | 11 | # Are special link options needed? 12 | LDFLAGS="@LDFLAGS@ $abs_top_builddir/lib/libcanal.la" 13 | 14 | # Are special libraries needed? 15 | LIBS="@LIBS@" 16 | -------------------------------------------------------------------------------- /lib/FunctionModelManager.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_FUNCTION_MODEL_MANAGER_H 2 | #define LIBCANAL_FUNCTION_MODEL_MANAGER_H 3 | 4 | #include "Prereq.h" 5 | 6 | namespace Canal { 7 | 8 | class FunctionModelMAnager 9 | { 10 | public: 11 | bool canHandle(llvm::Function *function, 12 | bool implementationAvailable); 13 | 14 | void handle(llvm::Function *function, 15 | State &state); 16 | }; 17 | 18 | } // namespace Canal 19 | 20 | #endif // LIBCANAL_FUNCTION_MODEL_MANAGER_H 21 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | compiler: 3 | - gcc 4 | - clang 5 | script: autoreconf -if && ./configure && make && make check 6 | install: sudo apt-get install llvm-dev libclang-dev libelf-dev libreadline-dev 7 | 8 | matrix: 9 | include: 10 | - script: mkdir build/ && cd build/ && cmake .. && make && make test 11 | compiler: gcc 12 | env: CTEST_OUTPUT_ON_FAILURE=1 13 | - script: mkdir build/ && cd build/ && cmake .. && make && make test 14 | compiler: clang 15 | env: CTEST_OUTPUT_ON_FAILURE=1 16 | -------------------------------------------------------------------------------- /tool/Utils.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_UTILS_H 2 | #define CANAL_UTILS_H 3 | 4 | #include "Prereq.h" 5 | #include 6 | 7 | // Asks a [y/n] question on stdin/stdout. 8 | // Returns true if the answer is yes, false otherwise. 9 | bool askYesNo(const char *question); 10 | 11 | unsigned stringToUnsigned(const char *str, bool &success); 12 | int stringToPositiveInt(const char *str, bool &success); 13 | int stringToInt(const char *str, bool &success); 14 | 15 | pid_t safeWaitPid(pid_t pid, int *wstat, int options); 16 | 17 | #endif // CANAL_UTILS_H 18 | -------------------------------------------------------------------------------- /lib/PointerUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_POINTER_UTILS_H 2 | #define LIBCANAL_POINTER_UTILS_H 3 | 4 | #include "PointerTarget.h" 5 | 6 | namespace Canal { 7 | namespace Pointer { 8 | namespace Utils { 9 | 10 | void addTarget(Domain &pointer, 11 | Target::Type type, 12 | const llvm::Value *place, 13 | const llvm::Value *target, 14 | const std::vector &offsets, 15 | Domain *numericOffset); 16 | 17 | } // namespace Utils 18 | } // namespace Pointer 19 | } // namespace Canal 20 | 21 | #endif // LIBCANAL_POINTER_UTILS_H 22 | -------------------------------------------------------------------------------- /tool/CommandFile.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_FILE_H 2 | #define CANAL_COMMAND_FILE_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandFile : public Command 7 | { 8 | public: 9 | CommandFile(Commands &commands); 10 | 11 | // Implementation of Command::getCompletionMatches(). 12 | virtual std::vector getCompletionMatches( 13 | const std::vector &args, 14 | int pointArg, 15 | int pointArgOffset) const; 16 | 17 | // Implementation of Command::run(). 18 | virtual void run(const std::vector &args); 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /tool/CommandCd.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_CD_H 2 | #define CANAL_COMMAND_CD_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandCd : public Command 7 | { 8 | public: 9 | CommandCd(Commands &commands); 10 | 11 | // Implementation of Command::getCompletionMatches(). 12 | virtual std::vector getCompletionMatches( 13 | const std::vector &args, 14 | int pointArg, 15 | int pointArgOffset) const; 16 | 17 | // Implementation of Command::run(). 18 | virtual void run(const std::vector &args); 19 | }; 20 | 21 | #endif // CANAL_COMMAND_CD_H 22 | -------------------------------------------------------------------------------- /FindReadline.cmake: -------------------------------------------------------------------------------- 1 | # Find readline 2 | # 3 | # It defines the following variables 4 | # READLINE_FOUND - If false, do not compile with readline. 5 | # READLINE_INCLUDE_DIRS - Where to find headers. 6 | # READLINE_LIBRARIES - The libraries to link against. 7 | 8 | find_path(READLINE_INCLUDE_DIRS readline/readline.h) 9 | find_library(READLINE_LIBRARIES readline) 10 | 11 | include(FindPackageHandleStandardArgs) 12 | 13 | find_package_handle_standard_args( 14 | Readline 15 | DEFAULT_MSG 16 | READLINE_LIBRARIES 17 | READLINE_INCLUDE_DIRS) 18 | 19 | mark_as_advanced(READLINE_INCLUDE_DIRS READLINE_LIBRARIES) 20 | -------------------------------------------------------------------------------- /tests/ArraySingleItemTest.cpp: -------------------------------------------------------------------------------- 1 | #include "lib/Utils.h" 2 | #include "lib/Environment.h" 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace Canal; 8 | 9 | static Environment *gEnvironment; 10 | 11 | int 12 | main(int argc, char **argv) 13 | { 14 | llvm::LLVMContext &context = llvm::getGlobalContext(); 15 | llvm::llvm_shutdown_obj y; // Call llvm_shutdown() on exit. 16 | 17 | llvm::Module *module = new llvm::Module("testModule", context); 18 | gEnvironment = new Environment(module); 19 | 20 | delete gEnvironment; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /lib/ProductMessage.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_PRODUCT_MESSAGE_H 2 | #define LIBCANAL_PRODUCT_MESSAGE_H 3 | 4 | #include "ProductMessageField.h" 5 | #include 6 | 7 | namespace Canal { 8 | namespace Product { 9 | 10 | class Message 11 | { 12 | public: 13 | typedef std::map Map; 14 | typedef Map::iterator iterator; 15 | typedef Map::const_iterator const_iterator; 16 | 17 | Map mFields; 18 | 19 | public: 20 | virtual ~Message(); 21 | 22 | Message &meet(const Message &other); 23 | }; 24 | 25 | } // namespace Product 26 | } // namespace Canal 27 | 28 | #endif // LIBCANAL_PRODUCT_MESSAGE_H 29 | -------------------------------------------------------------------------------- /tool/CommandDump.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_DUMP_H 2 | #define CANAL_COMMAND_DUMP_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandDump : public Command 7 | { 8 | public: 9 | CommandDump(Commands &commands); 10 | 11 | // Implementation of Command::getCompletionMatches(). 12 | virtual std::vector 13 | getCompletionMatches(const std::vector &args, 14 | int pointArg, 15 | int pointArgOffset) const; 16 | 17 | // Implementation of Command::run(). 18 | virtual void 19 | run(const std::vector &args); 20 | }; 21 | 22 | #endif // CANAL_COMMAND_DUMP_H 23 | -------------------------------------------------------------------------------- /tool/CommandContinue.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandContinue.h" 2 | #include "Commands.h" 3 | #include "State.h" 4 | 5 | CommandContinue::CommandContinue(Commands &commands) 6 | : Command("continue", 7 | "", 8 | "Continue the program being interpreted", 9 | "", 10 | commands) 11 | { 12 | } 13 | 14 | void 15 | CommandContinue::run(const std::vector &args) 16 | { 17 | if (!mCommands.getState() || !mCommands.getState()->isInterpreting()) 18 | { 19 | llvm::outs() << "The program is not being interpreted.\n"; 20 | return; 21 | } 22 | 23 | mCommands.getState()->run(); 24 | } 25 | -------------------------------------------------------------------------------- /tool/CommandHelp.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_HELP_H 2 | #define CANAL_COMMAND_HELP_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandHelp : public Command 7 | { 8 | public: 9 | CommandHelp(Commands &commands); 10 | 11 | // Implementation of Command::getCompletionMatches(). 12 | virtual std::vector getCompletionMatches( 13 | const std::vector &args, 14 | int pointArg, 15 | int pointArgOffset) const; 16 | 17 | // Implementation of Command::run(). 18 | virtual void run(const std::vector &args); 19 | 20 | private: 21 | void allCommandsHelp(); 22 | }; 23 | 24 | #endif // CANAL_COMMAND_HELP_H 25 | -------------------------------------------------------------------------------- /tool/Command.cpp: -------------------------------------------------------------------------------- 1 | #include "Command.h" 2 | 3 | Command::Command(const std::string &name, 4 | const std::string &shortcut, 5 | const std::string &helpLine, 6 | const std::string &help, 7 | Commands &commands) 8 | : mName(name), mShortcut(shortcut), 9 | mHelpLine(helpLine), mHelp(help), mCommands(commands) 10 | { 11 | } 12 | 13 | std::vector 14 | Command::getCompletionMatches(const std::vector &args, 15 | int pointArg, 16 | int pointArgOffset) const 17 | { 18 | // No completion by default. 19 | return std::vector(); 20 | } 21 | -------------------------------------------------------------------------------- /tool/CommandFinish.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandFinish.h" 2 | #include "Commands.h" 3 | #include "State.h" 4 | 5 | CommandFinish::CommandFinish(Commands &commands) 6 | : Command("finish", 7 | "fin", 8 | "Execute until selected stack frame returns", 9 | "Execute until selected stack frame returns.", 10 | commands) 11 | { 12 | } 13 | 14 | void 15 | CommandFinish::run(const std::vector &args) 16 | { 17 | if (!mCommands.getState() || !mCommands.getState()->isInterpreting()) 18 | { 19 | llvm::outs() << "The program is not being interpreted.\n"; 20 | return; 21 | } 22 | 23 | mCommands.getState()->finish(); 24 | } 25 | -------------------------------------------------------------------------------- /lib/FloatUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_FLOAT_UTILS_H 2 | #define LIBCANAL_FLOAT_UTILS_H 3 | 4 | #include "Prereq.h" 5 | 6 | namespace Canal { 7 | namespace Float { 8 | namespace Utils { 9 | 10 | const llvm::fltSemantics &getSemantics(const llvm::Type &type); 11 | 12 | const llvm::Type &getType(const llvm::fltSemantics &semantics, 13 | llvm::LLVMContext &context); 14 | 15 | llvm::APInt toInteger(const llvm::APFloat &num, 16 | unsigned bitWidth, 17 | bool isSigned, 18 | llvm::APFloat::opStatus &status); 19 | 20 | } // namespace Utils 21 | } // namespace Float 22 | } // namespace Canal 23 | 24 | #endif // LIBCANAL_FLOAT_UTILS_H 25 | -------------------------------------------------------------------------------- /tool/IteratorCallback.cpp: -------------------------------------------------------------------------------- 1 | #include "IteratorCallback.h" 2 | 3 | void 4 | IteratorCallback::onFixpointReached() 5 | { 6 | llvm::outs() << "Program finished.\n"; 7 | mFixpointReached = true; 8 | } 9 | 10 | void 11 | IteratorCallback::onFunctionEnter(Canal::Interpreter::Function &function) 12 | { 13 | if (!mFixpointReached) 14 | mFunctionEnter = true; 15 | } 16 | 17 | void 18 | IteratorCallback::onBasicBlockEnter(Canal::Interpreter::BasicBlock &basicBlock) 19 | { 20 | if (!mFixpointReached) 21 | mBasicBlockEnter = true; 22 | } 23 | 24 | void 25 | IteratorCallback::onInstructionExit(const llvm::Instruction &instruction) 26 | { 27 | mFunctionEnter = mBasicBlockEnter = false; 28 | } 29 | -------------------------------------------------------------------------------- /lib/ConfigCMake.h.in: -------------------------------------------------------------------------------- 1 | 2 | /* Define to 1 if you have the header file. */ 3 | #cmakedefine HAVE_GELF_H 1 4 | 5 | /* Define to 1 if you have the `elf' library (-lelf). */ 6 | #cmakedefine HAVE_LIBELF 1 7 | 8 | /* Define to 1 if you have the header file. */ 9 | #cmakedefine HAVE_LIBELF_H 1 10 | 11 | /* Define to 1 if you have the header file. */ 12 | #cmakedefine HAVE_READLINE_READLINE_H 1 13 | 14 | /* LLVM has been compiled with NDEBUG */ 15 | #cmakedefine LLVM_WITH_NDEBUG 1 16 | 17 | /* Have Clang. */ 18 | #cmakedefine HAVE_CLANG 1 19 | 20 | #define LLVM_VERSION_MAJOR @LLVM_VERSION_MAJOR@ 21 | 22 | #define LLVM_VERSION_MINOR @LLVM_VERSION_MINOR@ 23 | 24 | #define VERSION 2 25 | -------------------------------------------------------------------------------- /lib/ProductMessage.cpp: -------------------------------------------------------------------------------- 1 | #include "ProductMessage.h" 2 | #include "ProductMessageField.h" 3 | #include "Utils.h" 4 | 5 | namespace Canal { 6 | namespace Product { 7 | 8 | Message::~Message() 9 | { 10 | for(iterator it = mFields.begin(); it != mFields.end(); ++it) 11 | delete it->second; 12 | } 13 | 14 | Message& Message::meet(const Message& other) 15 | { 16 | for(const_iterator it = other.mFields.begin(); it != other.mFields.end(); ++it) { 17 | if (mFields[it->first]) 18 | mFields[it->first]->meet(*it->second); 19 | else 20 | mFields[it->first] = it->second->clone(); 21 | } 22 | 23 | return *this; 24 | } 25 | 26 | 27 | } // namespace Canal 28 | } // namespace Product 29 | -------------------------------------------------------------------------------- /lib/WideningPointers.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_WIDENING_POINTERS_H 2 | #define LIBCANAL_WIDENING_POINTERS_H 3 | 4 | #include "WideningInterface.h" 5 | 6 | namespace Canal { 7 | namespace Widening { 8 | 9 | class Pointers : public Interface 10 | { 11 | public: 12 | Pointers() : Interface(Interface::PointersKind) 13 | { 14 | } 15 | 16 | virtual void widen(const llvm::BasicBlock &wideningPoint, 17 | Domain &first, 18 | const Domain &second); 19 | 20 | static bool classof(const Interface *value) 21 | { 22 | return value->getKind() == PointersKind; 23 | } 24 | }; 25 | 26 | } // namespace Widening 27 | } // namespace Canal 28 | 29 | #endif // LIBCANAL_WIDENING_POINTERS_H 30 | -------------------------------------------------------------------------------- /lib/WideningDataIterationCount.cpp: -------------------------------------------------------------------------------- 1 | #include "WideningDataIterationCount.h" 2 | 3 | namespace Canal { 4 | namespace Widening { 5 | 6 | int DataIterationCount::ITERATION_COUNT = 2; 7 | 8 | void 9 | DataIterationCount::increase(const llvm::BasicBlock &block) 10 | { 11 | mCounts[&block] = count(block) + 1; 12 | } 13 | 14 | int 15 | DataIterationCount::count(const llvm::BasicBlock &block) const 16 | { 17 | std::map::const_iterator it; 18 | it = mCounts.find(&block); 19 | return it == mCounts.end() ? 0 : it->second; 20 | } 21 | 22 | DataIterationCount * 23 | DataIterationCount::clone() const 24 | { 25 | return new DataIterationCount(*this); 26 | } 27 | 28 | } // namespace Widening 29 | } // namespace Canal 30 | -------------------------------------------------------------------------------- /tests/0-numeric.c: -------------------------------------------------------------------------------- 1 | /* 2 | function main 3 | %^positive 4 | integer 5 | enumeration 3 6 | %^zero 7 | integer 8 | enumeration 0 9 | %^negative 10 | integer 11 | enumeration -8 12 | %^positive_negative 13 | integer 14 | enumeration 12 15 | */ 16 | // clang -emit-llvm -S 0.c 17 | 18 | int 19 | main(int argc, char **argv) 20 | { 21 | int a = 1, b = -4, c = 0; 22 | 23 | int positive = a * a; 24 | positive += a + a; 25 | positive += c; 26 | 27 | int zero = a * c; 28 | zero += b * c; 29 | zero += c; 30 | zero -= c; 31 | 32 | int negative = b * a; 33 | negative += b; 34 | negative += c - c; 35 | 36 | int positive_negative = a + b; 37 | positive_negative *= b; 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /FindLibElf.cmake: -------------------------------------------------------------------------------- 1 | # Find libelf from elfutils 2 | # 3 | # It defines the following variables 4 | # LIBELF_FOUND - If false, do not compile with libelf. 5 | # LIBELF_INCLUDE_DIRS - Where to find headers. 6 | # LIBELF_LIBRARIES - The libraries to link against. 7 | 8 | find_path(LIBELF_H_INCLUDE_DIR libelf.h) 9 | find_path(GELF_H_INCLUDE_DIR gelf.h) 10 | set(LIBELF_INCLUDE_DIRS ${LIBELF_H_INCLUDE_DIR} ${GELF_H_INCLUDE_DIR}) 11 | find_library(LIBELF_LIBRARIES elf) 12 | 13 | include(FindPackageHandleStandardArgs) 14 | 15 | find_package_handle_standard_args( 16 | LibElf 17 | DEFAULT_MSG 18 | LIBELF_LIBRARIES 19 | LIBELF_INCLUDE_DIRS 20 | LIBELF_H_INCLUDE_DIR 21 | GELF_H_INCLUDE_DIR) 22 | 23 | mark_as_advanced(LIBELF_INCLUDE_DIRS LIBELF_LIBRARIES) 24 | -------------------------------------------------------------------------------- /tool/CommandInfo.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_INFO_H 2 | #define CANAL_COMMAND_INFO_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandInfo : public Command 7 | { 8 | public: 9 | CommandInfo(Commands &commands); 10 | 11 | // Implementation of Command::getCompletionMatches(). 12 | virtual std::vector getCompletionMatches( 13 | const std::vector &args, 14 | int pointArg, 15 | int pointArgOffset) const; 16 | 17 | // Implementation of Command::run(). 18 | virtual void run(const std::vector &args); 19 | 20 | private: 21 | void infoModule() const; 22 | void infoFunctions() const; 23 | void infoFunction(const std::string &name) const; 24 | }; 25 | 26 | #endif // CANAL_COMMAND_INFO_H 27 | -------------------------------------------------------------------------------- /lib/WideningDataInterface.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_WIDENING_DATA_INTERFACE_H 2 | #define LIBCANAL_WIDENING_DATA_INTERFACE_H 3 | 4 | #include "Prereq.h" 5 | 6 | namespace Canal { 7 | namespace Widening { 8 | 9 | class DataInterface 10 | { 11 | public: 12 | enum DataInterfaceKind { 13 | DataIterationCountKind 14 | }; 15 | 16 | const DataInterfaceKind mKind; 17 | 18 | public: 19 | DataInterface(DataInterfaceKind kind) : mKind(kind) 20 | { 21 | } 22 | 23 | virtual ~DataInterface() 24 | { 25 | } 26 | 27 | DataInterfaceKind getKind() const 28 | { 29 | return mKind; 30 | } 31 | 32 | virtual DataInterface *clone() const = 0; 33 | }; 34 | 35 | } // namespace Widening 36 | } // namespace Canal 37 | 38 | #endif // LIBCANAL_WIDENING_DATA_INTERFACE_H 39 | -------------------------------------------------------------------------------- /tool/CommandShow.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_SHOW_H 2 | #define CANAL_COMMAND_SHOW_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandShow : public Command 7 | { 8 | public: 9 | CommandShow(Commands &commands); 10 | 11 | // Implementation of Command::getCompletionMatches(). 12 | virtual std::vector getCompletionMatches( 13 | const std::vector &args, 14 | int pointArg, 15 | int pointArgOffset) const; 16 | 17 | // Implementation of Command::run(). 18 | virtual void run(const std::vector &args); 19 | 20 | private: 21 | void showIterator() const; 22 | void showModule() const; 23 | void showFunctions() const; 24 | void showFunction(const std::string &name) const; 25 | }; 26 | 27 | #endif // CANAL_COMMAND_SHOW_H 28 | -------------------------------------------------------------------------------- /tool/CommandRun.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandRun.h" 2 | #include "Commands.h" 3 | #include "State.h" 4 | 5 | CommandRun::CommandRun(Commands &commands) 6 | : Command("run", 7 | "", 8 | "Start program interpretation", 9 | "Start program interpretation.", 10 | commands) 11 | { 12 | } 13 | 14 | void 15 | CommandRun::run(const std::vector &args) 16 | { 17 | if (!mCommands.getState()) 18 | { 19 | llvm::outs() << "No program specified. Use the \"file\" command.\n"; 20 | return; 21 | } 22 | 23 | if (mCommands.getState()->isInterpreting()) 24 | { 25 | llvm::outs() << "The program being interpreted has been started already.\n"; 26 | return; 27 | } 28 | 29 | mCommands.getState()->run(); 30 | } 31 | -------------------------------------------------------------------------------- /lib/PointerUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "PointerUtils.h" 2 | #include "Pointer.h" 3 | #include "Utils.h" 4 | 5 | namespace Canal { 6 | namespace Pointer { 7 | namespace Utils { 8 | 9 | void 10 | addTarget(Canal::Domain &pointer, 11 | Target::Type type, 12 | const llvm::Value *place, 13 | const llvm::Value *target, 14 | const std::vector &offsets, 15 | Canal::Domain *numericOffset) 16 | { 17 | checkedCast(pointer).addTarget(type, 18 | place, 19 | target, 20 | offsets, 21 | numericOffset); 22 | } 23 | 24 | } // namespace Utils 25 | } // namespace Pointer 26 | } // namespace Canal 27 | -------------------------------------------------------------------------------- /lib/WideningNumericalInfinity.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_WIDENING_NUMERICAL_INFINITY_H 2 | #define LIBCANAL_WIDENING_NUMERICAL_INFINITY_H 3 | 4 | #include "WideningInterface.h" 5 | 6 | namespace Canal { 7 | namespace Widening { 8 | 9 | class NumericalInfinity : public Interface 10 | { 11 | public: 12 | NumericalInfinity() : Interface(Interface::NumericalInfinityKind) 13 | { 14 | } 15 | 16 | virtual void widen(const llvm::BasicBlock &wideningPoint, 17 | Domain &first, 18 | const Domain &second); 19 | 20 | static bool classof(const Interface *value) 21 | { 22 | return value->getKind() == NumericalInfinityKind; 23 | } 24 | }; 25 | 26 | } // namespace Widening 27 | } // namespace Canal 28 | 29 | #endif // LIBCANAL_WIDENING_NUMERICAL_INFINITY_H 30 | -------------------------------------------------------------------------------- /tests/file_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TIME=30 4 | 5 | if [ $# -ne 2 ]; then 6 | echo "Usage: canal_tool_binary program_source"; 7 | exit 2 8 | fi 9 | 10 | #Get filename and extension of input file 11 | filename=$(basename "$2"); 12 | extension="${filename##*.}"; 13 | #Change extension to .s 14 | s_filename="${2%%.c}.s" 15 | 16 | 17 | #Run script 18 | ulimit -t $TIME 19 | $1 $2 -e "set no-missing" -e run -e quit 20 | exit_status=$? 21 | 22 | #Check exit status 23 | if [ $exit_status -ne 0 ]; then 24 | exit $exit_status 25 | fi 26 | 27 | #Check for failed compilation 28 | if [ $extension = "c" -a ! -f $s_filename ]; then 29 | echo "Compilation failed" 30 | exit 3 31 | fi 32 | 33 | #Delete .s file it was compiled and everything worked 34 | if [ $extension = "c" ]; then 35 | rm $s_filename 36 | fi 37 | exit 0 38 | -------------------------------------------------------------------------------- /lib/FieldMinMax.h: -------------------------------------------------------------------------------- 1 | #ifndef FIELD_FIELDMINMAX_H 2 | #define FIELD_FIELDMINMAX_H 3 | 4 | #include "ProductMessageField.h" 5 | #include "IntegerInterval.h" 6 | #include 7 | 8 | namespace Canal { 9 | namespace Field { 10 | 11 | class MinMax : public Product::MessageField 12 | { 13 | public: 14 | Integer::Interval* mInterval; 15 | 16 | static bool classof(const MessageField* field) 17 | { 18 | return field->getKind() == FieldMinMaxKind; 19 | } 20 | public: 21 | MinMax(const Integer::Interval& interval); 22 | MinMax(const MinMax& value); 23 | virtual ~MinMax(); 24 | 25 | virtual MessageField* clone() const; 26 | virtual MessageField& meet(const MessageField& other); 27 | }; 28 | 29 | } // namespace Field 30 | } // namespace Canal 31 | 32 | #endif // FIELD_FIELDMINMAX_H 33 | -------------------------------------------------------------------------------- /lib/Interpreter.cpp: -------------------------------------------------------------------------------- 1 | #include "Interpreter.h" 2 | #include "Utils.h" 3 | #include "Pointer.h" 4 | 5 | namespace Canal { 6 | namespace Interpreter { 7 | 8 | Interpreter::Interpreter(llvm::Module *module) 9 | : mEnvironment(module), 10 | mConstructors(mEnvironment), 11 | mModule(*module, mConstructors), 12 | mOperationsCallback(mModule, mConstructors), 13 | mOperations(mEnvironment, mConstructors, mOperationsCallback), 14 | mIterator(mModule, mOperations, mWideningManager) 15 | { 16 | } 17 | 18 | Interpreter::~Interpreter() 19 | { 20 | } 21 | 22 | std::string 23 | Interpreter::toString() const 24 | { 25 | StringStream ss; 26 | ss << mIterator.toString(); 27 | ss << "\n"; 28 | ss << mModule.toString(); 29 | return ss.str(); 30 | } 31 | 32 | } // namespace Interpreter 33 | } // namespace Canal 34 | -------------------------------------------------------------------------------- /tool/CommandSet.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_SET_H 2 | #define CANAL_COMMAND_SET_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandSet : public Command 7 | { 8 | enum Option 9 | { 10 | WideningIterations = 1, 11 | NoMissing, 12 | SetThreshold 13 | }; 14 | 15 | typedef std::map OptionMap; 16 | OptionMap mOptions; 17 | 18 | public: 19 | CommandSet(Commands &commands); 20 | 21 | // Implementation of Command::getCompletionMatches(). 22 | virtual std::vector getCompletionMatches( 23 | const std::vector &args, 24 | int pointArg, 25 | int pointArgOffset) const; 26 | 27 | 28 | // Implementation of Command::run(). 29 | virtual void run(const std::vector &args); 30 | }; 31 | 32 | #endif // CANAL_COMMAND_SET_H 33 | -------------------------------------------------------------------------------- /lib/FieldMinMax.cpp: -------------------------------------------------------------------------------- 1 | #include "FieldMinMax.h" 2 | #include "Utils.h" 3 | 4 | namespace Canal { 5 | namespace Field { 6 | 7 | MinMax::MinMax(const Integer::Interval& interval) 8 | : MessageField(MessageField::FieldMinMaxKind) 9 | { 10 | mInterval = interval.clone(); 11 | } 12 | 13 | MinMax::MinMax(const MinMax& value): MessageField(value) 14 | { 15 | mInterval = value.mInterval->clone(); 16 | } 17 | 18 | 19 | MinMax::~MinMax() 20 | { 21 | delete mInterval; 22 | } 23 | 24 | 25 | Product::MessageField* MinMax::clone() const 26 | { 27 | return new MinMax(*this); 28 | } 29 | 30 | 31 | Product::MessageField& MinMax::meet(const Product::MessageField& other) 32 | { 33 | const MinMax &minMax = checkedCast(other); 34 | mInterval->meet(*minMax.mInterval); 35 | } 36 | 37 | 38 | } // namespace Field 39 | } // namespace Canal 40 | -------------------------------------------------------------------------------- /lib/ProductMessageField.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_PRODUCT_MESSAGE_FIELD_H 2 | #define LIBCANAL_PRODUCT_MESSAGE_FIELD_H 3 | 4 | namespace Canal { 5 | namespace Product { 6 | 7 | class MessageField 8 | { 9 | public: 10 | /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.) 11 | enum MessageFieldKind { 12 | DummyMessageFieldKind, 13 | FieldMinMaxKind 14 | }; 15 | 16 | const MessageFieldKind mKind; 17 | 18 | MessageFieldKind getKind() const 19 | { 20 | return mKind; 21 | } 22 | 23 | public: 24 | MessageField(MessageFieldKind kind) : mKind(kind) {} 25 | virtual ~MessageField() {} 26 | 27 | virtual MessageField &meet(const MessageField &other) = 0; 28 | virtual MessageField* clone() const = 0; 29 | }; 30 | 31 | 32 | } // namespace Product 33 | } // namespace Canal 34 | 35 | #endif // LIBCANAL_PRODUCT_MESSAGE_FIELD_H 36 | -------------------------------------------------------------------------------- /tool/CommandPwd.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandPwd.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | CommandPwd::CommandPwd(Commands &commands) 8 | : Command("pwd", 9 | "", 10 | "Print working directory", 11 | "Print working directory.", 12 | commands) 13 | { 14 | } 15 | 16 | void 17 | CommandPwd::run(const std::vector &args) 18 | { 19 | if (args.size() > 1) 20 | { 21 | llvm::outs() << "Too many arguments.\n"; 22 | return; 23 | } 24 | 25 | int save_errno = errno; 26 | char *cwd = get_current_dir_name(); 27 | if (!cwd) 28 | { 29 | llvm::outs() << "Failed to get working directory: " << strerror(errno) << "\n"; 30 | errno = save_errno; 31 | } 32 | 33 | llvm::outs() << "Working directory " << cwd << ".\n"; 34 | free(cwd); 35 | } 36 | -------------------------------------------------------------------------------- /tests/1-pointer.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static void 4 | swap() 5 | { 6 | int x = 0, y = 1, *px = &x, *py = &y; 7 | int temp; 8 | temp = *px; *px = *py; *py = temp; 9 | } 10 | 11 | static void 12 | array(int i) 13 | { 14 | int a[3] = {0, 1, 2}; 15 | int *j = &a[i]; 16 | int *k = j; 17 | *k = 218; 18 | } 19 | 20 | static void 21 | strcpy_simple(char *s, char *t) 22 | { 23 | while ((*s++ = *t++)) ; 24 | } 25 | 26 | static void 27 | append(char *s) 28 | { 29 | *s++ = 'a'; 30 | *s++ = 'b'; 31 | *s++ = '\0'; 32 | } 33 | 34 | int 35 | main(int argc, char **argv) 36 | { 37 | char s[20]; 38 | append(s); 39 | array(0); 40 | swap(); 41 | 42 | int i = 3, ii = 6, *j, k[i]; 43 | j = &i; 44 | *j = 4; 45 | j = ⅈ 46 | *j = 5; 47 | int *l; 48 | l = j; 49 | j = NULL; 50 | *l = 1; 51 | k[*l] = 0; 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /tool/CommandStart.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandStart.h" 2 | #include "Commands.h" 3 | #include "State.h" 4 | #include "Utils.h" 5 | 6 | CommandStart::CommandStart(Commands &commands) 7 | : Command("start", 8 | "", 9 | "Interpret the program until the beginning of the main procedure", 10 | "Interpret the program until the beginning of the main procedure.", 11 | commands) 12 | { 13 | } 14 | 15 | void 16 | CommandStart::run(const std::vector &args) 17 | { 18 | if (!mCommands.getState()) 19 | { 20 | llvm::outs() << "No program specified. Use the \"file\" command.\n"; 21 | return; 22 | } 23 | 24 | if (mCommands.getState()->isInterpreting()) 25 | { 26 | llvm::outs() << "The program being interpreted has been started already.\n"; 27 | return; 28 | } 29 | 30 | mCommands.getState()->start(); 31 | } 32 | -------------------------------------------------------------------------------- /lib/WideningInterface.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_WIDENING_INTERFACE_H 2 | #define LIBCANAL_WIDENING_INTERFACE_H 3 | 4 | #include "Prereq.h" 5 | 6 | namespace Canal { 7 | 8 | class Domain; 9 | 10 | namespace Widening { 11 | 12 | class Interface 13 | { 14 | public: 15 | enum InterfaceKind { 16 | NumericalInfinityKind, 17 | PointersKind 18 | }; 19 | 20 | const InterfaceKind mKind; 21 | 22 | public: 23 | Interface(InterfaceKind kind) : mKind(kind) 24 | { 25 | } 26 | 27 | virtual ~Interface() 28 | { 29 | } 30 | 31 | InterfaceKind getKind() const 32 | { 33 | return mKind; 34 | } 35 | 36 | virtual void widen(const llvm::BasicBlock &wideningPoint, 37 | Domain &first, 38 | const Domain &second) = 0; 39 | }; 40 | 41 | } // namespace Widening 42 | } // namespace Canal 43 | 44 | #endif // LIBCANAL_WIDENING_INTERFACE_H 45 | -------------------------------------------------------------------------------- /tool/CommandQuit.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandQuit.h" 2 | #include "Commands.h" 3 | #include "State.h" 4 | #include "Utils.h" 5 | #include 6 | 7 | CommandQuit::CommandQuit(Commands &commands) 8 | : Command("quit", 9 | "", 10 | "Exit Canal", 11 | "Exit Canal. If a program is being interpreted, it " 12 | "asks for confirmation before terminating the interpretation.", 13 | commands) 14 | { 15 | } 16 | 17 | void 18 | CommandQuit::run(const std::vector &args) 19 | { 20 | if (mCommands.getState() && mCommands.getState()->isInterpreting()) 21 | { 22 | llvm::outs() << "A program is being interpreted.\n"; 23 | bool agreed = askYesNo("Quit anyway?"); 24 | if (!agreed) 25 | { 26 | llvm::outs() << "Not confirmed.\n"; 27 | return; 28 | } 29 | } 30 | 31 | exit(0); 32 | } 33 | -------------------------------------------------------------------------------- /lib/Environment.cpp: -------------------------------------------------------------------------------- 1 | #include "Environment.h" 2 | #include "Utils.h" 3 | 4 | namespace Canal { 5 | 6 | Environment::Environment(llvm::Module *module) 7 | : mModule(module), mTargetData(module), mSlotTracker(*module) 8 | { 9 | CANAL_ASSERT_MSG(module, "Module cannot be NULL"); 10 | } 11 | 12 | Environment::~Environment() 13 | { 14 | delete mModule; 15 | } 16 | 17 | llvm::LLVMContext & 18 | Environment::getContext() const 19 | { 20 | return mModule->getContext(); 21 | } 22 | 23 | uint64_t 24 | Environment::getTypeStoreSize(const llvm::Type &type) const 25 | { 26 | llvm::Type &modifiableType = const_cast(type); 27 | uint64_t size = mTargetData.getTypeStoreSize(&modifiableType); 28 | CANAL_ASSERT_MSG(mTargetData.getTypeAllocSize(&modifiableType) == size, 29 | "TODO: handle different alloc and store size"); 30 | 31 | return size; 32 | } 33 | 34 | } // namespace Canal 35 | -------------------------------------------------------------------------------- /tool/CommandBreak.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandBreak.h" 2 | #include "Commands.h" 3 | #include "State.h" 4 | 5 | CommandBreak::CommandBreak(Commands &commands) 6 | : Command("break", 7 | "", 8 | "Set breakpoint at specified function", 9 | "Set breakpoint at specified function.", 10 | commands) 11 | { 12 | } 13 | 14 | void 15 | CommandBreak::run(const std::vector &args) 16 | { 17 | if (!mCommands.getState()) 18 | { 19 | llvm::outs() << "No program specified. Use the \"file\" command.\n"; 20 | return; 21 | } 22 | 23 | if (args.size() == 1) 24 | { 25 | // TODO: Add breakpoint to current function. 26 | return; 27 | } 28 | 29 | std::vector::const_iterator it = args.begin() + 1, 30 | itend = args.end(); 31 | 32 | for (; it != itend; ++it) 33 | mCommands.getState()->addFunctionBreakpoint(*it); 34 | } 35 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = lib tool tests docs 2 | 3 | # Automatic update of libtool. 4 | libtool: $(LIBTOOL_DEPS) 5 | $(SHELL) ./config.status libtool 6 | 7 | pkgconfigdir = $(libdir)/pkgconfig 8 | pkgconfig_DATA = canal.pc 9 | DISTCLEANFILES = $(pkgconfig_DATA) 10 | EXTRA_DIST = canal.pc.in 11 | 12 | UPLOAD_URI = kklic@fedorahosted.org:canal 13 | .PHONY: upload 14 | upload: 15 | make dist-gzip 16 | scp $(distdir).tar.gz $(UPLOAD_URI) 17 | make dist-zip 18 | scp $(distdir).zip $(UPLOAD_URI) 19 | make dist-xz 20 | scp $(distdir).tar.xz $(UPLOAD_URI) 21 | 22 | RPM_DIRS = --define "_sourcedir `pwd`" \ 23 | --define "_rpmdir `pwd`" \ 24 | --define "_specdir `pwd`" \ 25 | --define "_builddir `pwd`" \ 26 | --define "_srcrpmdir `pwd`" 27 | 28 | EXTRA_DIST += canal.spec.in 29 | rpm: dist-xz canal.spec 30 | rpmbuild $(RPM_DIRS) -ba canal.spec 31 | srpm: dist-xz canal.spec 32 | rpmbuild $(RPM_DIRS) -bs canal.spec 33 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 2 | INCLUDE(CheckLibraryExists) 3 | INCLUDE(CheckIncludeFiles) 4 | 5 | project(CANAL) 6 | 7 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}) 8 | 9 | SET(CMAKE_BUILD_TYPE "debug") 10 | ENABLE_TESTING() 11 | 12 | find_package(Readline REQUIRED) 13 | find_package(LibElf) 14 | find_package(LLVM REQUIRED) 15 | find_package(Clang REQUIRED) 16 | 17 | include_directories(${LLVM_INCLUDE_DIRS}) 18 | link_directories(${LLVM_LIBRARY_DIRS}) 19 | add_definitions(${LLVM_CFLAGS}) 20 | add_definitions(-DDATADIR="${CMAKE_CURRENT_BINARY_DIR}") 21 | 22 | add_subdirectory("lib/") 23 | add_subdirectory("tool/") 24 | add_subdirectory("tests/") 25 | 26 | SET(HAVE_GELF_H ${LIBELF_FOUND}) 27 | SET(HAVE_LIBELF ${LIBELF_FOUND}) 28 | SET(HAVE_READLINE_READLINE_H ${READLINE_FOUND}) 29 | SET(HAVE_CLANG ${CLANG_FOUND}) 30 | 31 | CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/lib/ConfigCMake.h.in 32 | ${CMAKE_CURRENT_SOURCE_DIR}/lib/Config.h) 33 | -------------------------------------------------------------------------------- /lib/WideningDataIterationCount.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_WIDENING_DATA_ITERATION_COUNT_H 2 | #define LIBCANAL_WIDENING_DATA_ITERATION_COUNT_H 3 | 4 | #include "WideningDataInterface.h" 5 | #include 6 | 7 | namespace Canal { 8 | namespace Widening { 9 | 10 | class DataIterationCount : public DataInterface 11 | { 12 | std::map mCounts; 13 | 14 | public: 15 | static int ITERATION_COUNT; 16 | 17 | public: 18 | DataIterationCount() : DataInterface(DataInterface::DataIterationCountKind) 19 | { 20 | } 21 | 22 | void increase(const llvm::BasicBlock &block); 23 | 24 | int count(const llvm::BasicBlock &block) const; 25 | 26 | virtual DataIterationCount *clone() const; 27 | 28 | static bool classof(const DataInterface *value) 29 | { 30 | return value->getKind() == DataIterationCountKind; 31 | } 32 | }; 33 | 34 | } // namespace Widening 35 | } // namespace Canal 36 | 37 | #endif // LIBCANAL_WIDENING_DATA_ITERATION_COUNT_H 38 | -------------------------------------------------------------------------------- /tests/local.at: -------------------------------------------------------------------------------- 1 | # Source: bison local.at 2 | 3 | # ---------------------------------------- 4 | # AT_COMPILE(OUTPUT, [SOURCES = OUTPUT.c]) 5 | # ---------------------------------------- 6 | # Compile SOURCES into OUTPUT. If OUTPUT does not contain '.', 7 | # assume that we are linking too; this is a hack. 8 | m4_define([AT_COMPILE], 9 | [AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS m4_bmatch([$1], [[.]], [], [$LDFLAGS ])-o $1 m4_default([$2], [$1.c])[]m4_bmatch([$1], [[.]], [], [ $LIBS])], 10 | 0, [ignore], [ignore])]) 11 | 12 | # ------------------------ 13 | # AT_TESTFUN(NAME, SOURCE) 14 | # ------------------------ 15 | 16 | # Create a test named NAME by compiling and running C file with 17 | # contents SOURCE. The stdout and stderr output of the C program is 18 | # ignored by Autotest. 19 | 20 | m4_define([AT_TESTFUN], 21 | [AT_SETUP([$1]) 22 | AT_DATA([$1.c], [$2]) 23 | AT_COMPILE([$1]) 24 | AT_CHECK([./$1], 0, [ignore], [ignore]) 25 | AT_CLEANUP]) 26 | 27 | AT_INIT 28 | AT_COLOR_TESTS 29 | -------------------------------------------------------------------------------- /lib/WideningManager.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_WIDENING_MANAGER_H 2 | #define LIBCANAL_WIDENING_MANAGER_H 3 | 4 | #include "Prereq.h" 5 | #include 6 | 7 | namespace Canal { 8 | 9 | class Domain; 10 | class State; 11 | class StateMap; 12 | 13 | namespace Widening { 14 | 15 | class Interface; 16 | 17 | class Manager 18 | { 19 | public: 20 | Manager(); 21 | virtual ~Manager(); 22 | 23 | void widen(const llvm::BasicBlock &wideningPoint, 24 | State &first, 25 | const State &second) const; 26 | 27 | protected: 28 | void widen(const llvm::BasicBlock &wideningPoint, 29 | StateMap &first, 30 | const StateMap &second) const; 31 | 32 | void widen(const llvm::BasicBlock &wideningPoint, 33 | Domain &first, 34 | const Domain &second) const; 35 | 36 | std::vector mWidenings; 37 | }; 38 | 39 | } // namespace Widening 40 | } // namespace Canal 41 | 42 | #endif // LIBCANAL_WIDENING_MANAGER_H 43 | -------------------------------------------------------------------------------- /tool/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${CANAL_SOURCE_DIR} ${READLINE_INCLUDE_DIRS} ${LIBELF_INCLUDE_DIRS}) 2 | link_directories(${CANAL_SOURCE_DIR}/lib) 3 | 4 | add_executable(canal-tool 5 | Canal.cpp 6 | CommandBreak.cpp 7 | CommandCd.cpp 8 | CommandContinue.cpp 9 | CommandDump.cpp 10 | Command.cpp 11 | CommandFile.cpp 12 | CommandFinish.cpp 13 | CommandHelp.cpp 14 | CommandInfo.cpp 15 | CommandPrint.cpp 16 | CommandPwd.cpp 17 | CommandQuit.cpp 18 | CommandRun.cpp 19 | Commands.cpp 20 | CommandSet.cpp 21 | CommandShow.cpp 22 | CommandStart.cpp 23 | CommandStep.cpp 24 | IteratorCallback.cpp 25 | State.cpp 26 | Utils.cpp 27 | WrapperGcc.cpp) 28 | 29 | target_link_libraries(canal-tool 30 | canal 31 | ${CLANG_LIBS} 32 | ${READLINE_LIBRARIES} 33 | ${LIBELF_LIBRARIES}) 34 | 35 | set_target_properties(canal-tool 36 | PROPERTIES 37 | OUTPUT_NAME canal) 38 | 39 | install(TARGETS canal-tool DESTINATION bin) 40 | -------------------------------------------------------------------------------- /lib/OperationsCallback.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_OPERATIONS_CALLBACK_H 2 | #define LIBCANAL_OPERATIONS_CALLBACK_H 3 | 4 | #include "Prereq.h" 5 | #include 6 | 7 | namespace Canal { 8 | 9 | class Domain; 10 | class State; 11 | 12 | class OperationsCallback 13 | { 14 | public: 15 | virtual ~OperationsCallback() {} 16 | 17 | /// @param callState 18 | /// Contains function arguments and referenced memory blocks. 19 | /// @param resultState 20 | /// A state where the changes caused by the function can be 21 | /// merged. 22 | /// @param resultPlace 23 | /// A place in the resultState where the returned value should 24 | /// be merged. 25 | virtual void onFunctionCall(const llvm::Function &function, 26 | const State &callState, 27 | State &resultState, 28 | const llvm::Value &resultPlace) = 0; 29 | }; 30 | 31 | } // namespace Canal 32 | 33 | #endif // LIBCANAL_OPERATIONS_CALLBACK_H 34 | -------------------------------------------------------------------------------- /tool/CommandPrint.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_COMMAND_PRINT_H 2 | #define CANAL_COMMAND_PRINT_H 3 | 4 | #include "Command.h" 5 | 6 | class CommandPrint : public Command 7 | { 8 | public: 9 | /// Standard constructor. 10 | CommandPrint(Commands &commands); 11 | 12 | /// @note 13 | /// Implements Command::getCompletionMatches(). 14 | virtual std::vector getCompletionMatches( 15 | const std::vector &args, 16 | int pointArg, 17 | int pointArgOffset) const; 18 | 19 | /// @brief 20 | /// Prints current values of variables that were requested by 21 | /// arguments. 22 | /// 23 | /// "@" means all global values are printed. "%" means all local 24 | /// variables of current function are printed. 25 | /// 26 | /// @param args 27 | /// First argument is the name of the command. 28 | /// 29 | /// @note 30 | /// Implements Command::run(). 31 | virtual void run(const std::vector &args); 32 | }; 33 | 34 | #endif // CANAL_COMMAND_PRINT_H 35 | -------------------------------------------------------------------------------- /lib/InterpreterIteratorCallback.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_INTERPRETER_ITERATOR_CALLBACK_H 2 | #define LIBCANAL_INTERPRETER_ITERATOR_CALLBACK_H 3 | 4 | #include "Prereq.h" 5 | 6 | namespace Canal { 7 | namespace Interpreter { 8 | 9 | class BasicBlock; 10 | class Function; 11 | 12 | class IteratorCallback 13 | { 14 | public: 15 | virtual ~IteratorCallback() {} 16 | 17 | virtual void onFixpointReached() {} 18 | 19 | virtual void onModuleEnter() {} 20 | 21 | virtual void onModuleExit() {} 22 | 23 | virtual void onFunctionEnter(Function &function) {} 24 | 25 | virtual void onFunctionExit(Function &function) {} 26 | 27 | virtual void onBasicBlockEnter(BasicBlock &basicBlock) {} 28 | 29 | virtual void onBasicBlockExit(BasicBlock &basicBlock) {} 30 | 31 | virtual void onInstructionEnter(const llvm::Instruction &instruction) {} 32 | 33 | virtual void onInstructionExit(const llvm::Instruction &instruction) {} 34 | }; 35 | 36 | } // namespace Interpreter 37 | } // namespace Canal 38 | 39 | #endif // LIBCANAL_INTERPRETER_ITERATOR_CALLBACK_H 40 | -------------------------------------------------------------------------------- /tool/CommandStep.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandStep.h" 2 | #include "Commands.h" 3 | #include "State.h" 4 | #include "Utils.h" 5 | 6 | CommandStep::CommandStep(Commands &commands) 7 | : Command("step", 8 | "s", 9 | "Step one instruction exactly", 10 | "Step one instruction exactly,", 11 | commands) 12 | { 13 | } 14 | 15 | void 16 | CommandStep::run(const std::vector &args) 17 | { 18 | if (!mCommands.getState() || !mCommands.getState()->isInterpreting()) 19 | { 20 | llvm::outs() << "The program is not being interpreted.\n"; 21 | return; 22 | } 23 | 24 | if (args.size() <= 1) 25 | mCommands.getState()->step(1); 26 | else if (args.size() == 2) 27 | { 28 | bool success; 29 | int count = stringToPositiveInt(args[1].c_str(), success); 30 | if (success) 31 | mCommands.getState()->step(count); 32 | else 33 | llvm::outs() << "Not a positive number: " << args[1] << "\n"; 34 | } 35 | else 36 | llvm::outs() << "Invalid syntax.\n"; 37 | } 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | .deps 3 | .libs 4 | *~ 5 | Makefile 6 | Makefile.in 7 | CMakeFiles 8 | cmake_install.cmake 9 | CTestTestfile.cmake 10 | CMakeCache.txt 11 | 12 | /Testing 13 | /canal.pc 14 | /canal.config 15 | /canal.creator 16 | /canal.files 17 | /canal.includes 18 | /canal.spec 19 | /autom4te.cache 20 | /config.log 21 | /config.status 22 | /libtool 23 | /ar-lib 24 | /INSTALL 25 | /install_manifest.txt 26 | /aclocal.m4 27 | /config.guess 28 | /config.sub 29 | /configure 30 | /depcomp 31 | /install-sh 32 | /ltmain.sh 33 | /missing 34 | 35 | /docs/*.aux 36 | /docs/canal.idx 37 | /docs/canal.ilg 38 | /docs/canal.ind 39 | /docs/canal.log 40 | /docs/canal.out 41 | /docs/canal.toc 42 | /docs/canal.pdf 43 | /docs/doxygen-lib 44 | /docs/doxygen-tool 45 | 46 | /lib/libcanal.la 47 | /lib/libcanal*.lo 48 | /lib/Config.h 49 | /lib/stamp-h1 50 | /lib/libcanal.so 51 | /lib/ConfigAutotools.h.in 52 | 53 | /tool/canal 54 | 55 | /tests/atconfig 56 | /tests/atlocal 57 | /tests/package.m4 58 | /tests/testsuite 59 | /tests/testsuite.log 60 | /tests/testsuite.dir 61 | /tests/*Test 62 | /tests/*.o 63 | /tests/*.s 64 | /tests/integration 65 | 66 | /wrappers/config.py 67 | -------------------------------------------------------------------------------- /lib/ArrayUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "ArrayUtils.h" 2 | #include "ArrayStringPrefix.h" 3 | #include "ProductVector.h" 4 | #include "Utils.h" 5 | 6 | namespace Canal { 7 | namespace Array { 8 | namespace Utils { 9 | 10 | void 11 | strcat(Domain &destination, const Domain &source) 12 | { 13 | Product::Vector &destVector = checkedCast(destination); 14 | const Product::Vector &srcVector = checkedCast(source); 15 | 16 | std::vector::iterator destIt = destVector.mValues.begin(), 17 | destItEnd = destVector.mValues.end(); 18 | 19 | std::vector::const_iterator srcIt = srcVector.mValues.begin(); 20 | 21 | for (; destIt != destItEnd; ++destIt, ++srcIt) 22 | { 23 | StringPrefix *destPrefix = castOrNull(*destIt); 24 | if (!destPrefix) 25 | { 26 | (*destIt)->setTop(); 27 | continue; 28 | } 29 | 30 | const StringPrefix &srcPrefix = checkedCast(**srcIt); 31 | destPrefix->strcat(srcPrefix); 32 | } 33 | } 34 | 35 | } // namespace Utils 36 | } // namespace Array 37 | } // namespace Canal 38 | -------------------------------------------------------------------------------- /tests/ArrayExactSizeTest.cpp: -------------------------------------------------------------------------------- 1 | #include "lib/ArrayExactSize.h" 2 | #include "lib/IntegerInterval.h" 3 | #include "lib/Utils.h" 4 | #include "lib/Environment.h" 5 | #include "lib/Interpreter.h" 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace Canal; 11 | 12 | static Interpreter::Interpreter *gInterpreter; 13 | 14 | static void 15 | testConstructors() 16 | { 17 | const llvm::ArrayType &typeI10 = *llvm::ArrayType::get(llvm::Type::getInt32Ty( 18 | gInterpreter->getEnvironment().getContext()), 10); 19 | 20 | Array::ExactSize array(gInterpreter->getEnvironment(), typeI10); 21 | CANAL_ASSERT(array.isBottom()); 22 | CANAL_ASSERT(array == array); 23 | } 24 | 25 | int 26 | main(int argc, char **argv) 27 | { 28 | llvm::LLVMContext &context = llvm::getGlobalContext(); 29 | llvm::llvm_shutdown_obj y; // Call llvm_shutdown() on exit. 30 | llvm::Module *module = new llvm::Module("testModule", context); 31 | gInterpreter = new Interpreter::Interpreter(module); 32 | 33 | testConstructors(); 34 | 35 | delete gInterpreter; 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(canal SHARED 2 | ArrayExactSize.cpp 3 | ArraySingleItem.cpp 4 | ArrayStringPrefix.cpp 5 | ArrayStringTrie.cpp 6 | ArrayUtils.cpp 7 | Constructors.cpp 8 | Domain.cpp 9 | Environment.cpp 10 | FieldMinMax.cpp 11 | FloatInterval.cpp 12 | FloatUtils.cpp 13 | IntegerBitfield.cpp 14 | IntegerSet.cpp 15 | IntegerInterval.cpp 16 | IntegerUtils.cpp 17 | InterpreterBasicBlock.cpp 18 | InterpreterFunction.cpp 19 | Interpreter.cpp 20 | InterpreterIterator.cpp 21 | InterpreterModule.cpp 22 | InterpreterOperationsCallback.cpp 23 | Operations.cpp 24 | Pointer.cpp 25 | PointerTarget.cpp 26 | PointerUtils.cpp 27 | ProductMessage.cpp 28 | ProductVector.cpp 29 | SlotTracker.cpp 30 | State.cpp 31 | StateMap.cpp 32 | Structure.cpp 33 | Utils.cpp 34 | VariableArguments.cpp 35 | WideningDataIterationCount.cpp 36 | WideningManager.cpp 37 | WideningNumericalInfinity.cpp 38 | WideningPointers.cpp) 39 | 40 | target_link_libraries(canal 41 | ${LLVM_MODULE_LIBS} 42 | ${LLVM_LDFLAGS}) 43 | 44 | install(TARGETS canal DESTINATION lib) 45 | -------------------------------------------------------------------------------- /tool/IteratorCallback.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_ITERATOR_CALLBACK_H 2 | #define CANAL_ITERATOR_CALLBACK_H 3 | 4 | #include "Prereq.h" 5 | #include "lib/InterpreterIteratorCallback.h" 6 | 7 | class IteratorCallback : public Canal::Interpreter::IteratorCallback 8 | { 9 | bool mFixpointReached; 10 | 11 | bool mFunctionEnter; 12 | 13 | bool mBasicBlockEnter; 14 | 15 | public: 16 | IteratorCallback() 17 | : mFixpointReached(false), 18 | mFunctionEnter(false), 19 | mBasicBlockEnter(false) 20 | { 21 | } 22 | 23 | virtual void onFixpointReached(); 24 | 25 | virtual void onFunctionEnter(Canal::Interpreter::Function &function); 26 | 27 | virtual void onBasicBlockEnter(Canal::Interpreter::BasicBlock &basicBlock); 28 | 29 | virtual void onInstructionExit(const llvm::Instruction &instruction); 30 | 31 | bool isFixpointReached() const 32 | { 33 | return mFixpointReached; 34 | } 35 | 36 | bool isFunctionEnter() 37 | { 38 | return mFunctionEnter; 39 | } 40 | 41 | bool isBasicBlockEnter() 42 | { 43 | return mFunctionEnter; 44 | } 45 | }; 46 | 47 | #endif // CANAL_ITERATOR_CALLBACK 48 | -------------------------------------------------------------------------------- /tool/Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = canal 2 | canal_SOURCES = \ 3 | Canal.cpp \ 4 | Command.h \ 5 | Command.cpp \ 6 | CommandBreak.h \ 7 | CommandBreak.cpp \ 8 | CommandCd.h \ 9 | CommandCd.cpp \ 10 | CommandContinue.h \ 11 | CommandContinue.cpp \ 12 | CommandDump.h \ 13 | CommandDump.cpp \ 14 | CommandFile.h \ 15 | CommandFile.cpp \ 16 | CommandFinish.h \ 17 | CommandFinish.cpp \ 18 | CommandHelp.h \ 19 | CommandHelp.cpp \ 20 | CommandInfo.h \ 21 | CommandInfo.cpp \ 22 | CommandPrint.h \ 23 | CommandPrint.cpp \ 24 | CommandPwd.h \ 25 | CommandPwd.cpp \ 26 | CommandQuit.h \ 27 | CommandQuit.cpp \ 28 | CommandRun.h \ 29 | CommandRun.cpp \ 30 | CommandSet.h \ 31 | CommandSet.cpp \ 32 | CommandShow.h \ 33 | CommandShow.cpp \ 34 | CommandStart.h \ 35 | CommandStart.cpp \ 36 | CommandStep.h \ 37 | CommandStep.cpp \ 38 | Commands.h \ 39 | Commands.cpp \ 40 | IteratorCallback.h \ 41 | IteratorCallback.cpp \ 42 | Prereq.h \ 43 | State.h \ 44 | State.cpp \ 45 | Utils.h \ 46 | Utils.cpp \ 47 | WrapperGcc.h \ 48 | WrapperGcc.cpp 49 | 50 | canal_LDADD = $(top_builddir)/lib/libcanal.la -lreadline -lhistory $(LLVM_LDFLAGS) $(LLVM_LIBS) 51 | canal_CPPFLAGS = $(LLVM_CFLAGS) $(LIBEDIT_CFLAGS) -I$(top_srcdir) -DDATADIR='"$(datadir)"' 52 | 53 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${CANAL_SOURCE_DIR}) 2 | link_directories(${CANAL_SOURCE_DIR}/lib) 3 | 4 | set(CANAL_UNIT_TESTS 5 | ArrayExactSizeTest 6 | ArraySingleItemTest 7 | ArrayStringPrefixTest 8 | ArrayStringTrieTest 9 | FloatIntervalTest 10 | IntegerBitfieldTest 11 | IntegerSetTest 12 | IntegerIntervalTest 13 | PointerTest 14 | ProductMessageTest 15 | ProductVectorTest) 16 | 17 | foreach(test ${CANAL_UNIT_TESTS}) 18 | add_executable(${test} "${test}.cpp") 19 | target_link_libraries(${test} canal) 20 | add_test(${test} ${test}) 21 | endforeach() 22 | 23 | add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} DEPENDS ${CANAL_UNIT_TESTS}) 24 | 25 | file(GLOB files "*.c") 26 | foreach(file ${files}) 27 | get_filename_component(name ${file} NAME) 28 | add_test(validate_${name} 29 | "${CMAKE_SOURCE_DIR}/tests/file_test.sh" 30 | ${CMAKE_BINARY_DIR}/tool/canal 31 | ${file}) 32 | endforeach() 33 | 34 | file(GLOB files_integration "integration/*.c") 35 | foreach(file ${files_integration}) 36 | get_filename_component(name ${file} NAME) 37 | add_test(integration_${name} 38 | "${CMAKE_SOURCE_DIR}/tests/file_test.sh" 39 | ${CMAKE_BINARY_DIR}/tool/canal 40 | ${file}) 41 | endforeach() 42 | -------------------------------------------------------------------------------- /lib/InterpreterOperationsCallback.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_INTERPRETER_OPERATIONS_CALLBACK_H 2 | #define LIBCANAL_INTERPRETER_OPERATIONS_CALLBACK_H 3 | 4 | #include "OperationsCallback.h" 5 | 6 | namespace Canal { 7 | 8 | class Constructors; 9 | 10 | namespace Interpreter { 11 | 12 | extern bool printMissing; 13 | 14 | class Module; 15 | 16 | class OperationsCallback : public Canal::OperationsCallback 17 | { 18 | Module &mModule; 19 | Constructors &mConstructors; 20 | 21 | public: 22 | OperationsCallback(Module &module, 23 | Constructors &mConstructors); 24 | 25 | virtual void onFunctionCall(const llvm::Function &function, 26 | const State &callState, 27 | State &resultState, 28 | const llvm::Value &resultPlace); 29 | 30 | // char *strcat(char *destination, const char *source); 31 | void onFunctionCallStrcat(const llvm::Function &function, 32 | const State &callState, 33 | State &resultState, 34 | const llvm::Value &resultPlace); 35 | }; 36 | 37 | } // namespace Interpreter 38 | } // namespace Canal 39 | 40 | #endif // LIBCANAL_INTERPRETER_OPERATIONS_CALLBACK_H 41 | -------------------------------------------------------------------------------- /canal.spec.in: -------------------------------------------------------------------------------- 1 | Name: canal 2 | Version: @PACKAGE_VERSION@ 3 | Release: 1%{?dist} 4 | Summary: LLVM static analysis framework 5 | Group: Development/Libraries 6 | License: GPLv3+ 7 | Source0: https://fedorahosted.org/released/canal/canal-%{version}.tar.xz 8 | BuildRequires: llvm-devel clang-devel 9 | 10 | %description 11 | LLVM static analysis framework. 12 | 13 | %package devel 14 | Summary: Development libraries for %{name} 15 | Group: Development/Libraries 16 | Requires: %{name}%{?_isa} = %{version}-%{release} 17 | 18 | %description devel 19 | Development libraries and headers for %{name}. 20 | 21 | %prep 22 | %setup -q 23 | 24 | %build 25 | %configure 26 | make %{?_smp_mflags} 27 | 28 | %install 29 | make install DESTDIR=%{buildroot} 30 | 31 | # Remove all libtool archives (*.la) from modules directory. 32 | find %{buildroot} -regex ".*\.la$" | xargs rm -f -- 33 | 34 | %check 35 | make check 36 | 37 | %post -p /sbin/ldconfig 38 | %postun -p /sbin/ldconfig 39 | 40 | %files 41 | %doc README NEWS COPYING ChangeLog 42 | %{_bindir}/canal 43 | %{_libdir}/lib*.so.* 44 | /usr/share/canal/wrappers 45 | 46 | %files devel 47 | %{_includedir}/* 48 | %{_libdir}/lib*.so 49 | %{_libdir}/pkgconfig/* 50 | 51 | %changelog 52 | * Thu Mar 8 2012 Karel Klíč - @PACKAGE_VERSION@-1 53 | - Upstream package spec file 54 | -------------------------------------------------------------------------------- /lib/WideningNumericalInfinity.cpp: -------------------------------------------------------------------------------- 1 | #include "WideningNumericalInfinity.h" 2 | #include "WideningDataIterationCount.h" 3 | #include "ProductVector.h" 4 | #include "FloatInterval.h" 5 | #include "Utils.h" 6 | 7 | namespace Canal { 8 | namespace Widening { 9 | 10 | void 11 | NumericalInfinity::widen(const llvm::BasicBlock &wideningPoint, 12 | Domain &first, 13 | const Domain &second) 14 | { 15 | Product::Vector *firstContainer = 16 | dynCast(&first); 17 | 18 | Float::Interval *f = dynCast(&first); 19 | if (!firstContainer && !f) 20 | return; 21 | 22 | DataInterface *data = first.getWideningData(); 23 | DataIterationCount *iterationCount; 24 | if (data) 25 | iterationCount = checkedCast(data); 26 | else 27 | { 28 | iterationCount = new DataIterationCount(); 29 | first.setWideningData(iterationCount); 30 | } 31 | 32 | iterationCount->increase(wideningPoint); 33 | 34 | if (iterationCount->count(wideningPoint) < DataIterationCount::ITERATION_COUNT) 35 | return; 36 | 37 | // Widening. 38 | if (firstContainer) firstContainer->setTop(); 39 | else f->setTop(); 40 | } 41 | 42 | } // namespace Widening 43 | } // namespace Canal 44 | -------------------------------------------------------------------------------- /lib/InterpreterBasicBlock.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_INTERPRETER_BASIC_BLOCK_H 2 | #define LIBCANAL_INTERPRETER_BASIC_BLOCK_H 3 | 4 | #include "State.h" 5 | 6 | namespace Canal { 7 | 8 | class Constructors; 9 | class Environment; 10 | 11 | namespace Interpreter { 12 | 13 | class BasicBlock 14 | { 15 | const llvm::BasicBlock &mBasicBlock; 16 | const Environment &mEnvironment; 17 | 18 | State mInputState; 19 | State mOutputState; 20 | 21 | public: 22 | BasicBlock(const llvm::BasicBlock &basicBlock, 23 | const Constructors &constructors); 24 | 25 | const llvm::BasicBlock &getLlvmBasicBlock() const 26 | { 27 | return mBasicBlock; 28 | } 29 | 30 | llvm::BasicBlock::const_iterator begin() const 31 | { 32 | return mBasicBlock.begin(); 33 | } 34 | 35 | llvm::BasicBlock::const_iterator end() const 36 | { 37 | return mBasicBlock.end(); 38 | } 39 | 40 | State &getInputState() 41 | { 42 | return mInputState; 43 | } 44 | 45 | State &getOutputState() 46 | { 47 | return mOutputState; 48 | } 49 | 50 | /// Get memory usage (used byte count) of this basic block interpretation. 51 | size_t memoryUsage() const; 52 | 53 | std::string toString() const; 54 | }; 55 | 56 | } // namespace Interpreter 57 | } // namespace Canal 58 | 59 | #endif // LIBCANAL_INTERPRETER_BASIC_BLOCK_H 60 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Canal Team 2 | All rights reserved. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal with the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | 1. Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimers. 14 | 15 | 2. Redistributions in binary form must reproduce the above copyright 16 | notice, this list of conditions and the following disclaimers in 17 | the documentation and/or other materials provided with the 18 | distribution. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT 24 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 25 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 26 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE 27 | SOFTWARE. 28 | -------------------------------------------------------------------------------- /tool/Prereq.h: -------------------------------------------------------------------------------- 1 | #ifndef CANAL_PREREQ_H 2 | #define CANAL_PREREQ_H 3 | 4 | #include "lib/Prereq.h" 5 | 6 | #ifdef LLVM_WITH_NDEBUG 7 | # ifndef NDEBUG 8 | # define NDEBUG 9 | # define CANAL_NDEBUG_SWITCHED 10 | # endif 11 | #else 12 | # ifdef NDEBUG 13 | # undef NDEBUG 14 | # define CANAL_NDEBUG_SWITCHED 15 | # endif 16 | #endif 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #ifdef HAVE_CLANG 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | # if CLANG_VERSION_MAJOR < 3 || (CLANG_VERSION_MAJOR == 3 && CLANG_VERSION_MINOR < 2) 37 | # include 38 | # else 39 | # include 40 | # endif 41 | #endif 42 | 43 | #ifdef CANAL_NDEBUG_SWITCHED 44 | # undef CANAL_NDEBUG_SWITCHED 45 | # ifdef NDEBUG 46 | # undef NDEBUG 47 | # else 48 | # define NDEBUG 49 | # endif 50 | #endif 51 | 52 | #endif // CANAL_PREREQ_H 53 | -------------------------------------------------------------------------------- /lib/VariableArguments.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCANAL_VARIABLE_ARGUMENTS_H 2 | #define LIBCANAL_VARIABLE_ARGUMENTS_H 3 | 4 | #include "Prereq.h" 5 | #include 6 | #include 7 | 8 | namespace Canal { 9 | 10 | class Domain; 11 | 12 | class VariableArguments 13 | { 14 | // llvm::Instruction represents the calling instruction providing 15 | // the variable arguments. 16 | typedef std::map > CallMap; 17 | 18 | CallMap mCalls; 19 | 20 | public: 21 | /// Standard constructor. 22 | VariableArguments() {} 23 | 24 | /// Copy constructor. Makes a deep copy of all arguments. 25 | VariableArguments(const VariableArguments &arguments); 26 | 27 | /// Standard destructor. Deletes all arguments. 28 | ~VariableArguments(); 29 | 30 | bool operator==(const VariableArguments &arguments) const; 31 | 32 | /// Merges the arguments per every instruction. 33 | void merge(const VariableArguments &arguments); 34 | 35 | /// Adds an argument at the end of the argument list for an 36 | /// instruction. 37 | void addArgument(const llvm::Instruction &place, Domain *argument); 38 | 39 | private: 40 | /// Assignment operator declaration. Prevents accidental 41 | /// assignments. Do not implement! 42 | VariableArguments &operator=(const VariableArguments &arguments); 43 | }; 44 | 45 | } // namespace Canal 46 | 47 | #endif // LIBCANAL_VARIABLE_ARGUMENTS_H 48 | -------------------------------------------------------------------------------- /lib/InterpreterBasicBlock.cpp: -------------------------------------------------------------------------------- 1 | #include "InterpreterBasicBlock.h" 2 | #include "Constructors.h" 3 | #include "Environment.h" 4 | #include "Utils.h" 5 | 6 | namespace Canal { 7 | namespace Interpreter { 8 | 9 | BasicBlock::BasicBlock(const llvm::BasicBlock &basicBlock, 10 | const Constructors &constructors) 11 | : mBasicBlock(basicBlock), mEnvironment(constructors.getEnvironment()) 12 | { 13 | } 14 | 15 | size_t 16 | BasicBlock::memoryUsage() const 17 | { 18 | size_t result = sizeof(BasicBlock); 19 | result += mInputState.memoryUsage(); 20 | result += mOutputState.memoryUsage(); 21 | return result; 22 | } 23 | 24 | std::string 25 | BasicBlock::toString() const 26 | { 27 | SlotTracker &slotTracker = mEnvironment.getSlotTracker(); 28 | slotTracker.setActiveFunction(*mBasicBlock.getParent()); 29 | 30 | StringStream ss; 31 | ss << "*** basicBlock "; 32 | if (mBasicBlock.hasName()) 33 | ss << mBasicBlock.getName(); 34 | else 35 | ss << "