17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include "snap.h"
57dd7cddfSDavid du Colombier
67dd7cddfSDavid du Colombier void
panic(char * s)77dd7cddfSDavid du Colombier panic(char *s)
87dd7cddfSDavid du Colombier {
97dd7cddfSDavid du Colombier fprint(2, "%s\n", s);
107dd7cddfSDavid du Colombier abort();
117dd7cddfSDavid du Colombier exits(s);
127dd7cddfSDavid du Colombier }
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier static Proc*
findpid(Proc * plist,long pid)157dd7cddfSDavid du Colombier findpid(Proc *plist, long pid)
167dd7cddfSDavid du Colombier {
177dd7cddfSDavid du Colombier while(plist) {
187dd7cddfSDavid du Colombier if(plist->pid == pid)
197dd7cddfSDavid du Colombier break;
207dd7cddfSDavid du Colombier plist = plist->link;
217dd7cddfSDavid du Colombier }
227dd7cddfSDavid du Colombier return plist;
237dd7cddfSDavid du Colombier }
247dd7cddfSDavid du Colombier
257dd7cddfSDavid du Colombier Page*
findpage(Proc * plist,long pid,int type,uvlong off)2650e5f38dSDavid du Colombier findpage(Proc *plist, long pid, int type, uvlong off)
277dd7cddfSDavid du Colombier {
287dd7cddfSDavid du Colombier Seg *s;
297dd7cddfSDavid du Colombier int i;
307dd7cddfSDavid du Colombier
317dd7cddfSDavid du Colombier plist = findpid(plist, pid);
327dd7cddfSDavid du Colombier if(plist == nil)
337dd7cddfSDavid du Colombier panic("can't find referenced pid");
347dd7cddfSDavid du Colombier
357dd7cddfSDavid du Colombier if(type == 't') {
367dd7cddfSDavid du Colombier if(off%Pagesize)
377dd7cddfSDavid du Colombier panic("bad text offset alignment");
387dd7cddfSDavid du Colombier s = plist->text;
397dd7cddfSDavid du Colombier if(off >= s->len)
407dd7cddfSDavid du Colombier return nil;
417dd7cddfSDavid du Colombier return s->pg[off/Pagesize];
427dd7cddfSDavid du Colombier }
437dd7cddfSDavid du Colombier
447dd7cddfSDavid du Colombier s = nil;
457dd7cddfSDavid du Colombier for(i=0; i<plist->nseg; i++) {
467dd7cddfSDavid du Colombier s = plist->seg[i];
477dd7cddfSDavid du Colombier if(s && s->offset <= off && off < s->offset+s->len)
487dd7cddfSDavid du Colombier break;
497dd7cddfSDavid du Colombier s = nil;
507dd7cddfSDavid du Colombier }
517dd7cddfSDavid du Colombier if(s == nil)
527dd7cddfSDavid du Colombier return nil;
537dd7cddfSDavid du Colombier
547dd7cddfSDavid du Colombier off -= s->offset;
557dd7cddfSDavid du Colombier if(off%Pagesize)
567dd7cddfSDavid du Colombier panic("bad mem offset alignment");
577dd7cddfSDavid du Colombier
587dd7cddfSDavid du Colombier return s->pg[off/Pagesize];
597dd7cddfSDavid du Colombier }
607dd7cddfSDavid du Colombier
6150e5f38dSDavid du Colombier static int
Breadnumber(Biobuf * b,char * buf)6250e5f38dSDavid du Colombier Breadnumber(Biobuf *b, char *buf)
6350e5f38dSDavid du Colombier {
6450e5f38dSDavid du Colombier int i;
6550e5f38dSDavid du Colombier int c;
6650e5f38dSDavid du Colombier int havedigits;
6750e5f38dSDavid du Colombier
6850e5f38dSDavid du Colombier havedigits = 0;
6950e5f38dSDavid du Colombier for(i=0; i<22; i++){
7050e5f38dSDavid du Colombier if((c = Bgetc(b)) == Beof)
7150e5f38dSDavid du Colombier return -1;
7250e5f38dSDavid du Colombier if('0' <= c && c <= '9'){
7350e5f38dSDavid du Colombier *buf++ = c;
7450e5f38dSDavid du Colombier havedigits = 1;
7550e5f38dSDavid du Colombier }else if(c == ' '){
7650e5f38dSDavid du Colombier if(havedigits){
7750e5f38dSDavid du Colombier while((c = Bgetc(b)) == ' ')
7850e5f38dSDavid du Colombier ;
7950e5f38dSDavid du Colombier if(c != Beof)
8050e5f38dSDavid du Colombier Bungetc(b);
8150e5f38dSDavid du Colombier break;
8250e5f38dSDavid du Colombier }
8350e5f38dSDavid du Colombier }else{
8450e5f38dSDavid du Colombier werrstr("bad character %.2ux", c);
8550e5f38dSDavid du Colombier return -1;
8650e5f38dSDavid du Colombier }
8750e5f38dSDavid du Colombier }
8850e5f38dSDavid du Colombier *buf = 0;
8950e5f38dSDavid du Colombier return 0;
9050e5f38dSDavid du Colombier }
9150e5f38dSDavid du Colombier
9250e5f38dSDavid du Colombier static int
Breadulong(Biobuf * b,ulong * x)9350e5f38dSDavid du Colombier Breadulong(Biobuf *b, ulong *x)
9450e5f38dSDavid du Colombier {
9550e5f38dSDavid du Colombier char buf[32];
9650e5f38dSDavid du Colombier
9750e5f38dSDavid du Colombier if(Breadnumber(b, buf) < 0)
9850e5f38dSDavid du Colombier return -1;
9950e5f38dSDavid du Colombier *x = strtoul(buf, 0, 0);
10050e5f38dSDavid du Colombier return 0;
10150e5f38dSDavid du Colombier }
10250e5f38dSDavid du Colombier
10350e5f38dSDavid du Colombier static int
Breaduvlong(Biobuf * b,uvlong * x)10450e5f38dSDavid du Colombier Breaduvlong(Biobuf *b, uvlong *x)
10550e5f38dSDavid du Colombier {
10650e5f38dSDavid du Colombier char buf[32];
10750e5f38dSDavid du Colombier
10850e5f38dSDavid du Colombier if(Breadnumber(b, buf) < 0)
10950e5f38dSDavid du Colombier return -1;
11050e5f38dSDavid du Colombier *x = strtoull(buf, 0, 0);
11150e5f38dSDavid du Colombier return 0;
11250e5f38dSDavid du Colombier }
11350e5f38dSDavid du Colombier
1147dd7cddfSDavid du Colombier static Data*
readdata(Biobuf * b)1157dd7cddfSDavid du Colombier readdata(Biobuf *b)
1167dd7cddfSDavid du Colombier {
1177dd7cddfSDavid du Colombier Data *d;
1187dd7cddfSDavid du Colombier char str[32];
1197dd7cddfSDavid du Colombier long len;
1207dd7cddfSDavid du Colombier
1217dd7cddfSDavid du Colombier if(Bread(b, str, 12) != 12)
1227dd7cddfSDavid du Colombier panic("can't read data hdr\n");
1237dd7cddfSDavid du Colombier
1247dd7cddfSDavid du Colombier len = atoi(str);
1257dd7cddfSDavid du Colombier d = emalloc(sizeof(*d) + len);
1267dd7cddfSDavid du Colombier if(Bread(b, d->data, len) != len)
1277dd7cddfSDavid du Colombier panic("can't read data body\n");
1287dd7cddfSDavid du Colombier d->len = len;
1297dd7cddfSDavid du Colombier return d;
1307dd7cddfSDavid du Colombier }
1317dd7cddfSDavid du Colombier
1327dd7cddfSDavid du Colombier static Seg*
readseg(Seg ** ps,Biobuf * b,Proc * plist)1337dd7cddfSDavid du Colombier readseg(Seg **ps, Biobuf *b, Proc *plist)
1347dd7cddfSDavid du Colombier {
1357dd7cddfSDavid du Colombier Seg *s;
1367dd7cddfSDavid du Colombier Page **pp;
1377dd7cddfSDavid du Colombier int i, npg;
1387dd7cddfSDavid du Colombier int t;
139*35393782SDavid du Colombier int n, len;
14050e5f38dSDavid du Colombier ulong pid;
14150e5f38dSDavid du Colombier uvlong off;
1427dd7cddfSDavid du Colombier char buf[Pagesize];
1437dd7cddfSDavid du Colombier static char zero[Pagesize];
1447dd7cddfSDavid du Colombier
1457dd7cddfSDavid du Colombier s = emalloc(sizeof *s);
14650e5f38dSDavid du Colombier if(Breaduvlong(b, &s->offset) < 0
14750e5f38dSDavid du Colombier || Breaduvlong(b, &s->len) < 0)
1487dd7cddfSDavid du Colombier panic("error reading segment");
1497dd7cddfSDavid du Colombier
1507dd7cddfSDavid du Colombier npg = (s->len + Pagesize-1)/Pagesize;
1517dd7cddfSDavid du Colombier s->npg = npg;
1527dd7cddfSDavid du Colombier
1533ff48bf5SDavid du Colombier if(s->npg == 0)
1543ff48bf5SDavid du Colombier return s;
1553ff48bf5SDavid du Colombier
1567dd7cddfSDavid du Colombier pp = emalloc(sizeof(*pp)*npg);
1577dd7cddfSDavid du Colombier s->pg = pp;
1587dd7cddfSDavid du Colombier *ps = s;
1597dd7cddfSDavid du Colombier
1607dd7cddfSDavid du Colombier len = Pagesize;
1617dd7cddfSDavid du Colombier for(i=0; i<npg; i++) {
1627dd7cddfSDavid du Colombier if(i == npg-1)
1637dd7cddfSDavid du Colombier len = s->len - i*Pagesize;
1647dd7cddfSDavid du Colombier
1657dd7cddfSDavid du Colombier switch(t = Bgetc(b)) {
1667dd7cddfSDavid du Colombier case 'z':
1677dd7cddfSDavid du Colombier pp[i] = datapage(zero, len);
1689a747e4fSDavid du Colombier if(debug)
16950e5f38dSDavid du Colombier fprint(2, "0x%.8llux all zeros\n", s->offset+i*Pagesize);
1707dd7cddfSDavid du Colombier break;
1717dd7cddfSDavid du Colombier case 'm':
1727dd7cddfSDavid du Colombier case 't':
17350e5f38dSDavid du Colombier if(Breadulong(b, &pid) < 0
17450e5f38dSDavid du Colombier || Breaduvlong(b, &off) < 0)
17550e5f38dSDavid du Colombier panic("error reading segment x");
1767dd7cddfSDavid du Colombier pp[i] = findpage(plist, pid, t, off);
1777dd7cddfSDavid du Colombier if(pp[i] == nil)
1787dd7cddfSDavid du Colombier panic("bad page reference in snapshot");
1799a747e4fSDavid du Colombier if(debug)
18050e5f38dSDavid du Colombier fprint(2, "0x%.8llux same as %s pid %lud 0x%.8llux\n", s->offset+i*Pagesize, t=='m'?"mem":"text", pid, off);
1817dd7cddfSDavid du Colombier break;
1827dd7cddfSDavid du Colombier case 'r':
183*35393782SDavid du Colombier if((n=Bread(b, buf, len)) != len)
184*35393782SDavid du Colombier sysfatal("short read of segment %d/%d at %llx: %r", n, len, Boffset(b));
1857dd7cddfSDavid du Colombier pp[i] = datapage(buf, len);
1869a747e4fSDavid du Colombier if(debug)
18750e5f38dSDavid du Colombier fprint(2, "0x%.8llux is raw data\n", s->offset+i*Pagesize);
1887dd7cddfSDavid du Colombier break;
1897dd7cddfSDavid du Colombier default:
19050e5f38dSDavid du Colombier fprint(2, "bad type char %#.2ux\n", t);
1917dd7cddfSDavid du Colombier panic("error reading segment");
1927dd7cddfSDavid du Colombier }
1937dd7cddfSDavid du Colombier }
1947dd7cddfSDavid du Colombier return s;
1957dd7cddfSDavid du Colombier }
1967dd7cddfSDavid du Colombier
1977dd7cddfSDavid du Colombier Proc*
readsnap(Biobuf * b)1987dd7cddfSDavid du Colombier readsnap(Biobuf *b)
1997dd7cddfSDavid du Colombier {
2007dd7cddfSDavid du Colombier char *q;
2017dd7cddfSDavid du Colombier char buf[12];
2027dd7cddfSDavid du Colombier long pid;
2037dd7cddfSDavid du Colombier Proc *p, *plist;
2047dd7cddfSDavid du Colombier int i, n;
2057dd7cddfSDavid du Colombier
2067dd7cddfSDavid du Colombier if((q = Brdline(b, '\n')) == nil)
2077dd7cddfSDavid du Colombier panic("error reading snapshot file");
2087dd7cddfSDavid du Colombier if(strncmp(q, "process snapshot", strlen("process snapshot")) != 0)
2097dd7cddfSDavid du Colombier panic("bad snapshot file format");
2107dd7cddfSDavid du Colombier
2117dd7cddfSDavid du Colombier plist = nil;
2127dd7cddfSDavid du Colombier while(q = Brdline(b, '\n')) {
2137dd7cddfSDavid du Colombier q[Blinelen(b)-1] = 0;
2147dd7cddfSDavid du Colombier pid = atol(q);
2157dd7cddfSDavid du Colombier q += 12;
2167dd7cddfSDavid du Colombier p = findpid(plist, pid);
2177dd7cddfSDavid du Colombier if(p == nil) {
2187dd7cddfSDavid du Colombier p = emalloc(sizeof(*p));
2197dd7cddfSDavid du Colombier p->link = plist;
2207dd7cddfSDavid du Colombier p->pid = pid;
2217dd7cddfSDavid du Colombier plist = p;
2227dd7cddfSDavid du Colombier }
2237dd7cddfSDavid du Colombier
2247dd7cddfSDavid du Colombier for(i=0; i<Npfile; i++) {
2257dd7cddfSDavid du Colombier if(strcmp(pfile[i], q) == 0) {
2267dd7cddfSDavid du Colombier p->d[i] = readdata(b);
2277dd7cddfSDavid du Colombier break;
2287dd7cddfSDavid du Colombier }
2297dd7cddfSDavid du Colombier }
2307dd7cddfSDavid du Colombier if(i != Npfile)
2317dd7cddfSDavid du Colombier continue;
2327dd7cddfSDavid du Colombier if(strcmp(q, "mem") == 0) {
2337dd7cddfSDavid du Colombier if(Bread(b, buf, 12) != 12)
2347dd7cddfSDavid du Colombier panic("can't read memory section");
2357dd7cddfSDavid du Colombier n = atoi(buf);
2367dd7cddfSDavid du Colombier p->nseg = n;
2377dd7cddfSDavid du Colombier p->seg = emalloc(n*sizeof(*p->seg));
2387dd7cddfSDavid du Colombier for(i=0; i<n; i++)
2397dd7cddfSDavid du Colombier readseg(&p->seg[i], b, plist);
2407dd7cddfSDavid du Colombier } else if(strcmp(q, "text") == 0)
2417dd7cddfSDavid du Colombier readseg(&p->text, b, plist);
2427dd7cddfSDavid du Colombier else
2437dd7cddfSDavid du Colombier panic("unknown section");
2447dd7cddfSDavid du Colombier }
2457dd7cddfSDavid du Colombier return plist;
2467dd7cddfSDavid du Colombier }
247