diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/snap |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/snap')
-rwxr-xr-x | sys/src/cmd/snap/mkfile | 22 | ||||
-rwxr-xr-x | sys/src/cmd/snap/read.c | 246 | ||||
-rwxr-xr-x | sys/src/cmd/snap/snap.c | 65 | ||||
-rwxr-xr-x | sys/src/cmd/snap/snap.h | 66 | ||||
-rwxr-xr-x | sys/src/cmd/snap/snapfs.c | 191 | ||||
-rwxr-xr-x | sys/src/cmd/snap/take.c | 295 | ||||
-rwxr-xr-x | sys/src/cmd/snap/util.c | 39 | ||||
-rwxr-xr-x | sys/src/cmd/snap/write.c | 82 |
8 files changed, 1006 insertions, 0 deletions
diff --git a/sys/src/cmd/snap/mkfile b/sys/src/cmd/snap/mkfile new file mode 100755 index 000000000..78835b215 --- /dev/null +++ b/sys/src/cmd/snap/mkfile @@ -0,0 +1,22 @@ +</$objtype/mkfile +BIN=/$objtype/bin + +TARG=snap snapfs +OFILES=\ + read.$O\ + take.$O\ + util.$O\ + write.$O\ + +HFILES=snap.h + +UPDATE=\ + mkfile\ + $HFILES\ + ${OFILES:%.$O=%.c}\ + ${TARG:%=%.c}\ + ${TARG:%=/386/bin/%}\ + +LIB=/$objtype/lib/lib9p.a + +</sys/src/cmd/mkmany diff --git a/sys/src/cmd/snap/read.c b/sys/src/cmd/snap/read.c new file mode 100755 index 000000000..961781807 --- /dev/null +++ b/sys/src/cmd/snap/read.c @@ -0,0 +1,246 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include "snap.h" + +void +panic(char *s) +{ + fprint(2, "%s\n", s); + abort(); + exits(s); +} + +static Proc* +findpid(Proc *plist, long pid) +{ + while(plist) { + if(plist->pid == pid) + break; + plist = plist->link; + } + return plist; +} + +Page* +findpage(Proc *plist, long pid, int type, uvlong off) +{ + Seg *s; + int i; + + plist = findpid(plist, pid); + if(plist == nil) + panic("can't find referenced pid"); + + if(type == 't') { + if(off%Pagesize) + panic("bad text offset alignment"); + s = plist->text; + if(off >= s->len) + return nil; + return s->pg[off/Pagesize]; + } + + s = nil; + for(i=0; i<plist->nseg; i++) { + s = plist->seg[i]; + if(s && s->offset <= off && off < s->offset+s->len) + break; + s = nil; + } + if(s == nil) + return nil; + + off -= s->offset; + if(off%Pagesize) + panic("bad mem offset alignment"); + + return s->pg[off/Pagesize]; +} + +static int +Breadnumber(Biobuf *b, char *buf) +{ + int i; + int c; + int havedigits; + + havedigits = 0; + for(i=0; i<22; i++){ + if((c = Bgetc(b)) == Beof) + return -1; + if('0' <= c && c <= '9'){ + *buf++ = c; + havedigits = 1; + }else if(c == ' '){ + if(havedigits){ + while((c = Bgetc(b)) == ' ') + ; + if(c != Beof) + Bungetc(b); + break; + } + }else{ + werrstr("bad character %.2ux", c); + return -1; + } + } + *buf = 0; + return 0; +} + +static int +Breadulong(Biobuf *b, ulong *x) +{ + char buf[32]; + + if(Breadnumber(b, buf) < 0) + return -1; + *x = strtoul(buf, 0, 0); + return 0; +} + +static int +Breaduvlong(Biobuf *b, uvlong *x) +{ + char buf[32]; + + if(Breadnumber(b, buf) < 0) + return -1; + *x = strtoull(buf, 0, 0); + return 0; +} + +static Data* +readdata(Biobuf *b) +{ + Data *d; + char str[32]; + long len; + + if(Bread(b, str, 12) != 12) + panic("can't read data hdr\n"); + + len = atoi(str); + d = emalloc(sizeof(*d) + len); + if(Bread(b, d->data, len) != len) + panic("can't read data body\n"); + d->len = len; + return d; +} + +static Seg* +readseg(Seg **ps, Biobuf *b, Proc *plist) +{ + Seg *s; + Page **pp; + int i, npg; + int t; + int n, len; + ulong pid; + uvlong off; + char buf[Pagesize]; + static char zero[Pagesize]; + + s = emalloc(sizeof *s); + if(Breaduvlong(b, &s->offset) < 0 + || Breaduvlong(b, &s->len) < 0) + panic("error reading segment"); + + npg = (s->len + Pagesize-1)/Pagesize; + s->npg = npg; + + if(s->npg == 0) + return s; + + pp = emalloc(sizeof(*pp)*npg); + s->pg = pp; + *ps = s; + + len = Pagesize; + for(i=0; i<npg; i++) { + if(i == npg-1) + len = s->len - i*Pagesize; + + switch(t = Bgetc(b)) { + case 'z': + pp[i] = datapage(zero, len); + if(debug) + fprint(2, "0x%.8llux all zeros\n", s->offset+i*Pagesize); + break; + case 'm': + case 't': + if(Breadulong(b, &pid) < 0 + || Breaduvlong(b, &off) < 0) + panic("error reading segment x"); + pp[i] = findpage(plist, pid, t, off); + if(pp[i] == nil) + panic("bad page reference in snapshot"); + if(debug) + fprint(2, "0x%.8llux same as %s pid %lud 0x%.8llux\n", s->offset+i*Pagesize, t=='m'?"mem":"text", pid, off); + break; + case 'r': + if((n=Bread(b, buf, len)) != len) + sysfatal("short read of segment %d/%d at %llx: %r", n, len, Boffset(b)); + pp[i] = datapage(buf, len); + if(debug) + fprint(2, "0x%.8llux is raw data\n", s->offset+i*Pagesize); + break; + default: + fprint(2, "bad type char %#.2ux\n", t); + panic("error reading segment"); + } + } + return s; +} + +Proc* +readsnap(Biobuf *b) +{ + char *q; + char buf[12]; + long pid; + Proc *p, *plist; + int i, n; + + if((q = Brdline(b, '\n')) == nil) + panic("error reading snapshot file"); + if(strncmp(q, "process snapshot", strlen("process snapshot")) != 0) + panic("bad snapshot file format"); + + plist = nil; + while(q = Brdline(b, '\n')) { + q[Blinelen(b)-1] = 0; + pid = atol(q); + q += 12; + p = findpid(plist, pid); + if(p == nil) { + p = emalloc(sizeof(*p)); + p->link = plist; + p->pid = pid; + plist = p; + } + + for(i=0; i<Npfile; i++) { + if(strcmp(pfile[i], q) == 0) { + p->d[i] = readdata(b); + break; + } + } + if(i != Npfile) + continue; + if(strcmp(q, "mem") == 0) { + if(Bread(b, buf, 12) != 12) + panic("can't read memory section"); + n = atoi(buf); + p->nseg = n; + p->seg = emalloc(n*sizeof(*p->seg)); + for(i=0; i<n; i++) + readseg(&p->seg[i], b, plist); + } else if(strcmp(q, "text") == 0) + readseg(&p->text, b, plist); + else + panic("unknown section"); + } + return plist; +} diff --git a/sys/src/cmd/snap/snap.c b/sys/src/cmd/snap/snap.c new file mode 100755 index 000000000..16912be34 --- /dev/null +++ b/sys/src/cmd/snap/snap.c @@ -0,0 +1,65 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include "snap.h" + +void +usage(void) +{ + fprint(2, "usage: %s [-o snapfile] pid...\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char *user, *sys, *arch, *term, *ofile; + int i; + long pid, me; + Biobuf *b; + Dir *d; + Proc *p; + + ofile = "/fd/1"; + ARGBEGIN{ + case 'o': + ofile = ARGF(); + break; + default: + usage(); + }ARGEND; + + if(argc < 1) + usage(); + + /* get kernel compilation time */ + if((d = dirstat("#/")) == nil) { + fprint(2, "cannot stat #/ ???\n"); + exits("stat"); + } + + if((b = Bopen(ofile, OWRITE)) == nil) { + fprint(2, "cannot write to \"%s\"\n", ofile); + exits("Bopen"); + } + + if((user = getuser()) == nil) + user = "gre"; + if((sys = sysname()) == nil) + sys = "gnot"; + if((arch = getenv("cputype")) == nil) + arch = "unknown"; + if((term = getenv("terminal")) == nil) + term = "unknown terminal type"; + + Bprint(b, "process snapshot %ld %s@%s %s %ld \"%s\"\n", + time(0), user, sys, arch, d->mtime, term); + me = getpid(); + for(i=0; i<argc; i++) { + if((pid = atol(argv[i])) == me) + fprint(2, "warning: will not snapshot self\n"); + else if(p = snap(pid, 1)) + writesnap(b, p); + } + exits(0); +} diff --git a/sys/src/cmd/snap/snap.h b/sys/src/cmd/snap/snap.h new file mode 100755 index 000000000..cc50b8a38 --- /dev/null +++ b/sys/src/cmd/snap/snap.h @@ -0,0 +1,66 @@ +typedef struct Data Data; +typedef struct Page Page; +typedef struct Proc Proc; +typedef struct Seg Seg; + +enum { + Psegment = 0, + Pfd, + Pfpregs, + Pkregs, + Pnoteid, + Pns, + Pproc, + Pregs, + Pstatus, + Npfile, + + Pagesize = 1024, /* need not relate to kernel */ +}; + +struct Data { + ulong len; + char data[1]; +}; + +struct Seg { + char* name; + uvlong offset; + uvlong len; + Page** pg; + int npg; +}; + +struct Page { + Page* link; + ulong len; + char* data; + + /* when page is written, these hold the ptr to it */ + int written; + int type; + ulong pid; + uvlong offset; +}; + +struct Proc { + Proc *link; + long pid; + Data* d[Npfile]; + Seg** seg; /* memory segments */ + int nseg; + Seg* text; /* text file */ +}; + +extern char *pfile[Npfile]; + +Proc* snap(long pid, int usetext); +void* emalloc(ulong); +void* erealloc(void*, ulong); +char* estrdup(char*); +void writesnap(Biobuf*, Proc*); +Page* datapage(char *p, long len); +Proc* readsnap(Biobuf *b); +Page* findpage(Proc *plist, long pid, int type, uvlong off); + +int debug; diff --git a/sys/src/cmd/snap/snapfs.c b/sys/src/cmd/snap/snapfs.c new file mode 100755 index 000000000..d27305ae5 --- /dev/null +++ b/sys/src/cmd/snap/snapfs.c @@ -0,0 +1,191 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <auth.h> +#include <fcall.h> +#include <thread.h> +#include <9p.h> +#include "snap.h" + +typedef struct PD PD; +struct PD { + int isproc; + union { + Proc *p; + Data *d; + }; +}; + +PD* +PDProc(Proc *p) +{ + PD *pd; + + pd = emalloc(sizeof(*pd)); + pd->isproc = 1; + pd->p = p; + return pd; +} + +PD* +PDData(Data *d) +{ + PD *pd; + + pd = emalloc(sizeof(*pd)); + pd->isproc = 0; + pd->d = d; + return pd; +} + +void +usage(void) +{ + fprint(2, "usage: snapfs [-a] [-m mtpt] file\n"); + exits("usage"); +} + +char* +memread(Proc *p, File *f, void *buf, long *count, vlong offset) +{ + Page *pg; + int po; + + po = offset%Pagesize; + if(!(pg = findpage(p, p->pid, f->name[0], offset-po))) + return "address not mapped"; + + if(*count > Pagesize-po) + *count = Pagesize-po; + + memmove(buf, pg->data+po, *count); + return nil; +} + +char* +dataread(Data *d, void *buf, long *count, vlong offset) +{ + assert(d != nil); + + if(offset >= d->len) { + *count = 0; + return nil; + } + + if(offset+*count >= d->len) + *count = d->len - offset; + + memmove(buf, d->data+offset, *count); + return nil; +} + +void +fsread(Req *r) +{ + char *e; + PD *pd; + Fid *fid; + void *data; + vlong offset; + long count; + + fid = r->fid; + data = r->ofcall.data; + offset = r->ifcall.offset; + count = r->ifcall.count; + pd = fid->file->aux; + + if(pd->isproc) + e = memread(pd->p, fid->file, data, &count, offset); + else + e = dataread(pd->d, data, &count, offset); + + if(e == nil) + r->ofcall.count = count; + respond(r, e); +} + +Srv fs = { + .read = fsread, +}; + +File* +ecreatefile(File *a, char *b, char *c, ulong d, void *e) +{ + File *f; + + f = createfile(a, b, c, d, e); + if(f == nil) + sysfatal("error creating snap tree: %r"); + return f; +} + +void +main(int argc, char **argv) +{ + Biobuf *b; + Data *d; + File *fdir, *f; + Proc *p, *plist; + Tree *tree; + char *mtpt, buf[32]; + int i, mflag; + + mtpt = "/proc"; + mflag = MBEFORE; + + ARGBEGIN{ + case 'D': + chatty9p++; + break; + case 'd': + debug = 1; + break; + case 'a': + mflag = MAFTER; + break; + case 'm': + mtpt = ARGF(); + break; + default: + usage(); + }ARGEND + + if(argc != 1) + usage(); + + b = Bopen(argv[0], OREAD); + if(b == nil) { + fprint(2, "cannot open \"%s\": %r\n", argv[0]); + exits("Bopen"); + } + + if((plist = readsnap(b)) == nil) { + fprint(2, "readsnap fails\n"); + exits("readsnap"); + } + + tree = alloctree(nil, nil, DMDIR|0555, nil); + fs.tree = tree; + + for(p=plist; p; p=p->link) { + print("process %ld %.*s\n", p->pid, 28, p->d[Pstatus] ? p->d[Pstatus]->data : ""); + + snprint(buf, sizeof buf, "%ld", p->pid); + fdir = ecreatefile(tree->root, buf, nil, DMDIR|0555, nil); + ecreatefile(fdir, "ctl", nil, 0777, nil); + if(p->text) + ecreatefile(fdir, "text", nil, 0777, PDProc(p)); + + ecreatefile(fdir, "mem", nil, 0666, PDProc(p)); + for(i=0; i<Npfile; i++) { + if(d = p->d[i]) { + f = ecreatefile(fdir, pfile[i], nil, 0666, PDData(d)); + f->length = d->len; + } + } + } + + postmountsrv(&fs, nil, mtpt, mflag); + exits(0); +} diff --git a/sys/src/cmd/snap/take.c b/sys/src/cmd/snap/take.c new file mode 100755 index 000000000..bea32bf2a --- /dev/null +++ b/sys/src/cmd/snap/take.c @@ -0,0 +1,295 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#include "snap.h" + +/* research 16-bit crc. good enough. */ +static ulong +sumr(ulong sum, void *buf, int n) +{ + uchar *s, *send; + + if(buf == 0) + return sum; + for(s=buf, send=s+n; s<send; s++) + if(sum & 1) + sum = 0xffff & ((sum>>1)+*s+0x8000); + else + sum = 0xffff & ((sum>>1)+*s); + return sum; +} + +static int npage; +static Page *pgtab[1<<10]; + +Page* +datapage(char *p, long len) +{ + Page *pg; + char *q, *ep; + long sum; + int iszero; + + if(len > Pagesize) { + fprint(2, "datapage cannot handle pages > 1024\n"); + exits("datapage"); + } + + sum = sumr(0, p, len) & (nelem(pgtab)-1); + if(sum == 0) { + iszero = 1; + for(q=p, ep=p+len; q<ep; q++) + if(*q != 0) { + iszero = 0; + break; + } + } else + iszero = 0; + + for(pg = pgtab[sum]; pg; pg=pg->link) + if(pg->len == len && memcmp(pg->data, p, len) == 0) + break; + if(pg) + return pg; + + pg = emalloc(sizeof(*pg)+len); + pg->data = (char*)&pg[1]; + pg->type = 0; + pg->len = len; + memmove(pg->data, p, len); + pg->link = pgtab[sum]; + pgtab[sum] = pg; + if(iszero) { + pg->type = 'z'; + pg->written = 1; + } + + ++npage; + return pg; +} + +static Data* +readsection(long pid, char *sec) +{ + char buf[8192]; + int n, fd; + int hdr, tot; + Data *d = nil; + + snprint(buf, sizeof buf, "/proc/%ld/%s", pid, sec); + if((fd = open(buf, OREAD)) < 0) + return nil; + + tot = 0; + hdr = (int)((Data*)0)->data; + while((n = read(fd, buf, sizeof buf)) > 0) { + d = erealloc(d, tot+n+hdr); + memmove(d->data+tot, buf, n); + tot += n; + } + close(fd); + if(d == nil) + return nil; + d->len = tot; + return d; +} + +static Seg* +readseg(int fd, vlong off, ulong len, char *name) +{ + char buf[Pagesize]; + Page **pg; + int npg; + Seg *s; + ulong i; + int n; + + s = emalloc(sizeof(*s)); + s->name = estrdup(name); + + if(seek(fd, off, 0) < 0) { + fprint(2, "seek fails\n"); + goto Die; + } + + pg = nil; + npg = 0; + for(i=0; i<len; ) { + n = Pagesize; + if(n > len-i) + n = len-i; + if((n = readn(fd, buf, n)) <= 0) + break; + pg = erealloc(pg, sizeof(*pg)*(npg+1)); + pg[npg++] = datapage(buf, n); + i += n; + if(n != Pagesize) /* any short read, planned or otherwise */ + break; + } + + if(i==0 && len!=0) + goto Die; + + s->offset = off; + s->len = i; + s->pg = pg; + s->npg = npg; + return s; + +Die: + free(s->name); + free(s); + return nil; +} + +/* discover the stack pointer of the given process */ +ulong +stackptr(Proc *proc, int fd) +{ + char *q; + Fhdr f; + Reglist *r; + long textoff; + int i; + Data *dreg; + + textoff = -1; + for(i=0; i<proc->nseg; i++) + if(proc->seg[i] && strcmp(proc->seg[i]->name, "Text") == 0) + textoff = proc->seg[i]->offset; + + if(textoff == -1) + return 0; + + seek(fd, textoff, 0); + if(crackhdr(fd, &f) == 0) + return 0; + + machbytype(f.type); + for(r=mach->reglist; r->rname; r++) + if(strcmp(r->rname, mach->sp) == 0) + break; + if(r == nil) { + fprint(2, "couldn't find stack pointer register?\n"); + return 0; + } + + if((dreg = proc->d[Pregs]) == nil) + return 0; + + if(r->roffs+mach->szreg > dreg->len) { + fprint(2, "SP register too far into registers?\n"); + return 0; + } + + q = dreg->data+r->roffs; + switch(mach->szreg) { + case 2: return machdata->swab(*(ushort*)q); + case 4: return machdata->swal(*(ulong*)q); + case 8: return machdata->swav(*(uvlong*)q); + default: + fprint(2, "register size is %d bytes?\n", mach->szreg); + return 0; + } +} + +Proc* +snap(long pid, int usetext) +{ + Data *d; + Proc *proc; + Seg **s; + char *name, *segdat, *q, *f[128+1], buf[128]; + int fd, i, stacki, nf, np; + uvlong off, len, stackoff, stacklen; + uvlong sp; + + proc = emalloc(sizeof(*proc)); + proc->pid = pid; + + np = 0; + for(i=0; i<Npfile; i++) { + if(proc->d[i] = readsection(pid, pfile[i])) + np++; + else + fprint(2, "warning: can't include /proc/%ld/%s\n", pid, pfile[i]); + } + if(np == 0) + return nil; + + if(usetext) { + snprint(buf, sizeof buf, "/proc/%ld/text", pid); + if((fd = open(buf, OREAD)) >= 0) { + werrstr(""); + if((proc->text = readseg(fd, 0, 1<<31, "textfile")) == nil) + fprint(2, "warning: can't include %s: %r\n", buf); + close(fd); + } else + fprint(2, "warning: can't include /proc/%ld/text\n", pid); + } + + if((d=proc->d[Psegment]) == nil) { + fprint(2, "warning: no segment table, no memory image\n"); + return proc; + } + + segdat = emalloc(d->len+1); + memmove(segdat, d->data, d->len); + segdat[d->len] = 0; + + nf = getfields(segdat, f, nelem(f), 1, "\n"); + if(nf == nelem(f)) { + nf--; + fprint(2, "process %ld has >%d segments; only using first %d\n", + pid, nf, nf); + } + if(nf <= 0) { + fprint(2, "warning: couldn't understand segment table, no memory image\n"); + free(segdat); + return proc; + } + + snprint(buf, sizeof buf, "/proc/%ld/mem", pid); + if((fd = open(buf, OREAD)) < 0) { + fprint(2, "warning: can't include /proc/%ld/mem\n", pid); + return proc; + } + + s = emalloc(nf*sizeof(*s)); + stacklen = 0; + stackoff = 0; + stacki = 0; + for(i=0; i<nf; i++) { + if(q = strchr(f[i], ' ')) + *q = 0; + name = f[i]; + off = strtoull(name+10, &q, 16); + len = strtoull(q, &q, 16) - off; + if(strcmp(name, "Stack") == 0) { + stackoff = off; + stacklen = len; + stacki = i; + } else + s[i] = readseg(fd, off, len, name); + } + proc->nseg = nf; + proc->seg = s; + + /* stack hack: figure sp so don't need to page in the whole segment */ + if(stacklen) { + sp = stackptr(proc, fd); + if(stackoff <= sp && sp < stackoff+stacklen) { + off = (sp - Pagesize) & ~(Pagesize - 1); + if(off < stackoff) + off = stackoff; + len = stacklen - (off - stackoff); + } else { /* stack pointer not in segment. thread library? */ + off = stackoff + stacklen - 16*1024; + len = 16*1024; + } + s[stacki] = readseg(fd, off, len, "Stack"); + } + + return proc; +} diff --git a/sys/src/cmd/snap/util.c b/sys/src/cmd/snap/util.c new file mode 100755 index 000000000..bfca991ed --- /dev/null +++ b/sys/src/cmd/snap/util.c @@ -0,0 +1,39 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include "snap.h" + +void* +emalloc(ulong n) +{ + void *v; + v = malloc(n); + if(v == nil){ + fprint(2, "out of memory\n"); + exits("memory"); + } + memset(v, 0, n); + return v; +} + +void* +erealloc(void *v, ulong n) +{ + v = realloc(v, n); + if(v == nil) { + fprint(2, "out of memory\n"); + exits("memory"); + } + return v; +} + +char* +estrdup(char *s) +{ + s = strdup(s); + if(s == nil) { + fprint(2, "out of memory\n"); + exits("memory"); + } + return s; +} diff --git a/sys/src/cmd/snap/write.c b/sys/src/cmd/snap/write.c new file mode 100755 index 000000000..2cbb1e5c0 --- /dev/null +++ b/sys/src/cmd/snap/write.c @@ -0,0 +1,82 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include "snap.h" + +char *pfile[Npfile] = { + [Psegment] "segment", + [Pfd] "fd", + [Pfpregs] "fpregs", + [Pnoteid] "noteid", + [Pkregs] "kregs", + [Pns] "ns", + [Pproc] "proc", + [Pregs] "regs", + [Pstatus] "status", +}; + +static void +writeseg(Biobuf *b, Proc *proc, Seg *s) +{ + int i, npg; + Page **pp, *p; + int type; + + if(s == nil){ + Bprint(b, "%-11ud %-11ud ", 0, 0); + return; + } + + type = proc->text == s ? 't' : 'm'; + npg = (s->len+Pagesize-1)/Pagesize; + if(npg != s->npg) + abort(); + + Bprint(b, "%-11llud %-11llud ", s->offset, s->len); + if(s->len == 0) + return; + + for(i=0, pp=s->pg, p=*pp; i<npg; i++, pp++, p=*pp) { + if(p->written) { + if(p->type == 'z') { + Bprint(b, "z"); + continue; + } + Bprint(b, "%c%-11ld %-11llud ", p->type, p->pid, p->offset); + } else { + Bprint(b, "r"); + Bwrite(b, p->data, p->len); + if(p->len != Pagesize && i != npg-1) + abort(); + p->written = 1; + p->type = type; + p->offset = s->offset + i*Pagesize; + p->pid = proc->pid; + } + } +} + + +void +writesnap(Biobuf *b, Proc *p) +{ + int i, n; + Data *d; + + for(i=0; i<Npfile; i++) + if(d = p->d[i]) { + Bprint(b, "%-11ld %s\n%-11lud ", p->pid, pfile[i], d->len); + Bwrite(b, d->data, d->len); + } + + if(p->text) { + Bprint(b, "%-11ld text\n", p->pid); + writeseg(b, p, p->text); + } + + if(n = p->nseg) { + Bprint(b, "%-11ld mem\n%-11d ", p->pid, n); + for(i=0; i<n; i++) + writeseg(b, p, p->seg[i]); + } +} |