debug.c 10 KB

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