qi.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  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 <tos.h>
  14. #define Extern
  15. #include "power.h"
  16. char *file = "q.out";
  17. int datasize;
  18. uint32_t textbase;
  19. Biobuf bp, bi;
  20. Fhdr fhdr;
  21. uint32_t bits[32];
  22. void
  23. main(int argc, char **argv)
  24. {
  25. int pid, i;
  26. argc--;
  27. argv++;
  28. bioout = &bp;
  29. bin = &bi;
  30. Binit(bioout, 1, OWRITE);
  31. Binit(bin, 0, OREAD);
  32. if(argc) {
  33. pid = atoi(argv[0]);
  34. if(pid != 0) {
  35. procinit(pid);
  36. cmd();
  37. }
  38. file = argv[0];
  39. }
  40. argc--;
  41. argv++;
  42. text = open(file, OREAD);
  43. if(text < 0)
  44. fatal(1, "open text '%s'", file);
  45. Bprint(bioout, "qi\n");
  46. inithdr(text);
  47. initstk(argc, argv);
  48. for(i=0; i<32; i++)
  49. bits[i] = 1L << (31-i);
  50. fpreginit();
  51. cmd();
  52. }
  53. /*
  54. * we're rounding segment boundaries to the nearest 1MB on power now,
  55. * and mach->pgsize is actually what to round segment boundaries up to.
  56. */
  57. #define SEGROUND mach->pgsize
  58. void
  59. initmap(void)
  60. {
  61. uint32_t t, d, b, bssend;
  62. Segment *s;
  63. t = (fhdr.txtaddr+fhdr.txtsz+(SEGROUND-1)) & ~(SEGROUND-1);
  64. d = (t + fhdr.datsz + (SEGROUND-1)) & ~(SEGROUND-1);
  65. bssend = t + fhdr.datsz + fhdr.bsssz;
  66. b = (bssend + (SEGROUND-1)) & ~(SEGROUND-1);
  67. s = &memory.seg[Text];
  68. s->type = Text;
  69. s->base = fhdr.txtaddr - fhdr.hdrsz;
  70. s->end = t;
  71. s->fileoff = fhdr.txtoff - fhdr.hdrsz;
  72. s->fileend = s->fileoff + fhdr.txtsz;
  73. s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uint8_t*));
  74. iprofsize = (s->end-s->base)/PROFGRAN;
  75. iprof = emalloc(iprofsize*sizeof(int32_t));
  76. textbase = s->base;
  77. s = &memory.seg[Data];
  78. s->type = Data;
  79. s->base = t;
  80. s->end = t+(d-t);
  81. s->fileoff = fhdr.datoff;
  82. s->fileend = s->fileoff + fhdr.datsz;
  83. datasize = fhdr.datsz;
  84. s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uint8_t*));
  85. s = &memory.seg[Bss];
  86. s->type = Bss;
  87. s->base = d;
  88. s->end = d+(b-d);
  89. s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uint8_t*));
  90. s = &memory.seg[Stack];
  91. s->type = Stack;
  92. s->base = STACKTOP-STACKSIZE;
  93. s->end = STACKTOP;
  94. s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uint8_t*));
  95. reg.pc = fhdr.entry;
  96. }
  97. void
  98. inithdr(int fd)
  99. {
  100. Symbol s;
  101. extern Machdata powermach;
  102. seek(fd, 0, 0);
  103. if (!crackhdr(fd, &fhdr))
  104. fatal(0, "read text header");
  105. if(fhdr.type != FPOWER)
  106. fatal(0, "bad magic number");
  107. if(syminit(fd, &fhdr) < 0)
  108. fatal(0, "%r\n");
  109. symmap = loadmap(symmap, fd, &fhdr);
  110. if (mach->sbreg && lookup(0, mach->sbreg, &s))
  111. mach->sb = s.value;
  112. machdata = &powermach;
  113. }
  114. uint32_t
  115. greg(int f, uint32_t off)
  116. {
  117. int n;
  118. uint32_t l;
  119. uint8_t wd[BY2WD];
  120. seek(f, off, 0);
  121. n = read(f, wd, BY2WD);
  122. if(n != BY2WD)
  123. fatal(1, "read register");
  124. l = wd[0]<<24;
  125. l |= wd[1]<<16;
  126. l |= wd[2]<<8;
  127. l |= wd[3];
  128. return l;
  129. }
  130. uint32_t
  131. roff[] = {
  132. REGOFF(r0),
  133. REGOFF(r1), REGOFF(r2), REGOFF(r3),
  134. REGOFF(r4), REGOFF(r5), REGOFF(r6),
  135. REGOFF(r7), REGOFF(r8), REGOFF(r9),
  136. REGOFF(r10), REGOFF(r11), REGOFF(r12),
  137. REGOFF(r13), REGOFF(r14), REGOFF(r15),
  138. REGOFF(r16), REGOFF(r17), REGOFF(r18),
  139. REGOFF(r19), REGOFF(r20), REGOFF(r21),
  140. REGOFF(r22), REGOFF(r23), REGOFF(r24),
  141. REGOFF(r25), REGOFF(r26), REGOFF(r27),
  142. REGOFF(r28), REGOFF(r29), REGOFF(r30),
  143. REGOFF(r31),
  144. };
  145. void
  146. seginit(int fd, Segment *s, int idx, uint32_t vastart, uint32_t vaend)
  147. {
  148. int n;
  149. while(vastart < vaend) {
  150. seek(fd, vastart, 0);
  151. s->table[idx] = emalloc(BY2PG);
  152. n = read(fd, s->table[idx], BY2PG);
  153. if(n != BY2PG)
  154. fatal(1, "data read");
  155. vastart += BY2PG;
  156. idx++;
  157. }
  158. }
  159. void
  160. procinit(int pid)
  161. {
  162. char *p;
  163. Segment *s;
  164. int n, m, sg, i;
  165. uint32_t vastart, vaend;
  166. char mfile[128], tfile[128], sfile[1024];
  167. sprint(mfile, "/proc/%d/mem", pid);
  168. sprint(tfile, "/proc/%d/text", pid);
  169. sprint(sfile, "/proc/%d/segment", pid);
  170. text = open(tfile, OREAD);
  171. if(text < 0)
  172. fatal(1, "open text %s", tfile);
  173. inithdr(text);
  174. sg = open(sfile, OREAD);
  175. if(sg < 0)
  176. fatal(1, "open text %s", sfile);
  177. n = read(sg, sfile, sizeof(sfile));
  178. if(n >= sizeof(sfile))
  179. fatal(0, "segment file buffer too small");
  180. close(sg);
  181. m = open(mfile, OREAD);
  182. if(m < 0)
  183. fatal(1, "open %s", mfile);
  184. initmap();
  185. p = strstr(sfile, "Data");
  186. if(p == 0)
  187. fatal(0, "no data");
  188. vastart = strtoul(p+9, 0, 16);
  189. vaend = strtoul(p+18, 0, 16);
  190. s = &memory.seg[Data];
  191. if(s->base != vastart || s->end != vaend) {
  192. s->base = vastart;
  193. s->end = vaend;
  194. free(s->table);
  195. s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uint8_t*));
  196. }
  197. seginit(m, s, 0, vastart, vaend);
  198. p = strstr(sfile, "Bss");
  199. if(p == 0)
  200. fatal(0, "no bss");
  201. vastart = strtoul(p+9, 0, 16);
  202. vaend = strtoul(p+18, 0, 16);
  203. s = &memory.seg[Bss];
  204. if(s->base != vastart || s->end != vaend) {
  205. s->base = vastart;
  206. s->end = vaend;
  207. free(s->table);
  208. s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uint8_t*));
  209. }
  210. seginit(m, s, 0, vastart, vaend);
  211. reg.pc = greg(m, REGOFF(pc));
  212. reg.r[1] = greg(m, REGOFF(sp));
  213. reg.r[2] = greg(m, REGOFF(r2));
  214. reg.r[30] = greg(m, REGOFF(r30));
  215. reg.r[31] = greg(m, REGOFF(r31));
  216. for(i = 0; i < 32; i++)
  217. reg.r[i] = greg(m, roff[i-1]);
  218. s = &memory.seg[Stack];
  219. vastart = reg.r[1] & ~(BY2PG-1);
  220. seginit(m, s, (vastart-s->base)/BY2PG, vastart, STACKTOP);
  221. close(m);
  222. Bprint(bioout, "qi\n");
  223. }
  224. void
  225. reset(void)
  226. {
  227. int i, l, m;
  228. Segment *s;
  229. Breakpoint *b;
  230. memset(&reg, 0, sizeof(Registers));
  231. fpreginit();
  232. for(i = 0; i > Nseg; i++) {
  233. s = &memory.seg[i];
  234. l = ((s->end-s->base)/BY2PG)*sizeof(uint8_t*);
  235. for(m = 0; m < l; m++)
  236. if(s->table[m])
  237. free(s->table[m]);
  238. free(s->table);
  239. }
  240. free(iprof);
  241. memset(&memory, 0, sizeof(memory));
  242. for(b = bplist; b; b = b->next)
  243. b->done = b->count;
  244. }
  245. void
  246. initstk(int argc, char *argv[])
  247. {
  248. uint32_t size, sp, ap, tos;
  249. int i;
  250. char *p;
  251. initmap();
  252. tos = STACKTOP - sizeof(Tos)*2; /* we'll assume twice the host's is big enough */
  253. sp = tos;
  254. for (i = 0; i < sizeof(Tos)*2; i++)
  255. putmem_b(tos + i, 0);
  256. /*
  257. * pid is second word from end of tos and needs to be set for nsec().
  258. * we know power is a 32-bit cpu, so we'll assume knowledge of the Tos
  259. * struct for now, and use our pid.
  260. */
  261. putmem_w(tos + 4*4 + 2*sizeof(uint32_t) + 3*sizeof(uvlong), getpid());
  262. /* Build exec stack */
  263. size = strlen(file)+1+BY2WD+BY2WD+(BY2WD*2);
  264. for(i = 0; i < argc; i++)
  265. size += strlen(argv[i])+BY2WD+1;
  266. sp -= size;
  267. sp &= ~7;
  268. reg.r[1] = sp;
  269. reg.r[3] = tos; /* Plan 9 profiling clock, etc. */
  270. /* Push argc */
  271. putmem_w(sp, argc+1);
  272. sp += BY2WD;
  273. /* Compute sizeof(argv) and push argv[0] */
  274. ap = sp+((argc+1)*BY2WD)+BY2WD;
  275. putmem_w(sp, ap);
  276. sp += BY2WD;
  277. /* Build argv[0] string into stack */
  278. for(p = file; *p; p++)
  279. putmem_b(ap++, *p);
  280. putmem_b(ap++, '\0');
  281. /* Loop through pushing the arguments */
  282. for(i = 0; i < argc; i++) {
  283. putmem_w(sp, ap);
  284. sp += BY2WD;
  285. for(p = argv[i]; *p; p++)
  286. putmem_b(ap++, *p);
  287. putmem_b(ap++, '\0');
  288. }
  289. /* Null terminate argv */
  290. putmem_w(sp, 0);
  291. }
  292. void
  293. fatal(int syserr, char *fmt, ...)
  294. {
  295. char buf[ERRMAX], *s;
  296. va_list ap;
  297. va_start(ap, fmt);
  298. vseprint(buf, buf+sizeof(buf), fmt, ap);
  299. va_end(ap);
  300. s = "qi: %s\n";
  301. if(syserr)
  302. s = "qi: %s: %r\n";
  303. fprint(2, s, buf);
  304. exits(buf);
  305. }
  306. void
  307. itrace(char *fmt, ...)
  308. {
  309. char buf[128];
  310. va_list ap;
  311. va_start(ap, fmt);
  312. vseprint(buf, buf+sizeof(buf), fmt, ap);
  313. va_end(ap);
  314. Bprint(bioout, "%8lux %.8lux %s\n", reg.pc, reg.ir, buf);
  315. Bflush(bioout);
  316. }
  317. void
  318. dumpreg(void)
  319. {
  320. int i;
  321. Bprint(bioout, "PC #%-8lux SP #%-8lux CR #%-8lux LR #%-8lux CTR #%-8lux XER #%-8lux\n",
  322. reg.pc, reg.r[1], reg.cr, reg.lr, reg.ctr, reg.xer);
  323. for(i = 0; i < 32; i++) {
  324. if((i%4) == 0 && i != 0)
  325. Bprint(bioout, "\n");
  326. Bprint(bioout, "R%-2d #%-8lux ", i, reg.r[i]);
  327. }
  328. Bprint(bioout, "\n");
  329. }
  330. void
  331. dumpfreg(void)
  332. {
  333. dumpdreg();
  334. }
  335. void
  336. dumpdreg(void)
  337. {
  338. int i;
  339. char buf[64];
  340. FPdbleword d;
  341. i = 0;
  342. while(i < 32) {
  343. d.x = reg.fd[i];
  344. ieeedftos(buf, sizeof(buf), d.hi, d.lo);
  345. Bprint(bioout, "F%-2d %s\t", i, buf);
  346. i++;
  347. d.x = reg.fd[i];
  348. ieeedftos(buf, sizeof(buf), d.hi, d.lo);
  349. Bprint(bioout, "\tF%-2d %s\n", i, buf);
  350. i++;
  351. }
  352. }
  353. void *
  354. emalloc(uint32_t size)
  355. {
  356. void *a;
  357. a = malloc(size);
  358. if(a == 0)
  359. fatal(0, "no memory");
  360. memset(a, 0, size);
  361. return a;
  362. }
  363. void *
  364. erealloc(void *a, uint32_t oldsize, uint32_t size)
  365. {
  366. void *n;
  367. n = malloc(size);
  368. if(n == 0)
  369. fatal(0, "no memory");
  370. memset(n, 0, size);
  371. if(size > oldsize)
  372. size = oldsize;
  373. memmove(n, a, size);
  374. return n;
  375. }