take.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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 <mach.h>
  13. #include "snap.h"
  14. /* research 16-bit crc. good enough. */
  15. static uint32_t
  16. sumr(uint32_t sum, void *buf, int n)
  17. {
  18. uint8_t *s, *send;
  19. if(buf == 0)
  20. return sum;
  21. for(s=buf, send=s+n; s<send; s++)
  22. if(sum & 1)
  23. sum = 0xffff & ((sum>>1)+*s+0x8000);
  24. else
  25. sum = 0xffff & ((sum>>1)+*s);
  26. return sum;
  27. }
  28. static int npage;
  29. static Page *pgtab[1<<10];
  30. Page*
  31. datapage(char *p, int32_t len)
  32. {
  33. Page *pg;
  34. char *q, *ep;
  35. int32_t sum;
  36. int iszero;
  37. if(len > Pagesize) {
  38. fprint(2, "datapage cannot handle pages > 1024\n");
  39. exits("datapage");
  40. }
  41. sum = sumr(0, p, len) & (nelem(pgtab)-1);
  42. if(sum == 0) {
  43. iszero = 1;
  44. for(q=p, ep=p+len; q<ep; q++)
  45. if(*q != 0) {
  46. iszero = 0;
  47. break;
  48. }
  49. } else
  50. iszero = 0;
  51. for(pg = pgtab[sum]; pg; pg=pg->link)
  52. if(pg->len == len && memcmp(pg->data, p, len) == 0)
  53. break;
  54. if(pg)
  55. return pg;
  56. pg = emalloc(sizeof(*pg)+len);
  57. pg->data = (char*)&pg[1];
  58. pg->type = 0;
  59. pg->len = len;
  60. memmove(pg->data, p, len);
  61. pg->link = pgtab[sum];
  62. pgtab[sum] = pg;
  63. if(iszero) {
  64. pg->type = 'z';
  65. pg->written = 1;
  66. }
  67. ++npage;
  68. return pg;
  69. }
  70. static Data*
  71. readsection(int32_t pid, char *sec)
  72. {
  73. char buf[8192];
  74. int n, fd;
  75. int hdr, tot;
  76. Data *d = nil;
  77. snprint(buf, sizeof buf, "/proc/%ld/%s", pid, sec);
  78. if((fd = open(buf, OREAD)) < 0)
  79. return nil;
  80. tot = 0;
  81. hdr = (int)((Data*)0)->data;
  82. while((n = read(fd, buf, sizeof buf)) > 0) {
  83. d = erealloc(d, tot+n+hdr);
  84. memmove(d->data+tot, buf, n);
  85. tot += n;
  86. }
  87. close(fd);
  88. if(d == nil)
  89. return nil;
  90. d->len = tot;
  91. return d;
  92. }
  93. static Seg*
  94. readseg(int fd, int64_t off, uint32_t len, char *name)
  95. {
  96. char buf[Pagesize];
  97. Page **pg;
  98. int npg;
  99. Seg *s;
  100. uint32_t i;
  101. int n;
  102. s = emalloc(sizeof(*s));
  103. s->name = estrdup(name);
  104. if(seek(fd, off, 0) < 0) {
  105. fprint(2, "seek fails\n");
  106. goto Die;
  107. }
  108. pg = nil;
  109. npg = 0;
  110. for(i=0; i<len; ) {
  111. n = Pagesize;
  112. if(n > len-i)
  113. n = len-i;
  114. if((n = readn(fd, buf, n)) <= 0)
  115. break;
  116. pg = erealloc(pg, sizeof(*pg)*(npg+1));
  117. pg[npg++] = datapage(buf, n);
  118. i += n;
  119. if(n != Pagesize) /* any short read, planned or otherwise */
  120. break;
  121. }
  122. if(i==0 && len!=0)
  123. goto Die;
  124. s->offset = off;
  125. s->len = i;
  126. s->pg = pg;
  127. s->npg = npg;
  128. return s;
  129. Die:
  130. free(s->name);
  131. free(s);
  132. return nil;
  133. }
  134. /* discover the stack pointer of the given process */
  135. uint32_t
  136. stackptr(Proc *proc, int fd)
  137. {
  138. char *q;
  139. Fhdr f;
  140. Reglist *r;
  141. int32_t textoff;
  142. int i;
  143. Data *dreg;
  144. textoff = -1;
  145. for(i=0; i<proc->nseg; i++)
  146. if(proc->seg[i] && strcmp(proc->seg[i]->name, "Text") == 0)
  147. textoff = proc->seg[i]->offset;
  148. if(textoff == -1)
  149. return 0;
  150. seek(fd, textoff, 0);
  151. if(crackhdr(fd, &f) == 0)
  152. return 0;
  153. machbytype(f.type);
  154. for(r=mach->reglist; r->rname; r++)
  155. if(strcmp(r->rname, mach->sp) == 0)
  156. break;
  157. if(r == nil) {
  158. fprint(2, "couldn't find stack pointer register?\n");
  159. return 0;
  160. }
  161. if((dreg = proc->d[Pregs]) == nil)
  162. return 0;
  163. if(r->roffs+mach->szreg > dreg->len) {
  164. fprint(2, "SP register too far into registers?\n");
  165. return 0;
  166. }
  167. q = dreg->data+r->roffs;
  168. switch(mach->szreg) {
  169. case 2: return machdata->swab(*(uint16_t*)q);
  170. case 4: return machdata->swal(*(uint32_t*)q);
  171. case 8: return machdata->swav(*(uint64_t*)q);
  172. default:
  173. fprint(2, "register size is %d bytes?\n", mach->szreg);
  174. return 0;
  175. }
  176. }
  177. Proc*
  178. snap(int32_t pid, int usetext)
  179. {
  180. Data *d;
  181. Proc *proc;
  182. Seg **s;
  183. char *name, *segdat, *q, *f[128+1], buf[128];
  184. int fd, i, stacki, nf, np;
  185. uint64_t off, len, stackoff, stacklen;
  186. uint64_t sp;
  187. proc = emalloc(sizeof(*proc));
  188. proc->pid = pid;
  189. np = 0;
  190. for(i=0; i<Npfile; i++) {
  191. if(proc->d[i] = readsection(pid, pfile[i]))
  192. np++;
  193. else
  194. fprint(2, "warning: can't include /proc/%ld/%s\n", pid, pfile[i]);
  195. }
  196. if(np == 0)
  197. return nil;
  198. if(usetext) {
  199. snprint(buf, sizeof buf, "/proc/%ld/text", pid);
  200. if((fd = open(buf, OREAD)) >= 0) {
  201. werrstr("");
  202. if((proc->text = readseg(fd, 0, 1<<31, "textfile")) == nil)
  203. fprint(2, "warning: can't include %s: %r\n", buf);
  204. close(fd);
  205. } else
  206. fprint(2, "warning: can't include /proc/%ld/text\n", pid);
  207. }
  208. if((d=proc->d[Psegment]) == nil) {
  209. fprint(2, "warning: no segment table, no memory image\n");
  210. return proc;
  211. }
  212. segdat = emalloc(d->len+1);
  213. memmove(segdat, d->data, d->len);
  214. segdat[d->len] = 0;
  215. nf = getfields(segdat, f, nelem(f), 1, "\n");
  216. if(nf == nelem(f)) {
  217. nf--;
  218. fprint(2, "process %ld has >%d segments; only using first %d\n",
  219. pid, nf, nf);
  220. }
  221. if(nf <= 0) {
  222. fprint(2, "warning: couldn't understand segment table, no memory image\n");
  223. free(segdat);
  224. return proc;
  225. }
  226. snprint(buf, sizeof buf, "/proc/%ld/mem", pid);
  227. if((fd = open(buf, OREAD)) < 0) {
  228. fprint(2, "warning: can't include /proc/%ld/mem\n", pid);
  229. return proc;
  230. }
  231. s = emalloc(nf*sizeof(*s));
  232. stacklen = 0;
  233. stackoff = 0;
  234. stacki = 0;
  235. for(i=0; i<nf; i++) {
  236. if(q = strchr(f[i], ' '))
  237. *q = 0;
  238. name = f[i];
  239. off = strtoull(name+10, &q, 16);
  240. len = strtoull(q, &q, 16) - off;
  241. if(strcmp(name, "Stack") == 0) {
  242. stackoff = off;
  243. stacklen = len;
  244. stacki = i;
  245. } else
  246. s[i] = readseg(fd, off, len, name);
  247. }
  248. proc->nseg = nf;
  249. proc->seg = s;
  250. /* stack hack: figure sp so don't need to page in the whole segment */
  251. if(stacklen) {
  252. sp = stackptr(proc, fd);
  253. if(stackoff <= sp && sp < stackoff+stacklen) {
  254. off = (sp - Pagesize) & ~(Pagesize - 1);
  255. if(off < stackoff)
  256. off = stackoff;
  257. len = stacklen - (off - stackoff);
  258. } else { /* stack pointer not in segment. thread library? */
  259. off = stackoff + stacklen - 16*1024;
  260. len = 16*1024;
  261. }
  262. s[stacki] = readseg(fd, off, len, "Stack");
  263. }
  264. return proc;
  265. }