<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <title-group>
        <article-title>Bitfields and Tagged Unions in C - Verification through Automatic Generation</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Sydney Research Lab.</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>NICTA?</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Australia</string-name>
        </contrib>
      </contrib-group>
      <fpage>44</fpage>
      <lpage>55</lpage>
      <abstract>
        <p>We present a tool for automatic generation of packed bitfields and tagged unions for systems-level C, along with automatic, machine checked refinement proofs in Isabelle/HOL. Our approach provides greater predictability than compiler-specific bitfield implementations, and provides a basis for formal reasoning about these typically non-type-safe operations. The tool is used in the implementation of the seL4 microkernel, and hence also in the lowest-level refinement step of the L4.verified project which aims to prove the functional correctness of seL4. Within seL4, it has eliminated the need for unions entirely.</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>-</title>
      <p>David Cock</p>
    </sec>
    <sec id="sec-2">
      <title>Introduction</title>
      <p>union {
struct {</p>
      <p>BITFIELD2(word_t,
type : 2,
tcb_p : BITS_WORD - 2
};</p>
      <p>);
} x;
word_t raw;</p>
      <p>
        Our approach is to provide an opaque, abstract type, implementing the
tagged-union/bitfield semantics, together with generated accessor functions. The
tool automatically provides the proofs that the functions behave as expected.
Whilst this is not a radically new idea, our approach is successful precisely
because we target the regular low-level functions, which nonetheless comprise
14% of the code within seL4. This tool also provides a case study for the use
of the C semantics of Tuch et al. [
        <xref ref-type="bibr" rid="ref26">26</xref>
        ], and Dawson’s Isabelle/HOL library for
machine words [
        <xref ref-type="bibr" rid="ref4">4</xref>
        ]. The remainder of the paper is laid out as follows: Section
2 introduces the specification language used to describe the bit-level layout of
structures, Section 3 shows the C code generation framework, and Section 4
explains the framework of automatically generated proofs to allow reasoning
without descending to the level of pointers and bit manipulation.
2
      </p>
    </sec>
    <sec id="sec-3">
      <title>Specification Language</title>
      <p>The tagged-union/packed-bitfield structure is useful in a number of contexts e.g.
hardware-dictated page-table layouts, hardware register mapping, and highly
optimised data structure storage. As a running example, we will consider a subset
of the seL4/ARM capability representation. Capabilities are used as a proxy
for authority, and we consider only two capability types: Null caps (null cap)
which function as placeholders, and Untyped caps (untyped cap) which convey
authority over a power of two sized block of memory. The capability is represented
as a two word (64 bit) bitfield: Null caps contain no data other than the type
tag, whereas Untyped caps have two fields: capBlockSize and capPtr, a pointer
aligned on a 16-byte boundary.</p>
      <p>The cap representations are specified as follows (the full grammar is included
in Fig. 5). First the machine word size (32 bits for ARM) is specified with the
base keyword:
base 32</p>
      <p>Next, bitfield blocks are specified. Fields are listed from most-significant
to least-significant bit (Fig. 2). The padding keyword introduces anonymous
padding space, to achieve the desired alignment, and the field keyword reserves
space for a named field. In the null cap example, padding 32 reserves one
empty machine word, field capType 4 allocates a 4 bit field at the top of the
second word, and padding 28 explicitly fills the remainder of the second word.
The trailing padding is mandatory where the fields do not fill the lower bits of
the last word.
block null_cap {
padding 32
field capType 4
padding 28
}
}
block untyped_cap {
padding 27
field capBlockSize 5
field capType 4
field_high capPtr 28</p>
      <p>Padding between fields is inserted explicitly, fields are forbidden to cross
word boundaries, and the size of each block must be a multiple of the base
word size. These restrictions ensure that the implementation maps efficiently
onto common machine operations, and present no difficulties in practice. The
field high keyword specifies that a field should be left-aligned to the word size
when read or written, padded on the right with zero bits, see Fig. 3.
tagged_union cap capType {
tag null_cap 0
tag untyped_cap 1</p>
      <p>Finally, blocks are grouped together into tagged unions (Fig. 4). The keyword
tagged union is followed by the name of the union, and the name of the tag
field, then a list of block names, together with their associated tag values. All
blocks in the union must be the same size, and each must contain a tag field. All
tag fields must be the same size, and at the same location within the block.
entity_list ::= empty
| entity_list block
| entity_list tagged_union
| entity_list base
base ::= "base" INTLIT
block ::= "block" IDENTIFIER "{" fields "}"
fields ::= empty
| fields "padding" INTLIT
| fields "field_high" IDENTIFIER INTLIT
| fields "field" IDENTIFIER INTLIT
tagged_union ::= "tagged_union" IDENTIFIER IDENTIFIER "{" tags "}"
tags ::= empty
| tags "tag" IDENTIFIER INTLIT</p>
    </sec>
    <sec id="sec-4">
      <title>Generated Code</title>
      <p>This section gives a brief overview of the code generated from the specifications
above. Each block and union in the specification language is translated to a
C representation with appropriate access and update functions. Each object is
represented by a struct containing simply an array of machine words, and for
each union, an enum of tag values. The wrapping struct allows pass and return
by value in C.
struct cap {</p>
      <p>
        uint32_t words[
        <xref ref-type="bibr" rid="ref2">2</xref>
        ];
};
typedef struct cap cap_t;
enum cap_tag {
cap_null_cap = 0,
cap_untyped_cap = 1,
};
typedef enum cap_tag cap_tag_t;
      </p>
      <p>For each block and union, the tool generates create, access and update
functions. Each such function is generated in a purely functional version, which
passes and returns a stack object of appropriate struct type:
static inline cap_t CONST
cap_untyped_cap_set_capBlockSize(cap_t cap, uint32_t v) {
assert(((cap.words[0] &gt;&gt; 28) &amp; 0xf) ==</p>
      <p>
        cap_untyped_cap);
cap.words[
        <xref ref-type="bibr" rid="ref1">1</xref>
        ] &amp;= ~0x1f;
cap.words[
        <xref ref-type="bibr" rid="ref1">1</xref>
        ] |= (v &lt;&lt; 0) &amp; 0x1f;
return cap;
      </p>
      <p>Also generated is a pointer lifted version, which operates indirectly on heap
values through a supplied pointer:
}
}
static inline void
cap_untyped_cap_ptr_set_capBlockSize(cap_t *cap_ptr,</p>
      <p>uint32_t v) {
assert(((cap_ptr-&gt;words[0] &gt;&gt; 28) &amp; 0xf) ==</p>
      <p>
        cap_untyped_cap);
cap_ptr-&gt;words[
        <xref ref-type="bibr" rid="ref1">1</xref>
        ] &amp;= ~0x1f;
cap_ptr-&gt;words[
        <xref ref-type="bibr" rid="ref1">1</xref>
        ] |= (v &lt;&lt; 0) &amp; 0x1f;
The prototypes for the remaining functions are given in Fig. 6.
      </p>
      <p>Note that the generated API only provides functions that read the tag field
through the union type, and no function to write it directly. This imposes a
class-like behaviour on the types. The subtype is set implicitly at creation time,
and can only be modified by overwriting with an object of a different type. This
will turn out to be an important property for verification.</p>
      <p>In practice the output is automatically pruned, so that only those functions
actually used in the source are generated. This speeds the proof process. As the
specification language is highly focussed and carefully limited, the generated
code is simple and fast, highly predictable, and easily inlined by the compiler.
4</p>
    </sec>
    <sec id="sec-5">
      <title>Generated Specifications</title>
      <p>The final and most novel part of the approach consists of the automatically
generated, machine checked function specifications together with their automated
static inline uint32_t CONST
cap_get_capType(cap_t cap);
static inline uint32_t PURE
cap_ptr_get_capType(cap_t *cap_ptr);
static inline cap_t CONST
cap_untyped_cap_new(uint32_t capBlockSize,</p>
      <p>uint32_t capPtr);
static inline void PURE
cap_untyped_cap_ptr_new(cap_t *cap_ptr,
uint32_t capBlockSize,
uint32_t capPtr);
static inline uint32_t CONST
cap_untyped_cap_get_capBlockSize(cap_t cap);
static inline uint32_t PURE
cap_untyped_cap_ptr_get_capBlockSize(cap_t *cap_ptr);
static inline cap_t CONST
cap_untyped_cap_set_capBlockSize(cap_t cap,</p>
      <p>uint32_t v);
static inline void
cap_untyped_cap_ptr_set_capBlockSize(cap_t *cap_ptr,</p>
      <p>uint32_t v);
proofs. The function of the generated proofs is not only to show implementation
correctness, but also to provide sufficient reasoning power to allow any statement
involving the generated functions to be rephrased in terms of simple operations
on abstract, high-level types in the theorem prover. This means that we can
avoid invoking bit manipulations and pointer dereferences when reasoning about
the packed structures as part of a larger proof. We can instead reason about
higher-level types, for which there is well established support.</p>
      <p>This abstract representation is expressed in terms of Isabelle’s record types,
which behave much like struct or record constructs in typical programming
languages, providing access and update of disjoint fields. The bitfields from the
C level are represented as records of fields on the abstract level. For example,
the untyped cap block is represented as follows:
record cap_untyped_cap_CL =
capBlockSize_CL :: "word32"
capPtr_CL :: "word32"</p>
      <p>Tagged unions are represented by an algebraic datatype wrapping the records
corresponding to the component bitfields, with one constructor for each. Tag
fields are not included in the record representation, but are implied by the choice
of constructor within the union type. Any bitfields which are empty after the
removal of the tag field are represented simply by a naked constructor, with no
associated record. The cap union translates thus:
datatype cap_CL =</p>
      <p>Cap_null_cap
| Cap_untyped_cap cap_untyped_cap_CL</p>
      <p>The name convention is that the C types and identifiers, when parsed into
Isabelle, are tagged by appending C, whereas the lifted types are tagged with CL.
The connection between the C level and the abstract level will be provided by
two functions in the example below: cap_lift and cap_untyped_cap_lift. The former
lifts any cap_C to a cap_CL, and the latter lifts a cap_C with the untyped cap tag
directly to a cap_untyped_cap_CL. It is under-specified in all other cases.</p>
      <p>
        The properties of the generated functions are expressed as
strongest-postcondition Hoare rules. Specifically, we use Schirmer’s [
        <xref ref-type="bibr" rid="ref23">23</xref>
        ] verification environment
for imperative programs in Isabelle/HOL. It contains a verification condition
generator (VCG) which automates reasoning about Hoare-triples. Tuch’s et
al. [
        <xref ref-type="bibr" rid="ref26">26</xref>
        ] instantiation to C parses the generated code directly into Isabelle/HOL
and into Schirmer’s representation language SIMPL.
      </p>
      <p>As an example, we will take the generated specification of the generated
C function cap untyped cap set capBlockSize. It takes two arguments, an
untyped capability cap and a new block size v. It returns the original capability
updated with the new block size. The formal specification below translates this
into a record update:
" Γ ` {|s. cap_get_tag ´cap = cap_untyped_cap |}
´ret__struct_cap_C :==</p>
      <p>PROC cap_untyped_cap_set_capBlockSize( ´cap, ´v)
{|cap_untyped_cap_lift ´ret__struct_cap_C =
cap_untyped_cap_lift scap (|capBlockSize_CL := sv AND (mask 5) |) ∧
cap_get_tag ´ret__struct_cap_C = cap_untyped_cap |}"</p>
      <p>The specification above reads as follows. For all program contexts Γ , if the
tag of the C-struct cap in the current state (indicated by ´) equals the value
cap_untyped_cap, and we execute the function cap_untyped_cap_set_capBlockSize with
parameters cap and v, storing its return value in ret__struct_cap_C, we will arrive at
the following post condition: lifting the return value to the abstract record type
is the same as lifting the value of cap in the initial state s, and then performing
an update of the abstract record field capBlockSize_CL with the value v had in
state s. Additionally, as a convenience for automated methods in the larger proof,
we provide that the tag of the return value remains cap_untyped_cap. A separate
specification states (and the tool proves) that the function is side-effect free, i.e.
that no global variables, including the heap, are changed. The term AND (mask 5)
carries the additional information that the field has a size of 5 bits. This form
proved more convenient than the alternative of having an abstract field of word
length 5, because casting between word lengths often introduces additional proof
obligations.</p>
      <p>The meaning of the rule can also be expressed by means of the commuting
diagram in Fig. 7.</p>
      <p>λcap. cap(|capBlockSize CL := v AND (mask 5)|)</p>
      <p>•O / •/O
cap untyped cap lift</p>
      <p>cap untyped cap lift
•cap untyped cap set capBlockSize(...,v/)•</p>
      <p>For Fig. 7, consider cap untyped cap set capBlockSize as a function from
cap t (its first argument) to cap t (its return value). Control flows left to right,
and r (| a := x |) is the Isabelle syntax for the record r, with field a updated
with value x. This makes it clear that the function of the rule is to allow us to
transform a function call into a record update, by commuting it with a lift. We
can therefore take any precondition of the form P (cap_untyped_cap_lift cap), and
commute it past any number of field updates, to produce a postcondition of the
form P (f (cap_untyped_cap_lift cap)), where f is the composition of a number of
record updates.</p>
      <p>(|capBlockSize CL = capBlockSize AND (mask 5), capPtr CL = capPtr AND (mask 28)|)
• / •/O</p>
      <p>cap untyped cap lift
•cap untyped cap new(capBlockSize,capPt/r•)</p>
      <p>That this is useful becomes clear when we consider the equivalent diagram
for the cap_untyped_cap_new function (Fig 8), which returns a new untyped
capability. This provides a starting point for our chain of reasoning, by
providing the identity cap_untyped_cap_lift cap = (|capBlockSize_CL=capBlockSize AND (mask
5),capPtr_CL=capPtr AND (mask 28) |). We can base our argument on such a case, as
long as bitfield objects are only initialised via the appropriate * new functions,
and the type tags are never externally modified. This justifies the API restriction
introduced in Section 3, which is adhered to by the seL4 kernel implementation
without loss of convenience or performance.</p>
      <p>
        Equivalent rules are proved automatically for all the generated functions, and
their pointer-lifted versions. The latter involve direct heap access to record fields
and automate the interactive reasoning Tuch provides [
        <xref ref-type="bibr" rid="ref25">25</xref>
        ]. Additionally to what
Tuch provides, we make use of the concept of packed records, which allow us
to ignore padding in record implementations and derive more precise properties
of the corresponding memory layout. Packed records are represented by a type
class in Isabelle that simply states that all fields in the record are of a size that
makes padding unnecessary.
      </p>
      <p>The proofs of the specifications above are fully automated and generally
consists of two to three automated method invocations in Isabelle. The first of
these is a call to the C-level VCG mentioned above. The second and possibly
third, first reduce the remaining proof obligation from variable, heap, and
structupdates to a goal on bit-vectors only. This is then solved automatically with a
carefully designed set of generic, algebraic rewrite rules for the bit operations
involved in the generated functions. The direct proof script for one specification
of a typical C-function is typically about 10 lines long.
5</p>
    </sec>
    <sec id="sec-6">
      <title>Related Work</title>
      <p>
        Earlier work on OS verification includes PSOS [
        <xref ref-type="bibr" rid="ref10">10</xref>
        ] and UCLA Secure Unix [
        <xref ref-type="bibr" rid="ref27">27</xref>
        ].
Later, KIT [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ] describes verification of process isolation properties down to object
code level, but for an idealised kernel far simpler than modern microkernels. The
Verisoft project [
        <xref ref-type="bibr" rid="ref11 ref12">11, 12</xref>
        ] is attempting to verify a whole system stack, including
hardware, compiler, applications, and a simplified microkernel: VAMOS. The
VFiasco [
        <xref ref-type="bibr" rid="ref14">14</xref>
        ] project is attempting to verify the Fiasco kernel, another variant of
L4, directly at the C++ level. These verification projects do not use generated
C code for automating parts of their proof obligations. In the case of Verisoft,
there is no reason to distrust the compiler as it is also verified [
        <xref ref-type="bibr" rid="ref15 ref20">20, 15</xref>
        ]. Directly
using C or dropping down to assembly code to implement the desired features
does not have the benefit of the high-level reasoning support and API the tool
presented here provides, however.
      </p>
      <p>
        The verified proofs in this work build directly on Tuch’s et al. memory model
for C [
        <xref ref-type="bibr" rid="ref24 ref25 ref26">26, 25, 24</xref>
        ] which in turn builds on work by Schirmer [
        <xref ref-type="bibr" rid="ref22 ref23">23, 22</xref>
        ] that provides
a generic framework, verification condition generator, and Hoare logic [
        <xref ref-type="bibr" rid="ref13">13</xref>
        ] for
imperative programs. Both are intended for interactive verification. This paper
uses the predictable structure of the generated code to completely automate the
pointer level proofs on the C implementation.
      </p>
      <p>
        This work also builds directly on Dawson’s machine-word library [
        <xref ref-type="bibr" rid="ref4">4</xref>
        ] for
Isabelle/HOL. Despite recent progress in tools like Yices [
        <xref ref-type="bibr" rid="ref6">6</xref>
        ], bit-vector proofs for
machine words remain hard to automate. Traditional SAT solvers are usually too
slow to handle the resulting proof obligations on realistic word sizes. Again, due
to the predictable nature of the generated code, the tool is able to fully automate
the bit-level verification conditions with a set of algebraic rewrite rules. This
means that switching to different, say 64-bit, architectures should not result in
any noticeable slowdown of the generated proofs.
      </p>
      <p>
        General translation validation [
        <xref ref-type="bibr" rid="ref21">21</xref>
        ] and compiler correctness including Leroy’s
et al. work [
        <xref ref-type="bibr" rid="ref16">16</xref>
        ] are related to the topic. As mentioned above, the tool presented
here can exploit the known, predictable nature of the application domain to
provide a convenient interface to, and integration into, the user’s proofs.
      </p>
      <p>
        Also related to generated correctness proofs is the idea of proof-carrying
code [
        <xref ref-type="bibr" rid="ref18">18</xref>
        ], which usually focusses on the machine level and on specific properties
such as memory safety or resource constraints. Functional correctness is not
usually targeted, because it is impossible to automate completely. Barthe et
al. [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ] come close by automatically transforming certificates from source code
to machine code and, similarly to the work presented here, generating proofs
for generated code. In contrast to this, the bitfield generator here does not
require any source-level proof as input. It generates a full functional correctness
statement automatically.
      </p>
      <p>
        Denney et al. [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ] automatically prove properties about generated aerospace
software. The generated code appears more complex than that presented here,
but the semantics they are using is not foundational and the properties do not
cover full functional correctness, only specific safety properties.
6
      </p>
    </sec>
    <sec id="sec-7">
      <title>Conclusion</title>
      <p>This paper has summarised a generator for tagged unions of packed bitfields in
the C programming language, as they are used in low-level systems code and
operating system kernel implementations. In theory, this data structure can be
implemented with C primitives without resorting to a generator. However,
compiler implementations of bitfields seem to be so unpredictable in memory layout
and performance over different platforms and compilers that kernel programmers
distrust this compiler feature more than others.</p>
      <p>The tool generates efficient, predictable, and above all correct C code from a
short, high-level description that is detailed enough to provide precise memory
layout specification which is important to map data, for instance, to memory
mapped hardware device registers. The generated code includes the data type
itself as well as an API for convenient, high-level access on the stack and on the
heap.</p>
      <p>This work shows that an automatic correctness proof of generated code for
controlled environments is not hard to achieve, even if this code contains bit-level
reasoning and pointer access. The proof is foundational in the sense that it
assumes no specific axioms on the application domain, but is built directly on
the semantics of the C programming language. The proof is machine-checked
in the theorem prover Isabelle/HOL and provides an example of
translationvalidation: Instead of proving the correctness of the generator, the correctness of
the generated code is proven instead.</p>
      <p>The usefulness of the tool reaches further than a stand-alone correctness proof.
The Hoare-triples proven integrate directly, within the same formal model, with
larger implementation proofs of client code using the generated bitfields. The
Hoare-triples are designed such that client proofs and code have no need to reason
about the internal representation or bit-level operations that are carried out.
They provide an abstract interface. Translation validation has likely made this
easier to achieve than in a generator correctness proof. No meta-level reasoning
or switching of formal models is required.</p>
      <p>The tool is expected to automate 14% of the C implementation proofs in the
L4.verified project, covering 1,800 lines of C code with 7,800 lines of generated
proof. The seL4 kernel, including all generated inline functions, comprises 12,600
lines of code. The tool is generally applicable to code that needs to have direct,
reliable control over the memory layout of data structures. The technique of
generating proofs that integrate well into interactive environments should generalise
easily to constrained application domains where the structure of the generated
proof is predictable.</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          1.
          <string-name>
            <given-names>G.</given-names>
            <surname>Barthe</surname>
          </string-name>
          , B. Gr´egoire, C. Kunz, and
          <string-name>
            <given-names>T.</given-names>
            <surname>Rezk</surname>
          </string-name>
          .
          <article-title>Certificate translation for optimizing compilers</article-title>
          .
          <source>In Proceedings of the 13th International Static Analysis Symposium (SAS)</source>
          , volume
          <volume>4134</volume>
          <source>of LNCS</source>
          , pages
          <fpage>301</fpage>
          -
          <lpage>317</lpage>
          , Seoul, Korea,
          <year>August 2006</year>
          . Springer.
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          2.
          <string-name>
            <surname>William</surname>
            <given-names>R.</given-names>
          </string-name>
          <string-name>
            <surname>Bevier</surname>
          </string-name>
          . Kit:
          <article-title>A study in operating system verification</article-title>
          .
          <source>IEEE Transactions on Software Engineering</source>
          ,
          <volume>15</volume>
          (
          <issue>11</issue>
          ):
          <fpage>1382</fpage>
          -
          <lpage>1396</lpage>
          ,
          <year>1989</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          3.
          <string-name>
            <given-names>David</given-names>
            <surname>Cock</surname>
          </string-name>
          ,
          <string-name>
            <given-names>Gerwin</given-names>
            <surname>Klein</surname>
          </string-name>
          , and Thomas Sewell.
          <article-title>Secure microkernels, state monads and scalable refinement</article-title>
          .
          <source>In Cesar Munoz and Otmane Ait</source>
          , editors,
          <source>Proceedings of the 21st International Conference on Theorem Proving in Higher Order Logics (TPHOLs'08)</source>
          , LNCS. Springer,
          <year>2008</year>
          . To appear.
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          4.
          <string-name>
            <surname>Jeremy</surname>
            <given-names>E.</given-names>
          </string-name>
          <string-name>
            <surname>Dawson</surname>
          </string-name>
          .
          <article-title>Isabelle theories for machine words</article-title>
          .
          <source>In Seventh International Workshop on Automated Verification of Critical Systems (AVOCS'07)</source>
          , Electronic Notes in Computer Science, Oxford, UK,
          <year>September 2007</year>
          . Elsevier. To appear.
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          5.
          <string-name>
            <given-names>Philip</given-names>
            <surname>Derrin</surname>
          </string-name>
          , Kevin Elphinstone, Gerwin Klein, David Cock, and
          <string-name>
            <surname>Manuel</surname>
            <given-names>M. T.</given-names>
          </string-name>
          <string-name>
            <surname>Chakravarty</surname>
          </string-name>
          .
          <article-title>Running the manual: An approach to high-assurance microkernel development</article-title>
          .
          <source>In Proc. ACM SIGPLAN Haskell Workshop</source>
          , Portland,
          <string-name>
            <surname>OR</surname>
          </string-name>
          , USA,
          <year>September 2006</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          6.
          <string-name>
            <given-names>Bruno</given-names>
            <surname>Dutertre</surname>
          </string-name>
          and Leonardo de Moura.
          <article-title>The yices smt solver</article-title>
          . Tool paper at http://yices.csl.sri.com/tool-paper.pdf,
          <year>2006</year>
          . Link visited
          <year>June 2008</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          7.
          <string-name>
            <given-names>Dhammika</given-names>
            <surname>Elkaduwe</surname>
          </string-name>
          , Philip Derrin, and
          <string-name>
            <given-names>Kevin</given-names>
            <surname>Elphinstone</surname>
          </string-name>
          .
          <article-title>A memory allocation model for an embedded microkernel</article-title>
          .
          <source>In Proc. 1st MIKES</source>
          , pages
          <fpage>28</fpage>
          -
          <lpage>34</lpage>
          , Sydney, Australia,
          <year>2007</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          8.
          <string-name>
            <given-names>Kevin</given-names>
            <surname>Elphinstone</surname>
          </string-name>
          , Gerwin Klein, Philip Derrin, Timothy Roscoe, and
          <string-name>
            <given-names>Gernot</given-names>
            <surname>Heiser</surname>
          </string-name>
          .
          <article-title>Towards a practical, verified kernel</article-title>
          .
          <source>In Proc. 11th Workshop on Hot Topics in Operating Systems</source>
          , San Diego, CA, USA, May
          <year>2007</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          9.
          <string-name>
            <given-names>Bernd</given-names>
            <surname>Fischer Ewen</surname>
          </string-name>
          Denney and
          <string-name>
            <given-names>Johann</given-names>
            <surname>Schumann</surname>
          </string-name>
          .
          <article-title>Using automated theorem provers to certify auto-generated aerospace software</article-title>
          .
          <source>In Proc. 2nd International Joint Conference on Automated Reasoning (IJCAR'04)</source>
          , volume
          <volume>3097</volume>
          <source>of LNCS</source>
          , pages
          <fpage>198</fpage>
          -
          <lpage>212</lpage>
          . Springer,
          <year>2004</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          10.
          <string-name>
            <surname>Richard</surname>
            <given-names>J.</given-names>
          </string-name>
          <string-name>
            <surname>Feiertag</surname>
            and
            <given-names>Peter G. Neumann.</given-names>
          </string-name>
          <article-title>The foundations of a provably secure operating system (PSOS)</article-title>
          .
          <source>In AFIPS Conf. Proc., 1979National Comp. Conf.</source>
          , pages
          <fpage>329</fpage>
          -
          <lpage>334</lpage>
          , New York, NY, USA,
          <year>June 1979</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          11.
          <string-name>
            <surname>Mauro</surname>
            <given-names>Gargano</given-names>
          </string-name>
          , Mark Hillebrand, Dirk Leinenbach, and Wolfgang Paul.
          <article-title>On the correctness of operating system kernels</article-title>
          . In Joe Hurd and Thomas F. Melham, editors,
          <source>Proc. TPHOls'05</source>
          , volume
          <volume>3603</volume>
          <source>of LNCS</source>
          , pages
          <fpage>1</fpage>
          -
          <lpage>16</lpage>
          , Oxford, UK,
          <year>2005</year>
          . Springer.
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          12.
          <string-name>
            <surname>Mark</surname>
            <given-names>A.</given-names>
          </string-name>
          <string-name>
            <surname>Hillebrand</surname>
            and
            <given-names>Wolfgang J.</given-names>
          </string-name>
          <string-name>
            <surname>Paul</surname>
          </string-name>
          .
          <article-title>On the architecture of system verification environments</article-title>
          .
          <source>In Hardware and Software: Verification and Testing</source>
          , volume
          <volume>4899</volume>
          <source>of LNCS</source>
          , pages
          <fpage>153</fpage>
          -
          <lpage>168</lpage>
          , Berlin, Germany,
          <year>2008</year>
          . Springer.
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          13.
          <string-name>
            <given-names>C. A. R.</given-names>
            <surname>Hoare</surname>
          </string-name>
          .
          <article-title>An axiomatic basis for computer programming</article-title>
          .
          <source>Communications of the ACM</source>
          ,
          <volume>12</volume>
          (
          <issue>10</issue>
          ):
          <fpage>576</fpage>
          -
          <lpage>580</lpage>
          ,
          <year>1969</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref14">
        <mixed-citation>
          14.
          <string-name>
            <given-names>Michael</given-names>
            <surname>Hohmuth</surname>
          </string-name>
          and
          <string-name>
            <given-names>Hendrik</given-names>
            <surname>Tews</surname>
          </string-name>
          .
          <article-title>The VFiasco approach for a verified operating system</article-title>
          .
          <source>In Proc. 2nd ECOOP-PLOS Workshop</source>
          , Glasgow, UK,
          <year>October 2005</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref15">
        <mixed-citation>
          15.
          <string-name>
            <given-names>Dirk</given-names>
            <surname>Leinenbach</surname>
          </string-name>
          and
          <string-name>
            <given-names>Elena</given-names>
            <surname>Petrova</surname>
          </string-name>
          .
          <article-title>Pervasive compiler verification-from verified programs to verified systems</article-title>
          . In Ralf Huuck, Gerwin Klein, and Bastian Schlich, editors,
          <source>Proceedings of the 3rd international Workshop on Systems Software Verification (SSV'08)</source>
          , Electronic Notes in Computer Science, Sydney, Australia,
          <year>February 2008</year>
          . Elsevier. To appear.
        </mixed-citation>
      </ref>
      <ref id="ref16">
        <mixed-citation>
          16.
          <string-name>
            <given-names>Xavier</given-names>
            <surname>Leroy</surname>
          </string-name>
          .
          <article-title>Formal certification of a compiler back-end, or: Programming a compiler with a proof assistant</article-title>
          . In J. G. Morrisett and
          <string-name>
            <surname>S. L. P.</surname>
          </string-name>
          Jones, editors,
          <source>33rd symposium Principles of Programming Languages (POPL'06)</source>
          , pages
          <fpage>42</fpage>
          -
          <lpage>54</lpage>
          , New York, NY, USA,
          <year>2006</year>
          . ACM.
        </mixed-citation>
      </ref>
      <ref id="ref17">
        <mixed-citation>
          17.
          <string-name>
            <given-names>J.</given-names>
            <surname>Liedtke</surname>
          </string-name>
          .
          <article-title>On μ-kernel construction</article-title>
          .
          <source>In 15th ACM Symposium on Operating System Principles (SOSP)</source>
          ,
          <year>December 1995</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref18">
        <mixed-citation>
          18.
          <string-name>
            <surname>George</surname>
            <given-names>C.</given-names>
          </string-name>
          <string-name>
            <surname>Necula</surname>
          </string-name>
          .
          <article-title>Proof-carrying code</article-title>
          .
          <source>In POPL '97: Proceedings of the 24th ACM SIGPLANSIGACT symposium on Principles of programming languages</source>
          , pages
          <fpage>106</fpage>
          -
          <lpage>119</lpage>
          , New York, NY, USA,
          <year>1997</year>
          . ACM.
        </mixed-citation>
      </ref>
      <ref id="ref19">
        <mixed-citation>
          19.
          <string-name>
            <surname>Open</surname>
          </string-name>
          <article-title>Kernel Labs, Inc. OKL web site</article-title>
          . http://www.ok-labs.com,
          <year>2007</year>
          . Visited May
          <year>2008</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref20">
        <mixed-citation>
          20.
          <string-name>
            <given-names>Elena</given-names>
            <surname>Petrova</surname>
          </string-name>
          .
          <article-title>Verification of the C0 Compiler Implementation on the Source Code Level</article-title>
          .
          <source>PhD thesis</source>
          , Saarland University, Computer Science Department, Saarbru¨cken, Germany,
          <year>2007</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref21">
        <mixed-citation>
          21.
          <string-name>
            <surname>Amir</surname>
            <given-names>Pnueli</given-names>
          </string-name>
          ,
          <string-name>
            <given-names>Michael</given-names>
            <surname>Siegel</surname>
          </string-name>
          , and
          <string-name>
            <given-names>Eli</given-names>
            <surname>Singerman</surname>
          </string-name>
          .
          <article-title>Translation validation</article-title>
          . In Bernhard Steffen, editor,
          <source>Proc. 4th Intl. Conf. Tools and Algorithms for Construction and Analysis of Systems (TACAS'98)</source>
          , volume
          <volume>1384</volume>
          <source>of LNCS</source>
          , pages
          <fpage>151</fpage>
          -
          <lpage>166</lpage>
          . Springer,
          <year>1998</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref22">
        <mixed-citation>
          22.
          <string-name>
            <given-names>Norbert</given-names>
            <surname>Schirmer</surname>
          </string-name>
          .
          <article-title>A verification environment for sequential imperative programs in Isabelle/HOL</article-title>
          . In F. Baader and
          <string-name>
            <surname>A</surname>
          </string-name>
          . Voronkov, editors,
          <source>Logic for Programming</source>
          ,
          <source>AI, and Reasoning</source>
          , volume
          <volume>3452</volume>
          <source>of LNAI</source>
          , pages
          <fpage>398</fpage>
          -
          <lpage>414</lpage>
          . Springer,
          <year>2005</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref23">
        <mixed-citation>
          23.
          <string-name>
            <given-names>Norbert</given-names>
            <surname>Schirmer</surname>
          </string-name>
          .
          <article-title>Verification of Sequential Imperative Programs in Isabelle/HOL</article-title>
          .
          <source>PhD thesis</source>
          , Technische Universita¨t Mu¨nchen,
          <year>2006</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref24">
        <mixed-citation>
          24.
          <string-name>
            <given-names>Harvey</given-names>
            <surname>Tuch</surname>
          </string-name>
          .
          <article-title>Formal Memory Models for Verifying C Systems Code</article-title>
          .
          <source>PhD thesis</source>
          , School for Computer Science and Engineering, University of New South Wales, Sydney, Australia,
          <year>2008</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref25">
        <mixed-citation>
          25.
          <string-name>
            <given-names>Harvey</given-names>
            <surname>Tuch</surname>
          </string-name>
          .
          <article-title>Structured types and separation logic</article-title>
          . In Ralf Huuck, Gerwin Klein, and Bastian Schlich, editors,
          <source>Proceedings of the 3rd International Workshop on Systems Software Verification (SSV'08)</source>
          , Electronic Notes in Computer Science, Sydney, Australia,
          <year>February 2008</year>
          . Elsevier. To appear.
        </mixed-citation>
      </ref>
      <ref id="ref26">
        <mixed-citation>
          26.
          <string-name>
            <surname>Harvey</surname>
            <given-names>Tuch</given-names>
          </string-name>
          , Gerwin Klein, and
          <string-name>
            <given-names>Michael</given-names>
            <surname>Norrish</surname>
          </string-name>
          . Types, bytes, and
          <article-title>separation logic</article-title>
          .
          <source>In Martin Hofmann and Matthias Felleisen</source>
          , editors,
          <source>Proc. 34th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages</source>
          , pages
          <fpage>97</fpage>
          -
          <lpage>108</lpage>
          , Nice, France,
          <year>2007</year>
          . ACM.
        </mixed-citation>
      </ref>
      <ref id="ref27">
        <mixed-citation>
          27.
          <string-name>
            <surname>Bruce</surname>
            <given-names>Walker</given-names>
          </string-name>
          , Richard Kemmerer, and
          <string-name>
            <given-names>Gerald</given-names>
            <surname>Popek</surname>
          </string-name>
          .
          <article-title>Specification and verification of the UCLA Unix security kernel</article-title>
          .
          <source>Commun. ACM</source>
          ,
          <volume>23</volume>
          (
          <issue>2</issue>
          ):
          <fpage>118</fpage>
          -
          <lpage>131</lpage>
          ,
          <year>1980</year>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>