Avoid SIGSTOP/SIGCONT race when ptrace is disabled.
[wine/wine-kai.git] / debugger / break.c
blobd5fa64345e750f8b8b6c8ec922e13e4ad9e3b713
1 /*
2 * Debugger break-points handling
4 * Copyright 1994 Martin von Loewis
5 * Copyright 1995 Alexandre Julliard
6 */
8 #include "config.h"
9 #include <stdio.h>
10 #include "debugger.h"
12 #define INT3 0xcc /* int 3 opcode */
14 #define MAX_BREAKPOINTS 100
16 static BREAKPOINT breakpoints[MAX_BREAKPOINTS];
18 static int next_bp = 1; /* breakpoint 0 is reserved for step-over */
21 /***********************************************************************
22 * DEBUG_IsStepOverInstr
24 * Determine if the instruction at CS:EIP is an instruction that
25 * we need to step over (like a call or a repetitive string move).
27 static BOOL DEBUG_IsStepOverInstr(void)
29 #ifdef __i386__
30 BYTE* instr;
31 BYTE ch;
32 DBG_ADDR addr;
34 addr.seg = DEBUG_context.SegCs;
35 addr.off = DEBUG_context.Eip;
36 /* FIXME: old code was using V86BASE(DEBUG_context)
37 * instead of passing thru DOSMEM_MemoryBase
39 instr = (BYTE*)DEBUG_ToLinear(&addr);
41 for (;;)
43 if (!DEBUG_READ_MEM(instr, &ch, sizeof(ch)))
44 return FALSE;
46 switch (ch)
48 /* Skip all prefixes */
50 case 0x2e: /* cs: */
51 case 0x36: /* ss: */
52 case 0x3e: /* ds: */
53 case 0x26: /* es: */
54 case 0x64: /* fs: */
55 case 0x65: /* gs: */
56 case 0x66: /* opcode size prefix */
57 case 0x67: /* addr size prefix */
58 case 0xf0: /* lock */
59 case 0xf2: /* repne */
60 case 0xf3: /* repe */
61 instr++;
62 continue;
64 /* Handle call instructions */
66 case 0xcd: /* int <intno> */
67 case 0xe8: /* call <offset> */
68 case 0x9a: /* lcall <seg>:<off> */
69 return TRUE;
71 case 0xff: /* call <regmodrm> */
72 if (!DEBUG_READ_MEM(instr + 1, &ch, sizeof(ch)))
73 return FALSE;
74 return (((ch & 0x38) == 0x10) || ((ch & 0x38) == 0x18));
76 /* Handle string instructions */
78 case 0x6c: /* insb */
79 case 0x6d: /* insw */
80 case 0x6e: /* outsb */
81 case 0x6f: /* outsw */
82 case 0xa4: /* movsb */
83 case 0xa5: /* movsw */
84 case 0xa6: /* cmpsb */
85 case 0xa7: /* cmpsw */
86 case 0xaa: /* stosb */
87 case 0xab: /* stosw */
88 case 0xac: /* lodsb */
89 case 0xad: /* lodsw */
90 case 0xae: /* scasb */
91 case 0xaf: /* scasw */
92 return TRUE;
94 default:
95 return FALSE;
98 #else
99 return FALSE;
100 #endif
104 /***********************************************************************
105 * DEBUG_IsFctReturn
107 * Determine if the instruction at CS:EIP is an instruction that
108 * is a function return.
110 BOOL DEBUG_IsFctReturn(void)
112 #ifdef __i386__
113 BYTE* instr;
114 BYTE ch;
115 DBG_ADDR addr;
117 addr.seg = DEBUG_context.SegCs;
118 addr.off = DEBUG_context.Eip;
119 /* FIXME: old code was using V86BASE(DEBUG_context)
120 * instead of passing thru DOSMEM_MemoryBase
122 instr = (BYTE*)DEBUG_ToLinear(&addr);
124 if (!DEBUG_READ_MEM(instr, &ch, sizeof(ch)))
125 return FALSE;
127 return (ch == 0xc2) || (ch == 0xc3);
128 #else
129 return FALSE;
130 #endif
134 /***********************************************************************
135 * DEBUG_SetBreakpoints
137 * Set or remove all the breakpoints.
139 void DEBUG_SetBreakpoints( BOOL set )
141 int i;
142 char ch;
144 for (i = 0; i < MAX_BREAKPOINTS; i++)
146 if (breakpoints[i].refcount && breakpoints[i].enabled)
148 ch = set ? INT3 : breakpoints[i].opcode;
150 if (!DEBUG_WRITE_MEM( (void*)DEBUG_ToLinear(&breakpoints[i].addr), &ch, sizeof(ch) ))
152 fprintf( stderr, "Invalid address for breakpoint %d, disabling it\n", i );
153 breakpoints[i].enabled = FALSE;
160 /***********************************************************************
161 * DEBUG_FindBreakpoint
163 * Find the breakpoint for a given address. Return the breakpoint
164 * number or -1 if none.
166 int DEBUG_FindBreakpoint( const DBG_ADDR *addr )
168 int i;
170 for (i = 0; i < MAX_BREAKPOINTS; i++)
172 if (breakpoints[i].refcount && breakpoints[i].enabled &&
173 breakpoints[i].addr.seg == addr->seg &&
174 breakpoints[i].addr.off == addr->off) return i;
176 return -1;
180 /***********************************************************************
181 * DEBUG_AddBreakpoint
183 * Add a breakpoint.
185 void DEBUG_AddBreakpoint( const DBG_ADDR *address )
187 DBG_ADDR addr = *address;
188 int num;
189 unsigned int seg2;
190 BYTE ch;
192 DEBUG_FixAddress( &addr, DEBUG_context.SegCs );
194 if( addr.type != NULL && addr.type == DEBUG_TypeIntConst )
197 * We know that we have the actual offset stored somewhere
198 * else in 32-bit space. Grab it, and we
199 * should be all set.
201 seg2 = addr.seg;
202 addr.seg = 0;
203 addr.off = DEBUG_GetExprValue(&addr, NULL);
204 addr.seg = seg2;
207 if ((num = DEBUG_FindBreakpoint(&addr)) >= 1)
209 breakpoints[num].refcount++;
210 return;
213 if (!DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear( &addr ), &ch, sizeof(ch)))
214 return;
216 if (next_bp < MAX_BREAKPOINTS)
217 num = next_bp++;
218 else /* try to find an empty slot */
220 for (num = 1; num < MAX_BREAKPOINTS; num++)
221 if (!breakpoints[num].refcount) break;
222 if (num >= MAX_BREAKPOINTS)
224 fprintf( stderr, "Too many breakpoints. Please delete some.\n" );
225 return;
228 breakpoints[num].addr = addr;
229 breakpoints[num].addrlen = 32;
230 #ifdef __i386__
231 if (addr.seg)
232 breakpoints[num].addrlen = DEBUG_GetSelectorType( addr.seg );
233 if (breakpoints[num].addrlen == 0) fprintf(stderr, "in bad shape\n");
234 #endif
235 breakpoints[num].opcode = ch;
236 breakpoints[num].enabled = TRUE;
237 breakpoints[num].refcount = 1;
238 breakpoints[num].skipcount = 0;
239 fprintf( stderr, "Breakpoint %d at ", num );
240 DEBUG_PrintAddress( &breakpoints[num].addr, breakpoints[num].addrlen,
241 TRUE );
242 fprintf( stderr, "\n" );
246 /***********************************************************************
247 * DEBUG_DelBreakpoint
249 * Delete a breakpoint.
251 void DEBUG_DelBreakpoint( int num )
253 if ((num <= 0) || (num >= next_bp) || !breakpoints[num].refcount)
255 fprintf( stderr, "Invalid breakpoint number %d\n", num );
256 return;
259 if (--breakpoints[num].refcount > 0)
260 return;
262 if( breakpoints[num].condition != NULL )
264 DEBUG_FreeExpr(breakpoints[num].condition);
265 breakpoints[num].condition = NULL;
268 breakpoints[num].enabled = FALSE;
269 breakpoints[num].refcount = 0;
270 breakpoints[num].skipcount = 0;
274 /***********************************************************************
275 * DEBUG_EnableBreakpoint
277 * Enable or disable a break point.
279 void DEBUG_EnableBreakpoint( int num, BOOL enable )
281 if ((num <= 0) || (num >= next_bp) || !breakpoints[num].refcount)
283 fprintf( stderr, "Invalid breakpoint number %d\n", num );
284 return;
286 breakpoints[num].enabled = (enable) ? TRUE : FALSE;
287 breakpoints[num].skipcount = 0;
291 /***********************************************************************
292 * DEBUG_InfoBreakpoints
294 * Display break points information.
296 void DEBUG_InfoBreakpoints(void)
298 int i;
300 fprintf( stderr, "Breakpoints:\n" );
301 for (i = 1; i < next_bp; i++)
303 if (breakpoints[i].refcount)
305 fprintf( stderr, "%d: %c ", i, breakpoints[i].enabled ? 'y' : 'n');
306 DEBUG_PrintAddress( &breakpoints[i].addr, breakpoints[i].addrlen, TRUE);
307 fprintf( stderr, " (%u)\n", breakpoints[i].refcount );
308 if( breakpoints[i].condition != NULL )
310 fprintf(stderr, "\t\tstop when ");
311 DEBUG_DisplayExpr(breakpoints[i].condition);
312 fprintf(stderr, "\n");
318 /***********************************************************************
319 * DEBUG_ShouldContinue
321 * Determine if we should continue execution after a SIGTRAP signal when
322 * executing in the given mode.
324 BOOL DEBUG_ShouldContinue( DWORD code, enum exec_mode mode, int * count )
326 DBG_ADDR addr;
327 DBG_ADDR cond_addr;
328 int bpnum;
329 struct list_id list;
331 #ifdef __i386__
332 /* If not single-stepping, back up over the int3 instruction */
333 if (code == EXCEPTION_BREAKPOINT)
334 DEBUG_context.Eip--;
335 #endif
337 DEBUG_GetCurrentAddress( &addr );
338 bpnum = DEBUG_FindBreakpoint( &addr );
339 breakpoints[0].enabled = FALSE; /* disable the step-over breakpoint */
341 if ((bpnum != 0) && (bpnum != -1))
343 if( breakpoints[bpnum].condition != NULL )
345 cond_addr = DEBUG_EvalExpr(breakpoints[bpnum].condition);
346 if( cond_addr.type == NULL )
349 * Something wrong - unable to evaluate this expression.
351 fprintf(stderr, "Unable to evaluate expression ");
352 DEBUG_DisplayExpr(breakpoints[bpnum].condition);
353 fprintf(stderr, "\nTurning off condition\n");
354 DEBUG_AddBPCondition(bpnum, NULL);
356 else if( ! DEBUG_GetExprValue( &cond_addr, NULL) )
358 return TRUE;
362 if( breakpoints[bpnum].skipcount > 0 )
364 breakpoints[bpnum].skipcount--;
365 if( breakpoints[bpnum].skipcount > 0 )
367 return TRUE;
370 fprintf( stderr, "Stopped on breakpoint %d at ", bpnum );
371 DEBUG_PrintAddress( &breakpoints[bpnum].addr,
372 breakpoints[bpnum].addrlen, TRUE );
373 fprintf( stderr, "\n" );
376 * See if there is a source file for this bp. If so,
377 * then dig it out and display one line.
379 DEBUG_FindNearestSymbol( &addr, TRUE, NULL, 0, &list);
380 if( list.sourcefile != NULL )
382 DEBUG_List(&list, NULL, 0);
384 return FALSE;
388 * If our mode indicates that we are stepping line numbers,
389 * get the current function, and figure out if we are exactly
390 * on a line number or not.
392 if( mode == EXEC_STEP_OVER || mode == EXEC_STEP_INSTR )
394 if( DEBUG_CheckLinenoStatus(&addr) == AT_LINENUMBER )
396 (*count)--;
399 else if( mode == EXEC_STEPI_OVER
400 || mode == EXEC_STEPI_INSTR )
403 (*count)--;
406 if( *count > 0 || mode == EXEC_FINISH )
409 * We still need to execute more instructions.
411 return TRUE;
415 * If we are about to stop, then print out the source line if we
416 * have it.
418 if ((mode != EXEC_CONT && mode != EXEC_PASS && mode != EXEC_FINISH))
420 DEBUG_FindNearestSymbol( &addr, TRUE, NULL, 0, &list);
421 if( list.sourcefile != NULL )
423 DEBUG_List(&list, NULL, 0);
427 #ifdef __i386__
428 /* If there's no breakpoint and we are not single-stepping, then we */
429 /* must have encountered an int3 in the Windows program; let's skip it. */
430 if ((bpnum == -1) && code == EXCEPTION_BREAKPOINT)
431 DEBUG_context.Eip++;
432 #endif
434 /* no breakpoint, continue if in continuous mode */
435 return (mode == EXEC_CONT || mode == EXEC_PASS || mode == EXEC_FINISH);
438 /***********************************************************************
439 * DEBUG_RestartExecution
441 * Remove all breakpoints before entering the debug loop
443 void DEBUG_SuspendExecution( void )
445 DEBUG_SetBreakpoints( FALSE );
446 breakpoints[0] = DEBUG_CurrThread->stepOverBP;
449 /***********************************************************************
450 * DEBUG_RestartExecution
452 * Set the breakpoints to the correct state to restart execution
453 * in the given mode.
455 enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count )
457 DBG_ADDR addr;
458 DBG_ADDR addr2;
459 int bp;
460 int delta;
461 int status;
462 enum exec_mode ret_mode;
463 DWORD instr;
464 unsigned char ch;
466 DEBUG_GetCurrentAddress( &addr );
469 * This is the mode we will be running in after we finish. We would like
470 * to be able to modify this in certain cases.
472 ret_mode = mode;
474 bp = DEBUG_FindBreakpoint( &addr );
475 if ( bp != -1 && bp != 0)
478 * If we have set a new value, then save it in the BP number.
480 if( count != 0 && mode == EXEC_CONT )
482 breakpoints[bp].skipcount = count;
484 mode = EXEC_STEPI_INSTR; /* If there's a breakpoint, skip it */
486 else
488 if( mode == EXEC_CONT && count > 1 )
490 fprintf(stderr, "Not stopped at any breakpoint; argument ignored.\n");
494 if( mode == EXEC_FINISH && DEBUG_IsFctReturn() )
496 mode = ret_mode = EXEC_STEPI_INSTR;
499 instr = DEBUG_ToLinear( &addr );
500 DEBUG_READ_MEM((void*)instr, &ch, sizeof(ch));
502 * See if the function we are stepping into has debug info
503 * and line numbers. If not, then we step over it instead.
504 * FIXME - we need to check for things like thunks or trampolines,
505 * as the actual function may in fact have debug info.
507 if( ch == 0xe8 )
509 DEBUG_READ_MEM((void*)(instr + 1), &delta, sizeof(delta));
510 addr2 = addr;
511 DEBUG_Disasm(&addr2, FALSE);
512 addr2.off += delta;
514 status = DEBUG_CheckLinenoStatus(&addr2);
516 * Anytime we have a trampoline, step over it.
518 if( ((mode == EXEC_STEP_OVER) || (mode == EXEC_STEPI_OVER))
519 && status == FUNC_IS_TRAMPOLINE )
521 #if 0
522 fprintf(stderr, "Not stepping into trampoline at %x (no lines)\n",
523 addr2.off);
524 #endif
525 mode = EXEC_STEP_OVER_TRAMPOLINE;
528 if( mode == EXEC_STEP_INSTR && status == FUNC_HAS_NO_LINES )
530 #if 0
531 fprintf(stderr, "Not stepping into function at %x (no lines)\n",
532 addr2.off);
533 #endif
534 mode = EXEC_STEP_OVER;
539 if( mode == EXEC_STEP_INSTR )
541 if( DEBUG_CheckLinenoStatus(&addr) == FUNC_HAS_NO_LINES )
543 fprintf(stderr, "Single stepping until exit from function, \n");
544 fprintf(stderr, "which has no line number information.\n");
546 ret_mode = mode = EXEC_FINISH;
550 switch(mode)
552 case EXEC_CONT: /* Continuous execution */
553 case EXEC_PASS: /* Continue, passing exception */
554 #ifdef __i386__
555 DEBUG_context.EFlags &= ~STEP_FLAG;
556 #endif
557 DEBUG_SetBreakpoints( TRUE );
558 break;
560 case EXEC_STEP_OVER_TRAMPOLINE:
562 * This is the means by which we step over our conversion stubs
563 * in callfrom*.s and callto*.s. We dig the appropriate address
564 * off the stack, and we set the breakpoint there instead of the
565 * address just after the call.
567 #ifdef __i386__
568 DEBUG_READ_MEM((void*)(DEBUG_context.Esp +
569 2 * sizeof(unsigned int)),
570 &addr.off, sizeof(addr.off));
571 DEBUG_context.EFlags &= ~STEP_FLAG;
572 #endif
573 breakpoints[0].addr = addr;
574 breakpoints[0].enabled = TRUE;
575 breakpoints[0].refcount = 1;
576 breakpoints[0].skipcount = 0;
577 DEBUG_READ_MEM((void*)DEBUG_ToLinear( &addr ), &breakpoints[0].opcode, sizeof(char));
578 DEBUG_SetBreakpoints( TRUE );
579 break;
581 case EXEC_FINISH:
582 case EXEC_STEPI_OVER: /* Stepping over a call */
583 case EXEC_STEP_OVER: /* Stepping over a call */
584 if (DEBUG_IsStepOverInstr())
586 #ifdef __i386__
587 DEBUG_context.EFlags &= ~STEP_FLAG;
588 #endif
589 DEBUG_Disasm(&addr, FALSE);
590 breakpoints[0].addr = addr;
591 breakpoints[0].enabled = TRUE;
592 breakpoints[0].refcount = 1;
593 breakpoints[0].skipcount = 0;
594 DEBUG_READ_MEM((void*)DEBUG_ToLinear( &addr ), &breakpoints[0].opcode, sizeof(char));
595 DEBUG_SetBreakpoints( TRUE );
596 break;
598 /* else fall through to single-stepping */
600 case EXEC_STEP_INSTR: /* Single-stepping an instruction */
601 case EXEC_STEPI_INSTR: /* Single-stepping an instruction */
602 #ifdef __i386__
603 DEBUG_context.EFlags |= STEP_FLAG;
604 #endif
605 break;
607 DEBUG_CurrThread->stepOverBP = breakpoints[0];
608 return ret_mode;
612 DEBUG_AddBPCondition(int num, struct expr * exp)
614 if ((num <= 0) || (num >= next_bp) || !breakpoints[num].refcount)
616 fprintf( stderr, "Invalid breakpoint number %d\n", num );
617 return FALSE;
620 if( breakpoints[num].condition != NULL )
622 DEBUG_FreeExpr(breakpoints[num].condition);
623 breakpoints[num].condition = NULL;
626 if( exp != NULL )
628 breakpoints[num].condition = DEBUG_CloneExpr(exp);
631 return TRUE;