arpa command-line ReferenceAWS Proof Build Assistant
AWS Proof Build Assistant automatically finds build-related information such as file dependencies, included directories and defines for source files within a c
code base.
Users can access the AWS Proof Build Assistant through arpa
, the command-line interface.
This document serves as a reference for using arpa
and integrating it into your project.
arpa
accumulates build information for a complete c
code base inside an internal JSON representation which can be used to generate a Makefile
containing all the relevant information for a single given source file.
arpa
simplifies the task of proof developers by automatically generating a ready-to-use Makefile
containing information that developers previously had to find manually.
In order to use the generated Makefile
, developers must include it in another custom (and possibly trivial) Makefile
and run make
on it.
Its ease of use makes AWS Proof Build Assistant ideal for local proof implementation and building as well as part of CI.
Overview
Consider the following c
file, which is a CBMC proof harness (discussed below):
#include "api/s2n.h"
#include "stuffer/s2n_stuffer.h"
#include <assert.h>
#include <cbmc_proof/proof_allocators.h>
#include <cbmc_proof/make_common_datastructures.h>
void s2n_stuffer_alloc_harness() {
struct s2n_stuffer *stuffer =
can_fail_malloc(sizeof(*stuffer));
struct s2n_blob* in = cbmc_allocate_s2n_blob();
if (s2n_stuffer_init(stuffer, in) == S2N_SUCCESS){
assert(s2n_stuffer_is_valid(stuffer));
assert(s2n_blob_is_valid(in));
};
}
In order to run the above file as part of a CBMC proof, users must provide to CBMC a collection of build information for the file which consists of:
- Source file dependencies:
Obtained through static analysis. For this purpose, AWS Proof Build Assistant usescflow
, which generates a function-level call graph. - Included directories and Defined variables:
Required for compilation. A compilation command for each source file is generated by setting the-DCMAKE_EXPORT_COMPILE_COMMANDS
flag when callingcmake
on the code base.
AWS Proof Build Assistant calls the relevant tools, parses the outputs and gathers all the build information within an easy-to-read and easy-to-integrate Makefile
that is custom-build for the specific proof harness under test. Users can run the following command:
arpa run \
-file path/to/file_under_test.c \
-cc $BLDDIR/compile_commands.json \
-r $SRCDIR
Doing so generates the following Makefile
, which contains all the relevant build information for the above source file:
DEFINES += -DS2N_HAVE_EXECINFO
DEFINES += -DS2N_NO_PQ_ASM
DEFINES += -D_POSIX_C_SOURCE=200809L
INCLUDES += -I$(SRCDIR)
INCLUDES += -I$(SRCDIR)/api
PROOF_SOURCES += $(PROOF_SOURCE)/make_common_datastructures.c
PROOF_SOURCES += $(PROOF_SOURCE)/proof_allocators.c
PROJECT_SOURCES += $(SRCDIR)/stuffer/s2n_stuffer.c
PROJECT_SOURCES += $(SRCDIR)/utils/s2n_blob.c
PROJECT_SOURCES += $(SRCDIR)/utils/s2n_mem.c
PROJECT_SOURCES += $(SRCDIR)/utils/s2n_safety.c
Motivation
Although arpa
is capable of generating valuable Makefile
s for any source file of a code base, its main use case is in the context of running CBMC proofs.
Generally speaking, running a CBMC proof requires users to create a harness (a c
source file containing the CBMC call) and a corresponding Makefile.
This Makefile
should contain all the required build information for the proof harness under test and should include a Makefile.common
that contains all the make
rules.
arpa
is useful in this context as it generates a Makefile.arpa
that contains all the build information (excluding customizations) that can be included directly in a custom Makefile
.
arpa
would be ideal for code bases that already contain CBMC proofs. In this context, arpa
would be integrated as a submodule inside these code bases and would simplify the development of additional CBMC proofs. Currently, we can envision arpa
to be integrated in the following five AWS projects:
- S2n (Integration PR pending)
- AWS C Common
- AWS Encryption sdk
- Amazon FreeRTOS
- AWS Iot device sdk
For Proof Writers
In this section, we provide a step-by-step guide designed to help proof developers integrate AWS Proof Build Assistant into their project and use it for implementation of CBMC Proofs.
Integrating arpa
into a project
- Integrate AWS Proof Build Assistant as a submodule:
- Inside your git repository, run:
git submodule add https://github.com/path/to/aws/proof/assistant
- (Optional) Add the submodule root path to
PATH
:
export PATH=path/to/submodule/root/dir:$PATH
- Inside your git repository, run:
- Install the required dependencies listed below:
- Cmake (for tests) - (
apt-get install cmake
orbrew install cmake
) - GNU cflow - (
apt-get install cflow
orbrew install cflow
) - Voluptuous - (
python3 -m pip install voluptuous
)
- Cmake (for tests) - (
Using arpa
for writing proofs
If your project...
...conforms to the aws-templates-for-cbmc-proofs
- Further integrate
arpa
into the project by modifying the includedMakefile-project-defines
project:- Add the path to to the
arpa
executable :ARPA = /path/to/AWS_Proof_Build_Assistant/submodule/arpa
- Add project-specific
cmake
flags:ARPA_CMAKE_FLAGS += --cmake-flag-A ARPA_CMAKE_FLAGS += --cmake-flag-B ...
- Add the path to to the
- Generate a
Makefile.arpa
for a given proof harness:- Move to the proof directory which contains a harness source file:
cd $PROOFDIR
- Run
make arpa
(which runscmake
in the background, generates compilation commands, the runsarpa run
):make arpa
- This generates a
Makefile
at$PROOFDIR/Makefile.arpa
.
- Move to the proof directory which contains a harness source file:
...does not conform to the aws-templates-for-cbmc-proofs
- Generate the build files (including the compilation commands):
- Run
cmake
on the code base using project-specific flags, if necessary:cmake [--project-specific-flags] \ -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ -B $BLDDIR \ -S $SRCDIR
- This generates a JSON file containing compilation commands for each source file at
$BLDDIR/compile_commands.json
. - Currently,
arpa
can only handle projects that build withcmake
.
- Run
- Generate a
Makefile.arpa
for a given proof harness:- Move to the proof directory which contains a harness source file:
cd $PROOFDIR
- Run
arpa run
:arpa run \ -cc $BLDDIR/compile_commands.json \ -r $SRCDIR
- This generates a
Makefile
at$PROOFDIR/Makefile.arpa
.
- Move to the proof directory which contains a harness source file:
Running CBMC proofs
- Create a simple
Makefile
that callsMakefile.arpa
:- In the same directory as the harness, create a simple
Makefile
that:- contains variable name adaptations (if required)
- contains variable customizations (if required)
- includes
Makefile.arpa
- includes
Makefile.common
- Such a
Makefile
may resemble the following:# (Variable name adaptation): PROJECT_SPECIFIC_VAR_NAME = $(VAR_NAME_USED_BY_arpa) # ex. PROOFSOURCES += $(PROOFSTUB)/sysconf.c
# (Variable customizations): CUSTOM_VAR = CUSTOM_VAL # ex. CHECKFLAGS += --bounds-check
include $PROOFDIR/Makefile.arpa include path/to/Makefile.common
- In the same directory as the harness, create a simple
- Run CBMC:
- While in the directory containing the harness and the
Makefile
created in step 4, runmake
to run CBMC. - You may run a command such as:
make report
- While in the directory containing the harness and the
Subtool reference
arpa
consists of two user-facing commands:
arpa build
:
generate a JSON file containing the internal representation used byarpa
arpa run
:
generate a `Makefile` containing build information for a given harness
Regardless of the command, arpa
always recreates the internal representation from the command line flags (cmake
compilation commands and root directory). As such, the arpa
command simply defines how arpa
will process the generated internal representation and what artifact arpa
will generate.
arpa build
arpa build [-h] -cc FILE [-r DIR] [-jp FILE]
This command generates a JSON file containing the internal representation used by arpa
from the compilation commands generated through the cmake
call and from the root directory of the project.
-cc FILE, --compile-commands FILE
Path to the compile_commands.json
file generated during the cmake
call.
-r DIR, --root-dir DIR
Path to the root directory of the project under test. By default, this flag is set to the working directory.
-jp FILE, --json_path FILE
Output path for the generated JSON file. By default, arpa
generates an internal_rep.json
in the working directory.
arpa run
arpa run [-h] -cc FILE -r DIR [-file FILE] [-sp FILE]
[-def V] [-inc V] [-ext EXT]
[-mrv V] [-mrp DIR]
[-msrv V] [-msrp DIR]
[-mstv V] [-mstp DIR]
[-mproj V] [-mproo V]
This command generates a Makefile.arpa
containing relevant build information for a specified source file given cmake
compilation commands and the project root path.
-cc FILE, --compile-commands FILE
Path to the compile_commands.json
file generated during the cmake
call.
-r DIR, --root-dir DIR
Path to the root directory of the project under test.
-file FILE, --file-under-test FILE
Path to the harness source file under test for which a Makefile.arpa
will be generated. By default, arpa
will search the working directory for a file that ends with "_harness.c". If the number of such files in the working directory is not exactly 1, arpa
will throw an error.
-sp FILE, --save_path FILE
Output path for the generated Makefile
. By default, arpa
generates a Makefile.arpa
in the working directory.
Makefile Build Info Flags:
-def V
, -inc V
, -ext EXT
-def V, --define-name V
Name of the Makefile
variable containing the variable definitions required to compile the harness file. By default, the variable name is DEFINES
.
-inc V, --include-name V
Name of the Makefile
variable containing the included directories required to compile the harness file. By default, the variable name is INCLUDES
.
-ext EXT, --change-dependency-extension EXT
Modify the extension of the source file dependencies as they appear in the generated Makefile
. By default, source file dependency extensions are left intact when writing the Makefile
.
Makefile Root Variables Flags:
-mrv V
, -mrp DIR
-mrv V, --make-root-variable V
Name of the Makefile
variable containing the path to the source root directory. By default, the variable name is SRCDIR
.
-mrp DIR, --make-root-path DIR
Path to the project root directory as it appears in the generated Makefile
. By default, the project root directory is identical to the -r
flag value.
Makefile Proof Sources Flags:
-msrv V
, -msrp DIR
-msrv V, --make-proof-source-variable V
Name of the Makefile
variable containing the path to the proof sources directory. By default, the variable name is PROOF_SOURCE
.
-msrp DIR, --make-proof-source-path DIR
Relative path from the project source root directory to the proof sources directory. By default, the relative path is tests/cbmc/sources
.
Makefile Proof Stubs Flags:
-mstv V
, -mstp DIR
-mstv V, --make-proof-stub-variable V
Name of the Makefile
variable containing the path to the proof stubs directory. By default, the variable name is PROOF_STUB
.
-msrp DIR, --make-proof-source-path DIR
Relative path from the project source root directory to the proof stubs directory. By default, the relative path is tests/cbmc/stubs
.
Makefile Proof Dependencies Variable Flags:
-mproj V
, -mproo V
-mproj V, --make-project-sources-variable V
Name of the Makefile
variable defining the project dependencies. By default, the variable name is PROJECT_SOURCES
.
-mproo V, --make-proofs-sources-variable V
Name of the Makefile
variable defining the proof dependencies. By default, the variable name is PROOF_SOURCES
.