Skip to content

Commit 5e3df46

Browse files
committed
Introduce documentation for building a larger cargo project (rust-lang#554)
* Introduce documentation for building a larger cargo project * copyright on script * Edits in response to feedback
1 parent d13a7b7 commit 5e3df46

File tree

4 files changed

+124
-2
lines changed

4 files changed

+124
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ For example, we will describe using RMC as a backend to build the [`rand-core` c
159159
2. Clone `rand` and navigate to the `rand-core` directory:
160160
```
161161
git clone [email protected]:rust-random/rand.git
162-
cd rand/rand-core
162+
cd rand/rand_core
163163
```
164164
3. Next, we need to add an entry-point for CBMC to the crate's source. For now, we will just pick an existing unit test. Open `src/le.rs` and find the `test_read` function at the bottom of the file. Add the following attribute to keep the function name unmangled, so we can later pass it to CBMC.
165165

rmc-docs/src/SUMMARY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
- [Installation](./install-guide.md)
55
- [Comparison with other tools](./tool-comparison.md)
66
- [RMC on a single file](./rmc-single-file.md)
7-
- [RMC on a crate]()
7+
- [RMC on a package](./cargo-rmc.md)
88
- [Debugging failures]()
99
- [Debugging non-termination]()
1010
- [Debugging coverage]()

rmc-docs/src/cargo-rmc.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# RMC on a package
2+
3+
> RMC currently ships with a `cargo-rmc` script, but this support is deeply limited (e.g. to a single crate).
4+
> This will be corrected soon, and this documentation updated.
5+
> In the meantime, we document the current build process for a larger project with dependencies here.
6+
7+
To build a larger project (one with dependencies or multiple crates) with RMC, you currently need to:
8+
9+
1. Build the project with an appropriate set of flags to output CBMC "symbol table" `.json` files.
10+
2. Link these together into a single "goto binary", with appropriate preprocessing flags.
11+
3. Directly call CBMC on this resulting binary.
12+
13+
We give an example of this kind of script, with explanations, below.
14+
15+
# Building and running
16+
17+
Let's assume you have a project you can build with `cargo build` and you've written a proof harness somewhere in it that you want to run RMC on:
18+
19+
```rust
20+
#[no_mangle]
21+
#[cfg(rmc)]
22+
fn my_harness() {
23+
}
24+
```
25+
26+
A sample build script might start like this:
27+
28+
```bash
29+
{{#include sample-rmc-build.sh:cargo}}
30+
```
31+
32+
This allows us to re-use the `cargo` build system, but with flags that override `rustc` with RMC instead.
33+
More specifically, by setting the `RUSTC` environment variable to `rmc-rustc`, each Rust source file targeted by `cargo build` is "compiled" with RMC instead of `rustc`.
34+
The result of running `rmc-rustc` on a source file is a symbol table json file written in the CBMC Goto-C language.
35+
The use of an alternate target directory ensures RMC and rustc don't confuse each other with different intermediate output.
36+
37+
Next we can convert the symbol tables into goto binaries, in parallel, and then link them together:
38+
39+
```bash
40+
{{#include sample-rmc-build.sh:linking}}
41+
```
42+
43+
At this point we have the project built, but now we want to transform it into something that will run a specific proof harness.
44+
To do that, we specialize it, preprocess it, and then run CBMC on the result:
45+
(In practice, we might want to do the above steps once, then repeat the below steps for each proof harness.)
46+
47+
```bash
48+
{{#include sample-rmc-build.sh:cbmc}}
49+
```
50+
51+
At this point we have a complete script and should now be able to run `./sample-rmc-build my_harness` to run a particular proof harness.
52+
Even in very large projects the removal of unreachable code should mean only the parts relevant to that proof harness are preserved in the RMC run.

rmc-docs/src/sample-rmc-build.sh

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/bin/bash
2+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
# SPDX-License-Identifier: Apache-2.0 OR MIT
4+
5+
# ANCHOR: cargo
6+
set -eux
7+
8+
# The argument to this script will be the proof harness, e.g. 'my_harness' above
9+
ENTRY_POINT=$1
10+
11+
export CARGO_TARGET_DIR=target-rmc
12+
13+
env \
14+
RUST_BACKTRACE=1 \
15+
RUSTC=rmc-rustc \
16+
RUSTFLAGS="-Z trim-diagnostic-paths=no -Z codegen-backend=gotoc --cfg=rmc" \
17+
cargo build --target x86_64-unknown-linux-gnu
18+
# ANCHOR_END: cargo
19+
20+
21+
# ANCHOR: linking
22+
cd $CARGO_TARGET_DIR/x86_64-unknown-linux-gnu/debug/deps
23+
24+
# Independently translate each symbol table into a goto binary
25+
ls *.json | parallel symtab2gb {} --out {.}.out
26+
27+
# Link everything together
28+
goto-cc *.out -o linked-binary.out
29+
# ANCHOR_END: linking
30+
31+
32+
# TEMPORARY FIX
33+
# Empty C file so CBMC inserts its header
34+
touch empty.c
35+
# without this, we get cbmc errors about __CPROVER_dead_object missing
36+
37+
38+
# ANCHOR: cbmc
39+
# Now for each harness we specialize a binary:
40+
HARNESS_BIN="harness_${ENTRY_POINT}.out"
41+
goto-cc --function ${ENTRY_POINT} linked-binary.out empty.c -o "${HARNESS_BIN}"
42+
43+
# Perform some preprocessing
44+
INSTRUMENT_ARGS=(
45+
--drop-unused-functions
46+
)
47+
goto-instrument "${INSTRUMENT_ARGS[@]}" "${HARNESS_BIN}" "${HARNESS_BIN}"
48+
49+
# Run CBMC, passing along appropriate CBMC arguments:
50+
CBMC_ARGS=(
51+
# RMC defaults
52+
--unwinding-assertions
53+
--bounds-check
54+
--pointer-check
55+
--pointer-primitive-check
56+
--pointer-overflow-check
57+
--signed-overflow-check
58+
--undefined-shift-check
59+
--unsigned-overflow-check
60+
--conversion-check
61+
--div-by-zero-check
62+
--float-overflow-check
63+
--nan-check
64+
# Additional options
65+
--unwind 0
66+
--object-bits 11
67+
)
68+
69+
cbmc "${CBMC_ARGS[@]}" "${HARNESS_BIN}"
70+
# ANCHOR_END: cbmc

0 commit comments

Comments
 (0)