read.c 4.2 KB

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