debug.c 11 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 <stdarg.h>
  40. #include <common.h>
  41. #include <linux/ctype.h>
  42. #include "x86emu/x86emui.h"
  43. /*----------------------------- Implementation ----------------------------*/
  44. #ifdef CONFIG_X86EMU_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. 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. if (DEBUG_BREAK()) {
  213. if (M.x86.saved_ip != breakpoint) {
  214. return;
  215. } else {
  216. M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
  217. M.x86.debug |= DEBUG_TRACE_F;
  218. M.x86.debug &= ~DEBUG_BREAK_F;
  219. print_decoded_instruction();
  220. X86EMU_trace_regs();
  221. }
  222. }
  223. done = 0;
  224. offset = M.x86.saved_ip;
  225. while (!done) {
  226. printk("-");
  227. ps[1] = 0; /* Avoid dodgy compiler warnings */
  228. ps[2] = 0;
  229. cmd = x86emu_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 x86emu_parse_line(char *s, int *ps, int *n)
  301. {
  302. int cmd;
  303. *n = 0;
  304. while (isblank(*s))
  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 (!isblank(*s) && *s != '\n')
  317. s++;
  318. if (*s == '\n')
  319. return cmd;
  320. while (isblank(*s))
  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. }