Skip to content

Commit 6a29bf5

Browse files
committed
Add documentation on CBMC Shadow Memory intrinsics
1 parent d38017c commit 6a29bf5

File tree

2 files changed

+149
-0
lines changed

2 files changed

+149
-0
lines changed

doc/cprover-manual/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* [Floating Point](modeling/floating-point/)
2525
* [Generating Environments](goto-harness/)
2626
* [Memory-mapped I/O](modeling/mmio/)
27+
* [Shadow Memory](modeling/shadow-memory/)
2728

2829
8. Build Systems
2930

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# Shadow Memory
2+
3+
(The original artefact's implementation is outlined in the paper [CBMC-SSM:
4+
Bounded Model Checking of C Programs with Symbolic Shadow
5+
Memory](https://dl.acm.org/doi/abs/10.1145/3551349.3559523).)
6+
7+
## Introduction
8+
9+
CBMC contains a component that supports *Symbolic Shadow Memory*. Shadow memory
10+
allows one to create a parallel memory structure that is maintained by the
11+
analysis program and that shadows the standard memory of the program. In that
12+
memory structure, a user can create fields, for which he can later set and
13+
retrieve values.
14+
15+
By doing so, one can organise his own tracking of metadata related to the code,
16+
in a way that is then considered by the backend of CBMC during analysis. This
17+
can be used to implement novel analyses that the CBMC framework itself doesn't
18+
support - for example, the paper above presents as an example a taint analysis
19+
implemented with the use of the SSM component described here.
20+
21+
## Usage
22+
23+
A user can interact with the Symbolic Shadow Memory component (from now on
24+
onwards, SSM) through four CBMC primitives, which allow one to declare shadow
25+
memory fields, and retrieve/set their corresponding values:
26+
27+
* `__CPROVER_field_decl_local`
28+
* `__CPROVER_field_decl_global`
29+
* `__CPROVER_get_field`
30+
* `__CPROVER_set_field`
31+
32+
More precisely, their signatures (in pseudo-C, because of some constraints that
33+
we can't express using the type system), along with some small examples of their
34+
usage, look like this:
35+
36+
### `void __CPROVER_field_decl_local(type1 field_name, SSM_value_type init_value)`
37+
38+
Type constraints:
39+
40+
* `type1`: string literal, such as `"field"`,
41+
* `SSM_value_type`: value of maximum 8 bits, signed or unsigned or `_Bool`.
42+
43+
Declares a local (working for variable declared in the current function scope)
44+
shadow memory field called `field_name`, and initialises it with the value
45+
`init_value`. The field is going to be associated with local-scope objects (i.e.
46+
a variable on the stack).
47+
48+
```c
49+
void func() {
50+
// Sample local object (local variable)
51+
char x = 0;
52+
53+
// Shadow memory field associated with local objects.
54+
__CPROVER_field_decl_local("shadow", (_Bool)1);
55+
}
56+
```
57+
58+
### `void __CPROVER_field_decl_global(type1 field_name, SSM_value_type init_value)`
59+
60+
Type constraints:
61+
62+
* `type1`: string literal, such as `"field"`,
63+
* `SSM_value_type`: value of maximum 8 bits, signed or unsigned or `_Bool`.
64+
65+
Ditto as above, but the field declared is associated with global objects (i.e.
66+
global variables or heap allocated objects).
67+
68+
```c
69+
// Sample global object
70+
int a = 10;
71+
72+
void func() {
73+
// Shadow memory field associated with global objects.
74+
__CPROVER_field_decl_global("shadow", (_Bool)0);
75+
}
76+
```
77+
78+
### `SSM_VALUE_TYPE __CPROVER_get_field(type1 *p, type2 field_name)`
79+
80+
Type constraints:
81+
82+
* `SSM_VALUE_TYPE`: the type of the value that was used to intialise the field
83+
with during declaration,
84+
* `type1 *`: a non-`void` pointer to an object of type `type1`, whose address we
85+
are going to use for indexing the shadow memory component for the field
86+
declared,
87+
* `type2`: a string literal-typed value, denoting the name of the field whose
88+
value we want to retrieve, such as `"field"`.
89+
90+
Retrieves the value (currently) associated with a SSM field of the given
91+
pointer. This would be either the value the field was declared to be initialised
92+
with, or, if there had been subsequent changes to it through a `__CPROVER_set_field`,
93+
the value that it was last `set` with.
94+
95+
```c
96+
// Sample global object
97+
int a = 10;
98+
99+
void func() {
100+
// Shadow memory field (called "field") associated with global objects.
101+
__CPROVER_field_decl_global("shadow", (_Bool)0);
102+
103+
_Bool shadow_x = __CPROVER_get_field(&a, "shadow");
104+
__CPROVER_assert(shadow_x == 0, "expected success: field initialised with 0");
105+
__CPROVER_assert(shadow_x == 1, "expected fail: field initialised with 0");
106+
}
107+
```
108+
109+
### `void __CPROVER_set_field(type1 *p, type2 field_name, type3 set_value)`
110+
111+
Type constraints:
112+
113+
* `type1 *`: a non-`void` pointer to an object of type `type1`, whose address we
114+
are going to use for indexing the shadow memory component for the field
115+
declared,
116+
* `type2`: a string literal-typed value, denoting the name of the field whose
117+
value we want to retrieve, such as `"field"`,
118+
* `type3`: type of the value to be set. This can be `_Bool` or of any integer
119+
type signed or unsigned. Notice that if this type differs from the type the
120+
field was declared with (`SSM_VALUE_TYPE` above) it will be implicitly casted
121+
to it.
122+
123+
Sets the value of an SSM field, using the name supplied by the `field name` as an
124+
identifier for the field and using the pointer in `p` as the address for the location
125+
of the value to be changed, to the given value, supplied by the third argument
126+
`set_value`. This value needs to be of the same type as the type of the value the
127+
field was originally initialised with.
128+
129+
```c
130+
// Sample global object
131+
int a = 10;
132+
133+
void func() {
134+
// Shadow memory field (called "field") associated with global objects.
135+
// Originally assigned a value of `1`, of type `_Bool`.
136+
__CPROVER_field_decl_global("shadow", (_Bool)1);
137+
138+
// Set field "shadow" for the memory location denoted by the address of `a`
139+
// to a value of 0.
140+
__CPROVER_set_field(&a, "shadow", 0);
141+
142+
// Retrieve the value of the field named "shadow" associated with the address
143+
// of the object `a`.
144+
_Bool shadow_x = __CPROVER_get_field(&a, "shadow");
145+
__CPROVER_assert(shadow_x == 0, "expected success: field set to a value of 0");
146+
__CPROVER_assert(shadow_x == 1, "expected fail: field set to a value of 0");
147+
}
148+
```

0 commit comments

Comments
 (0)