#include #include #include #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, ulong 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; inseg; 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 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 len; ulong pid, off; char buf[Pagesize]; static char zero[Pagesize]; s = emalloc(sizeof *s); if(Bread(b, buf, 2*12) != 2*12) panic("error reading segment"); s->offset = atoi(buf); s->len = atoi(buf+12); 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; ilen - i*Pagesize; switch(t = Bgetc(b)) { case 'z': pp[i] = datapage(zero, len); if(debug) fprint(2, "0x%.8lux all zeros\n", s->offset+i*Pagesize); break; case 'm': case 't': if(Bread(b, buf, 2*12) != 2*12) panic("error reading segment"); pid = atol(buf); off = atol(buf+12); pp[i] = findpage(plist, pid, t, off); if(pp[i] == nil) panic("bad page reference in snapshot"); if(debug) fprint(2, "0x%.8lux same as %s pid %lud 0x%.8lux\n", s->offset+i*Pagesize, t=='m'?"mem":"text", pid, off); break; case 'r': if(Bread(b, buf, len) != len) panic("error reading segment"); pp[i] = datapage(buf, len); if(debug) fprint(2, "0x%.8lux is raw data\n", s->offset+i*Pagesize); break; default: 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; id[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; iseg[i], b, plist); } else if(strcmp(q, "text") == 0) readseg(&p->text, b, plist); else panic("unknown section"); } return plist; }