Makefile.common 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  1. # -*- mode: makefile -*-
  2. # The first line sets the emacs major mode to Makefile
  3. # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. # SPDX-License-Identifier: MIT-0
  5. CBMC_STARTER_KIT_VERSION = CBMC starter kit 2.5
  6. ################################################################
  7. # The CBMC Starter Kit depends on the files Makefile.common and
  8. # run-cbmc-proofs.py. They are installed by the setup script
  9. # cbmc-starter-kit-setup and updated to the latest version by the
  10. # update script cbmc-starter-kit-update. For more information about
  11. # the starter kit and these files and these scripts, see
  12. # https://model-checking.github.io/cbmc-starter-kit
  13. #
  14. # Makefile.common implements what we consider to be some best
  15. # practices for using cbmc for software verification.
  16. #
  17. # Section I gives default values for a large number of Makefile
  18. # variables that control
  19. # * how your code is built (include paths, etc),
  20. # * what program transformations are applied to your code (loop
  21. # unwinding, etc), and
  22. # * what properties cbmc checks for in your code (memory safety, etc).
  23. #
  24. # These variables are defined below with definitions of the form
  25. # VARIABLE ?= DEFAULT_VALUE
  26. # meaning VARIABLE is set to DEFAULT_VALUE if VARIABLE has not already
  27. # been given a value.
  28. #
  29. # For your project, you can override these default values with
  30. # project-specific definitions in Makefile-project-defines.
  31. #
  32. # For any individual proof, you can override these default values and
  33. # project-specific values with proof-specific definitions in the
  34. # Makefile for your proof.
  35. #
  36. # The definitions in the proof Makefile override definitions in the
  37. # project Makefile-project-defines which override definitions in this
  38. # Makefile.common.
  39. #
  40. # Section II uses the values defined in Section I to build your code, run
  41. # your proof, and build a report of your results. You should not need
  42. # to modify or override anything in Section II, but you may want to
  43. # read it to understand how the values defined in Section I control
  44. # things.
  45. #
  46. # To use Makefile.common, set variables as described above as needed,
  47. # and then for each proof,
  48. #
  49. # * Create a subdirectory <DIR>.
  50. # * Write a proof harness (a function) with the name <HARNESS_ENTRY>
  51. # in a file with the name <DIR>/<HARNESS_FILE>.c
  52. # * Write a makefile with the name <DIR>/Makefile that looks
  53. # something like
  54. #
  55. # HARNESS_FILE=<HARNESS_FILE>
  56. # HARNESS_ENTRY=<HARNESS_ENTRY>
  57. # PROOF_UID=<PROOF_UID>
  58. #
  59. # PROJECT_SOURCES += $(SRCDIR)/libraries/api_1.c
  60. # PROJECT_SOURCES += $(SRCDIR)/libraries/api_2.c
  61. #
  62. # PROOF_SOURCES += $(PROOFDIR)/harness.c
  63. # PROOF_SOURCES += $(SRCDIR)/cbmc/proofs/stub_a.c
  64. # PROOF_SOURCES += $(SRCDIR)/cbmc/proofs/stub_b.c
  65. #
  66. # UNWINDSET += foo.0:3
  67. # UNWINDSET += bar.1:6
  68. #
  69. # REMOVE_FUNCTION_BODY += api_stub_a
  70. # REMOVE_FUNCTION_BODY += api_stub_b
  71. #
  72. # DEFINES = -DDEBUG=0
  73. #
  74. # include ../Makefile.common
  75. #
  76. # * Change directory to <DIR> and run make
  77. #
  78. # The proof setup script cbmc-starter-kit-setup-proof from the CBMC
  79. # Starter Kit will do most of this for, creating a directory and
  80. # writing a basic Makefile and proof harness into it that you can edit
  81. # as described above.
  82. #
  83. # Warning: If you get results that are hard to explain, consider
  84. # running "make clean" or "make veryclean" before "make" if you get
  85. # results that are hard to explain. Dependency handling in this
  86. # Makefile.common may not be perfect.
  87. SHELL=/bin/bash
  88. default: report
  89. ################################################################
  90. ################################################################
  91. ## Section I: This section gives common variable definitions.
  92. ##
  93. ## Override these definitions in Makefile-project-defines or
  94. ## your proof Makefile.
  95. ##
  96. ## Remember that Makefile.common and Makefile-project-defines are
  97. ## included into the proof Makefile in your proof directory, so all
  98. ## relative pathnames defined there should be relative to your proof
  99. ## directory.
  100. ################################################################
  101. # Define the layout of the source tree and the proof subtree
  102. #
  103. # Generally speaking,
  104. #
  105. # SRCDIR = the root of the repository
  106. # CBMC_ROOT = /srcdir/cbmc
  107. # PROOF_ROOT = /srcdir/cbmc/proofs
  108. # PROOF_SOURCE = /srcdir/cbmc/sources
  109. # PROOF_INCLUDE = /srcdir/cbmc/include
  110. # PROOF_STUB = /srcdir/cbmc/stubs
  111. # PROOFDIR = the directory containing the Makefile for your proof
  112. #
  113. # The path /srcdir/cbmc used in the example above is determined by the
  114. # setup script cbmc-starter-kit-setup. Projects usually create a cbmc
  115. # directory somewhere in the source tree, and run the setup script in
  116. # that directory. The value of CBMC_ROOT becomes the absolute path to
  117. # that directory.
  118. #
  119. # The location of that cbmc directory in the source tree affects the
  120. # definition of SRCDIR, which is defined in terms of the relative path
  121. # from a proof directory to the repository root. The definition is
  122. # usually determined by the setup script cbmc-starter-kit-setup and
  123. # written to Makefile-template-defines, but you can override it for a
  124. # project in Makefile-project-defines and for a specific proof in the
  125. # Makefile for the proof.
  126. # Absolute path to the directory containing this Makefile.common
  127. # See https://ftp.gnu.org/old-gnu/Manuals/make-3.80/html_node/make_17.html
  128. #
  129. # Note: We compute the absolute paths to the makefiles in MAKEFILE_LIST
  130. # before we filter the list of makefiles for %/Makefile.common.
  131. # Otherwise an invocation of the form "make -f Makefile.common" will set
  132. # MAKEFILE_LIST to "Makefile.common" which will fail to match the
  133. # pattern %/Makefile.common.
  134. #
  135. MAKEFILE_PATHS = $(foreach makefile,$(MAKEFILE_LIST),$(abspath $(makefile)))
  136. PROOF_ROOT = $(dir $(filter %/Makefile.common,$(MAKEFILE_PATHS)))
  137. CBMC_ROOT = $(shell dirname $(PROOF_ROOT))
  138. PROOF_SOURCE = $(CBMC_ROOT)/sources
  139. PROOF_INCLUDE = $(CBMC_ROOT)/include
  140. PROOF_STUB = $(CBMC_ROOT)/stubs
  141. # Project-specific definitions to override default definitions below
  142. # * Makefile-project-defines will never be overwritten
  143. # * Makefile-template-defines may be overwritten when the starter
  144. # kit is updated
  145. sinclude $(PROOF_ROOT)/Makefile-project-defines
  146. sinclude $(PROOF_ROOT)/Makefile-template-defines
  147. # SRCDIR is the path to the root of the source tree
  148. # This is a default definition that is frequently overridden in
  149. # another Makefile, see the discussion of SRCDIR above.
  150. SRCDIR ?= $(abspath ../..)
  151. # PROOFDIR is the path to the directory containing the proof harness
  152. PROOFDIR ?= $(abspath .)
  153. ################################################################
  154. # Define how to run CBMC
  155. # Do property checking with the external SAT solver given by
  156. # EXTERNAL_SAT_SOLVER. Do coverage checking with the default solver,
  157. # since coverage checking requires the use of an incremental solver.
  158. # The EXTERNAL_SAT_SOLVER variable is typically set (if it is at all)
  159. # as an environment variable or as a makefile variable in
  160. # Makefile-project-defines.
  161. #
  162. # For a particular proof, if the default solver is faster, do property
  163. # checking with the default solver by including this definition in the
  164. # proof Makefile:
  165. # USE_EXTERNAL_SAT_SOLVER =
  166. #
  167. ifneq ($(strip $(EXTERNAL_SAT_SOLVER)),)
  168. USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver $(EXTERNAL_SAT_SOLVER)
  169. endif
  170. CHECKFLAGS += $(USE_EXTERNAL_SAT_SOLVER)
  171. # Job pools
  172. # For version of Litani that are new enough (where `litani print-capabilities`
  173. # prints "pools"), proofs for which `EXPENSIVE = true` is set can be added to a
  174. # "job pool" that restricts how many expensive proofs are run at a time. All
  175. # other proofs will be built in parallel as usual.
  176. #
  177. # In more detail: all compilation, instrumentation, and report jobs are run with
  178. # full parallelism as usual, even for expensive proofs. The CBMC jobs for
  179. # non-expensive proofs are also run in parallel. The only difference is that the
  180. # CBMC safety checks and coverage checks for expensive proofs are run with a
  181. # restricted parallelism level. At any one time, only N of these jobs are run at
  182. # once, amongst all the proofs.
  183. #
  184. # To configure N, Litani needs to be initialized with a pool called "expensive".
  185. # For example, to only run two CBMC safety/coverage jobs at a time from amongst
  186. # all the proofs, you would initialize litani like
  187. # litani init --pools expensive:2
  188. # The run-cbmc-proofs.py script takes care of this initialization through the
  189. # --expensive-jobs-parallelism flag.
  190. #
  191. # To enable this feature, set
  192. # the ENABLE_POOLS variable when running Make, like
  193. # `make ENABLE_POOLS=true report`
  194. # The run-cbmc-proofs.py script takes care of this through the
  195. # --restrict-expensive-jobs flag.
  196. ifeq ($(strip $(ENABLE_POOLS)),)
  197. POOL =
  198. else ifeq ($(strip $(EXPENSIVE)),)
  199. POOL =
  200. else
  201. POOL = --pool expensive
  202. endif
  203. # Similar to the pool feature above. If Litani is new enough, enable
  204. # profiling CBMC's memory use.
  205. ifeq ($(strip $(ENABLE_MEMORY_PROFILING)),)
  206. MEMORY_PROFILING =
  207. else
  208. MEMORY_PROFILING = --profile-memory
  209. endif
  210. # Property checking flags
  211. #
  212. # Each variable below controls a specific property checking flag
  213. # within CBMC. If desired, a property flag can be disabled within
  214. # a particular proof by nulling the corresponding variable. For
  215. # instance, the following line:
  216. #
  217. # CHECK_FLAG_POINTER_CHECK =
  218. #
  219. # would disable the --pointer-check CBMC flag within:
  220. # * an entire project when added to Makefile-project-defines
  221. # * a specific proof when added to the harness Makefile
  222. CBMC_FLAG_MALLOC_MAY_FAIL ?= --malloc-may-fail
  223. CBMC_FLAG_MALLOC_FAIL_NULL ?= --malloc-fail-null
  224. CBMC_FLAG_BOUNDS_CHECK ?= --bounds-check
  225. CBMC_FLAG_CONVERSION_CHECK ?= --conversion-check
  226. CBMC_FLAG_DIV_BY_ZERO_CHECK ?= --div-by-zero-check
  227. CBMC_FLAG_FLOAT_OVERFLOW_CHECK ?= --float-overflow-check
  228. CBMC_FLAG_NAN_CHECK ?= --nan-check
  229. CBMC_FLAG_POINTER_CHECK ?= --pointer-check
  230. CBMC_FLAG_POINTER_OVERFLOW_CHECK ?= --pointer-overflow-check
  231. CBMC_FLAG_POINTER_PRIMITIVE_CHECK ?= --pointer-primitive-check
  232. CBMC_FLAG_SIGNED_OVERFLOW_CHECK ?= --signed-overflow-check
  233. CBMC_FLAG_UNDEFINED_SHIFT_CHECK ?= --undefined-shift-check
  234. CBMC_FLAG_UNSIGNED_OVERFLOW_CHECK ?= --unsigned-overflow-check
  235. CBMC_FLAG_UNWINDING_ASSERTIONS ?= --unwinding-assertions
  236. CBMC_FLAG_UNWIND ?= --unwind 1
  237. CBMC_FLAG_FLUSH ?= --flush
  238. # CBMC flags used for property checking and coverage checking
  239. CBMCFLAGS += $(CBMC_FLAG_UNWIND) $(CBMC_UNWINDSET) $(CBMC_FLAG_FLUSH)
  240. # CBMC flags used for property checking
  241. CHECKFLAGS += $(CBMC_FLAG_MALLOC_MAY_FAIL)
  242. CHECKFLAGS += $(CBMC_FLAG_MALLOC_FAIL_NULL)
  243. CHECKFLAGS += $(CBMC_FLAG_BOUNDS_CHECK)
  244. CHECKFLAGS += $(CBMC_FLAG_CONVERSION_CHECK)
  245. CHECKFLAGS += $(CBMC_FLAG_DIV_BY_ZERO_CHECK)
  246. CHECKFLAGS += $(CBMC_FLAG_FLOAT_OVERFLOW_CHECK)
  247. CHECKFLAGS += $(CBMC_FLAG_NAN_CHECK)
  248. CHECKFLAGS += $(CBMC_FLAG_POINTER_CHECK)
  249. CHECKFLAGS += $(CBMC_FLAG_POINTER_OVERFLOW_CHECK)
  250. CHECKFLAGS += $(CBMC_FLAG_POINTER_PRIMITIVE_CHECK)
  251. CHECKFLAGS += $(CBMC_FLAG_SIGNED_OVERFLOW_CHECK)
  252. CHECKFLAGS += $(CBMC_FLAG_UNDEFINED_SHIFT_CHECK)
  253. CHECKFLAGS += $(CBMC_FLAG_UNSIGNED_OVERFLOW_CHECK)
  254. CHECKFLAGS += $(CBMC_FLAG_UNWINDING_ASSERTIONS)
  255. # CBMC flags used for coverage checking
  256. COVERFLAGS += $(CBMC_FLAG_MALLOC_MAY_FAIL)
  257. COVERFLAGS += $(CBMC_FLAG_MALLOC_FAIL_NULL)
  258. # Additional CBMC flag to CBMC control verbosity.
  259. #
  260. # Meaningful values are
  261. # 0 none
  262. # 1 only errors
  263. # 2 + warnings
  264. # 4 + results
  265. # 6 + status/phase information
  266. # 8 + statistical information
  267. # 9 + progress information
  268. # 10 + debug info
  269. #
  270. # Uncomment the following line or set in Makefile-project-defines
  271. # CBMC_VERBOSITY ?= --verbosity 4
  272. # Additional CBMC flag to control how CBMC treats static variables.
  273. #
  274. # NONDET_STATIC is a list of flags of the form --nondet-static
  275. # and --nondet-static-exclude VAR. The --nondet-static flag causes
  276. # CBMC to initialize static variables with unconstrained value
  277. # (ignoring initializers and default zero-initialization). The
  278. # --nondet-static-exclude VAR excludes VAR for the variables
  279. # initialized with unconstrained values.
  280. NONDET_STATIC ?=
  281. # Flags to pass to goto-cc for compilation and linking
  282. COMPILE_FLAGS ?= -Wall
  283. LINK_FLAGS ?= -Wall
  284. EXPORT_FILE_LOCAL_SYMBOLS ?= --export-file-local-symbols
  285. # Preprocessor include paths -I...
  286. INCLUDES ?=
  287. # Preprocessor definitions -D...
  288. DEFINES ?=
  289. # CBMC object model
  290. #
  291. # CBMC_OBJECT_BITS is the number of bits in a pointer CBMC uses for
  292. # the id of the object to which a pointer is pointing. CBMC uses 8
  293. # bits for the object id by default. The remaining bits in the pointer
  294. # are used for offset into the object. This limits the size of the
  295. # objects that CBMC can model. This Makefile defines this bound on
  296. # object size to be CBMC_MAX_OBJECT_SIZE. You are likely to get
  297. # unexpected results if you try to malloc an object larger than this
  298. # bound.
  299. CBMC_OBJECT_BITS ?= 8
  300. # CBMC loop unwinding (Normally set in the proof Makefile)
  301. #
  302. # UNWINDSET is a list of pairs of the form foo.1:4 meaning that
  303. # CBMC should unwind loop 1 in function foo no more than 4 times.
  304. # For historical reasons, the number 4 is one more than the number
  305. # of times CBMC actually unwinds the loop.
  306. UNWINDSET ?=
  307. # CBMC early loop unwinding (Normally set in the proof Makefile)
  308. #
  309. # Most users can ignore this variable.
  310. #
  311. # This variable exists to support the use of loop and function
  312. # contracts, two features under development for CBMC. Checking the
  313. # assigns clause for function contracts and loop invariants currently
  314. # assumes loop-free bodies for loops and functions with contracts
  315. # (possibly after replacing nested loops with their own loop
  316. # contracts). To satisfy this requirement, it may be necessary to
  317. # unwind some loops before the function contract and loop invariant
  318. # transformations are applied to the goto program. This variable
  319. # EARLY_UNWINDSET is identical to UNWINDSET, and we assume that the
  320. # loops mentioned in EARLY_UNWINDSET and UNWINDSET are disjoint.
  321. EARLY_UNWINDSET ?=
  322. # CBMC function removal (Normally set set in the proof Makefile)
  323. #
  324. # REMOVE_FUNCTION_BODY is a list of function names. CBMC will "undefine"
  325. # the function, and CBMC will treat the function as having no side effects
  326. # and returning an unconstrained value of the appropriate return type.
  327. # The list should include the names of functions being stubbed out.
  328. REMOVE_FUNCTION_BODY ?=
  329. # CBMC function pointer restriction (Normally set in the proof Makefile)
  330. #
  331. # RESTRICT_FUNCTION_POINTER is a list of function pointer restriction
  332. # instructions of the form:
  333. #
  334. # <fun_id>.function_pointer_call.<N>/<fun_id>[,<fun_id>]*
  335. #
  336. # The function pointer call number <N> in the specified function gets
  337. # rewritten to a case switch over a finite list of functions.
  338. # If some possible target functions are omitted from the list a counter
  339. # example trace will be found by CBMC, i.e. the transformation is sound.
  340. # If the target functions are file-local symbols, then mangled names must
  341. # be used.
  342. RESTRICT_FUNCTION_POINTER ?=
  343. # The project source files (Normally set set in the proof Makefile)
  344. #
  345. # PROJECT_SOURCES is the list of project source files to compile,
  346. # including the source file defining the function under test.
  347. PROJECT_SOURCES ?=
  348. # The proof source files (Normally set in the proof Makefile)
  349. #
  350. # PROOF_SOURCES is the list of proof source files to compile, including
  351. # the proof harness, and including any function stubs being used.
  352. PROOF_SOURCES ?=
  353. # The number of seconds that CBMC should be allowed to run for before
  354. # being forcefully terminated. Currently, this is set to be less than
  355. # the time limit for a CodeBuild job, which is eight hours. If a proof
  356. # run takes longer than the time limit of the CI environment, the
  357. # environment will halt the proof run without updating the Litani
  358. # report, making the proof run appear to "hang".
  359. CBMC_TIMEOUT ?= 21600
  360. # Proof writers could add function contracts in their source code.
  361. # These contracts are ignored by default, but may be enabled in two distinct
  362. # contexts using the following two variables:
  363. # 1. To check whether one or more function contracts are sound with respect to
  364. # the function implementation, CHECK_FUNCTION_CONTRACTS should be a list of
  365. # function names.
  366. # 2. To replace calls to certain functions with their correspondent function
  367. # contracts, USE_FUNCTION_CONTRACTS should be a list of function names.
  368. # One must check separately whether a function contract is sound before
  369. # replacing it in calling contexts.
  370. CHECK_FUNCTION_CONTRACTS ?=
  371. CBMC_CHECK_FUNCTION_CONTRACTS := $(patsubst %,--enforce-contract %, $(CHECK_FUNCTION_CONTRACTS))
  372. USE_FUNCTION_CONTRACTS ?=
  373. CBMC_USE_FUNCTION_CONTRACTS := $(patsubst %,--replace-call-with-contract %, $(USE_FUNCTION_CONTRACTS))
  374. # Similarly, proof writers could also add loop contracts in their source code
  375. # to obtain unbounded correctness proofs. Unlike function contracts, loop
  376. # contracts are not reusable and thus are checked and used simultaneously.
  377. # These contracts are also ignored by default, but may be enabled by setting
  378. # the APPLY_LOOP_CONTRACTS variable to 1.
  379. APPLY_LOOP_CONTRACTS ?= 0
  380. ifeq ($(APPLY_LOOP_CONTRACTS),1)
  381. CBMC_APPLY_LOOP_CONTRACTS ?= --apply-loop-contracts
  382. endif
  383. # Silence makefile output (eg, long litani commands) unless VERBOSE is set.
  384. ifndef VERBOSE
  385. MAKEFLAGS := $(MAKEFLAGS) -s
  386. endif
  387. ################################################################
  388. ################################################################
  389. ## Section II: This section defines the process of running a proof
  390. ##
  391. ## There should be no reason to edit anything below this line.
  392. ################################################################
  393. # Paths
  394. CBMC ?= cbmc
  395. GOTO_ANALYZER ?= goto-analyzer
  396. GOTO_CC ?= goto-cc
  397. GOTO_INSTRUMENT ?= goto-instrument
  398. CRANGLER ?= crangler
  399. VIEWER ?= cbmc-viewer
  400. MAKE_SOURCE ?= make-source
  401. VIEWER2 ?= cbmc-viewer
  402. CMAKE ?= cmake
  403. GOTODIR ?= $(PROOFDIR)/gotos
  404. LOGDIR ?= $(PROOFDIR)/logs
  405. PROJECT ?= project
  406. PROOF ?= proof
  407. HARNESS_GOTO ?= $(GOTODIR)/$(HARNESS_FILE)
  408. PROJECT_GOTO ?= $(GOTODIR)/$(PROJECT)
  409. PROOF_GOTO ?= $(GOTODIR)/$(PROOF)
  410. ################################################################
  411. # Useful macros for values that are hard to reference
  412. SPACE :=$() $()
  413. COMMA :=,
  414. ################################################################
  415. # Set C compiler defines
  416. CBMCFLAGS += --object-bits $(CBMC_OBJECT_BITS)
  417. COMPILE_FLAGS += --object-bits $(CBMC_OBJECT_BITS)
  418. DEFINES += -DCBMC=1
  419. DEFINES += -DCBMC_OBJECT_BITS=$(CBMC_OBJECT_BITS)
  420. DEFINES += -DCBMC_MAX_OBJECT_SIZE="(SIZE_MAX>>(CBMC_OBJECT_BITS+1))"
  421. # CI currently assumes cbmc invocation has at most one --unwindset
  422. ifdef UNWINDSET
  423. ifneq ($(strip $(UNWINDSET)),"")
  424. CBMC_UNWINDSET := --unwindset $(subst $(SPACE),$(COMMA),$(strip $(UNWINDSET)))
  425. endif
  426. endif
  427. ifdef EARLY_UNWINDSET
  428. ifneq ($(strip $(EARLY_UNWINDSET)),"")
  429. CBMC_EARLY_UNWINDSET := --unwindset $(subst $(SPACE),$(COMMA),$(strip $(EARLY_UNWINDSET)))
  430. endif
  431. endif
  432. CBMC_REMOVE_FUNCTION_BODY := $(patsubst %,--remove-function-body %, $(REMOVE_FUNCTION_BODY))
  433. CBMC_RESTRICT_FUNCTION_POINTER := $(patsubst %,--restrict-function-pointer %, $(RESTRICT_FUNCTION_POINTER))
  434. ################################################################
  435. # Targets for rewriting source files with crangler
  436. # Construct crangler configuration files
  437. #
  438. # REWRITTEN_SOURCES is a list of crangler output files source.i.
  439. # This target assumes that for each source.i
  440. # * source.i_SOURCE is the path to a source file,
  441. # * source.i_FUNCTIONS is a list of functions (may be empty)
  442. # * source.i_OBJECTS is a list of variables (may be empty)
  443. # This target constructs the crangler configuration file source.i.json
  444. # of the form
  445. # {
  446. # "sources": [ "/proj/code.c" ],
  447. # "includes": [ "/proj/include" ],
  448. # "defines": [ "VAR=1" ],
  449. # "functions": [ {"function_name": ["remove static"]} ],
  450. # "objects": [ {"variable_name": ["remove static"]} ],
  451. # "output": "source.i"
  452. # }
  453. # to remove the static attribute from function_name and variable_name
  454. # in the source file source.c and write the result to source.i.
  455. #
  456. # This target assumes that filenames include no spaces and that
  457. # the INCLUDES and DEFINES variables include no spaces after -I
  458. # and -D. For example, use "-DVAR=1" and not "-D VAR=1".
  459. #
  460. # Define *_SOURCE, *_FUNCTIONS, and *_OBJECTS in the proof Makefile.
  461. # The string source.i is usually an absolute path $(PROOFDIR)/code.i
  462. # to a file in the proof directory that contains the proof Makefile.
  463. # The proof Makefile usually includes the definitions
  464. # $(PROOFDIR)/code.i_SOURCE = /proj/code.c
  465. # $(PROOFDIR)/code.i_FUNCTIONS = function_name
  466. # $(PROOFDIR)/code.i_OBJECTS = variable_name
  467. # Because these definitions refer to PROOFDIR that is defined in this
  468. # Makefile.common, these definitions must appear after the inclusion
  469. # of Makefile.common in the proof Makefile.
  470. #
  471. $(foreach rs,$(REWRITTEN_SOURCES),$(eval $(rs).json: $($(rs)_SOURCE)))
  472. $(foreach rs,$(REWRITTEN_SOURCES),$(rs).json):
  473. echo '{'\
  474. '"sources": ['\
  475. '"$($(@:.json=)_SOURCE)"'\
  476. '],'\
  477. '"includes": ['\
  478. '$(subst $(SPACE),$(COMMA),$(patsubst -I%,"%",$(strip $(INCLUDES))))' \
  479. '],'\
  480. '"defines": ['\
  481. '$(subst $(SPACE),$(COMMA),$(patsubst -D%,"%",$(subst ",\",$(strip $(DEFINES)))))' \
  482. '],'\
  483. '"functions": ['\
  484. '{'\
  485. '$(subst ~, ,$(subst $(SPACE),$(COMMA),$(patsubst %,"%":["remove~static"],$($(@:.json=)_FUNCTIONS))))' \
  486. '}'\
  487. '],'\
  488. '"objects": ['\
  489. '{'\
  490. '$(subst ~, ,$(subst $(SPACE),$(COMMA),$(patsubst %,"%":["remove~static"],$($(@:.json=)_OBJECTS))))' \
  491. '}'\
  492. '],'\
  493. '"output": "$(@:.json=)"'\
  494. '}' > $@
  495. # Rewrite source files with crangler
  496. #
  497. $(foreach rs,$(REWRITTEN_SOURCES),$(eval $(rs): $(rs).json))
  498. $(REWRITTEN_SOURCES):
  499. $(LITANI) add-job \
  500. --command \
  501. '$(CRANGLER) $@.json' \
  502. --inputs $($@_SOURCE) \
  503. --outputs $@ \
  504. --stdout-file $(LOGDIR)/crangler-$(subst /,_,$(subst .,_,$@))-log.txt \
  505. --interleave-stdout-stderr \
  506. --pipeline-name "$(PROOF_UID)" \
  507. --ci-stage build \
  508. --description "$(PROOF_UID): removing static"
  509. ################################################################
  510. # Build targets that make the relevant .goto files
  511. # Compile project sources
  512. $(PROJECT_GOTO)1.goto: $(PROJECT_SOURCES) $(REWRITTEN_SOURCES)
  513. $(LITANI) add-job \
  514. --command \
  515. '$(GOTO_CC) $(CBMC_VERBOSITY) $(COMPILE_FLAGS) $(EXPORT_FILE_LOCAL_SYMBOLS) $(INCLUDES) $(DEFINES) $^ -o $@' \
  516. --inputs $^ \
  517. --outputs $@ \
  518. --stdout-file $(LOGDIR)/project_sources-log.txt \
  519. --pipeline-name "$(PROOF_UID)" \
  520. --ci-stage build \
  521. --description "$(PROOF_UID): building project binary"
  522. # Compile proof sources
  523. $(PROOF_GOTO)1.goto: $(PROOF_SOURCES)
  524. $(LITANI) add-job \
  525. --command \
  526. '$(GOTO_CC) $(CBMC_VERBOSITY) $(COMPILE_FLAGS) $(EXPORT_FILE_LOCAL_SYMBOLS) $(INCLUDES) $(DEFINES) $^ -o $@' \
  527. --inputs $^ \
  528. --outputs $@ \
  529. --stdout-file $(LOGDIR)/proof_sources-log.txt \
  530. --pipeline-name "$(PROOF_UID)" \
  531. --ci-stage build \
  532. --description "$(PROOF_UID): building proof binary"
  533. # Remove function bodies from project sources
  534. $(PROJECT_GOTO)2.goto: $(PROJECT_GOTO)1.goto
  535. $(LITANI) add-job \
  536. --command \
  537. '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_REMOVE_FUNCTION_BODY) $^ $@' \
  538. --inputs $^ \
  539. --outputs $@ \
  540. --stdout-file $(LOGDIR)/remove_function_body-log.txt \
  541. --pipeline-name "$(PROOF_UID)" \
  542. --ci-stage build \
  543. --description "$(PROOF_UID): removing function bodies from project sources"
  544. # Link project and proof sources into the proof harness
  545. $(HARNESS_GOTO)1.goto: $(PROOF_GOTO)1.goto $(PROJECT_GOTO)2.goto
  546. $(LITANI) add-job \
  547. --command '$(GOTO_CC) $(CBMC_VERBOSITY) --function $(HARNESS_ENTRY) $^ $(LINK_FLAGS) -o $@' \
  548. --inputs $^ \
  549. --outputs $@ \
  550. --stdout-file $(LOGDIR)/link_proof_project-log.txt \
  551. --pipeline-name "$(PROOF_UID)" \
  552. --ci-stage build \
  553. --description "$(PROOF_UID): linking project to proof"
  554. # Restrict function pointers
  555. $(HARNESS_GOTO)2.goto: $(HARNESS_GOTO)1.goto
  556. $(LITANI) add-job \
  557. --command \
  558. '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_RESTRICT_FUNCTION_POINTER) $^ $@' \
  559. --inputs $^ \
  560. --outputs $@ \
  561. --stdout-file $(LOGDIR)/restrict_function_pointer-log.txt \
  562. --pipeline-name "$(PROOF_UID)" \
  563. --ci-stage build \
  564. --description "$(PROOF_UID): restricting function pointers in project sources"
  565. # Fill static variable with unconstrained values
  566. $(HARNESS_GOTO)3.goto: $(HARNESS_GOTO)2.goto
  567. $(LITANI) add-job \
  568. --command \
  569. '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(NONDET_STATIC) $^ $@' \
  570. --inputs $^ \
  571. --outputs $@ \
  572. --stdout-file $(LOGDIR)/nondet_static-log.txt \
  573. --pipeline-name "$(PROOF_UID)" \
  574. --ci-stage build \
  575. --description "$(PROOF_UID): setting static variables to nondet"
  576. # Omit unused functions (sharpens coverage calculations)
  577. $(HARNESS_GOTO)4.goto: $(HARNESS_GOTO)3.goto
  578. $(LITANI) add-job \
  579. --command \
  580. '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) --drop-unused-functions $^ $@' \
  581. --inputs $^ \
  582. --outputs $@ \
  583. --stdout-file $(LOGDIR)/drop_unused_functions-log.txt \
  584. --pipeline-name "$(PROOF_UID)" \
  585. --ci-stage build \
  586. --description "$(PROOF_UID): dropping unused functions"
  587. # Omit initialization of unused global variables (reduces problem size)
  588. $(HARNESS_GOTO)5.goto: $(HARNESS_GOTO)4.goto
  589. $(LITANI) add-job \
  590. --command \
  591. '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) --slice-global-inits $^ $@' \
  592. --inputs $^ \
  593. --outputs $@ \
  594. --stdout-file $(LOGDIR)/slice_global_inits-log.txt \
  595. --pipeline-name "$(PROOF_UID)" \
  596. --ci-stage build \
  597. --description "$(PROOF_UID): slicing global initializations"
  598. # Replace function calls with function contracts
  599. # This must be done before enforcing function contracts,
  600. # since contract enforcement inlines all function calls.
  601. $(HARNESS_GOTO)6.goto: $(HARNESS_GOTO)5.goto
  602. $(LITANI) add-job \
  603. --command \
  604. '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_USE_FUNCTION_CONTRACTS) $^ $@' \
  605. --inputs $^ \
  606. --outputs $@ \
  607. --stdout-file $(LOGDIR)/use_function_contracts-log.txt \
  608. --pipeline-name "$(PROOF_UID)" \
  609. --ci-stage build \
  610. --description "$(PROOF_UID): replacing function calls with function contracts"
  611. # Unwind loops for loop and function contracts
  612. $(HARNESS_GOTO)7.goto: $(HARNESS_GOTO)6.goto
  613. $(LITANI) add-job \
  614. --command \
  615. '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_EARLY_UNWINDSET) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $^ $@' \
  616. --inputs $^ \
  617. --outputs $@ \
  618. --stdout-file $(LOGDIR)/unwind_loops-log.txt \
  619. --pipeline-name "$(PROOF_UID)" \
  620. --ci-stage build \
  621. --description "$(PROOF_UID): unwinding loops"
  622. # Apply loop contracts
  623. $(HARNESS_GOTO)8.goto: $(HARNESS_GOTO)7.goto
  624. $(LITANI) add-job \
  625. --command \
  626. '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_APPLY_LOOP_CONTRACTS) $^ $@' \
  627. --inputs $^ \
  628. --outputs $@ \
  629. --stdout-file $(LOGDIR)/apply_loop_contracts-log.txt \
  630. --pipeline-name "$(PROOF_UID)" \
  631. --ci-stage build \
  632. --description "$(PROOF_UID): applying loop contracts"
  633. # Check function contracts
  634. $(HARNESS_GOTO)9.goto: $(HARNESS_GOTO)8.goto
  635. $(LITANI) add-job \
  636. --command \
  637. '$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_CHECK_FUNCTION_CONTRACTS) $^ $@' \
  638. --inputs $^ \
  639. --outputs $@ \
  640. --stdout-file $(LOGDIR)/check_function_contracts-log.txt \
  641. --pipeline-name "$(PROOF_UID)" \
  642. --ci-stage build \
  643. --description "$(PROOF_UID): checking function contracts"
  644. # Final name for proof harness
  645. $(HARNESS_GOTO).goto: $(HARNESS_GOTO)9.goto
  646. $(LITANI) add-job \
  647. --command 'cp $< $@' \
  648. --inputs $^ \
  649. --outputs $@ \
  650. --pipeline-name "$(PROOF_UID)" \
  651. --ci-stage build \
  652. --description "$(PROOF_UID): copying final goto-binary"
  653. ################################################################
  654. # Targets to run the analysis commands
  655. $(LOGDIR)/result.txt: $(HARNESS_GOTO).goto
  656. $(LITANI) add-job \
  657. $(POOL) \
  658. --command \
  659. '$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $(CHECKFLAGS) --trace $<' \
  660. --inputs $^ \
  661. --outputs $@ \
  662. --ci-stage test \
  663. --stdout-file $@ \
  664. $(MEMORY_PROFILING) \
  665. --ignore-returns 10 \
  666. --timeout $(CBMC_TIMEOUT) \
  667. --pipeline-name "$(PROOF_UID)" \
  668. --tags "stats-group:safety checks" \
  669. --stderr-file $(LOGDIR)/result-err-log.txt \
  670. --description "$(PROOF_UID): checking safety properties"
  671. $(LOGDIR)/result.xml: $(HARNESS_GOTO).goto
  672. $(LITANI) add-job \
  673. $(POOL) \
  674. --command \
  675. '$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $(CHECKFLAGS) --trace --xml-ui $<' \
  676. --inputs $^ \
  677. --outputs $@ \
  678. --ci-stage test \
  679. --stdout-file $@ \
  680. $(MEMORY_PROFILING) \
  681. --ignore-returns 10 \
  682. --timeout $(CBMC_TIMEOUT) \
  683. --pipeline-name "$(PROOF_UID)" \
  684. --tags "stats-group:safety checks" \
  685. --stderr-file $(LOGDIR)/result-err-log.txt \
  686. --description "$(PROOF_UID): checking safety properties"
  687. $(LOGDIR)/property.xml: $(HARNESS_GOTO).goto
  688. $(LITANI) add-job \
  689. --command \
  690. '$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $(CHECKFLAGS) --show-properties --xml-ui $<' \
  691. --inputs $^ \
  692. --outputs $@ \
  693. --ci-stage test \
  694. --stdout-file $@ \
  695. --ignore-returns 10 \
  696. --pipeline-name "$(PROOF_UID)" \
  697. --stderr-file $(LOGDIR)/property-err-log.txt \
  698. --description "$(PROOF_UID): printing safety properties"
  699. $(LOGDIR)/coverage.xml: $(HARNESS_GOTO).goto
  700. $(LITANI) add-job \
  701. $(POOL) \
  702. --command \
  703. '$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(COVERFLAGS) --cover location --xml-ui $<' \
  704. --inputs $^ \
  705. --outputs $@ \
  706. --ci-stage test \
  707. --stdout-file $@ \
  708. $(MEMORY_PROFILING) \
  709. --ignore-returns 10 \
  710. --timeout $(CBMC_TIMEOUT) \
  711. --pipeline-name "$(PROOF_UID)" \
  712. --tags "stats-group:coverage computation" \
  713. --stderr-file $(LOGDIR)/coverage-err-log.txt \
  714. --description "$(PROOF_UID): calculating coverage"
  715. define VIEWER_CMD
  716. $(VIEWER) \
  717. --result $(LOGDIR)/result.txt \
  718. --block $(LOGDIR)/coverage.xml \
  719. --property $(LOGDIR)/property.xml \
  720. --srcdir $(SRCDIR) \
  721. --goto $(HARNESS_GOTO).goto \
  722. --htmldir $(PROOFDIR)/html
  723. endef
  724. export VIEWER_CMD
  725. $(PROOFDIR)/html: $(LOGDIR)/result.txt $(LOGDIR)/property.xml $(LOGDIR)/coverage.xml
  726. $(LITANI) add-job \
  727. --command "$$VIEWER_CMD" \
  728. --inputs $^ \
  729. --outputs $(PROOFDIR)/html \
  730. --pipeline-name "$(PROOF_UID)" \
  731. --ci-stage report \
  732. --stdout-file $(LOGDIR)/viewer-log.txt \
  733. --description "$(PROOF_UID): generating report"
  734. # Caution: run make-source before running property and coverage checking
  735. # The current make-source script removes the goto binary
  736. $(LOGDIR)/source.json:
  737. mkdir -p $(dir $@)
  738. $(RM) -r $(GOTODIR)
  739. $(MAKE_SOURCE) --srcdir $(SRCDIR) --wkdir $(PROOFDIR) > $@
  740. $(RM) -r $(GOTODIR)
  741. define VIEWER2_CMD
  742. $(VIEWER2) \
  743. --result $(LOGDIR)/result.xml \
  744. --coverage $(LOGDIR)/coverage.xml \
  745. --property $(LOGDIR)/property.xml \
  746. --srcdir $(SRCDIR) \
  747. --goto $(HARNESS_GOTO).goto \
  748. --reportdir $(PROOFDIR)/report \
  749. --config $(PROOFDIR)/cbmc-viewer.json
  750. endef
  751. export VIEWER2_CMD
  752. # Omit logs/source.json from report generation until make-sources
  753. # works correctly with Makefiles that invoke the compiler with
  754. # mutliple source files at once.
  755. $(PROOFDIR)/report: $(LOGDIR)/result.xml $(LOGDIR)/property.xml $(LOGDIR)/coverage.xml
  756. $(LITANI) add-job \
  757. --command "$$VIEWER2_CMD" \
  758. --inputs $^ \
  759. --outputs $(PROOFDIR)/report \
  760. --pipeline-name "$(PROOF_UID)" \
  761. --stdout-file $(LOGDIR)/viewer-log.txt \
  762. --ci-stage report \
  763. --description "$(PROOF_UID): generating report"
  764. litani-path:
  765. @echo $(LITANI)
  766. # ##############################################################
  767. # Phony Rules
  768. #
  769. # These rules provide a convenient way to run a single proof up to a
  770. # certain stage. Users can browse into a proof directory and run
  771. # "make -Bj 3 report" to generate a report for just that proof, or
  772. # "make goto" to build the goto binary. Under the hood, this runs litani
  773. # for just that proof.
  774. _goto: $(HARNESS_GOTO).goto
  775. goto:
  776. @ echo Running 'litani init'
  777. $(LITANI) init --project $(PROJECT_NAME)
  778. @ echo Running 'litani add-job'
  779. $(MAKE) -B _goto
  780. @ echo Running 'litani build'
  781. $(LITANI) run-build
  782. _result: $(LOGDIR)/result.txt
  783. result:
  784. @ echo Running 'litani init'
  785. $(LITANI) init --project $(PROJECT_NAME)
  786. @ echo Running 'litani add-job'
  787. $(MAKE) -B _result
  788. @ echo Running 'litani build'
  789. $(LITANI) run-build
  790. _property: $(LOGDIR)/property.xml
  791. property:
  792. @ echo Running 'litani init'
  793. $(LITANI) init --project $(PROJECT_NAME)
  794. @ echo Running 'litani add-job'
  795. $(MAKE) -B _property
  796. @ echo Running 'litani build'
  797. $(LITANI) run-build
  798. _coverage: $(LOGDIR)/coverage.xml
  799. coverage:
  800. @ echo Running 'litani init'
  801. $(LITANI) init --project $(PROJECT_NAME)
  802. @ echo Running 'litani add-job'
  803. $(MAKE) -B _coverage
  804. @ echo Running 'litani build'
  805. $(LITANI) run-build
  806. # Choose the invocation of cbmc-viewer depending on which version of
  807. # cbmc-viewer is installed. The --version flag is not implemented in
  808. # version 1 --- it is an "unrecognized argument" --- but it is
  809. # implemented in version 2.
  810. _report1: $(PROOFDIR)/html
  811. _report2: $(PROOFDIR)/report
  812. _report:
  813. (cbmc-viewer --version 2>&1 | grep "unrecognized argument" > /dev/null) && \
  814. $(MAKE) -B _report1 || $(MAKE) -B _report2
  815. report report1 report2:
  816. @ echo Running 'litani init'
  817. $(LITANI) init --project $(PROJECT_NAME)
  818. @ echo Running 'litani add-job'
  819. $(MAKE) -B _report
  820. @ echo Running 'litani build'
  821. $(LITANI) run-build
  822. ################################################################
  823. # Targets to clean up after ourselves
  824. clean:
  825. -$(RM) $(DEPENDENT_GOTOS)
  826. -$(RM) TAGS*
  827. -$(RM) *~ \#*
  828. -$(RM) $(REWRITTEN_SOURCES) $(foreach rs,$(REWRITTEN_SOURCES),$(rs).json)
  829. veryclean: clean
  830. -$(RM) -r html report
  831. -$(RM) -r $(LOGDIR) $(GOTODIR)
  832. .PHONY: \
  833. _coverage \
  834. _goto \
  835. _property \
  836. _report \
  837. _report2 \
  838. _result \
  839. clean \
  840. coverage \
  841. goto \
  842. litani-path \
  843. property \
  844. report \
  845. report2 \
  846. result \
  847. setup_dependencies \
  848. testdeps \
  849. veryclean \
  850. #
  851. ################################################################
  852. # Rule for generating cbmc-batch.yaml, used by the CI at
  853. # https://github.com/awslabs/aws-batch-cbmc/
  854. JOB_OS ?= ubuntu16
  855. JOB_MEMORY ?= 32000
  856. # Proofs that are expected to fail should set EXPECTED to
  857. # "FAILED" in their Makefile. Values other than SUCCESSFUL
  858. # or FAILED will cause a CI error.
  859. EXPECTED ?= SUCCESSFUL
  860. define yaml_encode_options
  861. "$(shell echo $(1) | sed 's/ ,/ /g' | sed 's/ /;/g')"
  862. endef
  863. CI_FLAGS = $(CBMCFLAGS) $(CHECKFLAGS) $(COVERFLAGS)
  864. cbmc-batch.yaml:
  865. @$(RM) $@
  866. @echo 'build_memory: $(JOB_MEMORY)' > $@
  867. @echo 'cbmcflags: $(strip $(call yaml_encode_options,$(CI_FLAGS)))' >> $@
  868. @echo 'coverage_memory: $(JOB_MEMORY)' >> $@
  869. @echo 'expected: $(EXPECTED)' >> $@
  870. @echo 'goto: $(HARNESS_GOTO).goto' >> $@
  871. @echo 'jobos: $(JOB_OS)' >> $@
  872. @echo 'property_memory: $(JOB_MEMORY)' >> $@
  873. @echo 'report_memory: $(JOB_MEMORY)' >> $@
  874. .PHONY: cbmc-batch.yaml
  875. ################################################################
  876. # Run "make echo-proof-uid" to print the proof ID of a proof. This can be
  877. # used by scripts to ensure that every proof has an ID, that there are
  878. # no duplicates, etc.
  879. .PHONY: echo-proof-uid
  880. echo-proof-uid:
  881. @echo $(PROOF_UID)
  882. .PHONY: echo-project-name
  883. echo-project-name:
  884. @echo $(PROJECT_NAME)
  885. ################################################################
  886. # Project-specific targets requiring values defined above
  887. sinclude $(PROOF_ROOT)/Makefile-project-targets
  888. # CI-specific targets to drive cbmc in CI
  889. sinclude $(PROOF_ROOT)/Makefile-project-testing
  890. ################################################################