Increase size of bootstrap bytes as some Linux distributions need more space.
[satcheck.git] / snapshot-interface.cc
1 /*      Copyright (c) 2015 Regents of the University of California
2  *
3  *      Author: Brian Demsky <bdemsky@uci.edu>
4  *
5  *      This program is free software; you can redistribute it and/or
6  *      modify it under the terms of the GNU General Public License
7  *      version 2 as published by the Free Software Foundation.
8  */
9
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <cstring>
13 #include <inttypes.h>
14 #include <fcntl.h>
15 #include <sys/types.h>
16 #include "snapshot-interface.h"
17 #include "snapshot.h"
18 #include "common.h"
19 #include "mymemory.h"
20 #include "stl-model.h"
21
22 /* MYBINARYNAME only works because our pathname usually includes 'model' (e.g.,
23  * /.../model-checker/test/userprog.o) */
24 #define MYBINARYNAME "model"
25 #define MAPFILE "/proc/self/maps"
26
27 struct snapshot_entry {
28         snapshot_entry(snapshot_id id, int idx) : snapshotid(id), index(idx) { }
29         snapshot_id snapshotid;
30         int index;
31         MEMALLOC;
32 };
33
34 class SnapshotStack {
35  public:
36         int backTrackBeforeStep(int seq_index);
37         void snapshotStep(int seq_index);
38
39         MEMALLOC;
40  private:
41         ModelVector<struct snapshot_entry> stack;
42 };
43
44 static SnapshotStack *snap_stack;
45
46 #ifdef MAC
47 /** The SnapshotGlobalSegments function computes the memory regions
48  *      that may contain globals and then configures the snapshotting
49  *      library to snapshot them.
50  */
51 static void SnapshotGlobalSegments()
52 {
53         int pid = getpid();
54         char buf[9000], execname[100];
55         FILE *map;
56
57         sprintf(execname, "vmmap -interleaved %d", pid);
58         map = popen(execname, "r");
59
60         if (!map) {
61                 perror("popen");
62                 exit(EXIT_FAILURE);
63         }
64
65         /* Wait for correct part */
66         while (fgets(buf, sizeof(buf), map)) {
67                 if (strstr(buf, "==== regions for process"))
68                         break;
69         }
70
71         while (fgets(buf, sizeof(buf), map)) {
72                 char regionname[200] = "";
73                 char type[23];
74                 char smstr[23];
75                 char r, w, x;
76                 char mr, mw, mx;
77                 int size;
78                 void *begin, *end;
79
80                 //Skip out at the end of the section
81                 if (buf[0] == '\n')
82                         break;
83
84                 sscanf(buf, "%22s %p-%p [%5dK] %c%c%c/%c%c%c SM=%3s %200s\n", type, &begin, &end, &size, &r, &w, &x, &mr, &mw, &mx, smstr, regionname);
85
86                 if (w == 'w' && strstr(regionname, MYBINARYNAME)) {
87                         size_t len = ((uintptr_t)end - (uintptr_t)begin) / PAGESIZE;
88                         if (len != 0)
89                                 snapshot_add_memory_region(begin, len);
90                 }
91         }
92         pclose(map);
93 }
94 #else
95
96 static void get_binary_name(char *buf, size_t len)
97 {
98         ssize_t size = readlink("/proc/self/exe", buf, len);
99         if (size < 0) {
100                 perror("readlink");
101                 exit(EXIT_FAILURE);
102         }
103
104         /* Terminate string */
105         if ((size_t)size > len)
106                 size = len;
107         buf[size] = '\0';
108 }
109
110 /** The SnapshotGlobalSegments function computes the memory regions
111  *      that may contain globals and then configures the snapshotting
112  *      library to snapshot them.
113  */
114 static void SnapshotGlobalSegments()
115 {
116         char buf[9000];
117         char binary_name[800];
118
119         int map = open(MAPFILE, O_RDONLY);
120         if (!map) {
121                 perror("fopen");
122                 exit(EXIT_FAILURE);
123         }
124         get_binary_name(binary_name, sizeof(binary_name));
125         bool done=false;
126         while (!done) {
127                 for(uint i=0;i<sizeof(buf);) {
128                         ssize_t t=read(map, &buf[i], 1);
129                         if (t==0) {
130                                 done=true;
131                                 break;
132                         } else if (t==1) {
133                                 i+=t;
134                                 if (buf[i-1]=='\n')
135                                         break;
136                         } else {
137                                 model_print("File read error.");
138                                 exit(-1);
139                         }
140                 }
141
142                 char regionname[200] = "";
143                 char r, w, x, p;
144                 void *begin, *end;
145
146                 sscanf(buf, "%p-%p %c%c%c%c %*x %*x:%*x %*u %200s\n", &begin, &end, &r, &w, &x, &p, regionname);
147                 if (w == 'w' && strstr(regionname, binary_name)) {
148                         size_t len = ((uintptr_t)end - (uintptr_t)begin) / PAGESIZE;
149                         if (len != 0)
150                                 snapshot_add_memory_region(begin, len);
151                         DEBUG("%55s: %18p - %18p\t%c%c%c%c\n", regionname, begin, end, r, w, x, p);
152                 }
153         }
154         close(map);
155 }
156 #endif
157
158 /** This method returns to the last snapshot before the inputted
159  * sequence number.  This function must be called from the model
160  * checking thread and not from a snapshotted stack.
161  * @param seqindex is the sequence number to rollback before.
162  * @return is the sequence number we actually rolled back to.
163  */
164 int SnapshotStack::backTrackBeforeStep(int seqindex)
165 {
166         int i;
167         for (i = (int)stack.size() - 1; i >= 0; i++)
168                 if (stack[i].index <= seqindex)
169                         break;
170                 else
171                         stack.pop_back();
172
173         ASSERT(i >= 0);
174         snapshot_roll_back(stack[i].snapshotid);
175         return stack[i].index;
176 }
177
178 /** This method takes a snapshot at the given sequence number. */
179 void SnapshotStack::snapshotStep(int seqindex)
180 {
181         stack.push_back(snapshot_entry(take_snapshot(), seqindex));
182 }
183
184 void snapshot_stack_init()
185 {
186         snap_stack = new SnapshotStack();
187         SnapshotGlobalSegments();
188 }
189
190 void snapshot_record(int seq_index)
191 {
192         snap_stack->snapshotStep(seq_index);
193 }
194
195 int snapshot_backtrack_before(int seq_index)
196 {
197         return snap_stack->backTrackBeforeStep(seq_index);
198 }