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/read.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/snap/read.c')
-rwxr-xr-x | sys/src/cmd/snap/read.c | 246 |
1 files changed, 246 insertions, 0 deletions
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; +} |