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