123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #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, int32_t pid)
- {
- while(plist) {
- if(plist->pid == pid)
- break;
- plist = plist->link;
- }
- return plist;
- }
- Page*
- findpage(Proc *plist, int32_t pid, int type, uint64_t 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, uint32_t *x)
- {
- char buf[32];
-
- if(Breadnumber(b, buf) < 0)
- return -1;
- *x = strtoul(buf, 0, 0);
- return 0;
- }
- static int
- Breaduvlong(Biobuf *b, uint64_t *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];
- int32_t 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;
- uint32_t pid;
- uint64_t 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];
- int32_t 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;
- }
|