1 /* Copyright (c) 2015 Regents of the University of California
3 * Author: Brian Demsky <bdemsky@uci.edu>
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.
15 #include <sys/types.h>
16 #include "snapshot-interface.h"
20 #include "stl-model.h"
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"
27 struct snapshot_entry {
28 snapshot_entry(snapshot_id id, int idx) : snapshotid(id), index(idx) { }
29 snapshot_id snapshotid;
36 int backTrackBeforeStep(int seq_index);
37 void snapshotStep(int seq_index);
41 ModelVector<struct snapshot_entry> stack;
44 static SnapshotStack *snap_stack;
47 /** The SnapshotGlobalSegments function computes the memory regions
48 * that may contain globals and then configures the snapshotting
49 * library to snapshot them.
51 static void SnapshotGlobalSegments()
54 char buf[9000], execname[100];
57 sprintf(execname, "vmmap -interleaved %d", pid);
58 map = popen(execname, "r");
65 /* Wait for correct part */
66 while (fgets(buf, sizeof(buf), map)) {
67 if (strstr(buf, "==== regions for process"))
71 while (fgets(buf, sizeof(buf), map)) {
72 char regionname[200] = "";
80 //Skip out at the end of the section
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);
86 if (w == 'w' && strstr(regionname, MYBINARYNAME)) {
87 size_t len = ((uintptr_t)end - (uintptr_t)begin) / PAGESIZE;
89 snapshot_add_memory_region(begin, len);
96 static void get_binary_name(char *buf, size_t len)
98 ssize_t size = readlink("/proc/self/exe", buf, len);
104 /* Terminate string */
105 if ((size_t)size > len)
110 /** The SnapshotGlobalSegments function computes the memory regions
111 * that may contain globals and then configures the snapshotting
112 * library to snapshot them.
114 static void SnapshotGlobalSegments()
117 char binary_name[800];
119 int map = open(MAPFILE, O_RDONLY);
124 get_binary_name(binary_name, sizeof(binary_name));
127 for(uint i=0;i<sizeof(buf);) {
128 ssize_t t=read(map, &buf[i], 1);
137 model_print("File read error.");
142 char regionname[200] = "";
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;
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);
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.
164 int SnapshotStack::backTrackBeforeStep(int seqindex)
167 for (i = (int)stack.size() - 1;i >= 0;i++)
168 if (stack[i].index <= seqindex)
174 snapshot_roll_back(stack[i].snapshotid);
175 return stack[i].index;
178 /** This method takes a snapshot at the given sequence number. */
179 void SnapshotStack::snapshotStep(int seqindex)
181 stack.push_back(snapshot_entry(take_snapshot(), seqindex));
184 void snapshot_stack_init()
186 snap_stack = new SnapshotStack();
187 SnapshotGlobalSegments();
190 void snapshot_record(int seq_index)
192 snap_stack->snapshotStep(seq_index);
195 int snapshot_backtrack_before(int seq_index)
197 return snap_stack->backTrackBeforeStep(seq_index);