Model Checking C and C++ Code via LLVM Bitcode
==============================================

The traditional "explicit-state" model checking practice is not widely adopted
in the programming community, and vice-versa, use of mainstream programming
languages is not a common practice in the model checking community. Hence,
model checking of systems expressed as C programs comes with some novelties for
both kinds of users.

First of all, the current main application of DIVINE is verification of safety
(and some liveness) properties of asynchronous, shared-memory programs. The
typical manifestation of such asynchronous parallelism is programming with
threads and shared memory. Often for performance and/or familiarity reasons,
programming with threads, shared memory and locking is the only viable
alternative, even though the approach is fraught with difficulties, and
presents many pitfalls that can catch even expert programmers unaware -- not to
say novices. Sadly, resource locking is inherently non-compositional, hence
there is virtually no way to provide a reliable yet powerful abstraction, all
that while retaining any semblance of speed and scalability.

Despite all its shortcomings, lock-based (or alternatively atomics-based, which
is yet more difficult) programming is on a rise. Model checking provides a
powerful tool to ascertain correctness of programs written with locks around
concurrent access to shared memory. Most programmers will agree that bugs that
show up rarely and are nearly impossible to reproduce are the worst kind to
deal with. Sadly, most concurrency bugs are of this nature, since they arise
from subtle interactions of nondeterministically scheduled threads of
execution. A test-case may work 99 times out of 100, yet the 100th time die in
a flames with an unfathomable invalid memory access. Even sophisticated modern
debugging tools like valgrind are often powerless in this situation.

This is where DIVINE can help, since it systematically and efficiently explores
all relevant execution orderings, discovering even the subtlest race
conditions, restoring a crucially important property of bugs: reproducibility.
If you have ever changed a program and watched the test-case run in a loop for
hundreds of iterations, wondering if the bug is really fixed, or it just
stubbornly refuses to crash the program... well, DIVINE is the tool you have
been waiting for.

Of course there are some catches. Model checking is computationally intensive
and memory-hungry. While this is usually not a problem with comparably small
unit tests, applying model checking to large programs may not be feasible,
depending on your use-case, and on the amount of memory and time that you have.

With the universal LLVM backend, DIVINE can support a wide range of compiled
programming languages. However, language-specific support is only provided for
C and C++. A fairly complete ISO C runtime library is provided as part of
DIVINE, with appropriate hooks into DIVINE, as well as an implementation of the
`pthread` specification, i.e. the POSIX threading interface.

If your language interfaces with the C library, that part of language support
can be re-used transparently. However, currently no other platform glue is
provided for other languages. Your mileage may vary. Data structure and
algorithmic code can be very likely processed with at most trivial additions to
the support code, in any language that can be compiled into LLVM bitcode.

Compiling Programs
------------------

The first step to take when you want to use DIVINE for C/C++ verification is to
compile your program into LLVM bitcode and link it against the DIVINE-provided
runtime libraries. When you issue `divine compile --llvm program.c`, `divine`
will compile the runtime support and your program and link them together
automatically, using clang. You can use `--only-libraries` (without a program)
to pre-build the three libraries (archives) of support bitcode: `libpdc.a`,
`libsupc++.a` and `libdivine.a`. When you have these files in the correct data
layout (basically, on common x86 platforms, this boils down to whether your
clang is configured to use 32b or 64b pointers), you can re-use them with later
`divine compile --llvm` invocations by adding the
`--precompiled=/path/to/the/libraries` switch. Please be sure that you always
use libraries built by a matching version of DIVINE. To change the switches
passed to clang when you compile your program, use `--cflags`.

Alternatively, you can compile your program manually (possibly to use
gcc/dragonegg instead of clang) and link the resulting bitcode with DIVINE's
runtime libraries mentioned above. You can obtain the correct linker invocation
from the output of `divine compile --llvm`. Assuming that you now have a
`program.bc` file, you should proceed to check that DIVINE can load it, by
issuing `divine info program.bc`. Your program might be missing some symbols,
as the LLVM linkers currently fail to report when this happens.

Limitations
-----------

When DIVINE interprets your program, it does so in a very strictly controlled
environment, so that every step is fully reproducible. Hence, no real IO is
allowed; the program can only see its own memory. External storage (a
filesystem) can be reasonably easily emulated in-memory, although no library
support is currently available (eventually, our C library will provide a
transparent virtual filesystem to mitigate this problem).

The current implementation does not support stack unwinding and exception
handling. Full support for LLVM exception handling is planned in a future
release.

The interpreter simulates an "in order" architecture, hence any possible
detrimental effects of instruction and memory access reordering won't be
detected. Again, an improvement in this area is planned for a future release.

State Space of a Program
------------------------

Internally, DIVINE constructs the state space of your program -- an oriented
graph, whose vertices represent various states your program can reach, i.e. the
values of all its mapped memory locations, the values in all machine registers,
etc. DIVINE normally doesn't store, or even construct, all the possible states
-- only a relevant subset. In a multi-threaded program, it often happens that
more than one thread can run at once, i.e. if your program is in a given state,
the next state it will get into is determined by chance -- it all hinges on
which thread gets to run. Hence, some (in fact, most) states in a parallel
program can proceed to multiple different configurations, depending on a
scheduling choice. In such cases, DIVINE has to explore both such "variant"
successors to determine the behaviour of the program in all possible scenarios.

You can visualise the state space DIVINE explores by using `divine draw` --
this will show how the "future" of your program branches through various
configurations, and how it converges back into a common point -- or, if its
behaviour had changed depending on scheduling, diverges into multiple different
outcomes.
