#include #include "goo.h" #include "snap.h" int pfile[] = { [Pregs] 252, [Pmem] 253, [Psegment] 254, }; int fakey[] = { [Pfpregs] 108, }; char *pname[] = { [Psegment] "segment", [Pfd] "fd", [Pfpregs] "fpregs", [Pkregs] "kregs", [Pnoteid] "noteid", [Pns] "ns", [Pproc] "proc", [Pregs] "regs", [Pstatus] "status", [Npfile] "", [Pmem] "mem", }; /* research 32-bit crc. good enough. */ static ulong sumr(ulong sum, void *buf, int n) { ushort *s, *send; if(buf == 0) return sum; for(s = buf, send = s+n/2; s < send; s++) if(sum & 1) sum = ((sum>>1)+*s+0x80000000); else sum = ((sum>>1)+*s); return sum; } static int npage; static Page *pgtab[1<<10]; static char zp[1024]; /* * hopefully we should need reread less than 5%. * otherwise our footprint will be gigabytes */ int recheck(Page *pg, char *p, long len) { int fd, r; char *buf; print("recheck!\n"); fd = aoeopen(pfile[pg->pfile]); print("recheck\n"); if(fd == -1) sysfatal("recheck: open %r"); buf = emalloc(len); if(aoepread(fd, buf, len, pg->offset) != len) sysfatal("aoereadp: short read: %r"); r = memcmp(buf, p, len); aoeclose(fd); return r; } Page* datapage(int pfile, char *p, long len, uvlong offset) { Page *pg; long sum, psum; int iszero; if(len > Pagesize) sysfatal("datapage cannot handle pages > 1024"); sum = sumr(0, p, len); if(sum == 0 && memcmp(p, zp, len) == 0) iszero = 1; else iszero = 0; psum = sum; psum &= nelem(pgtab)-1; for(pg = pgtab[psum]; pg; pg = pg->link) if(pg->len == len && pg->sum == sum) if(iszero || !recheck(pg, p, len)) return pg; // pg = emalloc(sizeof *pg+len); pg = emalloc(sizeof *pg); pg->type = 0; pg->len = len; pg->offset = offset; pg->pfile = pfile; // memmove(pg->data, p, len); pg->link = pgtab[psum]; pgtab[psum] = pg; if(iszero) { pg->type = 'z'; pg->written = 1; } ++npage; return pg; } void writeseg(Biobuf *b, Seg *s) { Bprint(&b->h, "%-11llud %-11llud ", s->offset, s->len); } void writepage(Biobuf *b, Proc *proc, Seg *s, Page *p, char *buf) { int type; type = proc->text == s ? 't' : 'm'; if(p->written){ if(p->type == 'z'){ Bprint(&b->h, "z"); return; } Bprint(&b->h, "%c%-11ld %-11llud ", p->type, p->pid, p->offset); return; } Bprint(&b->h, "r"); Bwrite(&b->h, buf, p->len); p->written = 1; p->type = type; p->pid = proc->pid; } static Data* readsection(int section) { char buf[8192]; int n, fd; int hdr, tot; Data *d; if((fd = aoeopen(pfile[section])) == -1) return 0; d = 0; tot = 0; hdr = (int)((Data*)0)->data; while((n = aoepread(fd, buf, sizeof buf, tot)) > 0) { d = erealloc(d, tot+n+hdr); memmove(d->data+tot, buf, n); tot += n; } aoeclose(fd); if(d == 0) return 0; d->len = tot; return d; } static void readwseg(Biobuf *b, Proc *proc, 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); s->offset = off; s->len = len; writeseg(b, s); // pg = emalloc((sizeof *pg*len)/Pagesize); npg = 0; for(i=0; i len-i) n = len-i; //print("aoepread(%d, %lld)\n", n, off+npg*Pagesize); if((n = aoepread(fd, buf, n, off+npg*Pagesize)) <= 0) break; pg = datapage(fd, buf, n, off+npg*Pagesize); npg++; i += n; writepage(b, proc, s, pg, buf); if(n != Pagesize) /* any short read, planned or otherwise */ break; } if(i != len) sysfatal("bad segment %s: %uld != %uld", s->name, len, i); s->pg = 0; s->npg = npg; free(s); } Proc* snapw(Biobuf *b, long pid) { Data *d; Proc *proc; Seg **s; char *name, *segdat, *q, *f[128+1]; int fd, i, nf, np; long n; uvlong off, len; shelf = pid; proc = emalloc(sizeof(*proc)); proc->pid = pid; np = 0; for(i=0; id[i] = readsection(i); if(!d){ fprint(2, "warning: can't include shelf %ld %s\n", pid, pname[i]); continue; } np++; Bprint(&b->h, "%-11ld %s\n%-11lud ", proc->pid, pname[i], d->len); Bwrite(&b->h, d->data, d->len); } /* add fakey sagments because acid pouts without */ for(i=0; ih, "%-11ld %s\n%-11lud ", proc->pid, pname[i], n); Bwrite(&b->h, q, n); free(q); } if(np == 0) return 0; if(!(d=proc->d[Psegment])) { 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, "shelf %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; } if((fd = aoeopen(pfile[Pmem])) == -1) { fprint(2, "warning: can't open memory image shelf %ld\n", pid); return proc; } Bprint(&b->h, "%-11ld mem\n%-11d ", proc->pid, nf); s = emalloc(nf*sizeof(*s)); for(i=0; inseg = nf; proc->seg = s; aoeclose(fd); return proc; }