diff --git a/doc/CPPLINT.cfg b/doc/CPPLINT.cfg new file mode 100644 index 00000000000..51ff339c184 --- /dev/null +++ b/doc/CPPLINT.cfg @@ -0,0 +1 @@ +exclude_files=.* diff --git a/doc/architectural/cbmc-guide.md b/doc/architectural/cbmc-guide.md new file mode 100644 index 00000000000..ccbf0068cea --- /dev/null +++ b/doc/architectural/cbmc-guide.md @@ -0,0 +1,601 @@ +\ingroup module_hidden +\page cbmc-guide CBMC Guide + +\author Martin Brain + +Background Information +====================== + +First off; read the \ref cprover-manual "CProver Manual". It describes +how to get, build and use CBMC and SATABS. This document covers the +internals of the system and how to get started on development. + +Documentation +------------- + +Apart from the (user-orientated) CPROVER manual and this document, most +of the rest of the documentation is inline in the code as `doxygen` and +some comments. A man page for CBMC, goto-cc and goto-instrument is +contained in the `doc/` directory and gives some options for these +tools. All of these could be improved and patches are very welcome. In +some cases the algorithms used are described in the relevant papers. + +Architecture +------------ + +CPROVER is structured in a similar fashion to a compiler. It has +language specific front-ends which perform limited syntactic analysis +and then convert to an intermediate format. The intermediate format can +be output to files (this is what `goto-cc` does) and are (informally) +referred to as “goto binaries” or “goto programs”. The back-end are +tools process this format, either directly from the front-end or from +it’s saved output. These include a wide range of analysis and +transformation tools (see Section \[section:other-apps\]). + +Coding Standards +---------------- + +CPROVER is written in a fairly minimalist subset of C++; templates and +meta-programming are avoided except where necessary. The standard +library is used but in many cases there are alternatives provided in +`util/` (see Section \[section:util\]) which are preferred. Boost is +not used. + +Patches should be formatted so that code is indented with two space +characters, not tab and wrapped to 75 or 72 columns. Headers for doxygen +should be given (and preferably filled!) and the author will be the +person who first created the file. + +Identifiers should be lower case with underscores to separate words. +Types (classes, structures and typedefs) names must[^1] end with a `t`. +Types that model types (i.e. C types in the program that is being +interpreted) are named with `_typet`. For example `ui_message_handlert` +rather than `UI_message_handlert` or `UIMessageHandler` and +`union_typet`. + +How to Contribute +----------------- + +Fixes, changes and enhancements to the CPROVER code base should be +developed against the `trunk` version and submitted to Daniel as patches +produced by `diff -Naur` or `svn diff`. Entire applications are best +developed independently (`git svn` is a popular choice for tracking the +main trunk but also having local development) until it is clear what +their utility, future and maintenance is likely to be. + +Other Useful Code {#section:other-apps} +----------------- + +The CPROVER subversion archive contains a number of separate programs. +Others are developed separately as patches or separate +branches.Interfaces are have been and are continuing to stablise but +older code may require work to compile and function correctly. + +In the main archive: + +* `CBMC`: A bounded model checking tool for C and C++. See Section + \[section:CBMC\]. + +* `goto-cc`: A drop-in, flag compatible replacement for GCC and other + compilers that produces goto-programs rather than executable binaries. + See Section \[section:goto-cc\]. + +* `goto-instrument`: A collection of functions for instrumenting and + modifying goto-programs. See Section \[section:goto-instrument\]. + +Model checkers and similar tools: + +* `SatABS`: A CEGAR model checker using predicate abstraction. Is + roughly 10,000 lines of code (on top of the CPROVER code base) and is + developed in its own subversion archive. It uses an external model + checker to find potentially feasible paths. Key limitations are + related to code with pointers and there is scope for significant + improvement. + +* `Scratch`: Alistair Donaldson’s k-induction based tool. The + front-end is in the old project CVS and some of the functionality is + in `goto-instrument`. + +* `Wolverine`: An implementation of Ken McMillan’s IMPACT algorithm + for sequential programs. In the old project CVS. + +* `C-Impact`: An implementation of Ken McMillan’s IMPACT algorithm for + parallel programs. In the old project CVS. + +* `LoopFrog`: A loop summarisation tool. + +* `???`: Christoph’s termination analyser. + +Test case generation: + +* `cover`: A basic test-input generation tool. In the old + project CVS. + +* `FShell`: A test-input generation tool that allows the user to + specify the desired coverage using a custom language (which includes + regular expressions over paths). It uses incremental SAT and is thus + faster than the naïve “add assertions one at a time and use the + counter-examples” approach. Is developed in its own subversion. + +Alternative front-ends and input translators: + +* `Scoot`: A System-C to C translator. Probably in the old + project CVS. + +* `???`: A Simulink to C translator. In the old project CVS. + +* `???`: A Verilog front-end. In the old project CVS. + +* `???`: A converter from Codewarrior project files to Makefiles. In + the old project CVS. + +Other tools: + +* `ai`: Leo’s hybrid abstract interpretation / CEGAR tool. + +* `DeltaCheck?`: Ajitha’s slicing tool, aimed at locating changes and + differential verification. In the old project CVS. + +There are tools based on the CPROVER framework from other research +groups which are not listed here. + +Source Walkthrough +================== + +This section walks through the code bases in a rough order of interest / +comprehensibility to the new developer. + +`doc` +----- + +At the moment just contains the CBMC man page. + +`regression/` +------------- + +The regression tests are currently being moved from CVS. The +`regression/` directory contains all of those that have +been moved. They are grouped into directories for each of the tools. +Each of these contains a directory per test case, containing a C or C++ +file that triggers the bug and a `.dsc` file that describes +the tests, expected output and so on. There is a Perl script, +`test.pl` that is used to invoke the tests as: + + ../test.pl -c PATH_TO_CBMC + +The `–help` option gives instructions for use and the +format of the description files. + +`src/` +------ + +The source code is divided into a number of sub-directories, each +containing the code for a different part of the system. In the top level +files there are only a few files: + +* `config.inc`: The user-editable configuration parameters for the + build process. The main use of this file is setting the paths for the + various external SAT solvers that are used. As such, anyone building + from source will likely need to edit this. + +* `Makefile`: The main systems Make file. Parallel builds are + supported and encouraged; please don’t break them! + +* `common`: System specific magic required to get the system to build. + This should only need to be edited if porting CBMC to a new platform / + build environment. + +* `doxygen.cfg`: The config file for doxygen.cfg + +### `util/` {#section:util} + +`util/` contains the low-level data structures and +manipulation functions that are used through-out the CPROVER code-base. +For almost any low-level task, the code required is probably in +`util/`. Key files include: + +* `irep.h`: This contains the definition of `irept`, the basis of many + of the data structures in the project. They should not be used + directly; one of the derived classes should be used. For more + information see Section \[section:irept\]. + +* `expr.h`: The parent class for all of the expressions. Provides a + number of generic functions, `exprt` can be used with these but when + creating data, subclasses of `exprt` should be used. + +* `std_expr.h`: Provides subclasses of `exprt` for common kinds of + expression for example `plus_exprt`, `minus_exprt`, + `dereference_exprt`. These are the intended interface for creating + expressions. + +* `std_types.h`: Provides subclasses of `typet` (a subclass of + `irept`) to model C and C++ types. This is one of the preferred + interfaces to `irept`. The front-ends handle type promotion and most + coercision so the type system and checking goto-programs is simpler + than C. + +* `dstring.h`: The CPROVER string class. This enables sharing between + strings which significantly reduces the amount of memory required and + speeds comparison. `dstring` should not be used directly, `irep_idt` + should be used instead, which (dependent on build options) is an alias + for `dstring`. + +* `mp_arith.h`: The wrapper class for multi-precision arithmetic + within CPROVER. Also see `arith_tools.h`. + +* `ieee_float.h`: The arbitrary precision float model used within + CPROVER. Based on `mp_integer`s. + +* `context.h`: A generic container for symbol table like constructs + such as namespaces. Lookup gives type, location of declaration, name, + ‘pretty name’, whether it is static or not. + +* `namespace.h`: The preferred interface for the context class. The + key function is `lookup` which converts a string (`irep_idt`) to a + symbol which gives the scope of declaration, type and so on. This + works for functions as well as variables. + +### `langapi/` + +This contains the basic interfaces and support classes for programming +language front ends. Developers only really need look at this if they +are adding support for a new language. It’s main users are the two (in +trunk) language front-ends; `ansi-c/` and +`cpp/`. + +### `ansi-c/` + +Contains the front-end for ANSI C, plus a variety of common extensions. +This parses the file, performs some basic sanity checks (this is one +area in which the UI could be improved; patches most welcome) and then +produces a goto-program (see below). The parser is a traditional Flex / +Bison system. + +`internal_addition.c` contains the implementation of various ‘magic’ +functions that are that allow control of the analysis from the source +code level. These include assertions, assumptions, atomic blocks, memory +fences and rounding modes. + +The `library/` subdirectory contains versions of some of the C standard +header files that make use of the CPROVER built-in functions. This +allows CPROVER programs to be ‘aware’ of the functionality and model it +correctly. Examples include `stdio.c`, `string.c`, `setjmp.c` and +various threading interfaces. + +### `cpp/` + +This directory contains the C++ front-end. It supports the subset of C++ +commonly found in embedded and system applications. Consequentially it +doesn’t have full support for templates and many of the more advanced +and obscure C++ features. The subset of the language that can be handled +is being extended over time so bug reports of programs that cannot be +parsed are useful. + +The functionality is very similar to the ANSI C front end; parsing the +code and converting to goto-programs. It makes use of code from +`langapi` and `ansi-c`. + +### `goto-programs/` + +Goto programs are the intermediate representation of the CPROVER tool +chain. They are language independent and similar to many of the compiler +intermediate languages. Section \[section:goto-programs\] describes the +`goto_programt` and `goto_functionst` data structures in detail. However +it useful to understand some of the basic concepts. Each function is a +list of instructions, each of which has a type (one of 18 kinds of +instruction), a code expression, a guard expression and potentially some +targets for the next instruction. They are not natively in static +single-assign (SSA) form. Transitions are nondeterministic (although in +practise the guards on the transitions normally cover form a disjoint +cover of all possibilities). Local variables have non-deterministic +values if they are not initialised. Variables and data within the +program is commonly one of three types (parameterised by width): +`unsignedbv_typet`, `signedbv_typet` and `floatbv_typet`, see +`util/std_types.h` for more information. Goto programs can be serialised +in a binary (wrapped in ELF headers) format or in XML (see the various +`_serialization` files). + +The `cbmc` option `–show-goto-programs` is often a good starting point +as it outputs goto-programs in a human readable form. However there are +a few things to be aware of. Functions have an internal name (for +example `c::f00`) and a ‘pretty name’ (for example `f00`) and which is +used depends on whether it is internal or being presented to the user. +The `main` method is the ‘logical’ main which is not necessarily the +main method from the code. In the output `NONDET` is use to represent a +nondeterministic assignment to a variable. Likewise `IF` as a beautified +`GOTO` instruction where the guard expression is used as the condition. +`RETURN` instructions may be dropped if they precede an `END_FUNCTION` +instruction. The comment lines are generated from the `locationt` field +of the `instructiont` structure. + +`goto-programs/` is one of the few places in the CPROVER codebase that +templates are used. The intention is to allow the general architecture +of program and functions to be used for other formalisms. At the moment +most of the templates have a single instantiation; for example +`goto_functionst` and `goto_function_templatet` and `goto_programt` and +`goto_program_templatet`. + +### `goto-symex/` + +This directory contains a symbolic evaluation system for goto-programs. +This takes a goto-program and translates it to an equation system by +traversing the program, branching and merging and unwinding loops as +needed. Each reverse goto has a separate counter (the actual counting is +handled by `cbmc`, see the `–unwind` and `–unwind-set` options). When a +counter limit is reach, an assertion can be added to explicitly show +when analysis is incomplete. The symbolic execution includes constant +folding so loops that have a constant number of iterations will be +handled completely (assuming the unwinding limit is sufficient). + +The output of the symbolic execution is a system of equations; an object +containing a list of `symex_target_elements`, each of which are +equalities between `expr` expressions. See `symex_target_equation.h`. +The output is in static, single assignment (SSA) form, which is *not* +the case for goto-programs. + +### `pointer-analysis/` + +To perform symbolic execution on programs with dereferencing of +arbitrary pointers, some alias analysis is needed. `pointer-analysis` +contains the three levels of analysis; flow and context insensitive, +context sensitive and flow and context sensitive. The code needed is +subtle and sophisticated and thus there may be bugs. + +### `solvers/` + +The `solvers/` directory contains interfaces to a number of +different decision procedures, roughly one per directory. + +* prop/: The basic and common functionality. The key file is + `prop_conv.h` which defines `prop_convt`. This is the base class that + is used to interface to the decision procedures. The key functions are + `convert` which takes an `exprt` and converts it to the appropriate, + solver specific, data structures and `dec_solve` (inherited from + `decision_proceduret`) which invokes the actual decision procedures. + Individual decision procedures (named `*_dect`) objects can be created + but `prop_convt` is the preferred interface for code that uses them. + +* flattening/: A library that converts operations to bit-vectors, + including calling the conversions in `floatbv` as necessary. Is + implemented as a simple conversion (with caching) and then a + post-processing function that adds extra constraints. This is not used + by the SMT or CVC back-ends. + +* dplib/: Provides the `dplib_dect` object which used the decision + procedure library from “Decision Procedures : An Algorithmic Point of + View”. + +* cvc/: Provides the `cvc_dect` type which interfaces to the old (pre + SMTLib) input format for the CVC family of solvers. This format is + still supported by depreciated in favour of SMTLib 2. + +* smt1/: Provides the `smt1_dect` type which converts the formulae to + SMTLib version 1 and then invokes one of Boolector, CVC3, OpenSMT, + Yices, MathSAT or Z3. Again, note that this format is depreciated. + +* smt2/: Provides the `smt2_dect` type which functions in a similar + way to `smt1_dect`, calling Boolector, CVC3, MathSAT, Yices or Z3. + Note that the interaction with the solver is batched and uses + temporary files rather than using the interactive command supported by + SMTLib 2. With the `–fpa` option, this output mode will not flatten + the floating point arithmetic and instead output the proposed SMTLib + floating point standard. + +* qbf/: Back-ends for a variety of QBF solvers. Appears to be no + longer used or maintained. + +* sat/: Back-ends for a variety of SAT solvers and DIMACS output. + +### `cbmc/` {#section:CBMC} + +This contains the first full application. CBMC is a bounded model +checker that uses the front ends (`ansi-c`, `cpp`, goto-program or +others) to create a goto-program, `goto-symex` to unwind the loops the +given number of times and to produce and equation system and finally +`solvers` to find a counter-example (technically, `goto-symex` is then +used to construct the counter-example trace). + +### `goto-cc/` {#section:goto-cc} + +`goto-cc` is a compiler replacement that just performs the first step of +the process; converting C or C++ programs to goto-binaries. It is +intended to be dropped in to an existing build procedure in place of the +compiler, thus it emulates flags that would affect the semantics of the +code produced. Which set of flags are emulated depends on the naming of +the `goto-cc/` binary. If it is called `goto-cc` then it emulates GCC +flags, `goto-armcc` emulates the ARM compiler, `goto-cl` emulates VCC +and `goto-cw` emulates the Code Warrior compiler. The output of this +tool can then be used with `cbmc` or `goto-instrument`. + +### `goto-instrument/` {#section:goto-instrument} + +The `goto-instrument/` directory contains a number of tools, one per +file, that are built into the `goto-instrument` program. All of them +take in a goto-program (produced by `goto-cc`) and either modify it or +perform some analysis. Examples include `nondet_static.cpp` which +initialises static variables to a non-deterministic value, +`nondet_volatile.cpp` which assigns a non-deterministic value to any +volatile variable before it is read and `weak_memory.h` which performs +the necessary transformations to reason about weak memory models. The +exception to the “one file for each piece of functionality” rule are the +program instrumentation options (mostly those given as “Safety checks” +in the `goto-instrument` help text) which are included in the +`goto-program/` directory. An example of this is +`goto-program/stack_depth.h` and the general rule seems to be that +transformations and instrumentation that `cbmc` uses should be in +`goto-program/`, others should be in `goto-instrument`. + +`goto-instrument` is a very good template for new analysis tools. New +developers are advised to copy the directory, remove all files apart +from `main.*`, `parseoptions.*` and the `Makefile` and use these as the +skeleton of their application. The `doit()` method in `parseoptions.cpp` +is the preferred location for the top level control for the program. + +### `linking/` + +Probably the code to emulate a linker. This allows multiple ‘object +files’ (goto-programs) to be linked into one ‘executable’ (another +goto-program), thus allowing existing build systems to be used to build +complete goto-program binaries. + +### `big-int/` + +CPROVER is distributed with its own multi-precision arithmetic library; +mainly for historical and portability reasons. The library is externally +developed and thus `big-int` contains the source as it is distributed. +This should not be used directly, see `util/mp_arith.h` for the CPROVER +interface. + +### `xmllang/` + +CPROVER has optional XML output for results and there is an XML format +for goto-programs. It is used to interface to various IDEs. The +`xmllang/` directory contains the parser and helper functions for +handling this format. + +### `floatbv/` + +This library contains the code that is used to convert floating point +variables (`floatbv`) to bit vectors (`bv`). This is referred to as +‘bit-blasting’ and is called in the `solver` code during conversion to +SAT or SMT. It also contains the abstraction code described in the +FMCAD09 paper. + +Data Structures +=============== + +This section discusses some of the key data-structures used in the +CPROVER codebase. + +`irept` {#section:irept} +------------------------ + +There are a large number of kind of tree structured or tree-like data in +CPROVER. `irept` provides a single, unified representation for all of +these, allowing structure sharing and reference counting of data. As +such `irept` is the basic unit of data in CPROVER. Each `irept` +contains[^2] a basic unit of data (of type `dt`) which contains four +things: + +* `data`: A string[^3], which is returned when the `id()` function is + used. + +* `named_sub`: A map from `irep_namet` (a string) to an `irept`. This + is used for named children, i.e. subexpressions, parameters, etc. + +* `comments`: Another map from `irep_namet` to `irept` which is used + for annotations and other ‘non-semantic’ information + +* `sub`: A vector of `irept` which is used to store ordered but + unnamed children. + +The `irept::pretty` function outputs the contents of an `irept` directly +and can be used to understand an debug problems with `irept`s. + +On their own `irept`s do not “mean” anything; they are effectively +generic tree nodes. Their interpretation depends on the contents of +result of the `id` function (the `data`) field. `util/irep_ids.txt` +contains the complete list of `id` values. During the build process it +is used to generate `util/irep_ids.h` which gives constants for each id +(named `ID_`). These can then be used to identify what kind of data +`irept` stores and thus what can be done with it. + +To simplify this process, there are a variety of classes that inherit +from `irept`, roughly corresponding to the ids listed (i.e. `ID_or` +(the string `"or”`) corresponds to the class `or_exprt`). These give +semantically relevant accessor functions for the data; effectively +different APIs for the same underlying data structure. None of these +classes add fields (only methods) and so static casting can be used. The +inheritance graph of the subclasses of `irept` is a useful starting +point for working out how to manipulate data. + +There are three main groups of classes (or APIs); those derived from +`typet`, `codet` and `exprt` respectively. Although all of these inherit +from `irept`, these are the most abstract level that code should handle +data. If code is manipulating plain `irept`s then something is wrong +with the architecture of the code. + +Many of the key descendent of `exprt` are declared in `std_expr.h`. All +expressions have a named subfield / annotation which gives the type of +the expression (slightly simplified from C/C++ as `unsignedbv_typet`, +`signedbv_typet`, `floatbv_typet`, etc.). All type conversions are +explicit with an expression with `id() == ID_typecast` and an ‘interface +class’ named `typecast_exprt`. One key descendent of `exprt` is +`symbol_exprt` which creates `irept` instances with the id of “symbol”. +These are used to represent variables; the name of which can be found +using the `get_identifier` accessor function. + +`codet` inherits from `exprt` and is defined in `std_code.h`. They +represent executable code; statements in C rather than expressions. In +the front-end there are versions of these that hold whole code blocks, +but in goto-programs these have been flattened so that each `irept` +represents one sequence point (almost one line of code / one +semi-colon). The most common descendents of `codet` are `code_assignt` +so a common pattern is to cast the `codet` to an assignment and then +recurse on the expression on either side. + +`goto-programs` {#section:goto-programs} +---------------------------------------- + +The common starting point for working with goto-programs is the +`read_goto_binary` function which populates an object of +`goto_functionst` type. This is defined in `goto_functions.h` and is an +instantiation of the template `goto_functions_templatet` which is +contained in `goto_functions_template.h`. They are wrappers around a map +from strings to `goto_programt`’s and iteration macros are provided. +Note that `goto_function_templatet` (no `s`) is defined in the same +header as `goto_functions_templatet` and is gives the C type for the +function and Boolean which indicates whether the body is available +(before linking this might not always be true). Also note the slightly +counter-intuitive naming; `goto_functionst` instances are the top level +structure representing the program and contain `goto_programt` instances +which represent the individual functions. At the time of writing +`goto_functionst` is the only instantiation of the template +`goto_functions_templatet` but other could be produced if a different +data-structures / kinds of models were needed for functions. + +`goto_programt` is also an instantiation of a template. In a similar +fashion it is `goto_program_templatet` and allows the types of the guard +and expression used in instructions to be parameterised. Again, this is +currently the only use of the template. As such there are only really +helper functions in `goto_program.h` and thus `goto_program_template.h` +is probably the key file that describes the representation of (C) +functions in the goto-program format. It is reasonably stable and +reasonably documented and thus is a good place to start looking at the +code. + +An instance of `goto_program_templatet` is effectively a list of +instructions (and inner template called `instructiont`). It is important +to use the copy and insertion functions that are provided as iterators +are used to link instructions to their predecessors and targets and +careless manipulation of the list could break these. Likewise there are +helper macros for iterating over the instructions in an instance of +`goto_program_templatet` and the use of these is good style and strongly +encouraged. + +Individual instructions are instances of type `instructiont`. They +represent one step in the function. Each has a type, an instance of +`goto_program_instruction_typet` which denotes what kind of instruction +it is. They can be computational (such as `ASSIGN` or `FUNCTION_CALL`), +logical (such as `ASSUME` and `ASSERT`) or informational (such as +`LOCATION` and `DEAD`). At the time of writing there are 18 possible +values for `goto_program_instruction_typet` / kinds of instruction. +Instructions also have a guard field (the condition under which it is +executed) and a code field (what the instruction does). These may be +empty depending on the kind of instruction. In the default +instantiations these are of type `exprt` and `codet` respectively and +thus covered by the previous discussion of `irept` and its descendents. +The next instructions (remembering that transitions are guarded by +non-deterministic) are given by the list `targets` (with the +corresponding list of labels `labels`) and the corresponding set of +previous instructions is get by `incoming_edges`. Finally `instructiont` +have informational `function` and `location` fields that indicate where +they are in the code. + +[^1]: There are a couple of exceptions, including the graph classes + +[^2]: Or references, if reference counted data sharing is enabled. It is + enabled by default; see the `SHARING` macro. + +[^3]: When `USE_DSTRING` is enabled (it is by default), this is actually +a `dstring` and thus an integer which is a reference into a string table diff --git a/doc/architectural/front-page.md b/doc/architectural/front-page.md new file mode 100644 index 00000000000..13e832074a8 --- /dev/null +++ b/doc/architectural/front-page.md @@ -0,0 +1,46 @@ +CProver Documentation +===================== + +\author Kareem Khazem + +These pages contain user tutorials, automatically-generated API +documentation, and higher-level architectural overviews for the +CProver codebase. Users can download CProver tools from the +CProver website; contributors +should use the repository +hosted on GitHub. + +### For users: + +* The \ref cprover-manual "CProver Manual" details the capabilities of + CBMC and SATABS and describes how to install and use these tools. It + also covers the underlying theory and prerequisite concepts behind how + these tools work. + +### For contributors: + +* If you already know exactly what you're looking for, the API reference + is generated from the codebase. You can search for classes and class + members in the search bar at top-right or use one of the links in the + sidebar. + +* For higher-level architectural information, each of the pages under + the "Modules" link in the sidebar gives an overview of a directory in + the CProver codebase. + +* The \ref module_cbmc "CBMC guided tour" is a good start for new + contributors to CBMC. It describes the stages through which CBMC + transforms source files into bug reports and counterexamples, linking + to the relevant documentation for each stage. + +* The \subpage cbmc-hacking "CBMC hacking HOWTO" helps new contributors + to CProver to get their feet wet through a series of programming + exercises---mostly modifying goto-instrument, and thus learning to + manipulate the main data structures used within CBMC. + +* The \subpage cbmc-guide "CBMC guide" is a single document describing + the layout of the codebase and many of the important data structures. + It probably contains more information than the module pages at the + moment, but may be somewhat out-of-date. + +\defgroup module_hidden _hidden diff --git a/doc/architectural/howto.md b/doc/architectural/howto.md new file mode 100644 index 00000000000..5eee0f0058f --- /dev/null +++ b/doc/architectural/howto.md @@ -0,0 +1,243 @@ +\ingroup module_hidden +\page cbmc-hacking CBMC Hacking HOWTO + +\author Kareem Khazem + +This is an introduction to hacking on the `cprover` codebase. It is not +intended as a user guide to `CBMC` or related tools. It is structured +as a series of programming exercises that aim to acclimatise the reader +to the basic data structures and workflow needed for contributing to +`CBMC`. + + +## Initial setup + +Clone the [CBMC repository][cbmc-repo] and build it: + + git clone https://github.com/diffblue/cbmc.git + cd cbmc/src + make minisat2-download + make + +Ensure that [graphviz][graphviz] is installed on your system (in +particular, you should be able to run a program called `dot`). Install +[Doxygen][doxygen] and generate doxygen documentation: + + # In the src directory + doxygen doxyfile + # View the documentation in a web browser + firefox doxy/html/index.html + +If you've never used doxygen documentation before, get familiar with the +layout. Open the generated HTML page in a web browser; search for the +class `goto_programt` in the search bar, and jump to the documentation +for that class; and read through the copious documentation. + +The build writes executable programs into several of the source +directories. In this tutorial, we'll be using binaries inside the +`cbmc`, `goto-instrument`, and `goto-cc` directories. Add these +directories to your `$PATH`: + + # Assuming you cloned CBMC into ~/code + export PATH=~/code/cbmc/src/goto-instrument:~/code/cbmc/src/goto-cc:~/code/cbmc/src/cbmc:$PATH + # Add to your shell's startup configuration file so that you don't have to run that command every time. + echo 'export PATH=~/code/cbmc/src/goto-instrument:~/code/cbmc/src/goto-cc:~/code/cbmc/src/cbmc:$PATH' >> .bashrc + +Optional: install an image viewer that can read images on stdin. +I use [feh][feh]. + +[cbmc-repo]: https://github.com/diffblue/cbmc/ +[doxygen]: http://www.stack.nl/~dimitri/doxygen/ +[graphviz]: http://www.graphviz.org/ +[feh]: https://feh.finalrewind.org/ + + + +## Whirlwind tour of the tools + +CBMC's code is located under the `cbmc` directory. Even if you plan to +contribute only to CBMC, it is important to be familiar with several +other of cprover's auxiliary tools. + + +### Compiling with `goto-cc` + +There should be an executable file called `goto-cc` in the `goto-cc` +directory; make a symbolic link to it called `goto-gcc`: + + cd cbmc/src/goto-cc + ln -s "$(pwd)/goto-cc" goto-gcc + +Find or write a moderately-interesting C program; we'll call it `main.c`. +Run the following commands: + + goto-gcc -o main.goto main.c + cc -o main.exe main.c + +Invoke `./main.goto` and `./main.exe` and observe that they run identically. +The version that was compiled with `goto-gcc` is larger, though: + + du -hs *.{goto,exe} + +Programs compiled with `goto-gcc` are mostly identical to their `clang`- +or `gcc`-compiled counterparts, but contain additional object code in +cprover's intermediate representation. The intermediate representation +is (informally) called a *goto-program*. + + +### Viewing goto-programs + +`goto-instrument` is a Swiss army knife for viewing goto-programs and +performing single program analyses on them. Run the following command: + + goto-instrument --show-goto-functions main.goto + +Many of the instructions in the goto-program intermediate representation +are similar to their C counterparts. `if` and `goto` statements replace +structured programming constructs. + +Find or write a small C program (2 or 3 functions, each containing a few +varied statements). Compile it using `goto-gcc` as above into an object +file called `main`. If you installed `feh`, try the following command +to dump a control-flow graph: + + goto-instrument --dot main | tail -n +2 | dot -Tpng | feh - + +If you didn't install `feh`, you can write the diagram to the file and +then view it: + + goto-instrument --dot main | tail -n +2 | dot -Tpng > main.png + Now open main.png with an image viewer + +(the invocation of `tail` is used to filter out the first line of +`goto-instrument` output. If `goto-instrument` writes more or less +debug output by the time you read this, read the output of +`goto-instrument --dot main` and change the invocation of `tail` +accordingly.) + +There are a few other views of goto-programs. Run `goto-instrument -h` +and try the various switches under the "Diagnosis" section. + + + +## Learning about goto-programs + +In this section, you will learn about the basic goto-program data +structures. Reading from and manipulating these data structures form +the core of writing an analysis for CBMC. + + +### First steps with `goto-instrument` + +
-The following sections summarize the functions available to programs -that are passed to the CPROVER tools. -
- -
-void __CPROVER_assume(_Bool assumption);
-void __CPROVER_assert(_Bool assertion, const char *description);
-void assert(_Bool assertion);
-
--The function __CPROVER_assume adds an expression as a constraint -to the program. If the expression evaluates to false, the execution -aborts without failure. More detail on the use of assumptions is -in the section on Assumptions -and Assertions. -
- -
-_Bool __CPROVER_same_object(const void *, const void *);
-unsigned __CPROVER_POINTER_OBJECT(const void *p);
-signed __CPROVER_POINTER_OFFSET(const void *p);
-_Bool __CPROVER_DYNAMIC_OBJECT(const void *p);
-
--The function __CPROVER_same_object returns true -if the two pointers given as arguments point to the same -object. -The function __CPROVER_POINTER_OFFSET returns -the offset of the given pointer relative to the base -address of the object. -The function __CPROVER_DYNAMIC_OBJECT -returns true if the pointer passed -as arguments points to a dynamically allocated object. -
- -
-_Bool __CPROVER_is_zero_string(const void *);
-__CPROVER_size_t __CPROVER_zero_string_length(const void *);
-__CPROVER_size_t __CPROVER_buffer_size(const void *);
-
--
- -
-void __CPROVER_initialize(void);
-
--The function __CPROVER_initialize computes the initial -state of the program. It is called prior to calling the -main procedure of the program. -
- -
-void __CPROVER_input(const char *id, ...);
-void __CPROVER_output(const char *id, ...);
-
--The functions __CPROVER_input and __CPROVER_output -are used to report an input or output value. Note that they do not generate -input or output values. The first argument is a string constant -to distinguish multiple inputs and outputs (inputs are typically -generated using nondeterminism, as described -here). -The string constant is followed by an arbitrary number of values of -arbitrary types. -
- -
-void __CPROVER_cover(_Bool condition);
-
-This statement defines a custom coverage criterion, for usage -with the test suite generation feature.
- --
- -
-_Bool __CPROVER_isnan(double f);
-_Bool __CPROVER_isfinite(double f);
-_Bool __CPROVER_isinf(double f);
-_Bool __CPROVER_isnormal(double f);
-_Bool __CPROVER_sign(double f);
-
--The function __CPROVER_isnan returns true if the double-precision -floating-point number passed as argument is a -NaN. -
- --The function __CPROVER_isfinite returns true if the double-precision -floating-point number passed as argument is a -finite number. -
- --This function __CPROVER_isinf returns true if the double-precision -floating-point number passed as argument is plus -or minus infinity. -
- --The function __CPROVER_isnormal returns true if the double-precision -floating-point number passed as argument is a -normal number. -
- --This function __CPROVER_sign returns true if the double-precision -floating-point number passed as argument is -negative. -
- -
-int __CPROVER_abs(int x);
-long int __CPROVER_labs(long int x);
-double __CPROVER_fabs(double x);
-long double __CPROVER_fabsl(long double x);
-float __CPROVER_fabsf(float x);
-
--These functions return the absolute value of the given -argument. -
- -
-_Bool __CPROVER_array_equal(const void array1[], const void array2[]);
-void __CPROVER_array_copy(const void dest[], const void src[]);
-void __CPROVER_array_set(const void dest[], value);
-
--The function __CPROVER_array_equal returns true if the values -stored in the given arrays are equal. -The function __CPROVER_array_copy copies the contents of -the array src to the array dest. -The function __CPROVER_array_set initializes the array dest with -the given value. -
- --Uninterpreted functions are documented here. -
- -
-__CPROVER_bitvector [ expression ]
-
--This type is only available in the C frontend. It is used -to specify a bit vector with arbitrary but fixed size. The -usual integer type modifiers signed and unsigned -can be applied. The usual arithmetic promotions will be -applied to operands of this type. -
- -
-__CPROVER_floatbv [ expression ] [ expression ]
-
--This type is only available in the C frontend. It is used -to specify an IEEE-754 floating point number with arbitrary -but fixed size. The first parameter is the total size (in bits) -of the number, and the second is the size (in bits) of the -mantissa, or significand (not including the hidden bit, thus for -single precision this should be 23). -
- -
-__CPROVER_fixedbv [ expression ] [ expression ]
-
--This type is only available in the C frontend. It is used -to specify a fixed-point bit vector with arbitrary -but fixed size. The first parameter is the total size (in bits) -of the type, and the second is the number of bits after the radix -point. -
- --The type of sizeof expressions. -
- -
-extern int __CPROVER_rounding_mode;
-
--This variable contains the IEEE floating-point -arithmetic rounding mode. -
- --This is a constant that models a large unsigned -integer. -
- --__CPROVER_integer is an unbounded, signed integer type. -__CPROVER_rational is an unbounded, signed rational -number type. -
- -
-extern unsigned char __CPROVER_memory[];
-
--This array models the contents of integer-addressed memory. -
- -This type is the equivalent of unsigned __CPROVER_bitvector[N] in the C++ front-end. -
- -This type is the equivalent of signed __CPROVER_bitvector[N] in the C++ front-end. -
- -This type is the equivalent of __CPROVER_fixedbv[N,m] in the C++ front-end. -
- --Asynchronous threads are created by preceding an instruction with a label with the prefix __CPROVER_ASYNC_. -
- - diff --git a/doc/html-manual/architecture.shtml b/doc/html-manual/architecture.shtml deleted file mode 100644 index 18ef3e0b1fc..00000000000 --- a/doc/html-manual/architecture.shtml +++ /dev/null @@ -1,93 +0,0 @@ - - - - -The behavior of a C/C++ program depends on a number of -parameters that are specific to the architecture the program was compiled -for. The three most important architectural parameters are:
- -sizeof(long int)
on various machines.sizeof(int *)
on various machines.
-In general, the CPROVER tools attempt to adopt the settings of the
-particular architecture the tool itself was compiled for. For example,
-when running a 64 bit binary of CBMC on Linux, the program will be processed
-assuming that sizeof(long int)==8
.
-As a consequence of these architectural parameters, -you may observe different verification results for an identical -program when running CBMC on different machines. In order to get -consistent results, or when aiming at validating a program written -for a different platform, the following command-line arguments can -be passed to the CPROVER tools:
- ---16
,
---32
, --64
.--little-endian
and --big-endian
.-When using a goto binary, CBMC and the other tools read the configuration -from the binary, i.e., the setting when running goto-cc is the one that -matters; the option given to the model checker is ignored in this case. -
- -
-In order to see the effect of the options --16
,
---32
and --64
, pass
-the following program to CBMC:
-#include <stdio.h>
-#include <assert.h>
-
-int main() {
- printf("sizeof(long int): %d\n", (int)sizeof(long int));
- printf("sizeof(int *): %d\n", (int)sizeof(int *));
- assert(0);
-}
-
-
-The counterexample trace contains the strings printed by the
-printf
command.
-The effects of endianness are
-more subtle. Try the following program with --big-endian
-and --little-endian
:
-#include <stdio.h>
-#include <assert.h>
-
-int main() {
- int i=0x01020304;
- char *p=(char *)&i;
- printf("Bytes of i: %d, %d, %d, %d\n",
- p[0], p[1], p[2], p[3]);
- assert(0);
-}
-
--The basic idea of CBMC is to model the computation of the programs up to a -particular depth. Technically, this is achieved by a process that -essentially amounts to unwinding loops. This concept is best -illustrated with a generic example: -
- -int main(int argc, char **argv) {
- while(cond) {
- BODY CODE
- }
-}
-
-
--A BMC instance that will find bugs with up to five iterations of the loop would -contain five copies of the loop body, and essentially corresponds to checking -the following loop-free program: -
- -int main(int argc, char **argv) {
- if(cond) {
- BODY CODE COPY 1
- if(cond) {
- BODY CODE COPY 2
- if(cond) {
- BODY CODE COPY 3
- if(cond) {
- BODY CODE COPY 4
- if(cond) {
- BODY CODE COPY 5
- }
- }
- }
- }
- }
-}
-
-
-
-Note the use of the if
statement to prevent the execution of
-the loop body in the case that the loop ends before five iterations are executed.
-The construction above is meant to produce a program that is trace equivalent
-with the original programs for those traces that contain up to five iterations
-of the loop.
-
-In many cases, CBMC is able to automatically determine an upper bound on the - -number of loop iterations. This may even work when the number of loop -unwindings is not constant. Consider the following example: -
- -_Bool f();
-
-int main() {
- for(int i=0; i<100; i++) {
- if(f()) break;
- }
-
- assert(0);
-}
-
-
-
-The loop in the program above has an obvious upper bound on the number of
-iterations, but note that the loop may abort prematurely depending on the
-value that is returned by f()
. CBMC is nevertheless able to
-automatically unwind the loop to completion.
-This automatic detection of the unwinding
-bound may fail if the number of loop iterations is highly data-dependent.
-Furthermore, the number of iterations that are executed by any given
-loop may be too large or may simply be unbounded. For this case,
-CBMC offers the command-line option --unwind B
, where
-B
denotes a number that corresponds to the maximal number
-of loop unwindings CBMC performs on any loop.
-
-Note that the number of unwindings is measured by counting the number of
-backjumps. In the example above, note that the condition
-i<100
is in fact evaluated 101 times before the loop
-terminates. Thus, the loop requires a limit of 101, and not 100.
-The setting given with --unwind
is used globally,
-that is, for all loops in the program. In order to set individual
-limits for the loops, first use
-
- --show-loops
-
-
--to obtain a list of all loops in the program. Then identify the loops -you need to set a separate bound for, and note their loop ID. Then -use -
- -
- --unwindset L:B,L:B,...
-
-
-
-where L
denotes a loop ID and B
denotes
-the bound for that loop.
-As an example, consider a program with two loops in the function -main: -
- -
- --unwindset c::main.0:10,c::main.1:20
-
-
--This sets a bound of 10 for the first loop, and a bound of 20 for -the second loop. -
- -
-What if the number of unwindings specified is too small? In this case, bugs
-that require paths that are deeper may be missed. In order to address this
-problem, CBMC can optionally insert checks that the given unwinding bound is
-actually sufficiently large. These checks are called unwinding
-assertions, and are enabled with the option
---unwinding-assertions
. Continuing the generic example above,
-this unwinding assertion for a bound of five corresponds to checking the
-following loop-free program:
-
int main(int argc, char **argv) {
- if(cond) {
- BODY CODE COPY 1
- if(cond) {
- BODY CODE COPY 2
- if(cond) {
- BODY CODE COPY 3
- if(cond) {
- BODY CODE COPY 4
- if(cond) {
- BODY CODE COPY 5
- assert(!cond);
- }
- }
- }
- }
- }
-}
-
-
--The unwinding assertions can be verified just like any other generated -assertion. If all of them are proven to hold, the given loop bounds are -sufficient for the program. This establishes a high-level -worst-case execution time (WCET). -
- --In some cases, it is desirable to cut off very deep loops in favor -of code that follows the loop. As an example, consider the -following program: -
- -int main() {
- for(int i=0; i<10000; i++) {
- BODY CODE
- }
-
- assert(0);
-}
-
-
-
-In the example above, small values of --unwind
will
-prevent that the assertion is reached. If the code in the loop
-is considered irrelevant to the later assertion, use the option
-
- --partial-loops
-
-
--This option will allow paths that execute loops only partially, -enabling a counterexample for the assertion above even for -small unwinding bounds. The disadvantage of using this option -is that the resulting path may be spurious, i.e., may not -exist in the original program. -
- -
-The loop-based unwinding bound is not always appropriate. In particular,
-it is often difficult to control the size of the generated formula
-when using the --unwind
option. The option
-
- --depth nr
-
-
--specifies an unwinding bound in terms of the number of instructions that are -executed on a given path, irrespectively of the number of loop iterations. -Note that CBMC uses the number of instructions in the control-flow graph -as the criterion, not the number of instructions in the source code. -
- - diff --git a/doc/html-manual/cbmc.shtml b/doc/html-manual/cbmc.shtml deleted file mode 100644 index a52f39a90f5..00000000000 --- a/doc/html-manual/cbmc.shtml +++ /dev/null @@ -1,377 +0,0 @@ - - - - - - - - --We assume you have already installed CBMC and the necessary support files -on your system. If not so, please follow -these instructions. -
- --Like a compiler, CBMC takes the names of .c files as command line -arguments. CBMC then translates the program and merges the function -definitions from the various .c files, just like a linker. But instead -of producing a binary for execution, CBMC performs symbolic simulation on -the program. -
- --As an example, consider the following simple program, named -file1.c: -
- -int puts(const char *s) { }
-
-int main(int argc, char **argv) {
- puts(argv[2]);
-}
-
-
-
-Of course, this program is faulty, as the argv
array might have fewer
-than three elements, and then the array access argv[2]
is out of bounds.
-Now, run CBMC as follows:
-
- cbmc file1.c --show-properties --bounds-check --pointer-check
-
-
-The two options --bounds-check
and --pointer-check
-instruct CBMC to look for errors related to pointers and array bounds.
-CBMC will print the list of properties it checks. Note that it lists,
-among others, a property labeled with "object bounds in argv" together with
-the location of the faulty array access. As you can see, CBMC largely
-determines the property it needs to check itself. This is realized by means
-of a preliminary static analysis, which relies on computing a fixed point on
-various abstract
-domains. More detail on automatically generated properties is provided
-here.
-Note that these automatically generated properties need not necessarily -correspond to bugs – these are just potential flaws, as -abstract interpretation might be imprecise. Whether these properties -hold or correspond to actual bugs needs to be determined by further analysis. -
- --CBMC performs this analysis using symbolic simulation, which -corresponds to a translation of the program into a formula. The formula is -then combined with the property. Let's look at the formula that is -generated by CBMC's symbolic simulation:
- -
- cbmc file1.c --show-vcc --bounds-check --pointer-check
-
-
--With this option, CBMC performs the symbolic simulation and prints the -verification conditions on the screen. A verification condition needs -to be proven to be valid by a -decision procedure in order to assert that the corresponding property -holds. Let's run the decision procedure:
- -
- cbmc file1.c --bounds-check --pointer-check
-
-
-
-CBMC transforms the equation you have seen before into CNF and passes it to
-a SAT solver (more background on this step is in the book on Decision Procedures). It
-then determines which of the properties that it has generated for the
-program hold and which do not. Using the SAT solver, CBMC detects that the
-property for the object bounds of argv
does not hold, and will
-thus print a line as follows:
-
-[main.pointer_dereference.6] dereference failure: object bounds in argv[(signed long int)2]: FAILURE
-
-
--Let us have a closer look at this property and why it fails. To aid the -understanding of the problem, CBMC can generate a counterexample -trace for failed properties. To obtain this trace, run -
- -
- cbmc file1.c --bounds-check --trace
-
-
-
-CBMC then prints a counterexample trace, i.e., a program trace that begins
-with main
and ends in a state which violates the property. In
-our example, the program trace ends in the faulty array access. It also
-gives the values the input variables must have for the bug to occur. In
-this example, argc
must be one to trigger the out-of-bounds
-array access. If you add a branch to the example that requires that
-argc>=3
, the bug is fixed and CBMC will report that the
-proofs of all properties have been successful.
-In the example above, we used a program that starts with a main
-function. However, CBMC is aimed at embedded software, and these
-kinds of programs usually have different entry points. Furthermore, CBMC
-is also useful for verifying program modules. Consider the following example,
-called file2.c:
-
int array[10];
-int sum() {
- unsigned i, sum;
-
- sum=0;
- for(i=0; i<10; i++)
- sum+=array[i];
-}
-
-
-
-In order to set the entry point to the sum
function, run
-
- cbmc file2.c --function sum --bounds-check
-
-
--It is often necessary to build a suitable harness for the function -in order to set up the environment appropriately. -
- -
-When running the previous example, you will have noted that CBMC unwinds the
-for
loop in the program. As CBMC performs Bounded Model
-Checking, all loops have to have a finite upper run-time bound in order to
-guarantee that all bugs are found. CBMC can optionally check that enough
-unwinding is performed. As an example, consider the program binsearch.c:
-
int binsearch(int x) {
- int a[16];
- signed low=0, high=16;
-
- while(low<high) {
- signed middle=low+((high-low)>>1);
-
- if(a[middle]<x)
- high=middle;
- else if(a[middle]>x)
- low=middle+1;
- else // a[middle]==x
- return middle;
- }
-
- return -1;
-}
-
-
--If you run CBMC on this function, you will notice that the unwinding -does not stop on its own. The built-in simplifier is not able to determine -a run time bound for this loop. The unwinding bound has to be given as a -command line argument:
- -
- cbmc binsearch.c --function binsearch --unwind 6 --bounds-check --unwinding-assertions
-
-
-
-CBMC verifies that verifies the array accesses are within the bounds; note
-that this actually depends on the result of the right shift. In addition,
-as CBMC is given the option
---unwinding-assertions
--property
.
-
-CBMC can also be used for programs with unbounded loops. In this -case, CBMC is used for bug hunting only; CBMC does not attempt to find -all bugs. The following program -(lock-example.c) is an example -of a program with a user-specified property:
- -_Bool nondet_bool();
-_Bool LOCK = 0;
-
-_Bool lock() {
- if(nondet_bool()) {
- assert(!LOCK);
- LOCK=1;
- return 1; }
-
- return 0;
-}
-
-void unlock() {
- assert(LOCK);
- LOCK=0;
-}
-
-int main() {
- unsigned got_lock = 0;
- int times;
-
- while(times > 0) {
- if(lock()) {
- got_lock++;
- /* critical section */
- }
-
- if(got_lock!=0)
- unlock();
-
- got_lock--;
- times--;
-} }
-
-
-
-The while
loop in the main
function has no
-(useful) run-time bound. Thus, a bound has to be set on the amount of
-unwinding that CBMC performs. There are two ways to do so:
-
--unwind
command-line parameter can to be used to limit
-the number of times loops are unwound.--depth
command-line parameter can be used to limit
-the number of program steps to be processed.
-Given the option --unwinding-assertions
, CBMC checks whether
-the arugment to --unwind
is large enough to cover all program
-paths. If the argument is too small, CBMC will detect that not enough
-unwinding is done reports that an unwinding assertion has failed.
-
-Reconsider the example. For a loop unwinding bound of one, no bug is found.
-But already for a bound of two, CBMC detects a trace that violates an
-assertion. Without unwinding assertions, or when using the --depth
-command line switch, CBMC does not prove the program correct, but it can be
-helpful to find program bugs. The various command line options that CBMC
-offers for loop unwinding are described in the section on
-understanding loop unwinding.
-Most C programs make use of functions provided by a library; instances are
-functions from the standard ANSI-C library such as malloc
or
-printf
. The verification of programs that use such functions
-has two requirements:
-Most C compilers come with header files for the ANSI-C library functions. -We briefly discuss how to obtain/install these library files. -
- --Linux systems that are able to compile software are usually equipped with -the appropriate header files. Consult the documentation of your distribution -on how to install the compiler and the header files. First try to compile -some significant program before attempting to verify it. -
- --On Microsoft Windows, CBMC is pre-configured to use the compiler that is -part of Microsoft's Visual Studio. Microsoft's -Visual Studio Community is fully featured and available for download for -free from the Microsoft webpage. Visual Studio installs the usual set of -header files together with the compiler. However, the Visual Studio -compiler requires a large set of environment variables to function -correctly. It is therefore required to run CBMC from the Visual Studio -Command Prompt, which can be found in the menu Visual Studio -Tools. -
- -
-Note that in both cases, only header files are available. CBMC only
-comes with a small set of definitions, which includes functions such as
-malloc
. Detailed information about the built-in definitions is
-here.
-This section describes the command line interface of CBMC. Like a C
-compiler, CBMC takes the names of the .c source files as arguments.
-Additional options allow to customize the behavior of CBMC. Use
-cbmc --help
to get a full list of the available options.
-
-Structured output can be obtained from CBMC using the option --xml-ui
.
-Any output from CBMC (e.g., counterexamples) will then use an XML
-representation.
-
-We also have a list of -interesting applications of CBMC.
- --We assume that CBMC is installed on your system. If not so, follow -these instructions.
- --CBMC can be used to automatically generate test cases that satisfy a certain code coverage -criterion. Common coverage criteria include branch coverage, condition -coverage and Modified -Condition/Decision Coverage (MC/DC). Among others, MC/DC is required -by several avionics software development guidelines to ensure adequate testing -of safety critical software. Briefly, in order to satisfy MC/DC, -for every conditional statement containing boolean decisions, each Boolean -variable should be evaluated one time to "true" and one time to "false", -in a way that affects the outcome of the decision. -
- --In the following, we are going to demonstrate how to apply the test suite -generation functionality in CBMC, by means of a case study. The program -pid.c is an excerpt from a real-time embedded benchmark PapaBench, -and implements part of a fly-by-wire autopilot for an Unmanned Aerial Vehicle (UAV). -It is adjusted mildly for our purposes. -
- -
-The aim of function climb_pid_run
is to control the vertical climb of the UAV.
-Details on the theory behind this operation are documented in the wiki for the Paparazzi UAV project.
-The behaviour of this simple controller, supposing that the desired speed is 0.5 meters per second,
-is plotted in the Figure below.
-
01: // CONSTANTS:
-02: #define MAX_CLIMB_SUM_ERR 10
-03: #define MAX_CLIMB 1
-04:
-05: #define CLOCK 16
-06: #define MAX_PPRZ (CLOCK*600)
-07:
-08: #define CLIMB_LEVEL_GAZ 0.31
-09: #define CLIMB_GAZ_OF_CLIMB 0.75
-10: #define CLIMB_PITCH_OF_VZ_PGAIN 0.05
-11: #define CLIMB_PGAIN -0.03
-12: #define CLIMB_IGAIN 0.1
-13:
-14: const float pitch_of_vz_pgain=CLIMB_PITCH_OF_VZ_PGAIN;
-15: const float climb_pgain=CLIMB_PGAIN;
-16: const float climb_igain=CLIMB_IGAIN;
-17: const float nav_pitch=0;
-18:
-19: /** PID function INPUTS */
-20: // The user input: target speed in vertical direction
-21: float desired_climb;
-22: // Vertical speed of the UAV detected by GPS sensor
-23: float estimator_z_dot;
-24:
-25: /** PID function OUTPUTS */
-26: float desired_gaz;
-27: float desired_pitch;
-28:
-29: /** The state variable: accumulated error in the control */
-30: float climb_sum_err=0;
-31:
-32: /** Computes desired_gaz and desired_pitch */
-33: void climb_pid_run()
-34: {
-35:
-36: float err=estimator_z_dot-desired_climb;
-37:
-38: float fgaz=climb_pgain*(err+climb_igain*climb_sum_err)+CLIMB_LEVEL_GAZ+CLIMB_GAZ_OF_CLIMB*desired_climb;
-39:
-40: float pprz=fgaz*MAX_PPRZ;
-41: desired_gaz=((pprz>=0 && pprz<=MAX_PPRZ) ? pprz : (pprz>MAX_PPRZ ? MAX_PPRZ : 0));
-42:
-43: /** pitch offset for climb */
-44: float pitch_of_vz=(desired_climb>0) ? desired_climb*pitch_of_vz_pgain : 0;
-45: desired_pitch=nav_pitch+pitch_of_vz;
-46:
-47: climb_sum_err=err+climb_sum_err;
-48: if (climb_sum_err>MAX_CLIMB_SUM_ERR) climb_sum_err=MAX_CLIMB_SUM_ERR;
-49: if (climb_sum_err<-MAX_CLIMB_SUM_ERR) climb_sum_err=-MAX_CLIMB_SUM_ERR;
-50:
-51: }
-52:
-53: int main()
-54: {
-55:
-56: while(1)
-57: {
-58: /** Non-deterministic input values */
-59: desired_climb=nondet_float();
-60: estimator_z_dot=nondet_float();
-61:
-62: /** Range of input values */
-63: __CPROVER_assume(desired_climb>=-MAX_CLIMB && desired_climb<=MAX_CLIMB);
-64: __CPROVER_assume(estimator_z_dot>=-MAX_CLIMB && estimator_z_dot<=MAX_CLIMB);
-65:
-66: __CPROVER_input("desired_climb", desired_climb);
-67: __CPROVER_input("estimator_z_dot", estimator_z_dot);
-68:
-69: climb_pid_run();
-70:
-71: __CPROVER_output("desired_gaz", desired_gaz);
-72: __CPROVER_output("desired_pitch", desired_pitch);
-73:
-74: }
-75:
-76: return 0;
-77: }
-
-
-
-In order to test the PID controller, we construct a main control loop,
-which repeatedly invokes the function climb_pid_run
(line 69).
-This PID function has two input variables: the desired speed desired_climb
-and the estimated speed estimated_z_dot
.
-In the beginning of each loop iteration, values of the inputs are assigned non-deterministically.
-Subsequently, the __CPROVER_assume
statement in lines 63 and 64 guarantees that
-both values are bounded within a valid range.
-The __CPROVER_input
and __CPROVER_output
will help clarify the inputs
-and outputs of interest for generating test suites.
-
-To demonstrate the automatic test suite generation in CBMC, -we call the following command and we are going to explain the command line options one by one. -
- -cbmc pid.c --cover mcdc --unwind 6 --xml-ui
-
-
-
-The option --cover mcdc
specifies the code coverage criterion.
-There are four conditional statements in the PID function: in line 41, line 44,
-line 48 and line 49.
-To satisfy MC/DC, the test suite has to meet multiple requirements.
-For instance, each conditional statement needs to evaluate to true and false.
-Consider the condition "pprz>=0 && pprz<=MAX_PPRZ"
in line 41. CBMC
-instruments three coverage goals to control the respective evaluated results of "pprz>=0"
and
-"pprz<=MAX_PPRZ"
.
-We list them in below and they satisfy the MC/DC rules.
-Note that MAX_PPRZ
is defined as 16 * 600 in line 06 of the program.
-
-!(pprz >= (float)0) && pprz <= (float)(16 * 600) id="climb_pid_run.coverage.1"
-pprz >= (float)0 && !(pprz <= (float)(16 * 600)) id="climb_pid_run.coverage.2"
-pprz >= (float)0 && pprz <= (float)(16 * 600) id="climb_pid_run.coverage.3"
-
-
-
-The "id" of each coverage goal is automatically assigned by CBMC. For every
-coverage goal, a test suite (if there exists) that
-satisfies such a goal is printed out in XML format, as the parameter
---xml-ui
is given. Multiple coverage goals can share a
-test suite, when the corresponding execution of the program satisfies all these
-goals at the same time.
-
-In the end, the following test suites are automatically generated for testing the PID controller.
-A test suite consists of a sequence of input parameters that are
-passed to the PID function climb_pid_run
at each loop iteration.
-For example, Test 1 covers the MC/DC goal with id="climb_pid_run.coverage.1".
-The complete output from CBMC is in
-pid_test_suites.xml, where every test suite and the coverage goals it is for
-are clearly described.
-
-
Test suite:
-Test 1.
- (iteration 1) desired_climb=-1.000000f, estimator_z_dot=1.000000f
-
-Test 2.
- (iteration 1) desired_climb=-1.000000f, estimator_z_dot=1.000000f
- (iteration 2) desired_climb=1.000000f, estimator_z_dot=-1.000000f
-
-Test 3.
- (iteration 1) desired_climb=0.000000f, estimator_z_dot=-1.000000f
- (iteration 2) desired_climb=1.000000f, estimator_z_dot=-1.000000f
-
-Test 4.
- (iteration 1) desired_climb=1.000000f, estimator_z_dot=-1.000000f
- (iteration 2) desired_climb=1.000000f, estimator_z_dot=-1.000000f
- (iteration 3) desired_climb=1.000000f, estimator_z_dot=-1.000000f
- (iteration 4) desired_climb=1.000000f, estimator_z_dot=-1.000000f
- (iteration 5) desired_climb=0.000000f, estimator_z_dot=-1.000000f
- (iteration 6) desired_climb=1.000000f, estimator_z_dot=-1.000000f
-
-Test 5.
- (iteration 1) desired_climb=-1.000000f, estimator_z_dot=1.000000f
- (iteration 2) desired_climb=-1.000000f, estimator_z_dot=1.000000f
- (iteration 3) desired_climb=-1.000000f, estimator_z_dot=1.000000f
- (iteration 4) desired_climb=-1.000000f, estimator_z_dot=1.000000f
- (iteration 5) desired_climb=-1.000000f, estimator_z_dot=1.000000f
- (iteration 6) desired_climb=-1.000000f, estimator_z_dot=1.000000f
-
-
-
-The option --unwind 6
unwinds the loop inside the main
-function body six times. In order to achieve the complete coverage on all the instrumented goals
-in the PID function climb_pid_run
, the loop must be unwound sufficient enough times.
-For example, climb_pid_run
needs to be called at least six times for evaluating the
-condition climb_sum_err>MAX_CLIMB_SUM_ERR
in line 48 to true.
-This corresponds to the Test 5.
-An introduction to the use of loop unwinding can be found
-in Understanding Loop Unwinding.
-
-In this small tutorial, we present the automatic test suite generation
-functionality of CBMC, by applying the MC/DC code coverage criterion to a
-PID controller case study. In addition to --cover mcdc
, other
-coverage criteria like branch
, decision
,
-path
etc. are also available when calling CBMC.
-
-The table below summarizes the coverage criteria that CBMC supports. -
- -Criterion | Definition |
---|---|
assertion | -For every assertion, generate a test that reaches it |
location | -For every location, generate a test that reaches it |
branch | -Generate a test for every branch outcome |
decision | -Generate a test for both outcomes of every Boolean expression -that is not an operand of a propositional connective |
condition | -Generate a test for both outcomes of every Boolean expression |
mcdc | -Modified Condition/Decision Coverage (MC/DC) |
path | -Bounded path coverage |
cover | -Generate a test for every __CPROVER_cover statement
- |
-The following sections provide an introduction for anybody who -wishes to modify CBMC or build new tools on top of the APIs used -by CBMC. They summarize key components, data structures and APIs -that are used to build the CPROVER tools. -
- --The most recent source code of CBMC and the CPROVER infrastructure can be obtained -via git at https://github.com/diffblue/cbmc.git. -Tar balls for releases are available at https://github.com/diffblue/cbmc/releases. -
- --Detailed instructions on how to build CBMC from source are given -in the file COMPILING. -
- --The sources of the C frontend are located in the "src/ansi-c" directory. It -uses a standard Flex/Bison setup for scanning and parsing the files. The -Flex scanner produces a token sequence, which is turned into a tree -representation of the input program using the Bison grammar. The -typechecker subsequently annotates this parse tree with types and generates -a symbol table. The symbol table is a map from identifiers (functions, -variables and types) to their definitions. -
- --The following example illustrates how to use the frontend for parsing files and -for translating them into a symbol table. A call to parse generates -the parse tree of the program. The conversion into the symbol table is -performed during type checking, which is done by a call to the -typecheck method. The symbol table is a map from identifiers to the -symbolt data structure. -
- -#include <iostream>
-#include <fstream>
-#include <sstream>
-#include <string>
-
-#include <ansi-c/ansi_c_language.h>
-#include <util/cmdline.h>
-#include <util/config.h>
-
-int main(int argc, const char* argv[])
-{
- // Command line: parse -I incl_dir file1 ...
- cmdlinet cmdl;
- cmdl.parse(argc, argv, "I:");
-
- config.init();
-
- if(cmdl.isset('I'))
- config.ansi_c.include_paths=cmdl.get_values('I');
-
- // Set language to C
- std::auto_ptr<languaget> clang=new_ansi_c_language();
-
- // Symbol table
- symbol_tablet my_symbol_table;
-
- for(const auto & arg : cmdl.args)
- {
- // Source code stream
- std::ifstream in(arg.c_str());
-
- // Parse
- clang->parse(in, "", std::cerr);
-
- // Typecheck
- clang->typecheck(my_symbol_table, arg, std::cerr);
- }
-
- // Do some final adjustements
- clang->final(my_symbol_table, std::cerr);
-
- my_symbol_table.show(std::cout);
-
- return 0;
-}
-
-
--The parse trees are implemented using a class called irept. Its -declaration and definiton can be found in the files "src/util/irep.h" and -"src/util/irep.cpp", respectively. -
- --The excerpt below gives some details of the class irept: -
- -class irept
-{
-public:
- typedef std::vector<irept> subt;
- typedef std::map<irep_name_string, irept> named_subt;
- ...
-
-public:
- class dt
- {
- public:
- unsigned ref_count;
- dstring data;
- named_subt named_sub;
- named_subt comments;
- subt sub;
- ...
- };
-
-protected:
- dt *data;
- ...
-};
-
-
--Every node of any tree is an object of class irept. Each node has a -pointer to an object of class dt. The dt objects are used -for storing the actual content of nodes. Objects of class dt are -dynamically allocated and can be shared between nodes. A reference-counter -mechanism is implemented to automatically free unreachable dt -objects. A shallow copy of a tree is an O(1) operation. -
- --The field data of class dt is a (hashed) string -representing the label of the nodes. The fields named_sub, -comments and sub are links to childs. Edges are either -labeled with a string or ordered. The string-labeled edges are stored in the -map comments if their first character is '#'. Otherwise, they are -stored in the map named_sub. The labels of edges are unique for a -given node; however, their ordering is not preserved. The field sub -is a vector of nodes that is used for storing the ordered children. The order -of edges of this kind is preserved during copy. -
- -const irep_idt &id();
-void id(const irep_idt &_data);
-
-
--The first method returns a constant reference to the label of the node. The -second method sets the label of the node. -
- -virtual bool is_nil() const;
-virtual bool is_not_nil() const;
-
-
--The first method returns true if the label of the node is equal to "nil". -The second method returns false if the label of the node is equal to "nil". -
- -const irept &find(const irep_namet &name) const;
-irept &add(const irep_namet &name);
-const irep_idt &get(const irep_namet &name) const;
-
-
-void set(const irep_namet &name,
- const irep_idt &value);
-void set(const irep_namet &name, const long value);
-void set(const irep_namet &name, const irept &irep);
-
-
--These methods create a new edge with label name. -
- --If the second argument is an object of class irept, then it is -assigned to the new child. - -
-If the second argument is a string, then it is set as node-label of the new child. - -
-If the second argument is a number, then it is converted to a -string and set as node-label of the new child. - -
void remove(const irep_namet &name);
-
-
--This method looks for an edge with label name -and removes it. - -
void move_to_sub(irept &irep);
-void move_to_named_sub(const irep_namet &name, irept &irep);
-
-
--The first method creates a new ordered edge with a child equal to -irep. Then it sets irep to nil. The index of the -edge is equal to the size of vector sub before the call. -
- --The second method does the same but for labeled edges. -
- -void swap(irept &irep);
-
-
--Exchange the content of the invoked node with the one of irep. -
- -void make_nil();
-
-
--Set the label of the node to "nil" and remove all outgoing edges. -
- -const subt &get_sub();
-const named_subt &get_named_sub();
-const named_subt &get_comments();
-
-
--Return a constant reference to -sub, named_sub, and comments, respectively. -
- --The class typet inherits from irept. Types may have -subtypes. This is modeled with two edges named "subtype" and "subtypes". The -class typet only add specialized methods for accessing the subtype -information to the interface of irept. -
- -bool has_subtype() const;
-bool has_subtypes() const;
-
-
--The first method returns true if the a subtype node exists. is not -nil. The second method returns true is a subtypes node exists. -
- -typet &subtype();
-typest &subtypes();
-
-
--The first method returns a reference to the 'subtype' node. -The second method returns a reference to the vector of subtypes. -
- -
-A number of subtypes of typet
exist which allow convenient
-creation and manipulation of typet
objects for special types.
-
Class | Description |
---|---|
bool_typet |
-Boolean type |
symbol_typet |
-Symbol type. Has edge "identifier" to a string value, which can be accessed with get_identifier and set_identifier . |
struct_typet , union_typet |
-Represent a struct, resp. union types. Convenience functions to access components components() . |
code_typet |
-The type of a function/procedure. Convenience functions to access arguments() and return_type() . |
array_typet |
-Convenience function size() to access size of the array. |
pointer_typet |
-Pointer type, subtype stores the type of the object pointed to. |
reference_typet |
-Represents a reference type, subtype stores the type of the object referenced to. |
bv_typet |
-Represents a bit vector type with variable width. |
fixed_bv_typet |
-Represents a bit vector that encodes a fixed-point number. |
floatbv_typet |
-Represents a bit vector that encodes a floating-point number. |
string_typet |
-Represents a string type. |
-The class source_locationt inherits from the class irept. It -is used to store locations in text files. It adds specialized methods to -manipulate the edges named "file", "line", "column", "function". -
- --The class exprt inherits from class irept. Expressions -have operands and a type. This is modeled with ordered edges for the -operands and an edge labeled"type", respectively. The class exprt -only adds specialized methods for accessing operands and type information -to the interface of irept. -
- -explicit exprt(const irep_idt &id);
-
-
--Creates an exprt object with a given label and no type. -
- -exprt(const irep_idt &id, const typet &type);
-
-
--Creates an exprt object with a given label and type. -
- -const typet &type() const;
-typet &type();
-
-
--Return a reference to the 'type' node -
- -bool has_operands() const;
-
-
--Return true if the expression has at least one operand. -
- -const operandst &operands() const;
-
-
--Return a reference to the vector of operands. -
- -const exprt &op0();
-const exprt &op1();
-const exprt &op2();
-const exprt &op3();
-exprt &op0();
-exprt &op1();
-exprt &op2();
-exprt &op3();
-
-
--Return a reference to a specific operand. Avoid calling -if the operand does not exist. -
- -void make_true();
-void make_false();
-void make_bool(bool value);
-
-
--Turn the current exprt instance into a expression of type "bool" -with label "constant" and a single edge labeled "value", which points to -a new node with label either "true" or "false". -
- -void make_typecast(const typet &_type);
-
-
--Turns the current exprt instance into a typecast. The old value of -the instance is appended as the single operand of the typecast, i.e., the -result is a typecast-expression of the old expression to the indicated type. -
- -void make_not();
-
-
--Turns the current exprt instance into an expression with label -"not" of the same type as the original expression. The old value of the -instance is appended as the operand of the "not"-node. If the original -expression is of type "bool", the result represents the negation of the -original expression with the following simplifications possibly applied: -
- --void negate(); -- -
-Turns the current exprt instance into a negation of itself, depending -on its type: -
- -make_not
is called.irept::make_nil
is called.bool sum(const exprt &expr);
-bool mul(const exprt &expr);
-bool subtract(const exprt &expr);
-
-
-
-Expect the "this" object and the function argument to be constants of the
-same numeric type. Turn the current exprt
instance into a
-constant expression of the same type, whose "value" edge points to the
-result of the sum, product, or difference of the two expressions. If the
-operation fails for some reason (e.g., the types are different),
-true
is returned.
-
bool is_constant() const;
-
-
--Returns true if the expression label is "constant". -
- -bool is_boolean() const;
-
-
--Returns true if the label of the type is "bool". - -
bool is_false() const;
-bool is_true() const;
-
-
--The first function returns true if the expression is a boolean constant with -value "false". The second function returns true for any boolean constant -that is not of value "false". -
- -bool is_zero() const;
-bool is_one() const;
-
-
--The first function returns true if the expression represents a zero numeric -constant, or if the expression represents a null pointer. The second -function returns true if the expression represents a numeric constant with -value "1". -
- -
-A number of subtypes of exprt
provide further convenience functions
-for edge access or other specialized behaviour:
-
Class | Description |
---|---|
transt |
-Represents an SMV-style transition system with invariants
-invar() , initial state init() and transition
-function trans() . |
-
true_exprt |
-Boolean constant true expression. | -
false_exprt |
-Boolean constant false expression. | -
symbol_exprt |
-Represents a symbol (e.g., a variable occurrence), convenience function for manipulating "identifier"-edge set_identifier and get_identifier |
-
predicate_exprt |
-Convenience constructors to create expressions of type "bool". | -
binary_relation_exprt : predicate_exprt |
-Convenience functions to create and manipulate binary expressions of type "bool". | -
equality_exprt : binary_relation_exprt |
-Convenience functions to create and manipulate equality expressions such as "a == b". | -
ieee_float_equal_exprt : binary_relation_exprt |
-Convenience functions to create and manipulate equality expressions between floating-point numbers. - | -
index_exprt |
-Represents an array access expression such as "a[i]". Convenience functions array() and index() for accessing the array expressions and indexing expression. |
-
typecast_exprt |
-Represents a cast to the type of the expression. | -
-and_exprt ,
-implies_exprt ,
-or_exprt ,
-not_exprt |
-Representations of logical operators with convenience constructors. | -
address_of_exprt |
-Representation of a C-style &a address-of operation. Convenience function object() for accessing operand. |
-
dereference_exprt |
-Representation of a C-style *a pointer-dereference operation. Convenience function object() for accessing operand. |
-
if_exprt |
-Representation of a conditional expresion, with convenience functions cond() , true_case() and false_case() for accessing operands. |
-
member_exprt |
-Represents a some_struct.some_field member access. |
-
codet |
-Represents a segment of code. | -
-A symbol is an object of class symbolt
. This class
-is declared in "util/symbol.h". The code below shows a partial
-declaration of the interface:
-
class symbolt
-{
-public:
- typet type;
- exprt value;
- std::string name;
- std::string base_name;
- ...
-};
-
-
--Symbol names are unique. Scopes are handled by adding prefixes -to symbols: -
- -int main(int argc, char* argv[]) {
-
- // Symbol name: c::main::0::alice
- char alice = 0; // Symbol base: alice
-
- {
- // Symbol name: c::main::1::alice
- int alice = 0; // Symbol base: alice
- }
-}
-
-
-A symbol table is an object of class contextt
. This class
-is declared in "util/context.h". The code below shows a partial
-declaration of the interface:
-
class symbol_tablett
-{
-public:
- // Insert the symbol
- bool add(const symbolt &symb);
- // Insert symb into the
- // table and erase it.
- // New_symbol points to the
- // newly inserted element.
- bool move(symbolt &symbol, symbolt *&new_symbol);
-
- // Insert symb into the
- // table. Then symb is erased.
- bool move(symbolt &syb);
-
- // Return the entry of the
- // symbol with given name.
- const irept &value(const std::string &name) const;
-};
-
-
--Goto programs are a representation of the control flow graph of a program -that uses only guarded goto and assume statements to model non-sequential -flow. The main definition can be found in -"src/goto-programs/goto_program_template.h", which is a template class. The -concrete instantiation of the template that is used in the framework can be -found in "src/goto-programs/goto_program.h". A single instruction in a goto -program is represented by the class goto_programt::instructiont -whose definition can be found again in -"goto-programs/goto_program_template.h". -
- -
-In the class goto_programt
, the control flow graph is represented
-as a mixture of sequential transitions between nodes, and non-sequential
-transitions at goto-nodes. The sequential flow of the program is captured
-by the list instructions
that is a field of the class
-goto_programt
. Transitions via goto statements are represented in
-the list targets
, which is a field of the class
-goto_programt::instructiont
, i.e., each goto-instruction carries a
-list of possible jump destinations. The latter list targets
is a
-list of iterators which point to elements of the list instructions
.
-An illustration is given in the figure below.
-
-Instructions can have a number of different types as represented by
-enum goto_program_instruction_typet
and can be accessed via the
-field type
in instructiont
. These include:
-
GOTO |
-Represents a non-deterministic branch to the instructions given in the
-list targets . Goto statements are guarded, i.e., the
-non-deterministic branch is only taken if the expression in
-guard evaluates to true, otherwise the program continues
-sequentially. Guarded gotos can be used, for example, to model if
-statements. The guard is then set to the negated condition of the
-statement, and goto target is set to bypass the conditionally executed code
-if this guard evaluates to true.
- |
-
ASSUME |
-An assumption statement that restricts viable paths reaching the
-instruction location to the ones that make the expression guard
-evaluate to true. |
-
ASSERT |
-An assertion whose guard is checked for validity when the instruction is
-reached. |
-
RETURN |
-A return statement in a function. | -
END_FUNCTION |
-Denotes the end of a function. | -
ASSIGN |
-A variable assignment. | -
SKIP |
-No operation. | -
OTHER |
-Any operation not covered by enum
-goto_program_instruction_typet . |
-
-A number of convenience functions in instructiont
, such as
-is_goto()
, is_assume()
, etc., simplify type queries.
-The following code segment gives a partial interface declaration of
-goto_program_template
and instructiont
.
-
template <class codeT, class guardT>
-class goto_program_templatet
-{
-public:
- //list of instruction type
- typedef std::list<class instructiont> instructionst;
-
- //a reference to an instruction in the list
- typedef typename
- std::list::iterator targett;
-
- //Sequential list of instructions,
- //representing sequential program flow
- instructionst instructions;
-
- typedef typename
- std::map<const_targett, unsigned> target_numberst;
-
- //A map containing the unique number of each target
- target_numberst target_numbers;
-
- //Get the successors of a given instruction
- void get_successors(targett target, targetst &successors);
-
- ...
-
-
- class instructiont
- {
- public:
- codeT code;
-
- //identifier of enclosing function
- irep_idt function;
-
- //location in the source file
- locationt location;
-
- //type of instruction?
- goto_program_instruction_typet type;
-
- //Guard statement for gotos, assume, assert
- guardT guard;
-
- //targets for gotos
- targetst targets;
-
- //set of all predecessors (sequential, and gotos)
- std::set<targett> incoming_edges;
-
- // a globally unique number to identify a
- // program location. It is guaranteed to be
- // ordered in program order within one
- // goto_program
- unsigned location_number;
-
- // a globally unique number to identify loops
- unsigned loop_number;
-
- // true if this is a goto jumping back to an
- // earlier instruction in the sequential program
- // flow
- bool is_backwards_goto() const;
- };
-
-}
-
-
-
-
-
-
-
diff --git a/doc/html-manual/footer.inc b/doc/html-manual/footer.inc
deleted file mode 100644
index 3e1257f5a2d..00000000000
--- a/doc/html-manual/footer.inc
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-