summaryrefslogtreecommitdiff
path: root/sys/src/cmd/snap/read.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/snap/read.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/snap/read.c')
-rwxr-xr-xsys/src/cmd/snap/read.c246
1 files changed, 246 insertions, 0 deletions
diff --git a/sys/src/cmd/snap/read.c b/sys/src/cmd/snap/read.c
new file mode 100755
index 000000000..961781807
--- /dev/null
+++ b/sys/src/cmd/snap/read.c
@@ -0,0 +1,246 @@
+#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, uvlong 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, ulong *x)
+{
+ char buf[32];
+
+ if(Breadnumber(b, buf) < 0)
+ return -1;
+ *x = strtoul(buf, 0, 0);
+ return 0;
+}
+
+static int
+Breaduvlong(Biobuf *b, uvlong *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];
+ 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 n, len;
+ ulong pid;
+ uvlong 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];
+ 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;
+}