Software plays an increasingly crucial role in nearly every facet of
modern life, from communications infrastructure to the control systems
in automobiles, airplanes, and power plants. To achieve the highest
degree of reliability for the most critical pieces of software, it is
necessary to move beyond ad hoc testing and review processes towards
verification---to prove using formal methods that a piece of code
exhibits exactly those behaviors allowed by its specification and no
others.
A significant portion of the existing software infrastructure is
written in low-level languages like C and C++. Features of these
language present significant verification challenges. For example,
unrestricted pointer manipulation means that we cannot prove even the
simplest properties of programs without first collecting precise
information about potential aliasing relationships between variables.
In this thesis, I present several contributions. The first is a
general framework for combining program analyses that are only
conditionally sound. Using this framework, I show it is possible to
design a sound verification tool that relies on a separate,
previously-computed pointer analysis.
The second contribution of this thesis is Cascade, a multi-platform,
multi-paradigm framework for verification. Cascade includes a support
for precise analysis of low-level C code, as well as for higher-level
languages such as SPL.
Finally, I describe a novel technique for the verification of datatype
invariants in low-level systems code. The programmer provides a
high-level specification for a low-level implementation in the form of
inductive datatype declarations and code assertions. The connection
between the high-level semantics and the implementation code is then
checked using bit-precise reasoning. An implementation of this
datatype verification technique is available as a Cascade module.