read.c 4.7 KB

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