debug.c 11 KB

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