Skip to content

Commit c95b4cc

Browse files
Petr BauchPetr Bauch
Petr Bauch
authored and
Petr Bauch
committed
Squashed commits from Prerequisite PR diffblue#4438 -- Do not review
1 parent ed7a3ba commit c95b4cc

File tree

98 files changed

+3184
-54
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+3184
-54
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ set_target_properties(
148148
json-symtab-language
149149
langapi
150150
linking
151+
memory-analyzer
152+
memory-analyzer-lib
151153
pointer-analysis
152154
solvers
153155
testing-utils

doc/cprover-manual/memory-analyzer.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
[CPROVER Manual TOC](../../)
2+
3+
## Memory Analyzer
4+
5+
The memory analyzer is a front-end for running and querying GDB in order to
6+
obtain a state of the input program. A common application would be to obtain a
7+
snapshot of a program under analysis at a particular state of execution. Such a
8+
snapshot could be useful on its own: to query about values of particular
9+
variables. Furthermore, since that snapshot is a state of a valid concrete
10+
execution, it can also be used for subsequent analyses.
11+
12+
## Usage
13+
14+
We assume that the user wants to inspect a binary executable compiled with
15+
debugging symbols and a symbol table information understandable by CBMC, e.g.
16+
(having `goto-gcc` on the `PATH`):
17+
18+
```sh
19+
$ goto-gcc -g -std=c11 input_program.c -o input_program_exe
20+
```
21+
22+
Calling `goto-gcc` instead of simply compiling with `gcc` produces an ELF binary
23+
with a goto section that contains the goto model (goto program + symbol table).
24+
25+
The user can choose to either run GDB from a core-file `--core-file cf` or to a
26+
break-point `--breakpoint bp` (and only one of those). The tool also expects a
27+
comma-separated list of symbols to be analysed `--symbols s1, s2, ..`. Given its
28+
dependence on GDB, `memory-analyzer` is a Unix-only tool. The tool calls `gdb`
29+
to obtain the snapshot which is why the `-g` option is necessary for the program
30+
symbols to be visible.
31+
32+
Take for example the following program:
33+
34+
```C
35+
// main.c
36+
void checkpoint() {}
37+
38+
int array[] = {1, 2, 3};
39+
40+
int main()
41+
{
42+
array[1] = 4;
43+
44+
checkpoint();
45+
46+
return 0;
47+
}
48+
```
49+
50+
Say we are interested in the evaluation of `array` at the call-site of
51+
`checkpoint`. We compile the program with
52+
53+
```sh
54+
$ goto-gcc -g -std=c11 main.c -o main_exe
55+
```
56+
57+
And then we call `memory-analyzer` with:
58+
59+
```sh
60+
$ memory-analyzer --breakpoint checkpoint --symbols array main_exe
61+
```
62+
63+
to obtain as output:
64+
65+
```
66+
{
67+
array = { 1, 4, 3 };
68+
}
69+
```
70+
71+
Finally, to obtain an output in JSON format, e.g. for further analyses by
72+
`goto-harness` pass the additional option `--json-ui` together with requesting
73+
the output to be a symbol table by `--symtab-snapshot`.
74+
75+
```sh
76+
$ memory-analyzer --symtab-snapshot --json-ui \
77+
--breakpoint checkpoint --symbols array main_exe > snapshot.json
78+
```

regression/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,4 @@ add_subdirectory(goto-cc-goto-analyzer)
5050
add_subdirectory(systemc)
5151
add_subdirectory(contracts)
5252
add_subdirectory(goto-harness)
53+
add_subdirectory(snapshot-harness)

regression/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ DIRS = cbmc \
2323
goto-cc-cbmc \
2424
cbmc-cpp \
2525
goto-cc-goto-analyzer \
26+
snapshot-harness \
2627
systemc \
2728
contracts \
2829
# Empty last line

regression/memory-analyzer/Makefile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
default: clean tests.log
2+
3+
clean:
4+
find -name '*.exe' -execdir $(RM) '{}' \;
5+
find -name '*.out' -execdir $(RM) '{}' \;
6+
$(RM) tests.log
7+
8+
test:
9+
-@ln -s goto-cc ../../src/goto-cc/goto-gcc
10+
@../test.pl -p -c ../chain.sh
11+
12+
tests.log: ../test.pl
13+
-@ln -s goto-cc ../../src/goto-cc/goto-gcc
14+
@../test.pl -p -c ../chain.sh
15+
16+
show:
17+
@for dir in *; do \
18+
if [ -d "$$dir" ]; then \
19+
vim -o "$$dir/*.c" "$$dir/*.out"; \
20+
fi; \
21+
done;
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//Copyright 2018 Author: Malte Mues <[email protected]>
2+
3+
/// \file
4+
/// This file test array support in the memory-analyzer.
5+
/// A more detailed description of the test idea is in example3.h.
6+
/// setup() prepares the data structure.
7+
/// manipulate_data() is the hook used for the test,
8+
/// where gdb reaches the breakpoint.
9+
/// main() is just the required boilerplate around this methods,
10+
/// to make the compiled result executable.
11+
12+
#include "arrays.h"
13+
14+
#include <stdio.h>
15+
#include <stdlib.h>
16+
#include <string.h>
17+
18+
void setup()
19+
{
20+
test_struct = malloc(sizeof(struct a_typet));
21+
for(int i = 0; i < 10; i++)
22+
{
23+
test_struct->config[i] = i + 10;
24+
}
25+
for(int i = 0; i < 10; i++)
26+
{
27+
test_struct->values[i] = 0xf3;
28+
}
29+
for(int i = 10; i < 20; i++)
30+
{
31+
test_struct->values[i] = 0x3f;
32+
}
33+
for(int i = 20; i < 30; i++)
34+
{
35+
test_struct->values[i] = 0x01;
36+
}
37+
for(int i = 30; i < 40; i++)
38+
{
39+
test_struct->values[i] = 0x01;
40+
}
41+
for(int i = 40; i < 50; i++)
42+
{
43+
test_struct->values[i] = 0xff;
44+
}
45+
for(int i = 50; i < 60; i++)
46+
{
47+
test_struct->values[i] = 0x00;
48+
}
49+
for(int i = 60; i < 70; i++)
50+
{
51+
test_struct->values[i] = 0xab;
52+
}
53+
messaget option1 = {.text = "accept"};
54+
for(int i = 0; i < 4; i++)
55+
{
56+
char *value = malloc(sizeof(char *));
57+
sprintf(value, "unique%i", i);
58+
entryt your_options = {
59+
.id = 1, .options[0] = option1, .options[1].text = value};
60+
your_options.id = i + 12;
61+
test_struct->childs[i].id = your_options.id;
62+
test_struct->childs[i].options[0] = your_options.options[0];
63+
test_struct->childs[i].options[1].text = your_options.options[1].text;
64+
}
65+
test_struct->initalized = true;
66+
}
67+
68+
int manipulate_data()
69+
{
70+
for(int i = 0; i < 4; i++)
71+
{
72+
free(test_struct->childs[i].options[1].text);
73+
test_struct->childs[i].options[1].text = "decline";
74+
}
75+
}
76+
77+
int main()
78+
{
79+
setup();
80+
manipulate_data();
81+
return 0;
82+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//Copyright 2018 Author: Malte Mues <[email protected]>
2+
3+
/// \file
4+
/// Example3 test explicitly the array support.
5+
/// It ensures, that arrays are handled right.
6+
/// The different typedefs have been used, to make sure the memory-analyzer
7+
/// is aware of the different appeareances in the gdb responses.
8+
9+
#include <stdbool.h>
10+
11+
struct a_sub_sub_typet
12+
{
13+
char *text;
14+
};
15+
16+
typedef struct a_sub_sub_typet messaget;
17+
18+
struct a_sub_typet
19+
{
20+
int id;
21+
messaget options[2];
22+
};
23+
24+
struct a_typet
25+
{
26+
int config[10];
27+
bool initalized;
28+
unsigned char values[70];
29+
struct a_sub_typet childs[4];
30+
} * test_struct;
31+
32+
typedef struct a_sub_typet entryt;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
FUTURE
2+
arrays.exe
3+
--breakpoint manipulate_data --symbols test_struct
4+
analyzing symbol: test_struct
5+
GENERATED CODE:
6+
\{
7+
char _test_struct_childs0_options0_text_1\[\]="accept";
8+
char _test_struct_childs0_options1_text_2\[\]="unique0";
9+
char _test_struct_childs1_options1_text_3\[\]="unique1";
10+
char _test_struct_childs2_options1_text_4\[\]="unique2";
11+
char _test_struct_childs3_options1_text_5\[\]="unique3";
12+
struct a_typet test_struct_0=\{ .config=\{ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 \}, .initalized=0,
13+
.values=\{ 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171 \}, .childs=\{ \{ .id=12, .options=\{ \{ .text=\(char \*\)&_test_struct_childs0_options0_text_1 \},
14+
\{ .text=\(char \*\)&_test_struct_childs0_options1_text_2 \} \} \},
15+
\{ .id=13, .options=\{ \{ .text=\(char \*\)&_test_struct_childs0_options0_text_1 \},
16+
\{ .text=\(char \*\)&_test_struct_childs1_options1_text_3 \} \} \},
17+
\{ .id=14, .options=\{ \{ .text=\(char \*\)&_test_struct_childs0_options0_text_1 \},
18+
\{ .text=\(char \*\)&_test_struct_childs2_options1_text_4 \} \} \},
19+
\{ .id=15, .options=\{ \{ .text=\(char \*\)&_test_struct_childs0_options0_text_1 \},
20+
\{ .text=\(char \*\)&_test_struct_childs3_options1_text_5 \} \} \} \} \};
21+
test_struct = &test_struct_0;
22+
\}
23+
^EXIT=0$
24+
^SIGNAL=0$
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
void checkpoint()
2+
{
3+
}
4+
5+
int array[] = {1, 2, 3};
6+
7+
int main()
8+
{
9+
array[1] = 4;
10+
11+
checkpoint();
12+
13+
return 0;
14+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CORE
2+
main.exe
3+
--breakpoint checkpoint --symbols array
4+
array = \{ 1, 4, 3 \};
5+
^EXIT=0$
6+
^SIGNAL=0$

regression/memory-analyzer/chain.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/bash
2+
3+
MEMORY_ANALYZER="../../../src/memory-analyzer/memory-analyzer"
4+
5+
set -e
6+
7+
NAME=${*:$#}
8+
NAME=${NAME%.exe}
9+
10+
../../../src/goto-cc/goto-gcc -g -std=c11 -o $NAME.exe $NAME.c
11+
$MEMORY_ANALYZER $@
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//Copyright 2018 Author: Malte Mues <[email protected]>
2+
3+
/// \file
4+
/// This example deals with cyclic data structures,
5+
/// see comment in example2.h explaining why this is necessary.
6+
/// add_element is just declared as a helper method for cycle construction.
7+
/// process_buffer isn't supposed to do meaningfull stuff.
8+
/// It is the hook for the gdb breakpoint used in the test.
9+
/// free_buffer just does clean up, if you run this.
10+
11+
#include "cycles.h"
12+
void add_element(char *content)
13+
{
14+
cycle_buffer_entry_t *new_entry = malloc(sizeof(cycle_buffer_entry_t));
15+
new_entry->data = content;
16+
if(buffer.end && buffer.start)
17+
{
18+
new_entry->next = buffer.start;
19+
buffer.end->next = new_entry;
20+
buffer.end = new_entry;
21+
}
22+
else
23+
{
24+
new_entry->next = new_entry;
25+
buffer.end = new_entry;
26+
buffer.start = new_entry;
27+
}
28+
}
29+
30+
int process_buffer()
31+
{
32+
return 0;
33+
}
34+
35+
void free_buffer()
36+
{
37+
cycle_buffer_entry_t *current;
38+
cycle_buffer_entry_t *free_next;
39+
if(buffer.start)
40+
{
41+
current = buffer.start->next;
42+
while(current != buffer.start)
43+
{
44+
free_next = current;
45+
current = current->next;
46+
free(free_next);
47+
}
48+
free(current);
49+
}
50+
}
51+
52+
int main()
53+
{
54+
add_element("snow");
55+
add_element("sun");
56+
add_element("rain");
57+
add_element("thunder storm");
58+
59+
process_buffer();
60+
free_buffer();
61+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//Copyright 2018 Author: Malte Mues <[email protected]>
2+
3+
/// \file
4+
/// Example2 deals with cycles in datastructures.
5+
///
6+
/// While it is common that some datastructures contain cylces,
7+
/// it is necessary that the memory-analyzer does recognize them.
8+
/// Otherwise it would follow the datastructures pointer establishing
9+
/// the cycle for ever and never terminate execution.
10+
/// The cycle_buffer described below contains a cycle.
11+
/// As long as this regression test works, cycle introduced by using pointers
12+
/// are handle the correct way.
13+
14+
#include <stdlib.h>
15+
typedef struct cycle_buffer_entry
16+
{
17+
char *data;
18+
struct cycle_buffer_entry *next;
19+
} cycle_buffer_entry_t;
20+
21+
struct cycle_buffer
22+
{
23+
cycle_buffer_entry_t *start;
24+
struct cycle_buffer_entry *end;
25+
};
26+
27+
struct cycle_buffer buffer;

0 commit comments

Comments
 (0)