Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature-vt/sys/src/cmd/snap/take.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | 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 <mach.h>
5
#include "snap.h"
6
 
7
/* research 16-bit crc.  good enough. */
8
static ulong
9
sumr(ulong sum, void *buf, int n)
10
{
11
	uchar *s, *send;
12
 
13
	if(buf == 0)
14
		return sum;
15
	for(s=buf, send=s+n; s<send; s++)
16
		if(sum & 1)
17
			sum = 0xffff & ((sum>>1)+*s+0x8000);
18
		else
19
			sum = 0xffff & ((sum>>1)+*s);
20
	return sum;
21
}
22
 
23
static int npage;
24
static Page *pgtab[1<<10];
25
 
26
Page*
27
datapage(char *p, long len)
28
{
29
	Page *pg;
30
	char *q, *ep;
31
	long	sum;
32
	int iszero;
33
 
34
	if(len > Pagesize) {
35
		fprint(2, "datapage cannot handle pages > 1024\n");
36
		exits("datapage");
37
	}
38
 
39
	sum = sumr(0, p, len) & (nelem(pgtab)-1);
40
	if(sum == 0) {
41
		iszero = 1;
42
		for(q=p, ep=p+len; q<ep; q++)
43
			if(*q != 0) {
44
				iszero = 0;
45
				break;
46
			}
47
	} else
48
		iszero = 0;
49
 
50
	for(pg = pgtab[sum]; pg; pg=pg->link)
51
		if(pg->len == len && memcmp(pg->data, p, len) == 0)
52
			break;
53
	if(pg)
54
		return pg;
55
 
56
	pg = emalloc(sizeof(*pg)+len);
57
	pg->data = (char*)&pg[1];
58
	pg->type = 0;
59
	pg->len = len;
60
	memmove(pg->data, p, len);
61
	pg->link = pgtab[sum];
62
	pgtab[sum] = pg;
63
	if(iszero) {
64
		pg->type = 'z';
65
		pg->written = 1;
66
	}
67
 
68
	++npage;
69
	return pg;
70
}
71
 
72
static Data*
73
readsection(long pid, char *sec)
74
{
75
	char buf[8192];
76
	int n, fd;
77
	int hdr, tot;
78
	Data *d = nil;
79
 
80
	snprint(buf, sizeof buf, "/proc/%ld/%s", pid, sec);
81
	if((fd = open(buf, OREAD)) < 0)
82
		return nil;
83
 
84
	tot = 0;
85
	hdr = (int)((Data*)0)->data;
86
	while((n = read(fd, buf, sizeof buf)) > 0) {
87
		d = erealloc(d, tot+n+hdr);
88
		memmove(d->data+tot, buf, n);
89
		tot += n;
90
	}
91
	close(fd);
92
	if(d == nil)
93
		return nil;
94
	d->len = tot;
95
	return d;
96
}
97
 
98
static Seg*
99
readseg(int fd, vlong off, ulong len, char *name)
100
{
101
	char buf[Pagesize];
102
	Page **pg;
103
	int npg;
104
	Seg *s;
105
	ulong i;
106
	int n;
107
 
108
	s = emalloc(sizeof(*s));
109
	s->name = estrdup(name);
110
 
111
	if(seek(fd, off, 0) < 0) {
112
		fprint(2, "seek fails\n");
113
		goto Die;
114
	}
115
 
116
	pg = nil;
117
	npg = 0;
118
	for(i=0; i<len; ) {
119
		n = Pagesize;
120
		if(n > len-i)
121
			n = len-i;
122
		if((n = readn(fd, buf, n)) <= 0)
123
			break;
124
		pg = erealloc(pg, sizeof(*pg)*(npg+1));
125
		pg[npg++] = datapage(buf, n);
126
		i += n;
127
		if(n != Pagesize)	/* any short read, planned or otherwise */
128
			break;
129
	}
130
 
131
	if(i==0 && len!=0)
132
		goto Die;
133
 
134
	s->offset = off;
135
	s->len = i;
136
	s->pg = pg;
137
	s->npg = npg;
138
	return s;
139
 
140
Die:
141
	free(s->name);
142
	free(s);
143
	return nil;
144
}
145
 
146
/* discover the stack pointer of the given process */
147
ulong
148
stackptr(Proc *proc, int fd)
149
{
150
	char *q;
151
	Fhdr f;
152
	Reglist *r;
153
	long textoff;
154
	int i;
155
	Data *dreg;
156
 
157
	textoff = -1;
158
	for(i=0; i<proc->nseg; i++)
159
		if(proc->seg[i] && strcmp(proc->seg[i]->name, "Text") == 0)
160
			textoff = proc->seg[i]->offset;
161
 
162
	if(textoff == -1)
163
		return 0;
164
 
165
	seek(fd, textoff, 0);
166
	if(crackhdr(fd, &f) == 0)
167
		return 0;
168
 
169
	machbytype(f.type);
170
	for(r=mach->reglist; r->rname; r++)
171
		if(strcmp(r->rname, mach->sp) == 0)
172
			break;
173
	if(r == nil) {
174
		fprint(2, "couldn't find stack pointer register?\n");
175
		return 0;
176
	}
177
 
178
	if((dreg = proc->d[Pregs]) == nil)
179
		return 0;
180
 
181
	if(r->roffs+mach->szreg > dreg->len) {
182
		fprint(2, "SP register too far into registers?\n");
183
		return 0;
184
	}
185
 
186
	q = dreg->data+r->roffs;
187
	switch(mach->szreg) {
188
	case 2:	return machdata->swab(*(ushort*)q);
189
	case 4:	return machdata->swal(*(ulong*)q);
190
	case 8:	return machdata->swav(*(uvlong*)q);
191
	default:
192
		fprint(2, "register size is %d bytes?\n", mach->szreg);
193
		return 0;
194
	}
195
}
196
 
197
Proc*
198
snap(long pid, int usetext)
199
{
200
	Data *d;
201
	Proc *proc;
202
	Seg **s;
203
	char *name, *segdat, *q, *f[128+1], buf[128];
204
	int fd, i, stacki, nf, np;
205
	uvlong off, len, stackoff, stacklen;
206
	uvlong sp;
207
 
208
	proc = emalloc(sizeof(*proc));
209
	proc->pid = pid;
210
 
211
	np = 0;
212
	for(i=0; i<Npfile; i++) {
213
		if(proc->d[i] = readsection(pid, pfile[i]))
214
			np++;
215
		else
216
			fprint(2, "warning: can't include /proc/%ld/%s\n", pid, pfile[i]);
217
	}
218
	if(np == 0)
219
		return nil;
220
 
221
	if(usetext) {
222
		snprint(buf, sizeof buf, "/proc/%ld/text", pid);
223
		if((fd = open(buf, OREAD)) >= 0) {
224
			werrstr("");
225
			if((proc->text = readseg(fd, 0, 1<<31, "textfile")) == nil)
226
				fprint(2, "warning: can't include %s: %r\n", buf);
227
			close(fd);
228
		} else
229
			fprint(2, "warning: can't include /proc/%ld/text\n", pid);
230
	}
231
 
232
	if((d=proc->d[Psegment]) == nil) {
233
		fprint(2, "warning: no segment table, no memory image\n");
234
		return proc;
235
	}
236
 
237
	segdat = emalloc(d->len+1);
238
	memmove(segdat, d->data, d->len);
239
	segdat[d->len] = 0;
240
 
241
	nf = getfields(segdat, f, nelem(f), 1, "\n");
242
	if(nf == nelem(f)) {
243
		nf--;
244
		fprint(2, "process %ld has >%d segments; only using first %d\n",
245
			pid, nf, nf);
246
	}
247
	if(nf <= 0) {
248
		fprint(2, "warning: couldn't understand segment table, no memory image\n");
249
		free(segdat);
250
		return proc;
251
	}
252
 
253
	snprint(buf, sizeof buf, "/proc/%ld/mem", pid);
254
	if((fd = open(buf, OREAD)) < 0) {
255
		fprint(2, "warning: can't include /proc/%ld/mem\n", pid);
256
		return proc;
257
	}
258
 
259
	s = emalloc(nf*sizeof(*s));
260
	stacklen = 0;
261
	stackoff = 0;
262
	stacki = 0;
263
	for(i=0; i<nf; i++) {
264
		if(q = strchr(f[i], ' ')) 
265
			*q = 0;
266
		name = f[i];
267
		off = strtoull(name+10, &q, 16);
268
		len = strtoull(q, &q, 16) - off;
269
		if(strcmp(name, "Stack") == 0) {
270
			stackoff = off;
271
			stacklen = len;
272
			stacki = i;
273
		} else
274
			s[i] = readseg(fd, off, len, name);
275
	}
276
	proc->nseg = nf;
277
	proc->seg = s;
278
 
279
	/* stack hack: figure sp so don't need to page in the whole segment */
280
	if(stacklen) {
281
		sp = stackptr(proc, fd);
282
		if(stackoff <= sp && sp < stackoff+stacklen) {
283
			off = (sp - Pagesize) & ~(Pagesize - 1);
284
			if(off < stackoff)
285
				off = stackoff;
286
			len = stacklen - (off - stackoff);
287
		} else {	/* stack pointer not in segment.  thread library? */
288
			off = stackoff + stacklen - 16*1024;
289
			len = 16*1024;
290
		}
291
		s[stacki] = readseg(fd, off, len, "Stack");
292
	}
293
 
294
	return proc;
295
}