devtrace.c 18 KB

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