]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/snap/read.c
snap: consequently use ulong for page index and count
[plan9front.git] / sys / src / cmd / snap / read.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include "snap.h"
5
6 void
7 panic(char *s)
8 {
9         fprint(2, "%s\n", s);
10         abort();
11         exits(s);
12 }
13
14 static Proc*
15 findpid(Proc *plist, long pid)
16 {
17         while(plist) {
18                 if(plist->pid == pid)
19                         break;
20                 plist = plist->link;
21         }
22         return plist;
23 }
24
25 Page*
26 findpage(Proc *plist, long pid, int type, uvlong off)
27 {
28         Seg *s;
29         int i;
30
31         plist = findpid(plist, pid);
32         if(plist == nil)
33                 panic("can't find referenced pid");
34
35         if(type == 't') {
36                 if(off%Pagesize)
37                         panic("bad text offset alignment");
38                 s = plist->text;
39                 if(off >= s->len)
40                         return nil;
41                 return s->pg[off/Pagesize];
42         }
43
44         s = nil;
45         for(i=0; i<plist->nseg; i++) {
46                 s = plist->seg[i];
47                 if(s && s->offset <= off && off < s->offset+s->len)
48                         break;
49                 s = nil;
50         }
51         if(s == nil)
52                 return nil;
53
54         off -= s->offset;
55         if(off%Pagesize)
56                 panic("bad mem offset alignment");
57
58         return s->pg[off/Pagesize];
59 }
60
61 static int
62 Breadnumber(Biobuf *b, char *buf)
63 {
64         int i;
65         int c;
66         int havedigits;
67         
68         havedigits = 0;
69         for(i=0; i<22; i++){
70                 if((c = Bgetc(b)) == Beof)
71                         return -1;
72                 if('0' <= c && c <= '9'){
73                         *buf++ = c;
74                         havedigits = 1;
75                 }else if(c == ' '){
76                         if(havedigits){
77                                 while((c = Bgetc(b)) == ' ')
78                                         ;
79                                 if(c != Beof)
80                                         Bungetc(b);
81                                 break;
82                         }
83                 }else{
84                         werrstr("bad character %.2ux", c);
85                         return -1;
86                 }
87         }
88         *buf = 0;
89         return 0;
90 }
91
92 static int
93 Breadulong(Biobuf *b, ulong *x)
94 {
95         char buf[32];
96         
97         if(Breadnumber(b, buf) < 0)
98                 return -1;
99         *x = strtoul(buf, 0, 0);
100         return 0;
101 }
102
103 static int
104 Breaduvlong(Biobuf *b, uvlong *x)
105 {
106         char buf[32];
107         
108         if(Breadnumber(b, buf) < 0)
109                 return -1;
110         *x = strtoull(buf, 0, 0);
111         return 0;
112 }
113
114 static Data*
115 readdata(Biobuf *b)
116 {
117         Data *d;
118         char str[32];
119         long len;
120
121         if(Bread(b, str, 12) != 12)
122                 panic("can't read data hdr\n");
123
124         len = atoi(str);
125         d = emalloc(sizeof(*d) + len);
126         if(Bread(b, d->data, len) != len)
127                 panic("can't read data body\n");
128         d->len = len;
129         return d;
130 }
131
132 static Seg*
133 readseg(Seg **ps, Biobuf *b, Proc *plist)
134 {
135         Seg *s;
136         Page **pp;
137         int t;
138         int n, len;
139         ulong i, npg;
140         ulong pid;
141         uvlong off;
142         char buf[Pagesize];
143         static char zero[Pagesize];
144
145         s = emalloc(sizeof *s);
146         if(Breaduvlong(b, &s->offset) < 0
147         || Breaduvlong(b, &s->len) < 0)
148                 panic("error reading segment");
149
150         npg = (s->len + Pagesize-1)/Pagesize;
151         s->npg = npg;
152
153         if(s->npg == 0)
154                 return s;
155
156         pp = emalloc(sizeof(*pp)*npg);
157         s->pg = pp;
158         *ps = s;
159
160         len = Pagesize;
161         for(i=0; i<npg; i++) {
162                 if(i == npg-1)
163                         len = s->len - (uvlong)i*Pagesize;
164
165                 switch(t = Bgetc(b)) {
166                 case 'z':
167                         pp[i] = datapage(zero, len);
168                         if(debug)
169                                 fprint(2, "0x%.8llux all zeros\n", s->offset+(uvlong)i*Pagesize);
170                         break;
171                 case 'm':
172                 case 't':
173                         if(Breadulong(b, &pid) < 0 
174                         || Breaduvlong(b, &off) < 0)
175                                 panic("error reading segment x");
176                         pp[i] = findpage(plist, pid, t, off);
177                         if(pp[i] == nil)
178                                 panic("bad page reference in snapshot");
179                         if(debug)
180                                 fprint(2, "0x%.8llux same as %s pid %lud 0x%.8llux\n",
181                                         s->offset+(uvlong)i*Pagesize, t=='m'?"mem":"text", pid, off);
182                         break;
183                 case 'r':
184                         if((n=Bread(b, buf, len)) != len)
185                                 sysfatal("short read of segment %d/%d at %llx: %r", n, len, Boffset(b));
186                         pp[i] = datapage(buf, len);
187                         if(debug)
188                                 fprint(2, "0x%.8llux is raw data\n", s->offset+(uvlong)i*Pagesize);
189                         break;
190                 default:
191                         fprint(2, "bad type char %#.2ux\n", t);
192                         panic("error reading segment");
193                 }
194         }
195         return s;
196 }
197
198 Proc*
199 readsnap(Biobuf *b)
200 {
201         char *q;
202         char buf[12];
203         long pid;
204         Proc *p, *plist;
205         int i, n;
206
207         if((q = Brdline(b, '\n')) == nil)
208                 panic("error reading snapshot file");
209         if(strncmp(q, "process snapshot", strlen("process snapshot")) != 0)
210                 panic("bad snapshot file format");
211
212         plist = nil;
213         while(q = Brdline(b, '\n')) {
214                 q[Blinelen(b)-1] = 0;
215                 pid = atol(q);
216                 q += 12;
217                 p = findpid(plist, pid);
218                 if(p == nil) {
219                         p = emalloc(sizeof(*p));
220                         p->link = plist;
221                         p->pid = pid;
222                         plist = p;
223                 }
224
225                 for(i=0; i<Npfile; i++) {
226                         if(strcmp(pfile[i], q) == 0) {
227                                 p->d[i] = readdata(b);
228                                 break;
229                         }
230                 }
231                 if(i != Npfile)
232                         continue;
233                 if(strcmp(q, "mem") == 0) {
234                         if(Bread(b, buf, 12) != 12) 
235                                 panic("can't read memory section");
236                         n = atoi(buf);
237                         p->nseg = n;
238                         p->seg = emalloc(n*sizeof(*p->seg));
239                         for(i=0; i<n; i++)
240                                 readseg(&p->seg[i], b, plist);
241                 } else if(strcmp(q, "text") == 0)
242                         readseg(&p->text, b, plist);
243                 else
244                         panic("unknown section");
245         }
246         return plist;
247 }