Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include "snap.h"
5
 
6
void
7
panic(char *s)
8
{
9
	fprint(2, "%s\n", s);
10
	abort();
11
	exits(s);
12
}
13
 
14
static Proc*
15
findpid(Proc *plist, long pid)
16
{
17
	while(plist) {
18
		if(plist->pid == pid)
19
			break;
20
		plist = plist->link;
21
	}
22
	return plist;
23
}
24
 
25
Page*
26
findpage(Proc *plist, long pid, int type, uvlong off)
27
{
28
	Seg *s;
29
	int i;
30
 
31
	plist = findpid(plist, pid);
32
	if(plist == nil)
33
		panic("can't find referenced pid");
34
 
35
	if(type == 't') {
36
		if(off%Pagesize)
37
			panic("bad text offset alignment");
38
		s = plist->text;
39
		if(off >= s->len)
40
			return nil;
41
		return s->pg[off/Pagesize];
42
	}
43
 
44
	s = nil;
45
	for(i=0; i<plist->nseg; i++) {
46
		s = plist->seg[i];
47
		if(s && s->offset <= off && off < s->offset+s->len)
48
			break;
49
		s = nil;
50
	}
51
	if(s == nil)
52
		return nil;
53
 
54
	off -= s->offset;
55
	if(off%Pagesize)
56
		panic("bad mem offset alignment");
57
 
58
	return s->pg[off/Pagesize];
59
}
60
 
61
static int
62
Breadnumber(Biobuf *b, char *buf)
63
{
64
	int i;
65
	int c;
66
	int havedigits;
67
 
68
	havedigits = 0;
69
	for(i=0; i<22; i++){
70
		if((c = Bgetc(b)) == Beof)
71
			return -1;
72
		if('0' <= c && c <= '9'){
73
			*buf++ = c;
74
			havedigits = 1;
75
		}else if(c == ' '){
76
			if(havedigits){
77
				while((c = Bgetc(b)) == ' ')
78
					;
79
				if(c != Beof)
80
					Bungetc(b);
81
				break;
82
			}
83
		}else{
84
			werrstr("bad character %.2ux", c);
85
			return -1;
86
		}
87
	}
88
	*buf = 0;
89
	return 0;
90
}
91
 
92
static int
93
Breadulong(Biobuf *b, ulong *x)
94
{
95
	char buf[32];
96
 
97
	if(Breadnumber(b, buf) < 0)
98
		return -1;
99
	*x = strtoul(buf, 0, 0);
100
	return 0;
101
}
102
 
103
static int
104
Breaduvlong(Biobuf *b, uvlong *x)
105
{
106
	char buf[32];
107
 
108
	if(Breadnumber(b, buf) < 0)
109
		return -1;
110
	*x = strtoull(buf, 0, 0);
111
	return 0;
112
}
113
 
114
static Data*
115
readdata(Biobuf *b)
116
{
117
	Data *d;
118
	char str[32];
119
	long len;
120
 
121
	if(Bread(b, str, 12) != 12)
122
		panic("can't read data hdr\n");
123
 
124
	len = atoi(str);
125
	d = emalloc(sizeof(*d) + len);
126
	if(Bread(b, d->data, len) != len)
127
		panic("can't read data body\n");
128
	d->len = len;
129
	return d;
130
}
131
 
132
static Seg*
133
readseg(Seg **ps, Biobuf *b, Proc *plist)
134
{
135
	Seg *s;
136
	Page **pp;
137
	int i, npg;
138
	int t;
139
	int n, len;
140
	ulong pid;
141
	uvlong off;
142
	char buf[Pagesize];
143
	static char zero[Pagesize];
144
 
145
	s = emalloc(sizeof *s);
146
	if(Breaduvlong(b, &s->offset) < 0
147
	|| Breaduvlong(b, &s->len) < 0)
148
		panic("error reading segment");
149
 
150
	npg = (s->len + Pagesize-1)/Pagesize;
151
	s->npg = npg;
152
 
153
	if(s->npg == 0)
154
		return s;
155
 
156
	pp = emalloc(sizeof(*pp)*npg);
157
	s->pg = pp;
158
	*ps = s;
159
 
160
	len = Pagesize;
161
	for(i=0; i<npg; i++) {
162
		if(i == npg-1)
163
			len = s->len - i*Pagesize;
164
 
165
		switch(t = Bgetc(b)) {
166
		case 'z':
167
			pp[i] = datapage(zero, len);
168
			if(debug)
169
				fprint(2, "0x%.8llux all zeros\n", s->offset+i*Pagesize);
170
			break;
171
		case 'm':
172
		case 't':
173
			if(Breadulong(b, &pid) < 0 
174
			|| Breaduvlong(b, &off) < 0)
175
				panic("error reading segment x");
176
			pp[i] = findpage(plist, pid, t, off);
177
			if(pp[i] == nil)
178
				panic("bad page reference in snapshot");
179
			if(debug)
180
				fprint(2, "0x%.8llux same as %s pid %lud 0x%.8llux\n", s->offset+i*Pagesize, t=='m'?"mem":"text", pid, off);
181
			break;
182
		case 'r':
183
			if((n=Bread(b, buf, len)) != len)
184
				sysfatal("short read of segment %d/%d at %llx: %r", n, len, Boffset(b));
185
			pp[i] = datapage(buf, len);
186
			if(debug)
187
				fprint(2, "0x%.8llux is raw data\n", s->offset+i*Pagesize);
188
			break;
189
		default:
190
			fprint(2, "bad type char %#.2ux\n", t);
191
			panic("error reading segment");
192
		}
193
	}
194
	return s;
195
}
196
 
197
Proc*
198
readsnap(Biobuf *b)
199
{
200
	char *q;
201
	char buf[12];
202
	long pid;
203
	Proc *p, *plist;
204
	int i, n;
205
 
206
	if((q = Brdline(b, '\n')) == nil)
207
		panic("error reading snapshot file");
208
	if(strncmp(q, "process snapshot", strlen("process snapshot")) != 0)
209
		panic("bad snapshot file format");
210
 
211
	plist = nil;
212
	while(q = Brdline(b, '\n')) {
213
		q[Blinelen(b)-1] = 0;
214
		pid = atol(q);
215
		q += 12;
216
		p = findpid(plist, pid);
217
		if(p == nil) {
218
			p = emalloc(sizeof(*p));
219
			p->link = plist;
220
			p->pid = pid;
221
			plist = p;
222
		}
223
 
224
		for(i=0; i<Npfile; i++) {
225
			if(strcmp(pfile[i], q) == 0) {
226
				p->d[i] = readdata(b);
227
				break;
228
			}
229
		}
230
		if(i != Npfile)
231
			continue;
232
		if(strcmp(q, "mem") == 0) {
233
			if(Bread(b, buf, 12) != 12) 
234
				panic("can't read memory section");
235
			n = atoi(buf);
236
			p->nseg = n;
237
			p->seg = emalloc(n*sizeof(*p->seg));
238
			for(i=0; i<n; i++)
239
				readseg(&p->seg[i], b, plist);
240
		} else if(strcmp(q, "text") == 0)
241
			readseg(&p->text, b, plist);
242
		else
243
			panic("unknown section");
244
	}
245
	return plist;
246
}