123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- #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, 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; 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 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; 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%.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; 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;
- }
|