devtrace.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  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 "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. #include "netif.h"
  16. #pragma profile 0
  17. typedef struct Trace Trace;
  18. /* This is a trace--a segment of memory to watch for entries and exits */
  19. struct Trace {
  20. struct Trace *next;
  21. char *func;
  22. char *start;
  23. char *end;
  24. int enabled;
  25. char name[16];
  26. };
  27. enum {
  28. Qdir,
  29. Qctl,
  30. Qdata,
  31. };
  32. enum {
  33. TraceEntry = 1,
  34. TraceExit,
  35. };
  36. /* fix me make this programmable */
  37. enum {
  38. defaultlogsize = 8192,
  39. };
  40. /* This represents a trace "hit" or event */
  41. typedef struct Tracelog Tracelog;
  42. struct Tracelog {
  43. uint64_t ticks;
  44. int info;
  45. uintptr_t pc;
  46. /* these are different depending on type */
  47. uintptr_t dat[5];
  48. int machno;
  49. };
  50. //static Rendez tracesleep;
  51. static QLock traceslock;
  52. /* this will contain as many entries as there are valid pc values */
  53. static Trace **tracemap;
  54. static Trace *traces; /* This stores all the traces */
  55. //static Lock loglk;
  56. static Tracelog *tracelog = nil;
  57. int traceactive = 0;
  58. /* trace indices. These are just unsigned longs. You mask them
  59. * to get an index. This makes fifo empty/full etc. trivial.
  60. */
  61. static uint pw = 0, pr = 0;
  62. static int tracesactive = 0;
  63. static int all = 0;
  64. static int watching = 0;
  65. static int slothits = 0;
  66. static unsigned int traceinhits = 0;
  67. static unsigned int newplfail = 0;
  68. static unsigned long logsize = defaultlogsize, logmask = defaultlogsize - 1;
  69. static int printsize = 0; //The length of a line being printed
  70. /* These are for observing a single process */
  71. static int *pidwatch = nil;
  72. static int numpids = 0;
  73. static const int PIDWATCHSIZE = 32; /* The number of PIDS that can be watched. Pretty arbitrary. */
  74. int codesize = 0;
  75. //static uint64_t lastestamp; /* last entry timestamp */
  76. //static uint64_t lastxstamp; /* last exit timestamp */
  77. /* Trace events can be either Entries or Exits */
  78. static char eventname[] = {
  79. [TraceEntry] = 'E',
  80. [TraceExit] = 'X',
  81. };
  82. static Dirtab tracedir[]={
  83. ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
  84. "tracectl", {Qctl}, 0, 0664,
  85. "trace", {Qdata}, 0, 0440,
  86. };
  87. char hex[] = {
  88. '0',
  89. '1',
  90. '2',
  91. '3',
  92. '4',
  93. '5',
  94. '6',
  95. '7',
  96. '8',
  97. '9',
  98. 'a',
  99. 'b',
  100. 'c',
  101. 'd',
  102. 'e',
  103. 'f',
  104. };
  105. /* big-endian ... */
  106. void
  107. hex8(uint32_t l, char *c)
  108. {
  109. int i;
  110. for(i = 2; i; i--){
  111. c[i-1] = hex[l&0xf];
  112. l >>= 4;
  113. }
  114. }
  115. void
  116. hex16(uint32_t l, char *c)
  117. {
  118. int i;
  119. for(i = 4; i; i--){
  120. c[i-1] = hex[l&0xf];
  121. l >>= 4;
  122. }
  123. }
  124. void
  125. hex32(uint32_t l, char *c)
  126. {
  127. int i;
  128. for(i = 8; i; i--){
  129. c[i-1] = hex[l&0xf];
  130. l >>= 4;
  131. }
  132. }
  133. void
  134. hex64(uint64_t l, char *c)
  135. {
  136. hex32(l>>32, c);
  137. hex32(l, &c[8]);
  138. }
  139. static int
  140. lognonempty(void *v)
  141. {
  142. return pw - pr;
  143. }
  144. #if 0
  145. static int
  146. logfull(void)
  147. {
  148. return (pw - pr) >= logsize;
  149. }
  150. #endif
  151. static uint64_t
  152. idx(uint64_t f)
  153. {
  154. return f & logmask;
  155. }
  156. /*
  157. * Check if the given trace overlaps any others
  158. * Returns 1 if there is overlap, 0 if clear.
  159. */
  160. int
  161. overlapping(Trace *p) {
  162. Trace *curr;
  163. curr = traces;
  164. if (!curr)
  165. return 0;
  166. do {
  167. if ((curr->start < p->start && p->start < curr->end) ||
  168. (curr->start < p->end && p->end < curr->end))
  169. return 1;
  170. curr = curr->next;
  171. } while (curr != nil);
  172. return 0;
  173. }
  174. /* Make sure a PC is valid and traced; if so, return its Trace */
  175. /* if dopanic == 1, the kernel will panic on an invalid PC */
  176. struct Trace **
  177. traceslot(char *pc, int dopanic)
  178. {
  179. int index;
  180. struct Trace **p;
  181. if (pc > etext) {
  182. if (dopanic)
  183. panic("Bad PC %p", pc);
  184. print("Invalid PC %p\n", pc);
  185. return nil;
  186. }
  187. index = (int)((uintptr_t)pc - KTZERO);
  188. if (index > codesize){
  189. if (dopanic) {
  190. panic("Bad PC %p", pc);
  191. while(1);
  192. }
  193. print("Invalid PC %p\n", pc);
  194. return nil;
  195. }
  196. p = &tracemap[index];
  197. if (tracemap[index])
  198. ainc(&slothits);
  199. return p;
  200. }
  201. /* Check if the given PC is traced and return a Trace if so */
  202. struct Trace *
  203. traced(char *pc, int dopanic)
  204. {
  205. struct Trace **p;
  206. p = traceslot(pc, dopanic);
  207. if (p == nil)
  208. return nil;
  209. return *p;
  210. }
  211. /*
  212. * Return 1 if pid is being watched or no pids are being watched.
  213. * Return 0 if pids are being watched and the argument is not
  214. * among them.
  215. */
  216. int
  217. watchingpid(int pid) {
  218. int i;
  219. if (pidwatch[0] == 0)
  220. return 1;
  221. for (i = 0; i < numpids; i++) {
  222. if (pidwatch[i] == pid)
  223. return 1;
  224. }
  225. return 0;
  226. }
  227. /*
  228. * Remove a trace.
  229. */
  230. void
  231. removetrace(Trace *p) {
  232. char *cp;
  233. struct Trace *prev;
  234. struct Trace *curr;
  235. struct Trace **slot;
  236. slot = traceslot(p->start, 0);
  237. for(cp = p->start; cp <= p->end; slot++, cp++)
  238. *slot = nil;
  239. curr = traces;
  240. if (curr == p) {
  241. if (curr->next) {
  242. traces = curr->next;
  243. } else {
  244. traces = nil; //this seems to work fine
  245. }
  246. free(curr);
  247. return;
  248. }
  249. prev = curr;
  250. curr = curr->next;
  251. do {
  252. if (curr == p) {
  253. prev->next = curr->next;
  254. return;
  255. }
  256. prev = curr;
  257. curr = curr->next;
  258. } while (curr != nil);
  259. }
  260. /* it is recommended that you call these with something sane. */
  261. /* these next two functions assume you locked tracelock */
  262. /* Turn on a trace */
  263. void
  264. traceon(struct Trace *p)
  265. {
  266. char *cp;
  267. struct Trace **slot;
  268. slot = traceslot(p->start, 0);
  269. for(cp = p->start; cp <= p->end; slot++, cp++)
  270. *slot = p;
  271. p->enabled = 1;
  272. tracesactive++;
  273. }
  274. /* Turn off a trace */
  275. void
  276. traceoff(struct Trace *p)
  277. {
  278. char *cp;
  279. struct Trace **slot;
  280. slot = traceslot(p->start, 0);
  281. for(cp = p->start; cp <= p->end; slot++, cp++)
  282. *slot = nil;
  283. p->enabled = 0;
  284. tracesactive--;
  285. }
  286. /* Make a new tracelog (an event) */
  287. /* can return NULL, meaning, no record for you */
  288. static struct Tracelog *
  289. newpl(void)
  290. {
  291. uint index;
  292. index = ainc((int *)&pw);
  293. return &tracelog[idx(index)];
  294. }
  295. /* Called every time a (traced) function starts */
  296. /* this is not really smp safe. FIX */
  297. void
  298. tracein(void* pc, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4)
  299. {
  300. Proc *up = externup();
  301. struct Tracelog *pl;
  302. /* if we are here, tracing is active. Turn it off. */
  303. traceactive = 0;
  304. if (! traced(pc, 1)){
  305. traceactive = 1;
  306. return;
  307. }
  308. ainc((int *)&traceinhits);
  309. /* Continue if we are watching this pid or we're not watching any */
  310. if (!all)
  311. if (!up || !watchingpid(up->pid)){
  312. traceactive = 1;
  313. return;
  314. }
  315. pl = newpl();
  316. if (! pl) {
  317. ainc((int *)&newplfail);
  318. traceactive = 1;
  319. return;
  320. }
  321. cycles(&pl->ticks);
  322. pl->pc = (uintptr_t)pc;
  323. if (up)
  324. pl->dat[0] = up->pid;
  325. else
  326. pl->dat[0] = (unsigned long)-1;
  327. pl->dat[1] = a1;
  328. pl->dat[2] = a2;
  329. pl->dat[3] = a3;
  330. pl->dat[4] = a4;
  331. pl->info = TraceEntry;
  332. pl->machno = machp()->machno;
  333. traceactive = 1;
  334. }
  335. /* Called every time a traced function exits */
  336. void
  337. traceout(void* pc, uintptr_t retval)
  338. {
  339. Proc *up = externup();
  340. struct Tracelog *pl;
  341. /* if we are here, tracing is active. Turn it off. */
  342. traceactive = 0;
  343. if (! traced(pc, 1)){
  344. traceactive = 1;
  345. return;
  346. }
  347. if (!all)
  348. if (!up || !watchingpid(up->pid)){
  349. traceactive = 1;
  350. return;
  351. }
  352. pl = newpl();
  353. if (! pl){
  354. traceactive = 1;
  355. return;
  356. }
  357. cycles(&pl->ticks);
  358. pl->pc = (uintptr_t)pc;
  359. if (up)
  360. pl->dat[0] = up->pid;
  361. else
  362. pl->dat[0] = (unsigned long)-1;
  363. pl->dat[1] = retval;
  364. pl->dat[2] = 0;
  365. pl->dat[3] = 0;
  366. pl->info = TraceExit;
  367. pl->machno = machp()->machno;
  368. traceactive = 1;
  369. }
  370. /* Create a new trace with the given range */
  371. static Trace *
  372. mktrace(void *func, void *start, void *end)
  373. {
  374. Trace *p;
  375. p = mallocz(sizeof p[0], 1);
  376. p->func = func;
  377. p->start = start;
  378. p->end = end;
  379. return p;
  380. }
  381. #if 0
  382. /* Get rid of an old trace */
  383. static void
  384. freetrace(Trace *p)
  385. {
  386. free(p);
  387. }
  388. #endif
  389. static Chan*
  390. traceattach(char *spec)
  391. {
  392. return devattach('T', spec);
  393. }
  394. static Walkqid*
  395. tracewalk(Chan *c, Chan *nc, char **name, int nname)
  396. {
  397. return devwalk(c, nc, name, nname, tracedir, nelem(tracedir), devgen);
  398. }
  399. static int32_t
  400. tracestat(Chan *c, uint8_t *db, int32_t n)
  401. {
  402. return devstat(c, db, n, tracedir, nelem(tracedir), devgen);
  403. }
  404. static Chan*
  405. traceopen(Chan *c, int omode)
  406. {
  407. /* if there is no tracelog, allocate one. Open always fails
  408. * if the basic alloc fails. You can resize it later.
  409. */
  410. codesize = (uintptr_t)etext - (uintptr_t)KTZERO;
  411. if (! tracemap)
  412. //tracemap = mallocz(sizeof(struct tracemap *)*codesize, 1);
  413. tracemap = mallocz(sizeof(struct Trace *)*codesize, 1);
  414. if (! tracemap)
  415. error("tracemap malloc failed");
  416. if (! tracelog)
  417. tracelog = mallocz(sizeof(*tracelog)*logsize, 1);
  418. /* I guess malloc doesn't toss an error */
  419. if (! tracelog)
  420. error("tracelog malloc failed");
  421. if (! pidwatch)
  422. pidwatch = mallocz(sizeof(int)*PIDWATCHSIZE, 1);
  423. if (! pidwatch)
  424. error("pidwatch malloc failed");
  425. c = devopen(c, omode, tracedir, nelem(tracedir), devgen);
  426. return c;
  427. }
  428. static void
  429. traceclose(Chan *c)
  430. {
  431. }
  432. /*
  433. * Reading from the device, either the data or control files.
  434. * The data reading involves deep rminnich magic so we don't have
  435. * to call print(), which is traced.
  436. */
  437. static int32_t
  438. traceread(Chan *c, void *a, int32_t n, int64_t offset)
  439. {
  440. Proc *up = externup();
  441. char *buf;
  442. char *cp = a;
  443. struct Tracelog *pl;
  444. Trace *p;
  445. int i, j;
  446. int saveactive = traceactive;
  447. traceactive = 0;
  448. // static QLock gate;
  449. if (waserror()) {
  450. traceactive = saveactive;
  451. nexterror();
  452. }
  453. if(c->qid.type == QTDIR) {
  454. int32_t l = devdirread(c, a, n, tracedir, nelem(tracedir), devgen);
  455. poperror();
  456. traceactive = saveactive;
  457. return l;
  458. }
  459. switch((int) c->qid.path){
  460. default:
  461. error("traceread: bad qid");
  462. case Qctl:
  463. i = 0;
  464. qlock(&traceslock);
  465. buf = malloc(READSTR);
  466. i += snprint(buf + i, READSTR - i, "logsize %lu\n", logsize);
  467. for(p = traces; p != nil; p = p->next)
  468. i += snprint(buf + i, READSTR - i, "trace %p %p new %s\n",
  469. p->start, p->end, p->name);
  470. for(p = traces; p != nil; p = p->next)
  471. i += snprint(buf + i, READSTR - i, "#trace %p traced? %p\n",
  472. p->func, traced(p->func, 0));
  473. for(p = traces; p != nil; p = p->next)
  474. if (p->enabled)
  475. i += snprint(buf + i, READSTR - i, "trace %s on\n",
  476. p->name);
  477. i += snprint(buf + i, READSTR - i, "#tracehits %d, in queue %d\n",
  478. pw, pw-pr);
  479. i += snprint(buf + i, READSTR - i, "#tracelog %p\n", tracelog);
  480. i += snprint(buf + i, READSTR - i, "#traceactive %d\n", saveactive);
  481. i += snprint(buf + i, READSTR - i, "#slothits %d\n", slothits);
  482. i += snprint(buf + i, READSTR - i, "#traceinhits %d\n", traceinhits);
  483. for (j = 0; j < numpids - 1; j++)
  484. i += snprint(buf + i, READSTR - i, "watch %d\n", pidwatch[j]);
  485. snprint(buf + i, READSTR - i, "watch %d\n", pidwatch[numpids - 1]);
  486. n = readstr(offset, a, n, buf);
  487. free(buf);
  488. qunlock(&traceslock);
  489. break;
  490. case Qdata:
  491. // Set the printsize
  492. /* 32-bit E PCPCPCPC TIMETIMETIMETIME PID# CR XXARG1XX XXARG2XX XXARG3XX XXARG4XX\n */
  493. if (sizeof(uintptr_t) == 4) {
  494. printsize = 73; // 32-bit format
  495. } else {
  496. printsize = 121; // must be 64-bit
  497. }
  498. i = 0;
  499. while(lognonempty((void *)0)){
  500. int j;
  501. if ((pw - pr) > logsize)
  502. pr = pw - logsize;
  503. pl = tracelog + idx(pr);
  504. if ((i + printsize) > n)
  505. break;
  506. /* simple format */
  507. if (sizeof(uintptr_t) == 4) {
  508. cp[0] = eventname[pl->info];
  509. cp ++;
  510. *cp++ = ' ';
  511. hex32((uint)pl->pc, cp);
  512. cp[8] = ' ';
  513. cp += 9;
  514. hex64(pl->ticks, cp);
  515. cp[16] = ' ';
  516. cp += 17;
  517. hex16(pl->dat[0], cp);
  518. cp += 4;
  519. cp[0] = ' ';
  520. cp++;
  521. hex8(pl->machno, cp);
  522. cp += 2;
  523. cp[0] = ' ';
  524. cp++;
  525. for(j = 1; j < 4; j++){
  526. hex32(pl->dat[j], cp);
  527. cp[8] = ' ';
  528. cp += 9;
  529. }
  530. /* adjust for extra skip above */
  531. cp--;
  532. *cp++ = '\n';
  533. pr++;
  534. i += printsize;
  535. } else {
  536. cp[0] = eventname[pl->info];
  537. cp ++;
  538. *cp++ = ' ';
  539. hex64((uint64_t)pl->pc, cp);
  540. cp[16] = ' ';
  541. cp += 17;
  542. hex64(pl->ticks, cp);
  543. cp[16] = ' ';
  544. cp += 17;
  545. hex32(pl->dat[0], cp);
  546. cp += 8;
  547. cp[0] = ' ';
  548. cp++;
  549. cp[0] = ' ';
  550. cp++;
  551. cp[0] = ' ';
  552. cp++;
  553. cp[0] = ' ';
  554. cp++;
  555. hex8(pl->machno, cp);
  556. cp += 4;
  557. for (j = 1; j < 5; j++) {
  558. hex64(pl->dat[j], cp);
  559. cp[16] = ' ';
  560. cp += 17;
  561. }
  562. cp--;
  563. *cp++ = '\n';
  564. pr++;
  565. i += printsize;
  566. }
  567. }
  568. n = i;
  569. break;
  570. }
  571. poperror();
  572. traceactive = saveactive;
  573. return n;
  574. }
  575. /*
  576. * Process commands sent to the ctl file.
  577. */
  578. static int32_t
  579. tracewrite(Chan *c, void *a, int32_t n, int64_t mm)
  580. {
  581. Proc *up = externup();
  582. char *tok[6]; //changed this so "tracein" works with the new 4th arg
  583. char *ep, *s = nil;
  584. Trace *p, **pp, *foo;
  585. int ntok;
  586. int saveactive = traceactive;
  587. traceactive = 0;
  588. qlock(&traceslock);
  589. if(waserror()){
  590. qunlock(&traceslock);
  591. if(s != nil) free(s);
  592. traceactive = saveactive;
  593. nexterror();
  594. }
  595. switch((uintptr_t)c->qid.path){
  596. default:
  597. error("tracewrite: bad qid");
  598. case Qctl:
  599. s = malloc(n + 1);
  600. memmove(s, a, n);
  601. s[n] = 0;
  602. ntok = tokenize(s, tok, nelem(tok));
  603. if(!strcmp(tok[0], "trace")){ /* 'trace' ktextaddr 'on'|'off'|'mk'|'del' [name] */
  604. if(ntok < 3) {
  605. error("devtrace: usage: 'trace' [ktextaddr|name] 'on'|'off'|'mk'|'del' [name]");
  606. }
  607. for(pp = &traces; *pp != nil; pp = &(*pp)->next){
  608. if(!strcmp(tok[1], (*pp)->name))
  609. break;
  610. }
  611. p = *pp;
  612. if((ntok > 3) && (!strcmp(tok[3], "new"))){
  613. uintptr_t addr;
  614. char *start, *end, *func;
  615. if (ntok != 5) {
  616. error("devtrace: usage: trace <ktextstart> <ktextend> new <name>");
  617. }
  618. addr = (uintptr_t)strtoul(tok[1], &ep, 16);
  619. if (addr < KTZERO)
  620. addr |= KTZERO;
  621. func = start = (void *)addr;
  622. if(*ep) {
  623. error("devtrace: start address not in recognized format");
  624. }
  625. addr = (uintptr_t)strtoul(tok[2], &ep, 16);
  626. if (addr < KTZERO)
  627. addr |= KTZERO;
  628. end = (void *)addr;
  629. if(*ep) {
  630. error("devtrace: end address not in recognized format");
  631. }
  632. if (start > end || start > etext || end > etext)
  633. error("devtrace: invalid address range");
  634. /* What do we do here? start and end are weird *
  635. if((addr < (uintptr)start) || (addr > (uintptr)end)
  636. error("devtrace: address out of bounds");
  637. */
  638. if(p) {
  639. error("devtrace: trace already exists");
  640. }
  641. p = mktrace(func, start, end);
  642. for (foo = traces; foo != nil; foo = foo->next) {
  643. if (!strcmp(tok[4], foo->name))
  644. error("devtrace: trace with that name already exists");
  645. }
  646. if (!overlapping(p)) {
  647. p->next = traces;
  648. if(ntok < 5)
  649. snprint(p->name, sizeof p->name, "%p", func);
  650. else
  651. strncpy(p->name, tok[4], sizeof p->name);
  652. traces = p;
  653. } else {
  654. error("devtrace: given range overlaps with existing trace");
  655. }
  656. } else if(!strcmp(tok[2], "remove")){
  657. if (ntok != 3)
  658. error("devtrace: usage: trace <name> remove");
  659. if (p == nil) {
  660. error("devtrace: trace not found");
  661. }
  662. removetrace(p);
  663. } else if(!strcmp(tok[2], "on")){
  664. if (ntok != 3)
  665. error("devtrace: usage: trace <name> on");
  666. if(p == nil) {
  667. error("devtrace: trace not found");
  668. }
  669. if (! traced(p->func, 0)){
  670. traceon(p);
  671. }
  672. } else if(!strcmp(tok[2], "off")){
  673. if (ntok != 3)
  674. error("devtrace: usage: trace <name> off");
  675. if(p == nil) {
  676. error("devtrace: trace not found");
  677. }
  678. if(traced(p->func, 0)){
  679. traceoff(p);
  680. }
  681. }
  682. } else if(!strcmp(tok[0], "query")){
  683. /* See if addr is being traced */
  684. Trace* p;
  685. uintptr_t addr;
  686. if (ntok != 2) {
  687. error("devtrace: usage: query <addr>");
  688. }
  689. addr = (uintptr_t)strtoul(tok[1], &ep, 16);
  690. if (addr < KTZERO)
  691. addr |= KTZERO;
  692. p = traced((void *)addr, 0);
  693. if (p) {
  694. print("Probing is enabled\n");
  695. } else {
  696. print("Probing is disabled\n");
  697. }
  698. } else if(!strcmp(tok[0], "size")){
  699. int l, size;
  700. struct Tracelog *newtracelog;
  701. if (ntok != 2)
  702. error("devtrace: usage: size <exponent>");
  703. l = strtoul(tok[1], &ep, 0);
  704. if(*ep) {
  705. error("devtrace: size not in recognized format");
  706. }
  707. size = 1 << l;
  708. /* sort of foolish. Alloc new trace first, then free old. */
  709. /* and too bad if there are unread traces */
  710. newtracelog = mallocz(sizeof(*newtracelog)*size, 1);
  711. /* does malloc throw waserror? I don't know */
  712. if (newtracelog){
  713. free(tracelog);
  714. tracelog = newtracelog;
  715. logsize = size;
  716. logmask = size - 1;
  717. pr = pw = 0;
  718. } else {
  719. error("devtrace: can't allocate that much");
  720. }
  721. } else if (!strcmp(tok[0], "testtracein")) {
  722. /* Manually jump to a certain bit of traced code */
  723. uintptr_t pc, a1, a2, a3, a4;
  724. int x;
  725. if (ntok != 6)
  726. error("devtrace: usage: testtracein <pc> <arg1> <arg2> <arg3> <arg4>");
  727. pc = (uintptr_t)strtoul(tok[1], &ep, 16);
  728. if (pc < KTZERO)
  729. pc |= KTZERO;
  730. a1 = (uintptr_t)strtoul(tok[2], &ep, 16);
  731. a2 = (uintptr_t)strtoul(tok[3], &ep, 16);
  732. a3 = (uintptr_t)strtoul(tok[4], &ep, 16);
  733. a4 = (uintptr_t)strtoul(tok[5], &ep, 16);
  734. if (traced((void *)pc, 0)) {
  735. x = splhi();
  736. watching = 1;
  737. tracein((void *)pc, a1, a2, a3, a4);
  738. watching = 0;
  739. splx(x);
  740. }
  741. } else if (!strcmp(tok[0], "watch")) {
  742. /* Watch a certain PID */
  743. int pid;
  744. if (ntok != 2) {
  745. error("devtrace: usage: watch [0|<PID>]");
  746. }
  747. pid = atoi(tok[1]);
  748. if (pid == 0) {
  749. pidwatch = mallocz(sizeof(int)*PIDWATCHSIZE, 1);
  750. numpids = 0;
  751. } else if (pid < 0) {
  752. error("PID must be greater than zero.");
  753. } else if (numpids < PIDWATCHSIZE) {
  754. pidwatch[numpids] = pid;
  755. ainc(&numpids);
  756. } else {
  757. error("pidwatch array full!");
  758. }
  759. } else if (!strcmp(tok[0], "start")) {
  760. if (ntok != 1)
  761. error("devtrace: usage: start");
  762. saveactive = 1;
  763. } else if (!strcmp(tok[0], "stop")) {
  764. if (ntok != 1)
  765. error("devtrace: usage: stop");
  766. saveactive = 0;
  767. all = 0;
  768. } else if (!strcmp(tok[0], "all")) {
  769. if (ntok != 1)
  770. error("devtrace: usage: all");
  771. saveactive = 1;
  772. all = 1;
  773. } else {
  774. error("devtrace: usage: 'trace' [ktextaddr|name] 'on'|'off'|'mk'|'del' [name] or: 'size' buffersize (power of 2)");
  775. }
  776. free(s);
  777. break;
  778. }
  779. poperror();
  780. qunlock(&traceslock);
  781. traceactive = saveactive;
  782. return n;
  783. }
  784. Dev tracedevtab = {
  785. .dc = 'T',
  786. .name = "trace",
  787. .reset = devreset,
  788. .init = devinit,
  789. .shutdown = devshutdown,
  790. .attach = traceattach,
  791. .walk = tracewalk,
  792. .stat = tracestat,
  793. .open = traceopen,
  794. .create = devcreate,
  795. .close = traceclose,
  796. .read = traceread,
  797. .bread = devbread,
  798. .write = tracewrite,
  799. .bwrite = devbwrite,
  800. .remove = devremove,
  801. .wstat = devwstat,
  802. };