debug.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /****************************************************************************
  2. *
  3. * Realmode X86 Emulator Library
  4. *
  5. * Copyright (C) 1991-2004 SciTech Software, Inc.
  6. * Copyright (C) David Mosberger-Tang
  7. * Copyright (C) 1999 Egbert Eich
  8. *
  9. * ========================================================================
  10. *
  11. * Permission to use, copy, modify, distribute, and sell this software and
  12. * its documentation for any purpose is hereby granted without fee,
  13. * provided that the above copyright notice appear in all copies and that
  14. * both that copyright notice and this permission notice appear in
  15. * supporting documentation, and that the name of the authors not be used
  16. * in advertising or publicity pertaining to distribution of the software
  17. * without specific, written prior permission. The authors makes no
  18. * representations about the suitability of this software for any purpose.
  19. * It is provided "as is" without express or implied warranty.
  20. *
  21. * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  22. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  23. * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  24. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  25. * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  26. * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  27. * PERFORMANCE OF THIS SOFTWARE.
  28. *
  29. * ========================================================================
  30. *
  31. * Language: ANSI C
  32. * Environment: Any
  33. * Developer: Kendall Bennett
  34. *
  35. * Description: This file contains the code to handle debugging of the
  36. * emulator.
  37. *
  38. ****************************************************************************/
  39. #include "x86emu/x86emui.h"
  40. #include <stdarg.h>
  41. #if defined(CONFIG_BIOSEMU)
  42. /*----------------------------- Implementation ----------------------------*/
  43. #ifdef DEBUG
  44. static void print_encoded_bytes(u16 s, u16 o);
  45. static void print_decoded_instruction(void);
  46. static int parse_line(char *s, int *ps, int *n);
  47. /* should look something like debug's output. */
  48. void X86EMU_trace_regs(void)
  49. {
  50. if (DEBUG_TRACE()) {
  51. x86emu_dump_regs();
  52. }
  53. if (DEBUG_DECODE() && !DEBUG_DECODE_NOPRINT()) {
  54. printk("%04x:%04x ", M.x86.saved_cs, M.x86.saved_ip);
  55. print_encoded_bytes(M.x86.saved_cs, M.x86.saved_ip);
  56. print_decoded_instruction();
  57. }
  58. }
  59. void X86EMU_trace_xregs(void)
  60. {
  61. if (DEBUG_TRACE()) {
  62. x86emu_dump_xregs();
  63. }
  64. }
  65. void x86emu_just_disassemble(void)
  66. {
  67. /*
  68. * This routine called if the flag DEBUG_DISASSEMBLE is set kind
  69. * of a hack!
  70. */
  71. printk("%04x:%04x ", M.x86.saved_cs, M.x86.saved_ip);
  72. print_encoded_bytes(M.x86.saved_cs, M.x86.saved_ip);
  73. print_decoded_instruction();
  74. }
  75. static void disassemble_forward(u16 seg, u16 off, int n)
  76. {
  77. X86EMU_sysEnv tregs;
  78. int i;
  79. u8 op1;
  80. /*
  81. * hack, hack, hack. What we do is use the exact machinery set up
  82. * for execution, except that now there is an additional state
  83. * flag associated with the "execution", and we are using a copy
  84. * of the register struct. All the major opcodes, once fully
  85. * decoded, have the following two steps: TRACE_REGS(r,m);
  86. * SINGLE_STEP(r,m); which disappear if DEBUG is not defined to
  87. * the preprocessor. The TRACE_REGS macro expands to:
  88. *
  89. * if (debug&DEBUG_DISASSEMBLE)
  90. * {just_disassemble(); goto EndOfInstruction;}
  91. * if (debug&DEBUG_TRACE) trace_regs(r,m);
  92. *
  93. * ...... and at the last line of the routine.
  94. *
  95. * EndOfInstruction: end_instr();
  96. *
  97. * Up to the point where TRACE_REG is expanded, NO modifications
  98. * are done to any register EXCEPT the IP register, for fetch and
  99. * decoding purposes.
  100. *
  101. * This was done for an entirely different reason, but makes a
  102. * nice way to get the system to help debug codes.
  103. */
  104. tregs = M;
  105. tregs.x86.R_IP = off;
  106. tregs.x86.R_CS = seg;
  107. /* reset the decoding buffers */
  108. tregs.x86.enc_str_pos = 0;
  109. tregs.x86.enc_pos = 0;
  110. /* turn on the "disassemble only, no execute" flag */
  111. tregs.x86.debug |= DEBUG_DISASSEMBLE_F;
  112. /* DUMP NEXT n instructions to screen in straight_line fashion */
  113. /*
  114. * This looks like the regular instruction fetch stream, except
  115. * that when this occurs, each fetched opcode, upon seeing the
  116. * DEBUG_DISASSEMBLE flag set, exits immediately after decoding
  117. * the instruction. XXX --- CHECK THAT MEM IS NOT AFFECTED!!!
  118. * Note the use of a copy of the register structure...
  119. */
  120. for (i = 0; i < n; i++) {
  121. op1 = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++));
  122. (x86emu_optab[op1]) (op1);
  123. }
  124. /* end major hack mode. */
  125. }
  126. void x86emu_check_ip_access(void)
  127. {
  128. /* NULL as of now */
  129. }
  130. void x86emu_check_sp_access(void)
  131. {
  132. }
  133. void x86emu_check_mem_access(u32 dummy)
  134. {
  135. /* check bounds, etc */
  136. }
  137. void x86emu_check_data_access(uint dummy1, uint dummy2)
  138. {
  139. /* check bounds, etc */
  140. }
  141. void x86emu_inc_decoded_inst_len(int x)
  142. {
  143. M.x86.enc_pos += x;
  144. }
  145. void x86emu_decode_printf(char *x)
  146. {
  147. sprintf(M.x86.decoded_buf + M.x86.enc_str_pos, "%s", x);
  148. M.x86.enc_str_pos += strlen(x);
  149. }
  150. void x86emu_decode_printf2(char *x, int y)
  151. {
  152. char temp[100];
  153. sprintf(temp, x, y);
  154. sprintf(M.x86.decoded_buf + M.x86.enc_str_pos, "%s", temp);
  155. M.x86.enc_str_pos += strlen(temp);
  156. }
  157. void x86emu_end_instr(void)
  158. {
  159. M.x86.enc_str_pos = 0;
  160. M.x86.enc_pos = 0;
  161. }
  162. static void print_encoded_bytes(u16 s, u16 o)
  163. {
  164. int i;
  165. char buf1[64];
  166. for (i = 0; i < M.x86.enc_pos; i++) {
  167. sprintf(buf1 + 2 * i, "%02x", fetch_data_byte_abs(s, o + i));
  168. }
  169. printk("%-20s", buf1);
  170. }
  171. static void print_decoded_instruction(void)
  172. {
  173. printk("%s", M.x86.decoded_buf);
  174. }
  175. void x86emu_print_int_vect(u16 iv)
  176. {
  177. u16 seg, off;
  178. if (iv > 256)
  179. return;
  180. seg = fetch_data_word_abs(0, iv * 4);
  181. off = fetch_data_word_abs(0, iv * 4 + 2);
  182. printk("%04x:%04x ", seg, off);
  183. }
  184. void X86EMU_dump_memory(u16 seg, u16 off, u32 amt)
  185. {
  186. u32 start = off & 0xfffffff0;
  187. u32 end = (off + 16) & 0xfffffff0;
  188. u32 i;
  189. u32 current;
  190. current = start;
  191. while (end <= off + amt) {
  192. printk("%04x:%04x ", seg, start);
  193. for (i = start; i < off; i++)
  194. printk(" ");
  195. for (; i < end; i++)
  196. printk("%02x ", fetch_data_byte_abs(seg, i));
  197. printk("\n");
  198. start = end;
  199. end = start + 16;
  200. }
  201. }
  202. void x86emu_single_step(void)
  203. {
  204. char s[1024];
  205. int ps[10];
  206. int ntok;
  207. int cmd;
  208. int done;
  209. int segment;
  210. int offset;
  211. static int breakpoint;
  212. static int noDecode = 1;
  213. char *p;
  214. if (DEBUG_BREAK()) {
  215. if (M.x86.saved_ip != breakpoint) {
  216. return;
  217. } else {
  218. M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
  219. M.x86.debug |= DEBUG_TRACE_F;
  220. M.x86.debug &= ~DEBUG_BREAK_F;
  221. print_decoded_instruction();
  222. X86EMU_trace_regs();
  223. }
  224. }
  225. done = 0;
  226. offset = M.x86.saved_ip;
  227. while (!done) {
  228. printk("-");
  229. cmd = parse_line(s, ps, &ntok);
  230. switch (cmd) {
  231. case 'u':
  232. disassemble_forward(M.x86.saved_cs, (u16) offset, 10);
  233. break;
  234. case 'd':
  235. if (ntok == 2) {
  236. segment = M.x86.saved_cs;
  237. offset = ps[1];
  238. X86EMU_dump_memory(segment, (u16) offset, 16);
  239. offset += 16;
  240. } else if (ntok == 3) {
  241. segment = ps[1];
  242. offset = ps[2];
  243. X86EMU_dump_memory(segment, (u16) offset, 16);
  244. offset += 16;
  245. } else {
  246. segment = M.x86.saved_cs;
  247. X86EMU_dump_memory(segment, (u16) offset, 16);
  248. offset += 16;
  249. }
  250. break;
  251. case 'c':
  252. M.x86.debug ^= DEBUG_TRACECALL_F;
  253. break;
  254. case 's':
  255. M.x86.debug ^=
  256. DEBUG_SVC_F | DEBUG_SYS_F | DEBUG_SYSINT_F;
  257. break;
  258. case 'r':
  259. X86EMU_trace_regs();
  260. break;
  261. case 'x':
  262. X86EMU_trace_xregs();
  263. break;
  264. case 'g':
  265. if (ntok == 2) {
  266. breakpoint = ps[1];
  267. if (noDecode) {
  268. M.x86.debug |= DEBUG_DECODE_NOPRINT_F;
  269. } else {
  270. M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
  271. }
  272. M.x86.debug &= ~DEBUG_TRACE_F;
  273. M.x86.debug |= DEBUG_BREAK_F;
  274. done = 1;
  275. }
  276. break;
  277. case 'q':
  278. M.x86.debug |= DEBUG_EXIT;
  279. return;
  280. case 'P':
  281. noDecode = (noDecode) ? 0 : 1;
  282. printk("Toggled decoding to %s\n",
  283. (noDecode) ? "FALSE" : "TRUE");
  284. break;
  285. case 't':
  286. case 0:
  287. done = 1;
  288. break;
  289. }
  290. }
  291. }
  292. int X86EMU_trace_on(void)
  293. {
  294. return M.x86.debug |= DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F;
  295. }
  296. int X86EMU_trace_off(void)
  297. {
  298. return M.x86.debug &= ~(DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F);
  299. }
  300. static int parse_line(char *s, int *ps, int *n)
  301. {
  302. int cmd;
  303. *n = 0;
  304. while (*s == ' ' || *s == '\t')
  305. s++;
  306. ps[*n] = *s;
  307. switch (*s) {
  308. case '\n':
  309. *n += 1;
  310. return 0;
  311. default:
  312. cmd = *s;
  313. *n += 1;
  314. }
  315. while (1) {
  316. while (*s != ' ' && *s != '\t' && *s != '\n')
  317. s++;
  318. if (*s == '\n')
  319. return cmd;
  320. while (*s == ' ' || *s == '\t')
  321. s++;
  322. *n += 1;
  323. }
  324. }
  325. #endif /* DEBUG */
  326. void x86emu_dump_regs(void)
  327. {
  328. printk("\tAX=%04x ", M.x86.R_AX);
  329. printk("BX=%04x ", M.x86.R_BX);
  330. printk("CX=%04x ", M.x86.R_CX);
  331. printk("DX=%04x ", M.x86.R_DX);
  332. printk("SP=%04x ", M.x86.R_SP);
  333. printk("BP=%04x ", M.x86.R_BP);
  334. printk("SI=%04x ", M.x86.R_SI);
  335. printk("DI=%04x\n", M.x86.R_DI);
  336. printk("\tDS=%04x ", M.x86.R_DS);
  337. printk("ES=%04x ", M.x86.R_ES);
  338. printk("SS=%04x ", M.x86.R_SS);
  339. printk("CS=%04x ", M.x86.R_CS);
  340. printk("IP=%04x ", M.x86.R_IP);
  341. if (ACCESS_FLAG(F_OF))
  342. printk("OV "); /* CHECKED... */
  343. else
  344. printk("NV ");
  345. if (ACCESS_FLAG(F_DF))
  346. printk("DN ");
  347. else
  348. printk("UP ");
  349. if (ACCESS_FLAG(F_IF))
  350. printk("EI ");
  351. else
  352. printk("DI ");
  353. if (ACCESS_FLAG(F_SF))
  354. printk("NG ");
  355. else
  356. printk("PL ");
  357. if (ACCESS_FLAG(F_ZF))
  358. printk("ZR ");
  359. else
  360. printk("NZ ");
  361. if (ACCESS_FLAG(F_AF))
  362. printk("AC ");
  363. else
  364. printk("NA ");
  365. if (ACCESS_FLAG(F_PF))
  366. printk("PE ");
  367. else
  368. printk("PO ");
  369. if (ACCESS_FLAG(F_CF))
  370. printk("CY ");
  371. else
  372. printk("NC ");
  373. printk("\n");
  374. }
  375. void x86emu_dump_xregs(void)
  376. {
  377. printk("\tEAX=%08x ", M.x86.R_EAX);
  378. printk("EBX=%08x ", M.x86.R_EBX);
  379. printk("ECX=%08x ", M.x86.R_ECX);
  380. printk("EDX=%08x \n", M.x86.R_EDX);
  381. printk("\tESP=%08x ", M.x86.R_ESP);
  382. printk("EBP=%08x ", M.x86.R_EBP);
  383. printk("ESI=%08x ", M.x86.R_ESI);
  384. printk("EDI=%08x\n", M.x86.R_EDI);
  385. printk("\tDS=%04x ", M.x86.R_DS);
  386. printk("ES=%04x ", M.x86.R_ES);
  387. printk("SS=%04x ", M.x86.R_SS);
  388. printk("CS=%04x ", M.x86.R_CS);
  389. printk("EIP=%08x\n\t", M.x86.R_EIP);
  390. if (ACCESS_FLAG(F_OF))
  391. printk("OV "); /* CHECKED... */
  392. else
  393. printk("NV ");
  394. if (ACCESS_FLAG(F_DF))
  395. printk("DN ");
  396. else
  397. printk("UP ");
  398. if (ACCESS_FLAG(F_IF))
  399. printk("EI ");
  400. else
  401. printk("DI ");
  402. if (ACCESS_FLAG(F_SF))
  403. printk("NG ");
  404. else
  405. printk("PL ");
  406. if (ACCESS_FLAG(F_ZF))
  407. printk("ZR ");
  408. else
  409. printk("NZ ");
  410. if (ACCESS_FLAG(F_AF))
  411. printk("AC ");
  412. else
  413. printk("NA ");
  414. if (ACCESS_FLAG(F_PF))
  415. printk("PE ");
  416. else
  417. printk("PO ");
  418. if (ACCESS_FLAG(F_CF))
  419. printk("CY ");
  420. else
  421. printk("NC ");
  422. printk("\n");
  423. }
  424. #endif