PageRenderTime 56ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/usr/src/lib/efcode/engine/debug.c

https://bitbucket.org/a3217055/illumos-2
C | 1601 lines | 1370 code | 167 blank | 64 comment | 315 complexity | e4ffe20b81981b5057ffb887a6b352a8 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, AGPL-3.0, BSD-3-Clause, LGPL-2.0, 0BSD, BSD-2-Clause, BSD-3-Clause-No-Nuclear-License-2014, AGPL-1.0, GPL-2.0
  1. /*
  2. * CDDL HEADER START
  3. *
  4. * The contents of this file are subject to the terms of the
  5. * Common Development and Distribution License, Version 1.0 only
  6. * (the "License"). You may not use this file except in compliance
  7. * with the License.
  8. *
  9. * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10. * or http://www.opensolaris.org/os/licensing.
  11. * See the License for the specific language governing permissions
  12. * and limitations under the License.
  13. *
  14. * When distributing Covered Code, include this CDDL HEADER in each
  15. * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16. * If applicable, add the following below this CDDL HEADER, with the
  17. * fields enclosed by brackets "[]" replaced with your own identifying
  18. * information: Portions Copyright [yyyy] [name of copyright owner]
  19. *
  20. * CDDL HEADER END
  21. */
  22. /*
  23. * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
  24. * Use is subject to license terms.
  25. */
  26. #pragma ident "%Z%%M% %I% %E% SMI"
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <stdarg.h>
  31. #include <unistd.h>
  32. #include <errno.h>
  33. #include <ctype.h>
  34. #include <fcode/private.h>
  35. #include <fcode/log.h>
  36. #ifndef DEBUG_LVL
  37. #define DEBUG_LVL 0
  38. #endif
  39. struct bitab {
  40. token_t bi_ptr;
  41. char *bi_name;
  42. int bi_type;
  43. };
  44. struct bitab *lookup_builtin(token_t);
  45. static int debug_level = DEBUG_LVL;
  46. void
  47. set_interpreter_debug_level(long lvl)
  48. {
  49. debug_level = lvl;
  50. }
  51. long
  52. get_interpreter_debug_level(void)
  53. {
  54. return (debug_level);
  55. }
  56. void
  57. output_data_stack(fcode_env_t *env, int msglevel)
  58. {
  59. int i;
  60. log_message(msglevel, "( ");
  61. if (DS > env->ds0) {
  62. for (i = 0; i < (DS - env->ds0); i++)
  63. log_message(msglevel, "%llx ",
  64. (uint64_t)(env->ds0[i + 1]));
  65. } else
  66. log_message(msglevel, "<empty> ");
  67. log_message(msglevel, ") ");
  68. }
  69. void
  70. output_return_stack(fcode_env_t *env, int show_wa, int msglevel)
  71. {
  72. int i;
  73. int anyout = 0;
  74. log_message(msglevel, "R:( ");
  75. if (show_wa) {
  76. log_message(msglevel, "%s ",
  77. acf_backup_search(env, (acf_t)WA));
  78. anyout++;
  79. }
  80. if (IP) {
  81. anyout++;
  82. log_message(msglevel, "%s ", acf_backup_search(env, IP));
  83. }
  84. for (i = (RS - env->rs0) - 1; i > 0; i--) {
  85. anyout++;
  86. log_message(msglevel, "%s ",
  87. acf_backup_search(env, (acf_t)env->rs0[i+1]));
  88. }
  89. if (!anyout)
  90. log_message(msglevel, "<empty> ");
  91. log_message(msglevel, ") ");
  92. }
  93. void
  94. dump_comma(fcode_env_t *env, char *type)
  95. {
  96. xforth_t d;
  97. if (strcmp(type, "x,") == 0)
  98. d = peek_xforth(env);
  99. else
  100. d = TOS;
  101. log_message(MSG_FC_DEBUG, "%s %p, %llx\n", type, HERE, (uint64_t)d);
  102. }
  103. static int ndebug_names;
  104. #define MAXDEBUG_NAMES 10
  105. static char *debug_names[MAXDEBUG_NAMES];
  106. static int ndebug_acfs;
  107. #define MAXDEBUG_ACFS 10
  108. static acf_t debug_acfs[MAXDEBUG_ACFS];
  109. void
  110. add_debug_acf(fcode_env_t *env, acf_t acf)
  111. {
  112. int i;
  113. for (i = 0; i < ndebug_acfs; i++)
  114. if (acf == debug_acfs[i])
  115. return;
  116. if (!within_dictionary(env, acf))
  117. log_message(MSG_ERROR, "Can't debug builtin\n");
  118. else if (ndebug_acfs >= MAXDEBUG_ACFS)
  119. log_message(MSG_ERROR, "Too many debug ACF's\n");
  120. else {
  121. debug_acfs[ndebug_acfs++] = acf;
  122. *LINK_TO_FLAGS(ACF_TO_LINK(acf)) |= FLAG_DEBUG;
  123. }
  124. }
  125. static void
  126. paren_debug(fcode_env_t *env)
  127. {
  128. acf_t acf;
  129. acf = (acf_t)POP(DS);
  130. if (!within_dictionary(env, acf)) {
  131. log_message(MSG_INFO, "acf: %llx not in dictionary\n",
  132. (uint64_t)acf);
  133. return;
  134. }
  135. if ((acf_t)_ALIGN(acf, token_t) != acf) {
  136. log_message(MSG_INFO, "acf: %llx not aligned\n",
  137. (uint64_t)acf);
  138. return;
  139. }
  140. if (*acf != (token_t)(&do_colon)) {
  141. log_message(MSG_INFO, "acf: %llx not a colon-def\n",
  142. (uint64_t)acf);
  143. return;
  144. }
  145. add_debug_acf(env, acf);
  146. }
  147. static void
  148. debug(fcode_env_t *env)
  149. {
  150. fstack_t d;
  151. char *word;
  152. acf_t acf;
  153. parse_word(env);
  154. dollar_find(env);
  155. d = POP(DS);
  156. if (d) {
  157. acf = (acf_t)POP(DS);
  158. add_debug_acf(env, acf);
  159. } else if (ndebug_names >= MAXDEBUG_NAMES) {
  160. log_message(MSG_ERROR, "Too many forward debug words\n");
  161. two_drop(env);
  162. } else {
  163. word = pop_a_duped_string(env, NULL);
  164. log_message(MSG_INFO, "Forward defined word: %s\n", word);
  165. debug_names[ndebug_names++] = word;
  166. }
  167. }
  168. /*
  169. * Eliminate dups and add vocabulary forth to end if not already on list.
  170. */
  171. static void
  172. order_to_dict_list(fcode_env_t *env, token_t *order[])
  173. {
  174. int i, j, norder = 0;
  175. if (env->current)
  176. order[norder++] = env->current;
  177. for (i = env->order_depth; i >= 0; i--) {
  178. for (j = 0; j < norder && order[j] != env->order[i]; j++)
  179. ;
  180. if (j == norder)
  181. order[norder++] = env->order[i];
  182. }
  183. for (j = 0; j < norder && order[j] != (token_t *)&env->forth_voc_link;
  184. j++)
  185. ;
  186. if (j == norder)
  187. order[norder++] = (token_t *)&env->forth_voc_link;
  188. order[norder] = NULL;
  189. }
  190. static acf_t
  191. search_all_dictionaries(fcode_env_t *env,
  192. acf_t (*fn)(fcode_env_t *, acf_t, void *),
  193. void *arg)
  194. {
  195. token_t *order[MAX_ORDER+1];
  196. int i;
  197. token_t *dptr;
  198. acf_t acf;
  199. order_to_dict_list(env, order);
  200. for (i = 0; (dptr = order[i]) != NULL; i++) {
  201. for (dptr = (token_t *)(*dptr); dptr;
  202. dptr = (token_t *)(*dptr))
  203. if ((acf = (*fn)(env, LINK_TO_ACF(dptr), arg)) != NULL)
  204. return (acf);
  205. }
  206. return (NULL);
  207. }
  208. char *
  209. acf_to_str(acf_t acf)
  210. {
  211. static char msg[(sizeof (acf) * 2) + 3];
  212. sprintf(msg, "(%08p)", acf);
  213. return (msg);
  214. }
  215. char *
  216. get_name_or_acf(token_t *dptr)
  217. {
  218. char *name;
  219. if ((name = get_name(dptr)) != NULL)
  220. return (name);
  221. return (acf_to_str(LINK_TO_ACF(dptr)));
  222. }
  223. static void
  224. output_acf_name(acf_t acf)
  225. {
  226. char *name;
  227. token_t *dptr;
  228. static int acf_count = 0;
  229. if (acf == NULL) {
  230. if (acf_count)
  231. log_message(MSG_INFO, "\n");
  232. acf_count = 0;
  233. return;
  234. }
  235. dptr = ACF_TO_LINK(acf);
  236. if ((name = get_name(dptr)) == NULL)
  237. name = "<noname>";
  238. log_message(MSG_INFO, "%24s (%08p)", name, acf);
  239. if (++acf_count >= 2) {
  240. log_message(MSG_INFO, "\n");
  241. acf_count = 0;
  242. } else
  243. log_message(MSG_INFO, " ");
  244. }
  245. static void
  246. dot_debug(fcode_env_t *env)
  247. {
  248. int i;
  249. token_t *dptr;
  250. if (ndebug_names == 0)
  251. log_message(MSG_INFO, "No forward debug words\n");
  252. else {
  253. for (i = 0; i < ndebug_names; i++)
  254. log_message(MSG_INFO, "%s Forward\n", debug_names[i]);
  255. }
  256. if (ndebug_acfs == 0)
  257. log_message(MSG_INFO, "No debug words\n");
  258. else {
  259. for (i = 0; i < ndebug_acfs; i++)
  260. log_message(MSG_INFO, "%s\n",
  261. get_name_or_acf(ACF_TO_LINK(debug_acfs[i])));
  262. }
  263. }
  264. static void
  265. do_undebug(fcode_env_t *env, char *name)
  266. {
  267. int i;
  268. for (i = 0; i < ndebug_names; i++) {
  269. if (strcmp(debug_names[i], name) == 0) {
  270. log_message(MSG_INFO, "Undebugging forward word %s\n",
  271. name);
  272. FREE(debug_names[i]);
  273. for (i++; i < ndebug_names; i++)
  274. debug_names[i - 1] = debug_names[i];
  275. ndebug_names--;
  276. break;
  277. }
  278. }
  279. }
  280. static void
  281. undebug(fcode_env_t *env)
  282. {
  283. fstack_t d;
  284. acf_t acf;
  285. flag_t *flagp;
  286. char *name;
  287. int i, j;
  288. parse_word(env);
  289. two_dup(env);
  290. dollar_find(env);
  291. d = POP(DS);
  292. if (d) {
  293. acf = (acf_t)POP(DS);
  294. flagp = LINK_TO_FLAGS(ACF_TO_LINK(acf));
  295. if ((*flagp & FLAG_DEBUG) == 0)
  296. log_message(MSG_WARN, "Word not debugged?\n");
  297. else {
  298. log_message(MSG_INFO, "Undebugging acf: %p\n", acf);
  299. *flagp &= ~FLAG_DEBUG;
  300. for (i = 0; i < ndebug_acfs; i++) {
  301. if (debug_acfs[i] == acf) {
  302. for (j = i + 1; j < ndebug_acfs; j++)
  303. debug_acfs[j-1] = debug_acfs[j];
  304. ndebug_acfs--;
  305. break;
  306. }
  307. }
  308. }
  309. } else
  310. two_drop(env);
  311. name = pop_a_string(env, NULL);
  312. do_undebug(env, name);
  313. }
  314. int
  315. name_is_debugged(fcode_env_t *env, char *name)
  316. {
  317. int i;
  318. if (ndebug_names <= 0)
  319. return (0);
  320. for (i = 0; i < ndebug_names; i++)
  321. if (strcmp(debug_names[i], name) == 0)
  322. return (1);
  323. return (0);
  324. }
  325. /*
  326. * This is complicated by being given ACF's to temporary compile words which
  327. * don't have a header.
  328. */
  329. int
  330. is_debug_word(fcode_env_t *env, acf_t acf)
  331. {
  332. flag_t *flagp;
  333. int i;
  334. /* check to see if any words are being debugged */
  335. if (ndebug_acfs == 0)
  336. return (0);
  337. /* only words in dictionary can be debugged */
  338. if (!within_dictionary(env, acf))
  339. return (0);
  340. /* check that word has "FLAG_DEBUG" on */
  341. flagp = LINK_TO_FLAGS(ACF_TO_LINK(acf));
  342. if ((*flagp & FLAG_DEBUG) == 0)
  343. return (0);
  344. /* look in table of debug acf's */
  345. for (i = 0; i < ndebug_acfs; i++)
  346. if (debug_acfs[i] == acf)
  347. return (1);
  348. return (0);
  349. }
  350. #define MAX_DEBUG_STACK 100
  351. token_t debug_low[MAX_DEBUG_STACK], debug_high[MAX_DEBUG_STACK];
  352. int debug_prev_level[MAX_DEBUG_STACK];
  353. int debug_curr_level[MAX_DEBUG_STACK];
  354. int ndebug_stack = 0;
  355. void
  356. debug_set_level(fcode_env_t *env, int level)
  357. {
  358. debug_curr_level[ndebug_stack - 1] = level;
  359. set_interpreter_debug_level(level);
  360. }
  361. token_t
  362. find_semi_in_colon_def(fcode_env_t *env, acf_t acf)
  363. {
  364. for (; within_dictionary(env, acf); acf++)
  365. if (*acf == (token_t)(&semi_ptr))
  366. return ((token_t)acf);
  367. return (0);
  368. }
  369. void
  370. check_for_debug_entry(fcode_env_t *env)
  371. {
  372. int top;
  373. if (is_debug_word(env, WA) && ndebug_stack < MAX_DEBUG_STACK) {
  374. top = ndebug_stack++;
  375. debug_prev_level[top] = get_interpreter_debug_level();
  376. debug_low[top] = (token_t)WA;
  377. if (*WA == (token_t)(&do_colon)) {
  378. debug_high[top] =
  379. find_semi_in_colon_def(env, WA);
  380. } else {
  381. debug_high[top] = 0; /* marker... */
  382. }
  383. debug_set_level(env, DEBUG_STEPPING);
  384. output_step_message(env);
  385. }
  386. }
  387. void
  388. check_for_debug_exit(fcode_env_t *env)
  389. {
  390. if (ndebug_stack) {
  391. int top = ndebug_stack - 1;
  392. if (debug_high[top] == 0) {
  393. set_interpreter_debug_level(debug_prev_level[top]);
  394. ndebug_stack--;
  395. } else if ((token_t)IP >= debug_low[top] &&
  396. (token_t)IP <= debug_high[top]) {
  397. set_interpreter_debug_level(debug_curr_level[top]);
  398. } else {
  399. set_interpreter_debug_level(debug_prev_level[top]);
  400. }
  401. }
  402. }
  403. void
  404. check_semi_debug_exit(fcode_env_t *env)
  405. {
  406. if (ndebug_stack) {
  407. int top = ndebug_stack - 1;
  408. if ((token_t)(IP - 1) == debug_high[top]) {
  409. set_interpreter_debug_level(debug_prev_level[top]);
  410. ndebug_stack--;
  411. }
  412. }
  413. }
  414. /*
  415. * Really entering do_run, since this may be a recursive entry to do_run,
  416. * we need to set the debug level to what it was previously.
  417. */
  418. int
  419. current_debug_state(fcode_env_t *env)
  420. {
  421. if (ndebug_stack) {
  422. int top = ndebug_stack - 1;
  423. set_interpreter_debug_level(debug_prev_level[top]);
  424. }
  425. return (ndebug_stack);
  426. }
  427. void
  428. clear_debug_state(fcode_env_t *env, int oldstate)
  429. {
  430. if (ndebug_stack && oldstate <= ndebug_stack) {
  431. set_interpreter_debug_level(debug_prev_level[oldstate]);
  432. ndebug_stack = oldstate;
  433. }
  434. }
  435. void
  436. unbug(fcode_env_t *env)
  437. {
  438. int i;
  439. token_t *link;
  440. flag_t *flag;
  441. for (i = ndebug_stack - 1; i >= 0; i--) {
  442. link = ACF_TO_LINK(debug_low[i]);
  443. flag = LINK_TO_FLAGS(link);
  444. *flag &= ~FLAG_DEBUG;
  445. }
  446. clear_debug_state(env, 0);
  447. }
  448. void
  449. output_vitals(fcode_env_t *env)
  450. {
  451. log_message(MSG_FC_DEBUG, "IP=%p, *IP=%p, WA=%p, *WA=%p ", IP,
  452. (IP ? *IP : 0), WA, (WA ? *WA : 0));
  453. }
  454. int
  455. do_exec_debug(fcode_env_t *env, void *fn)
  456. {
  457. int dl = debug_level;
  458. int show_wa = 1;
  459. if ((dl & (DEBUG_EXEC_DUMP_DS | DEBUG_EXEC_DUMP_RS |
  460. DEBUG_EXEC_SHOW_VITALS | DEBUG_EXEC_TRACE | DEBUG_TRACING |
  461. DEBUG_STEPPING)) == 0)
  462. return (0);
  463. if (dl & DEBUG_STEPPING) {
  464. dl |= DEBUG_EXEC_DUMP_DS;
  465. }
  466. if (dl & (DEBUG_STEPPING | DEBUG_EXEC_TRACE)) {
  467. log_message(MSG_FC_DEBUG, "%-15s ", acf_to_name(env, WA));
  468. show_wa = 0;
  469. }
  470. if (dl & DEBUG_EXEC_DUMP_DS)
  471. output_data_stack(env, MSG_FC_DEBUG);
  472. if (dl & DEBUG_EXEC_DUMP_RS)
  473. output_return_stack(env, show_wa, MSG_FC_DEBUG);
  474. if (dl & DEBUG_EXEC_SHOW_VITALS)
  475. output_vitals(env);
  476. if (dl & DEBUG_TRACING)
  477. do_fclib_trace(env, (void *) fn);
  478. log_message(MSG_FC_DEBUG, "\n");
  479. if (dl & DEBUG_STEPPING)
  480. return (do_fclib_step(env));
  481. return (0);
  482. }
  483. static void
  484. smatch(fcode_env_t *env)
  485. {
  486. int len;
  487. char *str, *p;
  488. if ((str = parse_a_string(env, &len)) == NULL)
  489. log_message(MSG_INFO, "smatch: no string\n");
  490. else {
  491. for (p = (char *)env->base; p < (char *)HERE; p++)
  492. if (memcmp(p, str, len) == 0)
  493. log_message(MSG_DEBUG, "%p\n", p);
  494. }
  495. }
  496. void
  497. check_vitals(fcode_env_t *env)
  498. {
  499. int i;
  500. token_t *dptr;
  501. dptr = env->current;
  502. if (*dptr && !within_dictionary(env, (uchar_t *)*dptr))
  503. log_message(MSG_ERROR, "Current: %p outside dictionary\n",
  504. *dptr);
  505. for (i = env->order_depth; i >= 0; i--) {
  506. dptr = env->order[i];
  507. if (!dptr)
  508. continue;
  509. if (*dptr && !within_dictionary(env, (uchar_t *)*dptr))
  510. log_message(MSG_ERROR, "Order%d: %p outside"
  511. " dictionary\n", i, *dptr);
  512. }
  513. if (HERE < env->base || HERE >= env->base + dict_size) {
  514. log_message(MSG_ERROR, "HERE: %p outside range\n", HERE);
  515. }
  516. if (DS < env->ds0 || DS >= &env->ds0[stack_size]) {
  517. forth_abort(env, "DS: %p outside range\n", DS);
  518. }
  519. if (RS < env->rs0 || RS >= &env->rs0[stack_size]) {
  520. log_message(MSG_ERROR, "RS: %p outside range\n", RS);
  521. RS = env->rs0;
  522. }
  523. if (IP && !within_dictionary(env, IP))
  524. log_message(MSG_ERROR, "IP: %p outside dictionary\n", IP);
  525. if (!within_dictionary(env, (void *)env->forth_voc_link))
  526. log_message(MSG_ERROR, "forth_voc_link: %p outside"
  527. " dictionary\n", env->forth_voc_link);
  528. }
  529. static void
  530. dump_table(fcode_env_t *env)
  531. {
  532. int i;
  533. for (i = 0; i < MAX_FCODE; i++) {
  534. if (*(env->table[i].apf) != (token_t)(&f_error)) {
  535. log_message(MSG_DEBUG, "Token: %4x %32s acf = %8p,"
  536. " %8p\n", i, env->table[i].name, env->table[i].apf,
  537. *(env->table[i].apf));
  538. }
  539. }
  540. log_message(MSG_DEBUG, "%d FCODES implemented\n", fcode_impl_count);
  541. }
  542. void
  543. verify_usage(fcode_env_t *env)
  544. {
  545. int i, untested = 0;
  546. for (i = 0; i < MAX_FCODE; i++) {
  547. int verify;
  548. verify = env->table[i].flags & (ANSI_WORD|P1275_WORD);
  549. if ((verify) &&
  550. #ifdef DEBUG
  551. (env->table[i].usage == 0) &&
  552. #endif
  553. (env->table[i].apf)) {
  554. log_message(MSG_DEBUG,
  555. "Untested: %4x %32s acf = %8p, %8p\n", i,
  556. env->table[i].name, env->table[i].apf,
  557. *(env->table[i].apf));
  558. untested++;
  559. }
  560. }
  561. if (untested)
  562. log_message(MSG_DEBUG, "%d untested tokens\n", untested);
  563. }
  564. static void
  565. debugf(fcode_env_t *env)
  566. {
  567. PUSH(DS, (fstack_t)&debug_level);
  568. }
  569. static void
  570. control(fcode_env_t *env)
  571. {
  572. PUSH(DS, (fstack_t)&env->control);
  573. }
  574. struct bittab {
  575. int b_bitval;
  576. char *b_bitname;
  577. } bittab[] = {
  578. DEBUG_CONTEXT, "context",
  579. DEBUG_BYTELOAD_DS, "byteload-ds",
  580. DEBUG_BYTELOAD_RS, "byteload-rs",
  581. DEBUG_BYTELOAD_TOKENS, "byteload-tokens",
  582. DEBUG_NEW_TOKEN, "new-token",
  583. DEBUG_EXEC_TRACE, "exec-trace",
  584. DEBUG_EXEC_SHOW_VITALS, "exec-show-vitals",
  585. DEBUG_EXEC_DUMP_DS, "exec-dump-ds",
  586. DEBUG_EXEC_DUMP_RS, "exec-dump-rs",
  587. DEBUG_COMMA, "comma",
  588. DEBUG_HEADER, "header",
  589. DEBUG_EXIT_WORDS, "exit-words",
  590. DEBUG_EXIT_DUMP, "exit-dump",
  591. DEBUG_DUMP_TOKENS, "dump-tokens",
  592. DEBUG_COLON, "colon",
  593. DEBUG_NEXT_VITALS, "next-vitals",
  594. DEBUG_VOC_FIND, "voc-find",
  595. DEBUG_DUMP_DICT_TOKENS, "dump-dict-tokens",
  596. DEBUG_TOKEN_USAGE, "token-usage",
  597. DEBUG_DUMP_TOKEN_TABLE, "dump-token-table",
  598. DEBUG_SHOW_STACK, "show-stack",
  599. DEBUG_SHOW_RS, "show-rs",
  600. DEBUG_TRACING, "tracing",
  601. DEBUG_TRACE_STACK, "trace-stack",
  602. DEBUG_CALL_METHOD, "call-method",
  603. DEBUG_ACTIONS, "actions",
  604. DEBUG_STEPPING, "stepping",
  605. DEBUG_REG_ACCESS, "reg-access",
  606. DEBUG_ADDR_ABUSE, "addr-abuse",
  607. DEBUG_FIND_FCODE, "find-fcode",
  608. DEBUG_UPLOAD, "upload",
  609. 0
  610. };
  611. void
  612. debug_flags_to_output(fcode_env_t *env, int flags)
  613. {
  614. int first = 1, i;
  615. for (i = 0; bittab[i].b_bitval != 0; i++)
  616. if (bittab[i].b_bitval & flags) {
  617. if (!first)
  618. log_message(MSG_INFO, ",");
  619. first = 0;
  620. log_message(MSG_INFO, bittab[i].b_bitname);
  621. }
  622. if (first)
  623. log_message(MSG_INFO, "<empty>");
  624. log_message(MSG_INFO, "\n");
  625. }
  626. static void
  627. dot_debugf(fcode_env_t *env)
  628. {
  629. debug_flags_to_output(env, debug_level);
  630. }
  631. static void
  632. debugf_qmark(fcode_env_t *env)
  633. {
  634. debug_flags_to_output(env, 0xffffffff);
  635. }
  636. int
  637. debug_flags_to_mask(char *str)
  638. {
  639. int flags = 0;
  640. char *p;
  641. int i;
  642. if (isdigit(*str)) {
  643. if (*str == '0') {
  644. str++;
  645. if (*str == 'x' || *str == 'X') {
  646. sscanf(str + 1, "%x", &flags);
  647. } else
  648. sscanf(str, "%o", &flags);
  649. } else
  650. sscanf(str, "%d", &flags);
  651. return (flags);
  652. }
  653. if (strcmp(str, "clear") == 0)
  654. return (0);
  655. if (strcmp(str, "all") == 0)
  656. return (0xffffffff & ~DEBUG_STEPPING);
  657. if (*str) {
  658. do {
  659. if (p = strchr(str, ','))
  660. *p++ = '\0';
  661. for (i = 0; bittab[i].b_bitname != 0; i++)
  662. if (strcmp(str, bittab[i].b_bitname) == 0) {
  663. flags |= bittab[i].b_bitval;
  664. break;
  665. }
  666. if (bittab[i].b_bitname == 0)
  667. log_message(MSG_WARN,
  668. "Unknown debug flag: '%s'\n", str);
  669. str = p;
  670. } while (p);
  671. }
  672. return (flags);
  673. }
  674. static void
  675. set_debugf(fcode_env_t *env)
  676. {
  677. char *str;
  678. str = parse_a_string(env, NULL);
  679. debug_level = debug_flags_to_mask(str);
  680. }
  681. static acf_t
  682. show_a_word(fcode_env_t *env, acf_t acf, void *arg)
  683. {
  684. static int nshow_words = 0;
  685. if (acf == NULL) {
  686. if (nshow_words > 0) {
  687. log_message(MSG_DEBUG, "\n");
  688. nshow_words = 0;
  689. }
  690. return (NULL);
  691. }
  692. log_message(MSG_DEBUG, "%15s ", get_name_or_acf(ACF_TO_LINK(acf)));
  693. nshow_words++;
  694. if (nshow_words >= 4) {
  695. log_message(MSG_DEBUG, "\n");
  696. nshow_words = 0;
  697. }
  698. return (NULL);
  699. }
  700. void
  701. words(fcode_env_t *env)
  702. {
  703. (void) search_all_dictionaries(env, show_a_word, NULL);
  704. (void) show_a_word(env, NULL, NULL);
  705. }
  706. static acf_t
  707. dump_a_word(fcode_env_t *env, acf_t acf, void *arg)
  708. {
  709. output_acf_name(acf);
  710. return (NULL);
  711. }
  712. void
  713. dump_words(fcode_env_t *env)
  714. {
  715. (void) search_all_dictionaries(env, dump_a_word, NULL);
  716. output_acf_name(NULL);
  717. }
  718. static void
  719. dump_line(uchar_t *ptr)
  720. {
  721. uchar_t *byte;
  722. int i;
  723. log_message(MSG_INFO, "%p ", ptr);
  724. for (i = 0, byte = ptr; i < 16; i++) {
  725. if (i == 8)
  726. log_message(MSG_INFO, " ");
  727. log_message(MSG_INFO, "%02.2x ", *byte++);
  728. }
  729. log_message(MSG_INFO, " ");
  730. for (i = 0, byte = ptr; i < 16; i++, byte++) {
  731. log_message(MSG_INFO, "%c",
  732. ((*byte < 0x20) || (*byte > 0x7f)) ? '.' : *byte);
  733. }
  734. log_message(MSG_INFO, "\n");
  735. }
  736. void
  737. dump_dictionary(fcode_env_t *env)
  738. {
  739. uchar_t *ptr;
  740. log_message(MSG_INFO, "Dictionary dump: base: %p\n", env->base);
  741. for (ptr = (uchar_t *)(((long)(env->base)) & ~0xf); ptr < HERE;
  742. ptr += 16)
  743. dump_line(ptr);
  744. }
  745. static char *
  746. acf_to_fcode_name(fcode_env_t *env, acf_t acf)
  747. {
  748. int i;
  749. for (i = 0; i < MAX_FCODE; i++)
  750. if (env->table[i].apf == acf)
  751. return (env->table[i].name);
  752. return (NULL);
  753. }
  754. static acf_t
  755. acf_match(fcode_env_t *env, acf_t sacf, void *macf)
  756. {
  757. if (sacf == (acf_t)macf)
  758. return (sacf);
  759. return (NULL);
  760. }
  761. /*
  762. * Given an ACF, return ptr to name or "unknown" string.
  763. */
  764. char *
  765. acf_to_name(fcode_env_t *env, acf_t acf)
  766. {
  767. struct bitab *bip;
  768. static char name_buf[256];
  769. uchar_t *p, *np;
  770. int i, n;
  771. if (!within_dictionary(env, acf)) {
  772. if ((bip = lookup_builtin((token_t)acf)) != NULL)
  773. return (bip->bi_name);
  774. return (NULL);
  775. }
  776. return (get_name_or_acf(ACF_TO_LINK(acf)));
  777. }
  778. int
  779. within_dictionary(fcode_env_t *env, void *addr)
  780. {
  781. return ((uchar_t *)addr >= env->base &&
  782. (uchar_t *)addr < env->base + dict_size);
  783. }
  784. static int
  785. within_word(fcode_env_t *env, acf_t acf, acf_t wacf)
  786. {
  787. if (acf == wacf || acf + 1 == wacf)
  788. return (1);
  789. if (*acf == (token_t)(&do_colon)) {
  790. do {
  791. if (acf == wacf)
  792. return (1);
  793. } while (*acf++ != (token_t)(&semi_ptr));
  794. }
  795. return (0);
  796. }
  797. /*
  798. * Given an ACF in the middle of a colon definition, search dictionary towards
  799. * beginning for "colon" acf. If we find a "semi" acf first, we're not in
  800. * the middle of a colon-def (temporary execute?).
  801. */
  802. char *
  803. acf_backup_search(fcode_env_t *env, acf_t acf)
  804. {
  805. acf_t nacf;
  806. char *name;
  807. if ((acf_t)_ALIGN(acf, token_t) == acf && within_dictionary(env, acf)) {
  808. for (nacf = acf; nacf >= (acf_t)env->base; nacf--)
  809. if (*nacf == (token_t)(&do_colon) ||
  810. *nacf == (token_t)(&semi_ptr))
  811. break;
  812. if (nacf >= (acf_t)env->base && *nacf == (token_t)(&do_colon) &&
  813. (name = get_name(ACF_TO_LINK(nacf))) != NULL)
  814. return (name);
  815. }
  816. return (acf_to_str(acf));
  817. }
  818. /*
  819. * Print out current process's C stack using /usr/proc/bin/pstack
  820. */
  821. void
  822. ctrace(fcode_env_t *env)
  823. {
  824. char buf[256];
  825. FILE *fd;
  826. log_message(MSG_DEBUG, "Interpreter C Stack:\n");
  827. sprintf(buf, "/usr/proc/bin/pstack %d", getpid());
  828. if ((fd = popen(buf, "r")) == NULL)
  829. log_perror(MSG_ERROR, "Can't run: %s", buf);
  830. else {
  831. while (fgets(buf, sizeof (buf), fd))
  832. log_message(MSG_DEBUG, buf);
  833. fclose(fd);
  834. }
  835. }
  836. /*
  837. * Dump data, return stacks, try to unthread forth calling stack.
  838. */
  839. void
  840. ftrace(fcode_env_t *env)
  841. {
  842. log_message(MSG_DEBUG, "Forth Interpreter Stacks:\n");
  843. output_data_stack(env, MSG_DEBUG);
  844. output_return_stack(env, 1, MSG_DEBUG);
  845. log_message(MSG_DEBUG, "\n");
  846. }
  847. int in_forth_abort;
  848. /*
  849. * Handle fatal error, if interactive mode, return to ok prompt.
  850. */
  851. void
  852. forth_abort(fcode_env_t *env, char *fmt, ...)
  853. {
  854. va_list ap;
  855. char msg[256];
  856. if (in_forth_abort) {
  857. log_message(MSG_FATAL, "ABORT: abort within forth_abort\n");
  858. abort();
  859. }
  860. in_forth_abort++;
  861. va_start(ap, fmt);
  862. vsprintf(msg, fmt, ap);
  863. log_message(MSG_ERROR, "ABORT: %s\n", msg);
  864. if (env) {
  865. ctrace(env);
  866. ftrace(env);
  867. }
  868. return_to_interact(env);
  869. /*
  870. * If not in interactive mode, return_to_interact just returns.
  871. */
  872. exit(1);
  873. }
  874. /*
  875. * Handle fatal system call error
  876. */
  877. void
  878. forth_perror(fcode_env_t *env, char *fmt, ...)
  879. {
  880. va_list ap;
  881. char msg[256];
  882. int save_errno = errno; /* just in case... */
  883. va_start(ap, fmt);
  884. vsprintf(msg, fmt, ap);
  885. forth_abort(env, "%s: %s", msg, strerror(save_errno));
  886. }
  887. static void
  888. show_stack(fcode_env_t *env)
  889. {
  890. #ifdef DEBUG
  891. debug_level ^= DEBUG_SHOW_STACK;
  892. #else
  893. /*EMPTY*/
  894. #endif
  895. }
  896. static void
  897. print_bytes_header(int width, int offset)
  898. {
  899. int i;
  900. for (i = 0; i < width; i++)
  901. log_message(MSG_INFO, " ");
  902. log_message(MSG_INFO, " ");
  903. for (i = 0; i < 16; i++) {
  904. if (i == 8)
  905. log_message(MSG_INFO, " ");
  906. if (i == offset)
  907. log_message(MSG_INFO, "\\/ ");
  908. else
  909. log_message(MSG_INFO, "%2x ", i);
  910. }
  911. log_message(MSG_INFO, " ");
  912. for (i = 0; i < 16; i++) {
  913. if (i == offset)
  914. log_message(MSG_INFO, "v");
  915. else
  916. log_message(MSG_INFO, "%x", i);
  917. }
  918. log_message(MSG_INFO, "\n");
  919. }
  920. static void
  921. dump(fcode_env_t *env)
  922. {
  923. uchar_t *data;
  924. int len, offset;
  925. char buf[20];
  926. len = POP(DS);
  927. data = (uchar_t *)POP(DS);
  928. offset = ((long)data) & 0xf;
  929. len += offset;
  930. data = (uchar_t *)((long)data & ~0xf);
  931. sprintf(buf, "%p", data);
  932. print_bytes_header(strlen(buf), offset);
  933. for (len += offset; len > 0; len -= 16, data += 16)
  934. dump_line(data);
  935. }
  936. static acf_t
  937. do_sifting(fcode_env_t *env, acf_t acf, void *pat)
  938. {
  939. char *name;
  940. if ((name = get_name(ACF_TO_LINK(acf))) != NULL && strstr(name, pat))
  941. output_acf_name(acf);
  942. return (NULL);
  943. }
  944. static void
  945. sifting(fcode_env_t *env)
  946. {
  947. char *pat;
  948. if ((pat = parse_a_string(env, NULL)) != NULL) {
  949. (void) search_all_dictionaries(env, do_sifting, pat);
  950. output_acf_name(NULL);
  951. }
  952. }
  953. void
  954. print_level(int level, int *doprint)
  955. {
  956. int i;
  957. if (*doprint) {
  958. log_message(MSG_DEBUG, "\n ");
  959. for (i = 0; i < level; i++)
  960. log_message(MSG_DEBUG, " ");
  961. *doprint = 0;
  962. }
  963. }
  964. #define BI_QUOTE 1
  965. #define BI_BLIT 2
  966. #define BI_BDO 3
  967. #define BI_QDO 4
  968. #define BI_BR 5
  969. #define BI_QBR 6
  970. #define BI_BOF 7
  971. #define BI_LOOP 8
  972. #define BI_PLOOP 9
  973. #define BI_TO 10
  974. #define BI_SEMI 11
  975. #define BI_COLON 12
  976. #define BI_NOOP 13
  977. #define BI_NOTYET 14 /* unimplented in "see" */
  978. struct bitab bitab[] = {
  979. (token_t)(&quote_ptr), "\"", BI_QUOTE,
  980. (token_t)(&blit_ptr), "blit", BI_BLIT,
  981. (token_t)(&do_bdo_ptr), "do", BI_BDO,
  982. (token_t)(&do_bqdo_ptr), "?do", BI_QDO,
  983. (token_t)(&bbranch_ptrs[0]), "br", BI_BR,
  984. (token_t)(&bbranch_ptrs[1]), "qbr", BI_QBR,
  985. (token_t)(&bbranch_ptrs[2]), "bof", BI_BOF,
  986. (token_t)(&do_loop_ptr), "loop", BI_LOOP,
  987. (token_t)(&do_ploop_ptr), "+loop", BI_PLOOP,
  988. (token_t)(&to_ptr), "to", BI_NOOP,
  989. (token_t)(&semi_ptr), ";", BI_SEMI,
  990. (token_t)(&do_colon), ":", BI_COLON,
  991. (token_t)(&tlit_ptr), "[']", BI_NOOP,
  992. (token_t)(&do_leave_ptr), "leave", BI_NOTYET,
  993. (token_t)(&create_ptr), "create", BI_NOTYET,
  994. (token_t)(&does_ptr), "does>", BI_NOTYET,
  995. (token_t)(&value_defines[0][0]), "a.@", BI_NOTYET,
  996. (token_t)(&value_defines[0][1]), "a.!", BI_NOTYET,
  997. (token_t)(&value_defines[0][2]), "a.nop", BI_NOTYET,
  998. (token_t)(&value_defines[1][0]), "a.i@", BI_NOTYET,
  999. (token_t)(&value_defines[1][1]), "a.i!", BI_NOTYET,
  1000. (token_t)(&value_defines[1][2]), "a.iad", BI_NOTYET,
  1001. (token_t)(&value_defines[2][0]), "a.defer", BI_NOTYET,
  1002. (token_t)(&value_defines[2][1]), "a.@", BI_NOTYET,
  1003. (token_t)(&value_defines[2][2]), "a.nop", BI_NOTYET,
  1004. (token_t)(&value_defines[3][0]), "a.defexec", BI_NOTYET,
  1005. (token_t)(&value_defines[3][1]), "a.iset", BI_NOTYET,
  1006. (token_t)(&value_defines[3][2]), "a.iad", BI_NOTYET,
  1007. (token_t)(&value_defines[4][0]), "a.binit", BI_NOTYET,
  1008. (token_t)(&value_defines[4][1]), "a.2drop", BI_NOTYET,
  1009. (token_t)(&value_defines[4][2]), "a.nop", BI_NOTYET,
  1010. (token_t)(&value_defines[5][0]), "a.ibinit", BI_NOTYET,
  1011. (token_t)(&value_defines[5][1]), "a.2drop", BI_NOTYET,
  1012. (token_t)(&value_defines[5][2]), "a.iad", BI_NOTYET,
  1013. 0
  1014. };
  1015. struct bitab *
  1016. lookup_builtin(token_t builtin)
  1017. {
  1018. int i;
  1019. for (i = 0; bitab[i].bi_ptr; i++)
  1020. if (bitab[i].bi_ptr == builtin)
  1021. return (&bitab[i]);
  1022. return (NULL);
  1023. }
  1024. static void
  1025. paren_see(fcode_env_t *env)
  1026. {
  1027. acf_t save_acf = (acf_t)POP(DS);
  1028. acf_t acf = save_acf;
  1029. int i, n, pass;
  1030. token_t brtab[30], thentab[30], brstk[30];
  1031. int nbrtab = 0, nthentab = 0, nbrstk = 0;
  1032. uchar_t *p;
  1033. int level = 0, doprintlevel = 1, nthen;
  1034. struct bitab *bip;
  1035. token_t last_lit = 0, case_lit = 0, endof_loc = 0, endcase_loc = 0;
  1036. if ((bip = lookup_builtin(*acf)) == NULL ||
  1037. bip->bi_type != BI_COLON) {
  1038. if (bip = lookup_builtin((token_t)acf))
  1039. log_message(MSG_INFO, "%s: builtin\n", bip->bi_name);
  1040. else
  1041. log_message(MSG_INFO, "%s: builtin\n",
  1042. acf_to_name(env, acf));
  1043. return;
  1044. }
  1045. log_message(MSG_INFO, ": %s", acf_to_name(env, acf));
  1046. for (pass = 0; pass < 2; pass++) {
  1047. acf = save_acf;
  1048. for (acf++; ; acf++) {
  1049. if (pass) {
  1050. print_level(level, &doprintlevel);
  1051. for (nthen = 0; nthentab > 0 &&
  1052. thentab[nthentab-1] == (token_t)acf;
  1053. nthentab--)
  1054. nthen++;
  1055. if (nthen) {
  1056. level -= nthen;
  1057. doprintlevel = 1;
  1058. print_level(level, &doprintlevel);
  1059. for (i = 0; i < nthen; i++)
  1060. log_message(MSG_INFO, "then ");
  1061. }
  1062. print_level(level, &doprintlevel);
  1063. for (i = 0; i < nbrtab; i += 2)
  1064. if ((token_t)acf == brtab[i]) {
  1065. log_message(MSG_INFO, "begin ");
  1066. brstk[nbrstk++] = brtab[i+1];
  1067. level++;
  1068. doprintlevel = 1;
  1069. }
  1070. print_level(level, &doprintlevel);
  1071. if (case_lit == (token_t)acf) {
  1072. log_message(MSG_INFO, "case ");
  1073. doprintlevel = 1;
  1074. print_level(level, &doprintlevel);
  1075. }
  1076. if (endof_loc == (token_t)acf) {
  1077. log_message(MSG_INFO, "endof ");
  1078. doprintlevel = 1;
  1079. print_level(level, &doprintlevel);
  1080. }
  1081. if (endcase_loc == (token_t)acf) {
  1082. doprintlevel = 1;
  1083. print_level(level, &doprintlevel);
  1084. log_message(MSG_INFO, "endcase ");
  1085. }
  1086. }
  1087. if ((bip = lookup_builtin((token_t)*acf)) == 0) {
  1088. last_lit = (token_t)acf;
  1089. if (pass)
  1090. log_message(MSG_INFO, "%s ",
  1091. acf_to_name(env, (acf_t)*acf));
  1092. continue;
  1093. }
  1094. if (bip->bi_type == BI_SEMI) {
  1095. if (pass) {
  1096. log_message(MSG_INFO, "\n");
  1097. log_message(MSG_INFO, "%s\n",
  1098. bip->bi_name);
  1099. }
  1100. break;
  1101. }
  1102. switch (bip->bi_type) {
  1103. case BI_NOOP:
  1104. case BI_NOTYET:
  1105. if (pass)
  1106. log_message(MSG_INFO, "%s ",
  1107. bip->bi_name);
  1108. break;
  1109. case BI_QUOTE:
  1110. if (pass)
  1111. log_message(MSG_INFO, "\" ");
  1112. acf++;
  1113. p = (uchar_t *)acf;
  1114. n = *p++;
  1115. if (pass)
  1116. log_message(MSG_INFO, "%s\" ", p);
  1117. p += n + 1;
  1118. for (; ((token_t)(p)) & (sizeof (token_t) - 1);
  1119. p++)
  1120. ;
  1121. acf = (acf_t)p;
  1122. acf--;
  1123. break;
  1124. case BI_BLIT:
  1125. acf++;
  1126. if (pass)
  1127. log_message(MSG_INFO, "%x ", *acf);
  1128. break;
  1129. case BI_BDO:
  1130. case BI_QDO:
  1131. if (pass) {
  1132. log_message(MSG_INFO, "%s ",
  1133. bip->bi_name);
  1134. doprintlevel = 1;
  1135. level++;
  1136. }
  1137. acf++;
  1138. break;
  1139. case BI_BR:
  1140. acf++;
  1141. if (pass) {
  1142. if (*acf < (token_t)acf) {
  1143. if (nbrstk) {
  1144. doprintlevel = 1;
  1145. level--;
  1146. print_level(level,
  1147. &doprintlevel);
  1148. log_message(MSG_INFO,
  1149. "repeat ");
  1150. nbrstk--;
  1151. } else
  1152. log_message(MSG_INFO,
  1153. "[br back?]");
  1154. } else if (nthentab) {
  1155. doprintlevel = 1;
  1156. print_level(level - 1,
  1157. &doprintlevel);
  1158. log_message(MSG_INFO, "else ");
  1159. doprintlevel = 1;
  1160. thentab[nthentab - 1] = *acf;
  1161. }
  1162. } else {
  1163. if (*acf < (token_t)acf) {
  1164. brtab[nbrtab++] = *acf;
  1165. brtab[nbrtab++] = (token_t)acf;
  1166. }
  1167. if (endcase_loc == 0 &&
  1168. case_lit) {
  1169. endcase_loc = *acf;
  1170. }
  1171. }
  1172. break;
  1173. case BI_QBR:
  1174. acf++;
  1175. if (pass) {
  1176. if (*acf < (token_t)acf) {
  1177. if (nbrstk) {
  1178. doprintlevel = 1;
  1179. level--;
  1180. print_level(level,
  1181. &doprintlevel);
  1182. log_message(MSG_INFO,
  1183. "until ");
  1184. nbrstk--;
  1185. } else
  1186. log_message(MSG_INFO,
  1187. "[br back?]");
  1188. } else if (nbrstk > 0 &&
  1189. *acf >= brstk[nbrstk - 1]) {
  1190. doprintlevel = 1;
  1191. print_level(level - 1,
  1192. &doprintlevel);
  1193. log_message(MSG_INFO,
  1194. "while ");
  1195. doprintlevel = 1;
  1196. } else {
  1197. log_message(MSG_INFO, "if ");
  1198. doprintlevel = 1;
  1199. level++;
  1200. thentab[nthentab++] = *acf;
  1201. }
  1202. } else if (*acf < (token_t)acf) {
  1203. brtab[nbrtab++] = *acf;
  1204. brtab[nbrtab++] = (token_t)acf;
  1205. }
  1206. break;
  1207. case BI_BOF:
  1208. acf++;
  1209. if (pass) {
  1210. log_message(MSG_INFO, "of ");
  1211. endof_loc = *acf;
  1212. } else if (case_lit == 0) {
  1213. case_lit = last_lit;
  1214. }
  1215. break;
  1216. case BI_LOOP:
  1217. case BI_PLOOP:
  1218. if (pass) {
  1219. level--;
  1220. doprintlevel = 1;
  1221. print_level(level, &doprintlevel);
  1222. log_message(MSG_INFO, "%s ",
  1223. bip->bi_name);
  1224. }
  1225. acf++;
  1226. break;
  1227. default:
  1228. log_message(MSG_ERROR, "Invalid builtin %s\n",
  1229. bip->bi_name);
  1230. }
  1231. }
  1232. }
  1233. }
  1234. static void
  1235. see(fcode_env_t *env)
  1236. {
  1237. fstack_t d;
  1238. parse_word(env);
  1239. dollar_find(env);
  1240. d = POP(DS);
  1241. if (d)
  1242. paren_see(env);
  1243. else {
  1244. log_message(MSG_WARN, "?");
  1245. two_drop(env);
  1246. }
  1247. }
  1248. static acf_t
  1249. do_dot_calls(fcode_env_t *env, acf_t acf, void *cacf)
  1250. {
  1251. token_t *dptr = ACF_TO_LINK(acf);
  1252. token_t *wptr = acf;
  1253. if (*wptr == (token_t)(&do_colon)) {
  1254. do {
  1255. if ((acf_t)(*wptr) == (acf_t)cacf)
  1256. output_acf_name(acf);
  1257. } while (*wptr++ != (token_t)(&semi_ptr));
  1258. } else if ((acf_t)(*wptr) == cacf)
  1259. output_acf_name(acf);
  1260. else if (wptr == (token_t *)cacf)
  1261. output_acf_name(acf);
  1262. return (NULL);
  1263. }
  1264. static void
  1265. dot_calls(fcode_env_t *env)
  1266. {
  1267. acf_t acf = (acf_t)POP(DS);
  1268. search_all_dictionaries(env, do_dot_calls, acf);
  1269. output_acf_name(NULL);
  1270. }
  1271. static void
  1272. dot_pci_space(fcode_env_t *env)
  1273. {
  1274. fstack_t d = POP(DS);
  1275. switch ((d >> 24) & 0x3) {
  1276. case 0: log_message(MSG_INFO, "Config,"); break;
  1277. case 1: log_message(MSG_INFO, "IO,"); break;
  1278. case 2: log_message(MSG_INFO, "Memory32,"); break;
  1279. case 3: log_message(MSG_INFO, "Memory64,"); break;
  1280. }
  1281. if (d & 0x80000000)
  1282. log_message(MSG_INFO, "Not_reloc,");
  1283. if (d & 0x400000000)
  1284. log_message(MSG_INFO, "Prefetch,");
  1285. if (d & 0x200000000)
  1286. log_message(MSG_INFO, "Alias,");
  1287. log_message(MSG_INFO, "Bus%d,", (d >> 16) & 0xff);
  1288. log_message(MSG_INFO, "Dev%d,", (d >> 11) & 0x1f);
  1289. log_message(MSG_INFO, "Func%d,", (d >> 8) & 0x7);
  1290. log_message(MSG_INFO, "Reg%x", d & 0xff);
  1291. log_message(MSG_INFO, "\n");
  1292. }
  1293. void
  1294. fcode_debug(fcode_env_t *env)
  1295. {
  1296. PUSH(DS, (fstack_t)(&env->fcode_debug));
  1297. }
  1298. static void
  1299. base_addr(fcode_env_t *env)
  1300. {
  1301. PUSH(DS, (fstack_t)env->base);
  1302. }
  1303. static int mw_valid;
  1304. static int mw_size;
  1305. static void *mw_addr;
  1306. static fstack_t mw_value;
  1307. static fstack_t mw_lastvalue;
  1308. static fstack_t
  1309. mw_fetch(void)
  1310. {
  1311. switch (mw_size) {
  1312. case 1: return (*((uint8_t *)mw_addr));
  1313. case 2: return (*((uint16_t *)mw_addr));
  1314. case 4: return (*((uint32_t *)mw_addr));
  1315. case 8: return (*((uint64_t *)mw_addr));
  1316. }
  1317. return (0);
  1318. }
  1319. void
  1320. do_memory_watch(fcode_env_t *env)
  1321. {
  1322. fstack_t value;
  1323. if (!mw_valid)
  1324. return;
  1325. value = mw_fetch();
  1326. if (value != mw_lastvalue) {
  1327. if (mw_valid == 1 || mw_value == value) {
  1328. log_message(MSG_INFO,
  1329. "memory-watch: %p/%d: %llx -> %llx\n",
  1330. mw_addr, mw_size, (uint64_t)mw_lastvalue,
  1331. (uint64_t)value);
  1332. do_fclib_step(env);
  1333. }
  1334. mw_lastvalue = value;
  1335. }
  1336. }
  1337. static void
  1338. set_memory_watch(fcode_env_t *env, int type, int size, void *addr,
  1339. fstack_t value)
  1340. {
  1341. switch (size) {
  1342. case 1: case 2: case 4: case 8:
  1343. break;
  1344. default:
  1345. log_message(MSG_ERROR, "set_memory_watch: invalid size: %d\n",
  1346. size);
  1347. return;
  1348. }
  1349. mw_valid = type;
  1350. mw_size = size;
  1351. mw_addr = addr;
  1352. mw_value = value;
  1353. mw_lastvalue = mw_fetch();
  1354. }
  1355. static void
  1356. memory_watch(fcode_env_t *env)
  1357. {
  1358. int size = POP(DS);
  1359. void *addr = (void *)POP(DS);
  1360. set_memory_watch(env, 1, size, addr, 0);
  1361. }
  1362. static void
  1363. memory_watch_value(fcode_env_t *env)
  1364. {
  1365. int size = POP(DS);
  1366. void *addr = (void *)POP(DS);
  1367. fstack_t value = POP(DS);
  1368. set_memory_watch(env, 2, size, addr, value);
  1369. }
  1370. static void
  1371. memory_watch_clear(fcode_env_t *env)
  1372. {
  1373. mw_valid = 0;
  1374. }
  1375. static void
  1376. vsearch(fcode_env_t *env)
  1377. {
  1378. fstack_t value;
  1379. int size = POP(DS);
  1380. fstack_t match_value = POP(DS);
  1381. uchar_t *toaddr = (uchar_t *)POP(DS);
  1382. uchar_t *fromaddr = (uchar_t *)POP(DS);
  1383. log_message(MSG_INFO, "%p to %p by %d looking for %llx\n", fromaddr,
  1384. toaddr, size, (uint64_t)match_value);
  1385. for (; fromaddr < toaddr; fromaddr += size) {
  1386. switch (size) {
  1387. case 1: value = *((uint8_t *)fromaddr); break;
  1388. case 2: value = *((uint16_t *)fromaddr); break;
  1389. case 4: value = *((uint32_t *)fromaddr); break;
  1390. case 8: value = *((uint64_t *)fromaddr); break;
  1391. default:
  1392. log_message(MSG_INFO, "Invalid size: %d\n", size);
  1393. return;
  1394. }
  1395. if (value == match_value)
  1396. log_message(MSG_INFO, "%p\n", fromaddr);
  1397. }
  1398. }
  1399. #pragma init(_init)
  1400. static void
  1401. _init(void)
  1402. {
  1403. fcode_env_t *env = initial_env;
  1404. ASSERT(env);
  1405. NOTICE;
  1406. FORTH(IMMEDIATE, "words", words);
  1407. FORTH(IMMEDIATE, "dump-words", dump_words);
  1408. FORTH(IMMEDIATE, "dump-dict", dump_dictionary);
  1409. FORTH(IMMEDIATE, "dump-table", dump_table);
  1410. FORTH(0, "debugf", debugf);
  1411. FORTH(0, ".debugf", dot_debugf);
  1412. FORTH(0, "set-debugf", set_debugf);
  1413. FORTH(0, "debugf?", debugf_qmark);
  1414. FORTH(0, "control", control);
  1415. FORTH(0, "dump", dump);
  1416. FORTH(IMMEDIATE, "showstack", show_stack);
  1417. FORTH(IMMEDIATE, "sifting", sifting);
  1418. FORTH(IMMEDIATE, "ctrace", ctrace);
  1419. FORTH(IMMEDIATE, "ftrace", ftrace);
  1420. FORTH(0, "see", see);
  1421. FORTH(0, "(see)", paren_see);
  1422. FORTH(0, "base-addr", base_addr);
  1423. FORTH(0, "smatch", smatch);
  1424. FORTH(0, ".calls", dot_calls);
  1425. FORTH(0, ".pci-space", dot_pci_space);
  1426. FORTH(0, "(debug)", paren_debug);
  1427. FORTH(0, "debug", debug);
  1428. FORTH(0, ".debug", dot_debug);
  1429. FORTH(0, "undebug", undebug);
  1430. FORTH(0, "memory-watch", memory_watch);
  1431. FORTH(0, "memory-watch-value", memory_watch_value);
  1432. FORTH(0, "memory-watch-clear", memory_watch_clear);
  1433. FORTH(0, "vsearch", vsearch);
  1434. }