CompCert Memory Model Because we need some way to understand how C - - PowerPoint PPT Presentation

compcert
SMART_READER_LITE
LIVE PREVIEW

CompCert Memory Model Because we need some way to understand how C - - PowerPoint PPT Presentation

The CompCert Memory Model Because we need some way to understand how C works Outline The general idea Version 1 Limitations Version 2 Problems solved? The general idea Blocks and memory states The idea: blocks*


slide-1
SLIDE 1

The

CompCert

Memory Model

Because we need some way to understand how C works

slide-2
SLIDE 2

Outline

 The general idea  Version 1  Limitations  Version 2  Problems solved?

slide-3
SLIDE 3

The general idea

Blocks and memory states

slide-4
SLIDE 4

The idea: blocks*

𝑚 low_bound 𝑛 𝑐 ℎ high_bound 𝑛 𝑐 𝑐 pointer is a pair: 𝑐, 𝑗 * version 1

slide-5
SLIDE 5

The idea: blocks*

𝑐 * version 1 𝑐′ 𝑐′′

slide-6
SLIDE 6

The idea: changing state*

𝑐 * version 1 𝑐′ 𝑐′′ Memory state 𝑛 ⇒ store 𝑛 𝜐 𝑐 𝑗 𝑤 ⇒ 𝑛′

slide-7
SLIDE 7

Version 1

Values, alignment and operations

slide-8
SLIDE 8

Version 1: store

 𝜐 – the type

𝜐 ∷= | Mint8signed | Mint8unsigned | Mint16signed | Mint16unsigned | Mint32 | Mfloat32 | Mfloat64 𝜐 is the size of 𝜐 in bytes 𝜐 is the natural alignment of 𝜐

 𝑤 – the value

𝑤 ∷= | Vint 𝑗 | Vfloat 𝑔 | Vptr 𝑐, 𝑗 | Vundef store 𝑛 𝜐 𝑐 𝑗 𝑤 = Some 𝑛′

slide-9
SLIDE 9

Version 1: store

mem → memory_chunk → block → Z → val → option mem

 Stores a value 𝑤 with type 𝜐 in block 𝑐 at offset 𝑗  Returns Some 𝑛′ if it succeeds  Returns None if it fails  So it can fail! When?

store 𝑛 𝜐 𝑐 𝑗 𝑤 = Some 𝑛′

slide-10
SLIDE 10

Version 1: alignment check

𝜐 divides 𝑗 ∧ low_bound 𝑛 𝑐 ≤ 𝑗 ∧ 𝑗 + 𝜐 ≤ high_bound m b

 𝑗 is aligned correctly  It doesn’t start too early  It doesn’t end too late

slide-11
SLIDE 11

Version 1: load

load 𝑛 𝜐 𝑐 𝑗 = Some 𝑤 mem → memory_chunk → block → Z → option val

 Reads value of type 𝜐 from block 𝑐 at offset 𝑗  Returns Some 𝑤 if it succeeds  Returns None if it fails  So it can fail! When?  Firstly: satisfy bounds and alignment constraints  Secondly...

slide-12
SLIDE 12

Version 1: alloc

alloc 𝑛 𝑚 ℎ = 𝑛′, 𝑐 mem → Z → Z → mem × block

 Creates a block 𝑐 with boundaries 𝑚 and ℎ  Leaves all other blocks unchanged, so:

load 𝑛′ 𝜐′ 𝑐′ 𝑗′ = load 𝑛 𝜐′ 𝑐′ 𝑗′ when 𝑐′ ≠ 𝑐

 If the load succeeds after an alloc, the value is Vundef:

load 𝑛 𝜐 𝑐 𝑗 = Some v → 𝑤 = Vundef

slide-13
SLIDE 13

Version 1: free

free 𝑛 𝑐 = 𝑛′ mem → block → mem

 Deallocates block 𝑐, giving it bounds 𝑚 = 0 and ℎ = 0  Returns updated memory state 𝑛′  Leaves all other blocks unchanged, so:

load 𝑛′ 𝜐′ 𝑐′ 𝑗′ = load 𝑛 𝜐′ 𝑐′ 𝑗′ when 𝑐′ ≠ 𝑐

 A load will not succeed after a free:

load 𝑛 𝜐 𝑐 𝑗 = None

slide-14
SLIDE 14

Version 1: store (revisited) Load: “Disjoint case”

store 𝑛 𝜐 𝑐 𝑗 𝑤 = Some 𝑛′ mem → memory_chunk → block → Z → val → option mem

 Stores stuff, returns new state or None  Again, leaves all other blocks unchanged, so:

load 𝑛′ 𝜐′ 𝑐′ 𝑗′ = load 𝑛 𝜐′ 𝑐′ 𝑗′ when 𝑐′ ≠ 𝑐

  • r 𝑗 + 𝜐 ≤ 𝑗′ or 𝑗′ + 𝜐′ ≤ 𝑗

 ...but also leaves the rest of the block unchanged!  And there is more!

slide-15
SLIDE 15

Version 1: store (revisited) Load: “Compatible case”

store 𝑛 𝜐 𝑐 𝑗 𝑤 = Some 𝑛′ mem → memory_chunk → block → Z → val → option mem

 When something is actually loaded from the right place,

with the right type, it all goes as expected! load 𝑛′ 𝜐′ 𝑐 𝑗 = Some 𝑤 load 𝑛′ 𝜐′ 𝑐 𝑗 = Some convert 𝜐′ 𝑤 if 𝜐′ = 𝜐

 ...well, almost.  And there is more!

slide-16
SLIDE 16

Version 1: store (revisited) Load: “Incompatible case”

store 𝑛 𝜐 𝑐 𝑗 𝑤 = Some 𝑛′ mem → memory_chunk → block → Z → val → option mem

 When something is loaded from the right place, but

with the wrong type... load 𝑛′ 𝜐′ 𝑐 𝑗 = Some 𝑤 and 𝜐′ ≠ 𝜐 → 𝑤 = Vundef

 And there is more!

slide-17
SLIDE 17

Version 1: store (revisited) Load: “Overlapping case”

store 𝑛 𝜐 𝑐 𝑗 𝑤 = Some 𝑛′ mem → memory_chunk → block → Z → val → option mem

 When something is just loaded from the wrong place...

load 𝑛′ 𝜐′ 𝑐 𝑗 = Some 𝑤 and 𝑗′ ≠ 𝑗 and 𝑗′ + 𝜐′ > 𝑗 and 𝑗 + 𝜐 > 𝑗′ → 𝑤 = Vundef

slide-18
SLIDE 18

Version 1: all operations

alloc 𝑛 𝑚 ℎ = 𝑛′, 𝑐 mem → Z → Z → mem × block store 𝑛 𝜐 𝑐 𝑗 𝑤 = Some 𝑛′ mem → memory_chunk → block → Z → val → option mem load 𝑛 𝜐 𝑐 𝑗 = Some 𝑤 mem → memory_chunk → block → Z → option val free 𝑛 𝑐 = 𝑛′ mem → block → mem

slide-19
SLIDE 19

Version 1: limitations

Why it kinda sucks

slide-20
SLIDE 20

Limitations

What it can do:

 Type compatibility

and type casting

What it can’t do:

slide-21
SLIDE 21

Examples: typecasting

int x = 3; *((int *) (double *) &x) = 4; Second line: same as “x=4;” struct {int x, y, z;} s; s.y = 42; ((int *) &s)[1] = 42; *((int *) ((char *) &s + sizeof(int))) = 42; Bottom 3 lines: equivalent union point3d { struct {double x, y, z;} s; double d[3]; } p; p.s.x, p.s.y and p.s.z also reachable as: p.d[0], p.d[1] and p.d[2]

slide-22
SLIDE 22

Limitations

What it can do:

 Type compatibility

and type casting

What it can’t do:

 Access in-memory data

representation

slide-23
SLIDE 23

Example: in-memory data representations

unsigned int bswap (unsigned int x) { union { unsigned int i; char c[4]; } src, dst; src.i = x; dst.c[3] = src.c[0]; dst.c[2] = src.c[1]; dst.c[1] = src.c[2]; dst.c[0] = src.c[3]; return dst.i; }

slide-24
SLIDE 24

Limitations

What it can do:

 Type compatibility

and type casting

 Invariance by memory

transformations

What it can’t do:

 Access in-memory data

representation

slide-25
SLIDE 25

Example: invariance by memory transformations

int x = 10; int y = 20; /* code */ 𝑦 gets saved in block 𝑐1 𝑧 gets saved in block 𝑐2 int y = 20; int x = 10; /* same code */ 𝑦 gets saved in block 𝑐2 𝑧 gets saved in block 𝑐1

slide-26
SLIDE 26

Example: invariance by memory transformations

int x = 10; int y = 20; /* code */ 𝑦 gets saved in block 𝑐𝑦 𝑧 gets saved in block 𝑐𝑧 There’s more... int y = 20; int x = 10; /* same code */ 𝑦 gets saved in block 𝑐𝑦 𝑧 gets saved in block 𝑐𝑧

slide-27
SLIDE 27

Limitations

What it can do:

 Type compatibility

and type casting

 Invariance by memory

transformations

What it can’t do:

 Access in-memory data

representation

 Fine-grained access

control

slide-28
SLIDE 28

More about access control

 load and store always succeed

(assuming correct alignment)

 A store should fail on a const  A load should fail on something being written to  free always succeeds

(even on a “free” block)

 A free should fail on something already “free”  A free should fail on global variables

slide-29
SLIDE 29

Limitations

What it can do:

 Type compatibility

and type casting

 Invariance by memory

transformations

What it can’t do:

 Access in-memory data

representation

 Fine-grained access

control

slide-30
SLIDE 30

Version 2

All of the pros, non of the cons

slide-31
SLIDE 31

Version 2: all operations

alloc 𝑛 𝑚 ℎ mem → Z → Z → mem × block store 𝑛 𝜐 𝑐 𝑗 𝑤 mem → memory_chunk → block → Z → val → option mem load 𝑛 𝜐 𝑐 𝑗 mem → memory_chunk → block → Z → option val free 𝑛 𝑐 mem → block → mem loadbytes 𝑛 𝑐 𝑗 𝑜 mem → block → Z → Z → option (list memval) storebytes 𝑛 𝑐 𝑗 𝐶 mem → block → Z → list memval → option mem drop_perm 𝑛 𝑐 𝑚 ℎ 𝑞 mem → block → Z → Z → permission → option mem

slide-32
SLIDE 32

Version 2: permissions

 Freeable: free, store, load, compare pointers  Writable: store, load, compare pointers  Readable: load, compare pointers  Nonempty: compare pointers

perm 𝑛 𝑐 𝑗 𝑙 𝑞

mem → block → Z → perm_kind → permission → Prop

 perm_kind is an enumeration (Max | Cur)  Cur permissions cannot exceed Max

slide-33
SLIDE 33

Version 2: permissions

Operation Effect on permissions alloc 𝑛 𝑚 ℎ = (𝑛′, 𝑐) Locations 𝑚, ℎ in block 𝑐 get Freeable permissions free 𝑛 𝑐 𝑚 ℎ Locations 𝑚, ℎ in block 𝑐 lose all permissions drop_perm 𝑛 𝑐 𝑚 ℎ 𝑞 Locations 𝑚, ℎ in block 𝑐 get permissions 𝑞 Operation Succeeds iff load 𝑛 𝜐 𝑐 𝑗 Range 𝑗, 𝑗 + 𝜐 (at least) readable store 𝑛 𝜐 𝑐 𝑗 𝑤 Range 𝑗, 𝑗 + 𝜐 (at least) writeable free 𝑛 𝑐 𝑚 ℎ Range 𝑚, ℎ freeable drop_perm 𝑛 𝑐 𝑚 ℎ 𝑞 Range 𝑚, ℎ freeable

slide-34
SLIDE 34

Version 2: permissions

 low_bound and high_bound no longer necessary  In version 1:

𝑐, 𝑗 is valid in 𝑛 ≝ low_bound 𝑛 𝑐 ≤ 𝑗 < high_bound 𝑛 𝑐

 In version 2:

𝑐, 𝑗 is valid in 𝑛 ≝ perm 𝑛 𝑐 𝑗 Max Nonempty

slide-35
SLIDE 35

Version 2: load/storebytes

loadbytes 𝑛 𝑐 𝑗 𝑜 mem → block → Z → Z → option (list memval) storebytes 𝑛 𝑐 𝑗 𝐶 mem → block → Z → list memval → option mem 𝑛𝑓𝑛𝑤𝑏𝑚 ∷= | Undef | Byte 𝑜 (𝑜 is a concrete integer in 0. . 255) | Pointer 𝑐 𝑗 𝑜 (the 𝑜-th byte of pointer 𝑐, 𝑗 )

 Again, these can both fail!

slide-36
SLIDE 36

Version 2: encoding/decoding

encode_val memory_chunk → val → list memval decode_val memory_chunk → list memval → val

slide-37
SLIDE 37

Version 2: loadbytes after storebytes

storebytes 𝑛 𝑐 𝑗 𝐶 = Some 𝑛′

 When something gets loaded from the right place with

the right length: loadbytes 𝑛′ 𝑐 𝑗 𝐶 = Some 𝐶

 When something gets loaded from the wrong place:

loadbytes 𝑛′ 𝑐′ 𝑗′ 𝑜′ = loadbytes 𝑛 𝑐′ 𝑗′ 𝑜′ if 𝑐′ ≠ 𝑐 or 𝑗′ + 𝑜′ ≤ 𝑗 or 𝑗 + 𝐶 ≤ 𝑗′

slide-38
SLIDE 38

Limitations

What it can do:

 Type compatibility

and type casting

 Invariance by memory

transformations

 Access in-memory data

representation

 Fine-grained access

control

What it can’t do:

 Access in-memory data

representation

 Fine-grained access

control

slide-39
SLIDE 39

In-memory data representations (revisited)

unsigned int bswap (unsigned int x) { union { unsigned int i; char c[4]; } src, dst; src.i = x; dst.c[3] = src.c[0]; dst.c[2] = src.c[1]; dst.c[1] = src.c[2]; dst.c[0] = src.c[3]; return dst.i; }

slide-40
SLIDE 40

More about access control (revisited)

 A store should fail on a const  A load should fail on something being written to  A free should fail on something already “free”  A free should fail on global variables

slide-41
SLIDE 41

Questions?

Because I, for one, would probably have slept through the whole thing

slide-42
SLIDE 42

You just had to ask, didn’t you?

 In the slides about

“Invariance by memory transformations” there was a line that said “There’s more...”

 The CompCert compiler does some weird sh*t to your

program.

 Local variables whose addresses are never taken,

will not be placed in memory

 ...until it becomes clear that they don’t fit into registers

anymore.

 Then they are “spilled” into memory.

 Which requires all sorts of formalizations  And I really don’t want to go into them anymore. I’m tired.