| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983 |
- # -*- mode: makefile -*-
- # The first line sets the emacs major mode to Makefile
- # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- # SPDX-License-Identifier: MIT-0
- CBMC_STARTER_KIT_VERSION = CBMC starter kit 2.8
- ################################################################
- # The CBMC Starter Kit depends on the files Makefile.common and
- # run-cbmc-proofs.py. They are installed by the setup script
- # cbmc-starter-kit-setup and updated to the latest version by the
- # update script cbmc-starter-kit-update. For more information about
- # the starter kit and these files and these scripts, see
- # https://model-checking.github.io/cbmc-starter-kit
- #
- # Makefile.common implements what we consider to be some best
- # practices for using cbmc for software verification.
- #
- # Section I gives default values for a large number of Makefile
- # variables that control
- # * how your code is built (include paths, etc),
- # * what program transformations are applied to your code (loop
- # unwinding, etc), and
- # * what properties cbmc checks for in your code (memory safety, etc).
- #
- # These variables are defined below with definitions of the form
- # VARIABLE ?= DEFAULT_VALUE
- # meaning VARIABLE is set to DEFAULT_VALUE if VARIABLE has not already
- # been given a value.
- #
- # For your project, you can override these default values with
- # project-specific definitions in Makefile-project-defines.
- #
- # For any individual proof, you can override these default values and
- # project-specific values with proof-specific definitions in the
- # Makefile for your proof.
- #
- # The definitions in the proof Makefile override definitions in the
- # project Makefile-project-defines which override definitions in this
- # Makefile.common.
- #
- # Section II uses the values defined in Section I to build your code, run
- # your proof, and build a report of your results. You should not need
- # to modify or override anything in Section II, but you may want to
- # read it to understand how the values defined in Section I control
- # things.
- #
- # To use Makefile.common, set variables as described above as needed,
- # and then for each proof,
- #
- # * Create a subdirectory <DIR>.
- # * Write a proof harness (a function) with the name <HARNESS_ENTRY>
- # in a file with the name <DIR>/<HARNESS_FILE>.c
- # * Write a makefile with the name <DIR>/Makefile that looks
- # something like
- #
- # HARNESS_FILE=<HARNESS_FILE>
- # HARNESS_ENTRY=<HARNESS_ENTRY>
- # PROOF_UID=<PROOF_UID>
- #
- # PROJECT_SOURCES += $(SRCDIR)/libraries/api_1.c
- # PROJECT_SOURCES += $(SRCDIR)/libraries/api_2.c
- #
- # PROOF_SOURCES += $(PROOFDIR)/harness.c
- # PROOF_SOURCES += $(SRCDIR)/cbmc/proofs/stub_a.c
- # PROOF_SOURCES += $(SRCDIR)/cbmc/proofs/stub_b.c
- #
- # UNWINDSET += foo.0:3
- # UNWINDSET += bar.1:6
- #
- # REMOVE_FUNCTION_BODY += api_stub_a
- # REMOVE_FUNCTION_BODY += api_stub_b
- #
- # DEFINES = -DDEBUG=0
- #
- # include ../Makefile.common
- #
- # * Change directory to <DIR> and run make
- #
- # The proof setup script cbmc-starter-kit-setup-proof from the CBMC
- # Starter Kit will do most of this for, creating a directory and
- # writing a basic Makefile and proof harness into it that you can edit
- # as described above.
- #
- # Warning: If you get results that are hard to explain, consider
- # running "make clean" or "make veryclean" before "make" if you get
- # results that are hard to explain. Dependency handling in this
- # Makefile.common may not be perfect.
- SHELL=/bin/bash
- default: report
- ################################################################
- ################################################################
- ## Section I: This section gives common variable definitions.
- ##
- ## Override these definitions in Makefile-project-defines or
- ## your proof Makefile.
- ##
- ## Remember that Makefile.common and Makefile-project-defines are
- ## included into the proof Makefile in your proof directory, so all
- ## relative pathnames defined there should be relative to your proof
- ## directory.
- ################################################################
- # Define the layout of the source tree and the proof subtree
- #
- # Generally speaking,
- #
- # SRCDIR = the root of the repository
- # CBMC_ROOT = /srcdir/cbmc
- # PROOF_ROOT = /srcdir/cbmc/proofs
- # PROOF_SOURCE = /srcdir/cbmc/sources
- # PROOF_INCLUDE = /srcdir/cbmc/include
- # PROOF_STUB = /srcdir/cbmc/stubs
- # PROOFDIR = the directory containing the Makefile for your proof
- #
- # The path /srcdir/cbmc used in the example above is determined by the
- # setup script cbmc-starter-kit-setup. Projects usually create a cbmc
- # directory somewhere in the source tree, and run the setup script in
- # that directory. The value of CBMC_ROOT becomes the absolute path to
- # that directory.
- #
- # The location of that cbmc directory in the source tree affects the
- # definition of SRCDIR, which is defined in terms of the relative path
- # from a proof directory to the repository root. The definition is
- # usually determined by the setup script cbmc-starter-kit-setup and
- # written to Makefile-template-defines, but you can override it for a
- # project in Makefile-project-defines and for a specific proof in the
- # Makefile for the proof.
- # Absolute path to the directory containing this Makefile.common
- # See https://ftp.gnu.org/old-gnu/Manuals/make-3.80/html_node/make_17.html
- #
- # Note: We compute the absolute paths to the makefiles in MAKEFILE_LIST
- # before we filter the list of makefiles for %/Makefile.common.
- # Otherwise an invocation of the form "make -f Makefile.common" will set
- # MAKEFILE_LIST to "Makefile.common" which will fail to match the
- # pattern %/Makefile.common.
- #
- MAKEFILE_PATHS = $(foreach makefile,$(MAKEFILE_LIST),$(abspath $(makefile)))
- PROOF_ROOT = $(dir $(filter %/Makefile.common,$(MAKEFILE_PATHS)))
- CBMC_ROOT = $(shell dirname $(PROOF_ROOT))
- PROOF_SOURCE = $(CBMC_ROOT)/sources
- PROOF_INCLUDE = $(CBMC_ROOT)/include
- PROOF_STUB = $(CBMC_ROOT)/stubs
- # Project-specific definitions to override default definitions below
- # * Makefile-project-defines will never be overwritten
- # * Makefile-template-defines may be overwritten when the starter
- # kit is updated
- sinclude $(PROOF_ROOT)/Makefile-project-defines
- sinclude $(PROOF_ROOT)/Makefile-template-defines
- # SRCDIR is the path to the root of the source tree
- # This is a default definition that is frequently overridden in
- # another Makefile, see the discussion of SRCDIR above.
- SRCDIR ?= $(abspath ../..)
- # PROOFDIR is the path to the directory containing the proof harness
- PROOFDIR ?= $(abspath .)
- ################################################################
- # Define how to run CBMC
- # Do property checking with the external SAT solver given by
- # EXTERNAL_SAT_SOLVER. Do coverage checking with the default solver,
- # since coverage checking requires the use of an incremental solver.
- # The EXTERNAL_SAT_SOLVER variable is typically set (if it is at all)
- # as an environment variable or as a makefile variable in
- # Makefile-project-defines.
- #
- # For a particular proof, if the default solver is faster, do property
- # checking with the default solver by including this definition in the
- # proof Makefile:
- # USE_EXTERNAL_SAT_SOLVER =
- #
- ifneq ($(strip $(EXTERNAL_SAT_SOLVER)),)
- USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver $(EXTERNAL_SAT_SOLVER)
- endif
- CHECKFLAGS += $(USE_EXTERNAL_SAT_SOLVER)
- # Job pools
- # For version of Litani that are new enough (where `litani print-capabilities`
- # prints "pools"), proofs for which `EXPENSIVE = true` is set can be added to a
- # "job pool" that restricts how many expensive proofs are run at a time. All
- # other proofs will be built in parallel as usual.
- #
- # In more detail: all compilation, instrumentation, and report jobs are run with
- # full parallelism as usual, even for expensive proofs. The CBMC jobs for
- # non-expensive proofs are also run in parallel. The only difference is that the
- # CBMC safety checks and coverage checks for expensive proofs are run with a
- # restricted parallelism level. At any one time, only N of these jobs are run at
- # once, amongst all the proofs.
- #
- # To configure N, Litani needs to be initialized with a pool called "expensive".
- # For example, to only run two CBMC safety/coverage jobs at a time from amongst
- # all the proofs, you would initialize litani like
- # litani init --pools expensive:2
- # The run-cbmc-proofs.py script takes care of this initialization through the
- # --expensive-jobs-parallelism flag.
- #
- # To enable this feature, set
- # the ENABLE_POOLS variable when running Make, like
- # `make ENABLE_POOLS=true report`
- # The run-cbmc-proofs.py script takes care of this through the
- # --restrict-expensive-jobs flag.
- ifeq ($(strip $(ENABLE_POOLS)),)
- POOL =
- else ifeq ($(strip $(EXPENSIVE)),)
- POOL =
- else
- POOL = --pool expensive
- endif
- # Similar to the pool feature above. If Litani is new enough, enable
- # profiling CBMC's memory use.
- ifeq ($(strip $(ENABLE_MEMORY_PROFILING)),)
- MEMORY_PROFILING =
- else
- MEMORY_PROFILING = --profile-memory
- endif
- # Property checking flags
- #
- # Each variable below controls a specific property checking flag
- # within CBMC. If desired, a property flag can be disabled within
- # a particular proof by nulling the corresponding variable. For
- # instance, the following line:
- #
- # CHECK_FLAG_POINTER_CHECK =
- #
- # would disable the --pointer-check CBMC flag within:
- # * an entire project when added to Makefile-project-defines
- # * a specific proof when added to the harness Makefile
- CBMC_FLAG_MALLOC_MAY_FAIL ?= --malloc-may-fail
- CBMC_FLAG_MALLOC_FAIL_NULL ?= --malloc-fail-null
- CBMC_FLAG_BOUNDS_CHECK ?= --bounds-check
- CBMC_FLAG_CONVERSION_CHECK ?= --conversion-check
- CBMC_FLAG_DIV_BY_ZERO_CHECK ?= --div-by-zero-check
- CBMC_FLAG_FLOAT_OVERFLOW_CHECK ?= --float-overflow-check
- CBMC_FLAG_NAN_CHECK ?= --nan-check
- CBMC_FLAG_POINTER_CHECK ?= --pointer-check
- CBMC_FLAG_POINTER_OVERFLOW_CHECK ?= --pointer-overflow-check
- CBMC_FLAG_POINTER_PRIMITIVE_CHECK ?= --pointer-primitive-check
- CBMC_FLAG_SIGNED_OVERFLOW_CHECK ?= --signed-overflow-check
- CBMC_FLAG_UNDEFINED_SHIFT_CHECK ?= --undefined-shift-check
- CBMC_FLAG_UNSIGNED_OVERFLOW_CHECK ?= --unsigned-overflow-check
- CBMC_FLAG_UNWINDING_ASSERTIONS ?= --unwinding-assertions
- CBMC_DEFAULT_UNWIND ?= --unwind 1
- CBMC_FLAG_FLUSH ?= --flush
- # CBMC flags used for property checking and coverage checking
- CBMCFLAGS += $(CBMC_FLAG_FLUSH)
- # CBMC flags used for property checking
- CHECKFLAGS += $(CBMC_FLAG_BOUNDS_CHECK)
- CHECKFLAGS += $(CBMC_FLAG_CONVERSION_CHECK)
- CHECKFLAGS += $(CBMC_FLAG_DIV_BY_ZERO_CHECK)
- CHECKFLAGS += $(CBMC_FLAG_FLOAT_OVERFLOW_CHECK)
- CHECKFLAGS += $(CBMC_FLAG_NAN_CHECK)
- CHECKFLAGS += $(CBMC_FLAG_POINTER_CHECK)
- CHECKFLAGS += $(CBMC_FLAG_POINTER_OVERFLOW_CHECK)
- CHECKFLAGS += $(CBMC_FLAG_POINTER_PRIMITIVE_CHECK)
- CHECKFLAGS += $(CBMC_FLAG_SIGNED_OVERFLOW_CHECK)
- CHECKFLAGS += $(CBMC_FLAG_UNDEFINED_SHIFT_CHECK)
- CHECKFLAGS += $(CBMC_FLAG_UNSIGNED_OVERFLOW_CHECK)
- # Additional CBMC flag to CBMC control verbosity.
- #
- # Meaningful values are
- # 0 none
- # 1 only errors
- # 2 + warnings
- # 4 + results
- # 6 + status/phase information
- # 8 + statistical information
- # 9 + progress information
- # 10 + debug info
- #
- # Uncomment the following line or set in Makefile-project-defines
- # CBMC_VERBOSITY ?= --verbosity 4
- # Additional CBMC flag to control how CBMC treats static variables.
- #
- # NONDET_STATIC is a list of flags of the form --nondet-static
- # and --nondet-static-exclude VAR. The --nondet-static flag causes
- # CBMC to initialize static variables with unconstrained value
- # (ignoring initializers and default zero-initialization). The
- # --nondet-static-exclude VAR excludes VAR for the variables
- # initialized with unconstrained values.
- NONDET_STATIC ?=
- # Flags to pass to goto-cc for compilation and linking
- COMPILE_FLAGS ?= -Wall
- LINK_FLAGS ?= -Wall
- EXPORT_FILE_LOCAL_SYMBOLS ?= --export-file-local-symbols
- # During instrumentation, it adds models of C library functions
- ADD_LIBRARY_FLAG := --add-library
- # Preprocessor include paths -I...
- INCLUDES ?=
- # Preprocessor definitions -D...
- DEFINES ?=
- # CBMC object model
- #
- # CBMC_OBJECT_BITS is the number of bits in a pointer CBMC uses for
- # the id of the object to which a pointer is pointing. CBMC uses 8
- # bits for the object id by default. The remaining bits in the pointer
- # are used for offset into the object. This limits the size of the
- # objects that CBMC can model. This Makefile defines this bound on
- # object size to be CBMC_MAX_OBJECT_SIZE. You are likely to get
- # unexpected results if you try to malloc an object larger than this
- # bound.
- CBMC_OBJECT_BITS ?= 8
- # CBMC loop unwinding (Normally set in the proof Makefile)
- #
- # UNWINDSET is a list of pairs of the form foo.1:4 meaning that
- # CBMC should unwind loop 1 in function foo no more than 4 times.
- # For historical reasons, the number 4 is one more than the number
- # of times CBMC actually unwinds the loop.
- UNWINDSET ?=
- # CBMC early loop unwinding (Normally set in the proof Makefile)
- #
- # Most users can ignore this variable.
- #
- # This variable exists to support the use of loop and function
- # contracts, two features under development for CBMC. Checking the
- # assigns clause for function contracts and loop invariants currently
- # assumes loop-free bodies for loops and functions with contracts
- # (possibly after replacing nested loops with their own loop
- # contracts). To satisfy this requirement, it may be necessary to
- # unwind some loops before the function contract and loop invariant
- # transformations are applied to the goto program. This variable
- # CPROVER_LIBRARY_UNWINDSET is identical to UNWINDSET, and we assume that the
- # loops mentioned in CPROVER_LIBRARY_UNWINDSET and UNWINDSET are disjoint.
- CPROVER_LIBRARY_UNWINDSET ?=
- # CBMC function removal (Normally set set in the proof Makefile)
- #
- # REMOVE_FUNCTION_BODY is a list of function names. CBMC will "undefine"
- # the function, and CBMC will treat the function as having no side effects
- # and returning an unconstrained value of the appropriate return type.
- # The list should include the names of functions being stubbed out.
- REMOVE_FUNCTION_BODY ?=
- # CBMC function pointer restriction (Normally set in the proof Makefile)
- #
- # RESTRICT_FUNCTION_POINTER is a list of function pointer restriction
- # instructions of the form:
- #
- # <fun_id>.function_pointer_call.<N>/<fun_id>[,<fun_id>]*
- #
- # The function pointer call number <N> in the specified function gets
- # rewritten to a case switch over a finite list of functions.
- # If some possible target functions are omitted from the list a counter
- # example trace will be found by CBMC, i.e. the transformation is sound.
- # If the target functions are file-local symbols, then mangled names must
- # be used.
- RESTRICT_FUNCTION_POINTER ?=
- # The project source files (Normally set set in the proof Makefile)
- #
- # PROJECT_SOURCES is the list of project source files to compile,
- # including the source file defining the function under test.
- PROJECT_SOURCES ?=
- # The proof source files (Normally set in the proof Makefile)
- #
- # PROOF_SOURCES is the list of proof source files to compile, including
- # the proof harness, and including any function stubs being used.
- PROOF_SOURCES ?=
- # The number of seconds that CBMC should be allowed to run for before
- # being forcefully terminated. Currently, this is set to be less than
- # the time limit for a CodeBuild job, which is eight hours. If a proof
- # run takes longer than the time limit of the CI environment, the
- # environment will halt the proof run without updating the Litani
- # report, making the proof run appear to "hang".
- CBMC_TIMEOUT ?= 21600
- # CBMC string abstraction
- #
- # Replace all uses of char * by a struct that carries that string,
- # and also the underlying allocation and the C string length.
- STRING_ABSTRACTION ?=
- ifdef STRING_ABSTRACTION
- ifneq ($(strip $(STRING_ABSTRACTION)),)
- CBMC_STRING_ABSTRACTION := --string-abstraction
- endif
- endif
- # Optional configuration library flags
- OPT_CONFIG_LIBRARY ?=
- CBMC_OPT_CONFIG_LIBRARY := $(CBMC_FLAG_MALLOC_MAY_FAIL) $(CBMC_FLAG_MALLOC_FAIL_NULL) $(CBMC_STRING_ABSTRACTION)
- # Proof writers could add function contracts in their source code.
- # These contracts are ignored by default, but may be enabled in two distinct
- # contexts using the following two variables:
- # 1. To check whether one or more function contracts are sound with respect to
- # the function implementation, CHECK_FUNCTION_CONTRACTS should be a list of
- # function names. Use CHECK_FUNCTION_CONTRACTS_REC to check contracts on
- # recursive functions.
- # 2. To replace calls to certain functions with their correspondent function
- # contracts, USE_FUNCTION_CONTRACTS should be a list of function names.
- # One must check separately whether a function contract is sound before
- # replacing it in calling contexts.
- CHECK_FUNCTION_CONTRACTS ?=
- CBMC_CHECK_FUNCTION_CONTRACTS := $(patsubst %,--enforce-contract %, $(CHECK_FUNCTION_CONTRACTS))
- CHECK_FUNCTION_CONTRACTS_REC ?=
- CBMC_CHECK_FUNCTION_CONTRACTS_REC := $(patsubst %,--enforce-contract-rec %, $(CHECK_FUNCTION_CONTRACTS_REC))
- USE_FUNCTION_CONTRACTS ?=
- CBMC_USE_FUNCTION_CONTRACTS := $(patsubst %,--replace-call-with-contract %, $(USE_FUNCTION_CONTRACTS))
- CODE_CONTRACTS := $(CHECK_FUNCTION_CONTRACTS)$(USE_FUNCTION_CONTRACTS)$(APPLY_LOOP_CONTRACTS)
- # Proof writers may also apply function contracts using the Dynamic Frame
- # Condition Checking (DFCC) mode. For more information on DFCC,
- # please see https://diffblue.github.io/cbmc/contracts-dev-spec-dfcc.html.
- USE_DYNAMIC_FRAMES ?=
- ifdef USE_DYNAMIC_FRAMES
- ifneq ($(strip $(USE_DYNAMIC_FRAMES)),)
- CBMC_USE_DYNAMIC_FRAMES := $(CBMC_OPT_CONFIG_LIBRARY) --dfcc $(HARNESS_ENTRY) $(CBMC_CHECK_FUNCTION_CONTRACTS_REC)
- endif
- endif
- # Similarly, proof writers could also add loop contracts in their source code
- # to obtain unbounded correctness proofs. Unlike function contracts, loop
- # contracts are not reusable and thus are checked and used simultaneously.
- # These contracts are also ignored by default, but may be enabled by setting
- # the APPLY_LOOP_CONTRACTS variable.
- APPLY_LOOP_CONTRACTS ?=
- ifdef APPLY_LOOP_CONTRACTS
- ifneq ($(strip $(APPLY_LOOP_CONTRACTS)),)
- CBMC_APPLY_LOOP_CONTRACTS := --apply-loop-contracts
- endif
- endif
- # Silence makefile output (eg, long litani commands) unless VERBOSE is set.
- ifndef VERBOSE
- MAKEFLAGS := $(MAKEFLAGS) -s
- endif
- ################################################################
- ################################################################
- ## Section II: This section defines the process of running a proof
- ##
- ## There should be no reason to edit anything below this line.
- ################################################################
- # Paths
- CBMC ?= cbmc
- GOTO_ANALYZER ?= goto-analyzer
- GOTO_CC ?= goto-cc
- GOTO_INSTRUMENT ?= goto-instrument
- CRANGLER ?= crangler
- VIEWER ?= cbmc-viewer
- VIEWER2 ?= cbmc-viewer
- CMAKE ?= cmake
- GOTODIR ?= $(PROOFDIR)/gotos
- LOGDIR ?= $(PROOFDIR)/logs
- PROJECT ?= project
- PROOF ?= proof
- HARNESS_GOTO ?= $(GOTODIR)/$(HARNESS_FILE)
- PROJECT_GOTO ?= $(GOTODIR)/$(PROJECT)
- PROOF_GOTO ?= $(GOTODIR)/$(PROOF)
- ################################################################
- # Useful macros for values that are hard to reference
- SPACE :=$() $()
- COMMA :=,
- ################################################################
- # Set C compiler defines
- CBMCFLAGS += --object-bits $(CBMC_OBJECT_BITS)
- COMPILE_FLAGS += --object-bits $(CBMC_OBJECT_BITS)
- DEFINES += -DCBMC=1
- DEFINES += -DCBMC_OBJECT_BITS=$(CBMC_OBJECT_BITS)
- DEFINES += -DCBMC_MAX_OBJECT_SIZE="(SIZE_MAX>>(CBMC_OBJECT_BITS+1))"
- # CI currently assumes cbmc invocation has at most one --unwindset
- # UNWINDSET is designed for user code (i.e., proof and project code)
- ifdef UNWINDSET
- ifneq ($(strip $(UNWINDSET)),)
- CBMC_UNWINDSET := --unwindset $(subst $(SPACE),$(COMMA),$(strip $(UNWINDSET)))
- endif
- endif
- # CPROVER_LIBRARY_UNWINDSET is designed for CPROVER library functions
- ifdef CPROVER_LIBRARY_UNWINDSET
- ifneq ($(strip $(CPROVER_LIBRARY_UNWINDSET)),)
- CBMC_CPROVER_LIBRARY_UNWINDSET := --unwindset $(subst $(SPACE),$(COMMA),$(strip $(CPROVER_LIBRARY_UNWINDSET)))
- endif
- endif
- CBMC_REMOVE_FUNCTION_BODY := $(patsubst %,--remove-function-body %, $(REMOVE_FUNCTION_BODY))
- ifdef RESTRICT_FUNCTION_POINTER
- ifneq ($(strip $(RESTRICT_FUNCTION_POINTER)),)
- CBMC_RESTRICT_FUNCTION_POINTER := $(patsubst %,--restrict-function-pointer %, $(RESTRICT_FUNCTION_POINTER))
- endif
- endif
- ################################################################
- # Targets for rewriting source files with crangler
- # Construct crangler configuration files
- #
- # REWRITTEN_SOURCES is a list of crangler output files source.i.
- # This target assumes that for each source.i
- # * source.i_SOURCE is the path to a source file,
- # * source.i_FUNCTIONS is a list of functions (may be empty)
- # * source.i_OBJECTS is a list of variables (may be empty)
- # This target constructs the crangler configuration file source.i.json
- # of the form
- # {
- # "sources": [ "/proj/code.c" ],
- # "includes": [ "/proj/include" ],
- # "defines": [ "VAR=1" ],
- # "functions": [ {"function_name": ["remove static"]} ],
- # "objects": [ {"variable_name": ["remove static"]} ],
- # "output": "source.i"
- # }
- # to remove the static attribute from function_name and variable_name
- # in the source file source.c and write the result to source.i.
- #
- # This target assumes that filenames include no spaces and that
- # the INCLUDES and DEFINES variables include no spaces after -I
- # and -D. For example, use "-DVAR=1" and not "-D VAR=1".
- #
- # Define *_SOURCE, *_FUNCTIONS, and *_OBJECTS in the proof Makefile.
- # The string source.i is usually an absolute path $(PROOFDIR)/code.i
- # to a file in the proof directory that contains the proof Makefile.
- # The proof Makefile usually includes the definitions
- # $(PROOFDIR)/code.i_SOURCE = /proj/code.c
- # $(PROOFDIR)/code.i_FUNCTIONS = function_name
- # $(PROOFDIR)/code.i_OBJECTS = variable_name
- # Because these definitions refer to PROOFDIR that is defined in this
- # Makefile.common, these definitions must appear after the inclusion
- # of Makefile.common in the proof Makefile.
- #
- $(foreach rs,$(REWRITTEN_SOURCES),$(eval $(rs).json: $($(rs)_SOURCE)))
- $(foreach rs,$(REWRITTEN_SOURCES),$(rs).json):
- echo '{'\
- '"sources": ['\
- '"$($(@:.json=)_SOURCE)"'\
- '],'\
- '"includes": ['\
- '$(subst $(SPACE),$(COMMA),$(patsubst -I%,"%",$(strip $(INCLUDES))))' \
- '],'\
- '"defines": ['\
- '$(subst $(SPACE),$(COMMA),$(patsubst -D%,"%",$(subst ",\",$(strip $(DEFINES)))))' \
- '],'\
- '"functions": ['\
- '{'\
- '$(subst ~, ,$(subst $(SPACE),$(COMMA),$(patsubst %,"%":["remove~static"],$($(@:.json=)_FUNCTIONS))))' \
- '}'\
- '],'\
- '"objects": ['\
- '{'\
- '$(subst ~, ,$(subst $(SPACE),$(COMMA),$(patsubst %,"%":["remove~static"],$($(@:.json=)_OBJECTS))))' \
- '}'\
- '],'\
- '"output": "$(@:.json=)"'\
- '}' > $@
- # Rewrite source files with crangler
- #
- $(foreach rs,$(REWRITTEN_SOURCES),$(eval $(rs): $(rs).json))
- $(REWRITTEN_SOURCES):
- $(LITANI) add-job \
- --command \
- '$(CRANGLER) $@.json' \
- --inputs $($@_SOURCE) \
- --outputs $@ \
- --stdout-file $(LOGDIR)/crangler-$(subst /,_,$(subst .,_,$@))-log.txt \
- --interleave-stdout-stderr \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): removing static"
- ################################################################
- # Build targets that make the relevant .goto files
- # Compile project sources
- $(PROJECT_GOTO)1.goto: $(PROJECT_SOURCES) $(REWRITTEN_SOURCES)
- $(LITANI) add-job \
- --command \
- '$(GOTO_CC) $(CBMC_VERBOSITY) $(COMPILE_FLAGS) $(EXPORT_FILE_LOCAL_SYMBOLS) $(INCLUDES) $(DEFINES) $^ -o $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/project_sources-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): building project binary"
- # Compile proof sources
- $(PROOF_GOTO)1.goto: $(PROOF_SOURCES)
- $(LITANI) add-job \
- --command \
- '$(GOTO_CC) $(CBMC_VERBOSITY) $(COMPILE_FLAGS) $(EXPORT_FILE_LOCAL_SYMBOLS) $(INCLUDES) $(DEFINES) $^ -o $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/proof_sources-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): building proof binary"
- # Remove function bodies from project sources
- $(PROJECT_GOTO)2.goto: $(PROJECT_GOTO)1.goto
- $(LITANI) add-job \
- --command \
- '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_REMOVE_FUNCTION_BODY) $^ $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/remove_function_body-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): removing function bodies from project sources"
- # Link project and proof sources into the proof harness
- $(HARNESS_GOTO)1.goto: $(PROOF_GOTO)1.goto $(PROJECT_GOTO)2.goto
- $(LITANI) add-job \
- --command '$(GOTO_CC) $(CBMC_VERBOSITY) --function $(HARNESS_ENTRY) $^ $(LINK_FLAGS) -o $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/link_proof_project-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): linking project to proof"
- # Restrict function pointers
- $(HARNESS_GOTO)2.goto: $(HARNESS_GOTO)1.goto
- $(LITANI) add-job \
- --command \
- '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_RESTRICT_FUNCTION_POINTER) --remove-function-pointers $^ $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/restrict_function_pointer-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): restricting function pointers in project sources"
- # Fill static variable with unconstrained values
- $(HARNESS_GOTO)3.goto: $(HARNESS_GOTO)2.goto
- ifneq ($(strip $(CODE_CONTRACTS)),)
- $(LITANI) add-job \
- --command 'cp $^ $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/nondet_static-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): not setting static variables to nondet (will do during contract instrumentation)"
- else
- $(LITANI) add-job \
- --command \
- '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(NONDET_STATIC) $^ $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/nondet_static-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): setting static variables to nondet"
- endif
- # Link CPROVER library if DFCC mode is on
- $(HARNESS_GOTO)4.goto: $(HARNESS_GOTO)3.goto
- ifneq ($(strip $(USE_DYNAMIC_FRAMES)),)
- $(LITANI) add-job \
- --command \
- '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(ADD_LIBRARY_FLAG) $(CBMC_OPT_CONFIG_LIBRARY) $^ $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/linking-library-models-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): linking CPROVER library"
- else
- $(LITANI) add-job \
- --command 'cp $^ $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/linking-library-models-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): not linking CPROVER library"
- endif
- # Early unwind all loops on DFCC mode; otherwise, only unwind loops in proof and project code
- $(HARNESS_GOTO)5.goto: $(HARNESS_GOTO)4.goto
- ifneq ($(strip $(USE_DYNAMIC_FRAMES)),)
- $(LITANI) add-job \
- --command \
- '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_UNWINDSET) $(CBMC_CPROVER_LIBRARY_UNWINDSET) $(CBMC_DEFAULT_UNWIND) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $^ $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/unwind_loops-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): unwinding all loops"
- else ifneq ($(strip $(CODE_CONTRACTS)),)
- $(LITANI) add-job \
- --command \
- '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_UNWINDSET) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $^ $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/unwind_loops-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): unwinding loops in proof and project code"
- else
- $(LITANI) add-job \
- --command 'cp $^ $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/linking-library-models-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): not unwinding loops"
- endif
- # Replace function contracts, check function contracts, instrument for loop contracts
- $(HARNESS_GOTO)6.goto: $(HARNESS_GOTO)5.goto
- $(LITANI) add-job \
- --command \
- '$(GOTO_INSTRUMENT) $(CBMC_USE_DYNAMIC_FRAMES) $(NONDET_STATIC) $(CBMC_VERBOSITY) $(CBMC_CHECK_FUNCTION_CONTRACTS) $(CBMC_USE_FUNCTION_CONTRACTS) $(CBMC_APPLY_LOOP_CONTRACTS) $^ $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/check_function_contracts-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): checking function contracts"
- # Omit initialization of unused global variables (reduces problem size)
- $(HARNESS_GOTO)7.goto: $(HARNESS_GOTO)6.goto
- $(LITANI) add-job \
- --command \
- '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) --slice-global-inits $^ $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/slice_global_inits-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): slicing global initializations"
- # Omit unused functions (sharpens coverage calculations)
- $(HARNESS_GOTO)8.goto: $(HARNESS_GOTO)7.goto
- $(LITANI) add-job \
- --command \
- '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) --drop-unused-functions $^ $@' \
- --inputs $^ \
- --outputs $@ \
- --stdout-file $(LOGDIR)/drop_unused_functions-log.txt \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): dropping unused functions"
- # Final name for proof harness
- $(HARNESS_GOTO).goto: $(HARNESS_GOTO)8.goto
- $(LITANI) add-job \
- --command 'cp $< $@' \
- --inputs $^ \
- --outputs $@ \
- --pipeline-name "$(PROOF_UID)" \
- --ci-stage build \
- --description "$(PROOF_UID): copying final goto-binary"
- ################################################################
- # Targets to run the analysis commands
- ifdef CBMCFLAGS
- ifeq ($(strip $(CODE_CONTRACTS)),)
- CBMCFLAGS += $(CBMC_UNWINDSET) $(CBMC_CPROVER_LIBRARY_UNWINDSET) $(CBMC_DEFAULT_UNWIND) $(CBMC_OPT_CONFIG_LIBRARY)
- else ifeq ($(strip $(USE_DYNAMIC_FRAMES)),)
- CBMCFLAGS += $(CBMC_CPROVER_LIBRARY_UNWINDSET) $(CBMC_DEFAULT_UNWIND) $(CBMC_OPT_CONFIG_LIBRARY)
- endif
- endif
- $(LOGDIR)/result.xml: $(HARNESS_GOTO).goto
- $(LITANI) add-job \
- $(POOL) \
- --command \
- '$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $(CHECKFLAGS) --trace --xml-ui $<' \
- --inputs $^ \
- --outputs $@ \
- --ci-stage test \
- --stdout-file $@ \
- $(MEMORY_PROFILING) \
- --ignore-returns 10 \
- --timeout $(CBMC_TIMEOUT) \
- --pipeline-name "$(PROOF_UID)" \
- --tags "stats-group:safety checks" \
- --stderr-file $(LOGDIR)/result-err-log.txt \
- --description "$(PROOF_UID): checking safety properties"
- $(LOGDIR)/property.xml: $(HARNESS_GOTO).goto
- $(LITANI) add-job \
- --command \
- '$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $(CHECKFLAGS) --show-properties --xml-ui $<' \
- --inputs $^ \
- --outputs $@ \
- --ci-stage test \
- --stdout-file $@ \
- --ignore-returns 10 \
- --pipeline-name "$(PROOF_UID)" \
- --stderr-file $(LOGDIR)/property-err-log.txt \
- --description "$(PROOF_UID): printing safety properties"
- $(LOGDIR)/coverage.xml: $(HARNESS_GOTO).goto
- $(LITANI) add-job \
- $(POOL) \
- --command \
- '$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(COVERFLAGS) --cover location --xml-ui $<' \
- --inputs $^ \
- --outputs $@ \
- --ci-stage test \
- --stdout-file $@ \
- $(MEMORY_PROFILING) \
- --ignore-returns 10 \
- --timeout $(CBMC_TIMEOUT) \
- --pipeline-name "$(PROOF_UID)" \
- --tags "stats-group:coverage computation" \
- --stderr-file $(LOGDIR)/coverage-err-log.txt \
- --description "$(PROOF_UID): calculating coverage"
- COVERAGE ?= $(LOGDIR)/coverage.xml
- VIEWER_COVERAGE_FLAG ?= --coverage $(COVERAGE)
- $(PROOFDIR)/report: $(LOGDIR)/result.xml $(LOGDIR)/property.xml $(COVERAGE)
- $(LITANI) add-job \
- --command " $(VIEWER) \
- --result $(LOGDIR)/result.xml \
- $(VIEWER_COVERAGE_FLAG) \
- --property $(LOGDIR)/property.xml \
- --srcdir $(SRCDIR) \
- --goto $(HARNESS_GOTO).goto \
- --reportdir $(PROOFDIR)/report \
- --config $(PROOFDIR)/cbmc-viewer.json" \
- --inputs $^ \
- --outputs $(PROOFDIR)/report \
- --pipeline-name "$(PROOF_UID)" \
- --stdout-file $(LOGDIR)/viewer-log.txt \
- --ci-stage report \
- --description "$(PROOF_UID): generating report"
- litani-path:
- @echo $(LITANI)
- # ##############################################################
- # Phony Rules
- #
- # These rules provide a convenient way to run a single proof up to a
- # certain stage. Users can browse into a proof directory and run
- # "make -Bj 3 report" to generate a report for just that proof, or
- # "make goto" to build the goto binary. Under the hood, this runs litani
- # for just that proof.
- _goto: $(HARNESS_GOTO).goto
- goto:
- @ echo Running 'litani init'
- $(LITANI) init --project $(PROJECT_NAME)
- @ echo Running 'litani add-job'
- $(MAKE) -B _goto
- @ echo Running 'litani build'
- $(LITANI) run-build
- _result: $(LOGDIR)/result.txt
- result:
- @ echo Running 'litani init'
- $(LITANI) init --project $(PROJECT_NAME)
- @ echo Running 'litani add-job'
- $(MAKE) -B _result
- @ echo Running 'litani build'
- $(LITANI) run-build
- _property: $(LOGDIR)/property.xml
- property:
- @ echo Running 'litani init'
- $(LITANI) init --project $(PROJECT_NAME)
- @ echo Running 'litani add-job'
- $(MAKE) -B _property
- @ echo Running 'litani build'
- $(LITANI) run-build
- _coverage: $(LOGDIR)/coverage.xml
- coverage:
- @ echo Running 'litani init'
- $(LITANI) init --project $(PROJECT_NAME)
- @ echo Running 'litani add-job'
- $(MAKE) -B _coverage
- @ echo Running 'litani build'
- $(LITANI) run-build
- _report: $(PROOFDIR)/report
- report:
- @ echo Running 'litani init'
- $(LITANI) init --project $(PROJECT_NAME)
- @ echo Running 'litani add-job'
- $(MAKE) -B _report
- @ echo Running 'litani build'
- $(LITANI) run-build
- _report_no_coverage:
- $(MAKE) COVERAGE="" VIEWER_COVERAGE_FLAG="" _report
- report-no-coverage:
- $(MAKE) COVERAGE="" VIEWER_COVERAGE_FLAG=" " report
- ################################################################
- # Targets to clean up after ourselves
- clean:
- -$(RM) $(DEPENDENT_GOTOS)
- -$(RM) TAGS*
- -$(RM) *~ \#*
- -$(RM) $(REWRITTEN_SOURCES) $(foreach rs,$(REWRITTEN_SOURCES),$(rs).json)
- veryclean: clean
- -$(RM) -r report
- -$(RM) -r $(LOGDIR) $(GOTODIR)
- .PHONY: \
- _coverage \
- _goto \
- _property \
- _report \
- _report_no_coverage \
- clean \
- coverage \
- goto \
- litani-path \
- property \
- report \
- report-no-coverage \
- result \
- setup_dependencies \
- testdeps \
- veryclean \
- #
- ################################################################
- # Run "make echo-proof-uid" to print the proof ID of a proof. This can be
- # used by scripts to ensure that every proof has an ID, that there are
- # no duplicates, etc.
- .PHONY: echo-proof-uid
- echo-proof-uid:
- @echo $(PROOF_UID)
- .PHONY: echo-project-name
- echo-project-name:
- @echo $(PROJECT_NAME)
- ################################################################
- # Project-specific targets requiring values defined above
- sinclude $(PROOF_ROOT)/Makefile-project-targets
- # CI-specific targets to drive cbmc in CI
- sinclude $(PROOF_ROOT)/Makefile-project-testing
- ################################################################
|