Stub UrlCombineA and initial implementation of UrlCombineW.
[wine] / debugger / break.c
1 /*
2  * Debugger break-points handling
3  *
4  * Copyright 1994 Martin von Loewis
5  * Copyright 1995 Alexandre Julliard
6  * Copyright 1999,2000 Eric Pouech
7  */
8
9 #include "config.h"
10 #include "debugger.h"
11
12 #ifdef __i386__
13 #define DR7_CONTROL_SHIFT       16
14 #define DR7_CONTROL_SIZE        4
15
16 #define DR7_RW_EXECUTE          (0x0)
17 #define DR7_RW_WRITE            (0x1)
18 #define DR7_RW_READ             (0x3)
19
20 #define DR7_LEN_1               (0x0)
21 #define DR7_LEN_2               (0x4)
22 #define DR7_LEN_4               (0xC)
23
24 #define DR7_LOCAL_ENABLE_SHIFT  0
25 #define DR7_GLOBAL_ENABLE_SHIFT 1
26 #define DR7_ENABLE_SIZE         2
27
28 #define DR7_LOCAL_ENABLE_MASK   (0x55)
29 #define DR7_GLOBAL_ENABLE_MASK  (0xAA)
30
31 #define DR7_CONTROL_RESERVED    (0xFC00)
32 #define DR7_LOCAL_SLOWDOWN      (0x100)
33 #define DR7_GLOBAL_SLOWDOWN     (0x200)
34
35 #define DR7_ENABLE_MASK(dr)     (1<<(DR7_LOCAL_ENABLE_SHIFT+DR7_ENABLE_SIZE*(dr)))
36 #define IS_DR7_SET(ctrl,dr)     ((ctrl)&DR7_ENABLE_MASK(dr))
37 #define INT3          0xcc   /* int 3 opcode */
38 #endif
39
40 #define MAX_BREAKPOINTS 100
41
42 static DBG_BREAKPOINT breakpoints[MAX_BREAKPOINTS];
43
44 static int next_bp = 1;  /* breakpoint 0 is reserved for step-over */
45
46 /***********************************************************************
47  *           DEBUG_IsStepOverInstr
48  *
49  * Determine if the instruction at CS:EIP is an instruction that
50  * we need to step over (like a call or a repetitive string move).
51  */
52 static BOOL DEBUG_IsStepOverInstr(void)
53 {
54 #ifdef __i386__
55     BYTE*       instr;
56     BYTE        ch;
57     DBG_ADDR    addr;
58
59     addr.seg = DEBUG_context.SegCs;
60     addr.off = DEBUG_context.Eip;
61     /* FIXME: old code was using V86BASE(DEBUG_context)
62      * instead of passing through DOSMEM_MemoryBase
63      */
64     instr = (BYTE*)DEBUG_ToLinear(&addr);
65
66     for (;;)
67     {
68         if (!DEBUG_READ_MEM(instr, &ch, sizeof(ch)))
69             return FALSE;
70
71         switch (ch)
72         {
73           /* Skip all prefixes */
74
75         case 0x2e:  /* cs: */
76         case 0x36:  /* ss: */
77         case 0x3e:  /* ds: */
78         case 0x26:  /* es: */
79         case 0x64:  /* fs: */
80         case 0x65:  /* gs: */
81         case 0x66:  /* opcode size prefix */
82         case 0x67:  /* addr size prefix */
83         case 0xf0:  /* lock */
84         case 0xf2:  /* repne */
85         case 0xf3:  /* repe */
86             instr++;
87             continue;
88
89           /* Handle call instructions */
90
91         case 0xcd:  /* int <intno> */
92         case 0xe8:  /* call <offset> */
93         case 0x9a:  /* lcall <seg>:<off> */
94             return TRUE;
95
96         case 0xff:  /* call <regmodrm> */
97             if (!DEBUG_READ_MEM(instr + 1, &ch, sizeof(ch)))
98                 return FALSE;
99             return (((ch & 0x38) == 0x10) || ((ch & 0x38) == 0x18));
100
101           /* Handle string instructions */
102
103         case 0x6c:  /* insb */
104         case 0x6d:  /* insw */
105         case 0x6e:  /* outsb */
106         case 0x6f:  /* outsw */
107         case 0xa4:  /* movsb */
108         case 0xa5:  /* movsw */
109         case 0xa6:  /* cmpsb */
110         case 0xa7:  /* cmpsw */
111         case 0xaa:  /* stosb */
112         case 0xab:  /* stosw */
113         case 0xac:  /* lodsb */
114         case 0xad:  /* lodsw */
115         case 0xae:  /* scasb */
116         case 0xaf:  /* scasw */
117             return TRUE;
118
119         default:
120             return FALSE;
121         }
122     }
123 #else
124     return FALSE;
125 #endif
126 }
127
128
129 /***********************************************************************
130  *           DEBUG_IsFctReturn
131  *
132  * Determine if the instruction at CS:EIP is an instruction that
133  * is a function return.
134  */
135 BOOL DEBUG_IsFctReturn(void)
136 {
137 #ifdef __i386__
138     BYTE*       instr;
139     BYTE        ch;
140     DBG_ADDR    addr;
141
142     addr.seg = DEBUG_context.SegCs;
143     addr.off = DEBUG_context.Eip;
144     /* FIXME: old code was using V86BASE(DEBUG_context)
145      * instead of passing through DOSMEM_MemoryBase
146      */
147     instr = (BYTE*)DEBUG_ToLinear(&addr);
148
149     if (!DEBUG_READ_MEM(instr, &ch, sizeof(ch)))
150         return FALSE;
151
152     return (ch == 0xc2) || (ch == 0xc3);
153 #else
154     return FALSE;
155 #endif
156 }
157
158
159 /***********************************************************************
160  *           DEBUG_SetBreakpoints
161  *
162  * Set or remove all the breakpoints.
163  */
164 void DEBUG_SetBreakpoints( BOOL set )
165 {
166    int          i;
167    
168 #ifdef __i386__
169    DEBUG_context.Dr7 &= ~DR7_LOCAL_ENABLE_MASK;
170 #endif
171    
172    for (i = 0; i < next_bp; i++)
173    {
174       if (!(breakpoints[i].refcount && breakpoints[i].enabled))
175          continue;
176       
177       switch (breakpoints[i].type) {
178       case DBG_BREAK:
179          {
180 #ifdef __i386__
181             char ch = set ? INT3 : breakpoints[i].u.b.opcode;
182             
183             if (!DEBUG_WRITE_MEM( (void*)DEBUG_ToLinear(&breakpoints[i].addr), 
184                                   &ch, sizeof(ch) ))
185             {
186                DEBUG_Printf(DBG_CHN_MESG, "Invalid address for breakpoint %d, disabling it\n", i);
187                breakpoints[i].enabled = FALSE;
188             }
189 #endif
190          }
191          break;
192       case DBG_WATCH:
193          if (set) 
194          {
195 #ifdef __i386__
196             DWORD       bits;
197             int         reg = breakpoints[i].u.w.reg;
198             LPDWORD     lpdr = NULL;
199
200             switch (reg) 
201             {
202                case 0: lpdr = &DEBUG_context.Dr0; break;
203                case 1: lpdr = &DEBUG_context.Dr1; break;
204                case 2: lpdr = &DEBUG_context.Dr2; break;
205                case 3: lpdr = &DEBUG_context.Dr3; break;
206                default: RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
207             }
208             
209             *lpdr = DEBUG_ToLinear(&breakpoints[i].addr);
210             bits = (breakpoints[i].u.w.rw) ? DR7_RW_WRITE : DR7_RW_READ;
211             switch (breakpoints[i].u.w.len + 1)
212             {
213                case 4: bits |= DR7_LEN_4;       break;
214                case 2: bits |= DR7_LEN_2;       break;
215                case 1: bits |= DR7_LEN_1;       break;
216                default: RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
217             }
218             
219             DEBUG_context.Dr7 &= ~(0x0F << (DR7_CONTROL_SHIFT + DR7_CONTROL_SIZE * reg));
220             DEBUG_context.Dr7 |= bits << (DR7_CONTROL_SHIFT + DR7_CONTROL_SIZE * reg);
221             DEBUG_context.Dr7 |= DR7_ENABLE_MASK(reg) | DR7_LOCAL_SLOWDOWN;
222 #endif
223          }
224          break;
225       }
226    }
227 }
228
229 /***********************************************************************
230  *           DEBUG_FindBreakpoint
231  *
232  * Find the breakpoint for a given address. Return the breakpoint
233  * number or -1 if none.
234  * If type is DBG_BREAKPOINT, addr is a complete addr
235  * If type is DBG_WATCHPOINT, only addr.off is meaningful and contains 
236  * linear address
237  */
238 static int DEBUG_FindBreakpoint( const DBG_ADDR *addr, int type )
239 {
240    int i;
241    
242    for (i = 0; i < next_bp; i++)
243    {
244       if (breakpoints[i].refcount && breakpoints[i].enabled &&
245           breakpoints[i].type == type )
246       {
247          if ((type == DBG_BREAK && 
248               breakpoints[i].addr.seg == addr->seg &&
249               breakpoints[i].addr.off == addr->off) ||
250              (type == DBG_WATCH && 
251               DEBUG_ToLinear(&breakpoints[i].addr) == addr->off))
252             return i;
253       }
254    }
255    return -1;
256 }
257
258 /***********************************************************************
259  *           DEBUG_InitXPoint
260  *
261  * Find an empty slot in BP table to add a new break/watch point
262  */
263 static  int     DEBUG_InitXPoint(int type, DBG_ADDR* addr)
264 {
265    int  num;
266    
267    for (num = (next_bp < MAX_BREAKPOINTS) ? next_bp++ : 1; 
268         num < MAX_BREAKPOINTS; num++) 
269    {
270       if (breakpoints[num].refcount == 0) 
271       {
272           breakpoints[num].refcount = 1;
273           breakpoints[num].enabled = TRUE;
274           breakpoints[num].type    = type;
275           breakpoints[num].skipcount = 0;
276           breakpoints[num].addr = *addr;
277           switch (DEBUG_GetSelectorType( addr->seg ))
278           {
279           case MODE_32:
280               breakpoints[num].is32 = 1;
281               break;
282           case MODE_VM86:
283           case MODE_16:
284               breakpoints[num].is32 = 0;
285               break;
286           default:
287               RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
288           }
289           return num;
290       }
291    }
292
293    DEBUG_Printf( DBG_CHN_MESG, "Too many breakpoints. Please delete some.\n" );
294    return -1;
295 }
296
297 /***********************************************************************
298  *           DEBUG_GetWatchedValue
299  *
300  * Returns the value watched by watch point 'num'.
301  */
302 static  BOOL    DEBUG_GetWatchedValue( int num, LPDWORD val )
303 {
304    BYTE         buf[4];
305    
306    if (!DEBUG_READ_MEM((void*)DEBUG_ToLinear(&breakpoints[num].addr), 
307                        buf, breakpoints[num].u.w.len + 1))
308       return FALSE;
309    
310    switch (breakpoints[num].u.w.len + 1) 
311    {
312       case 4:   *val = *(DWORD*)buf;    break;
313       case 2:   *val = *(WORD*)buf;     break;
314       case 1:   *val = *(BYTE*)buf;     break;
315       default: RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
316    }
317    return TRUE;
318 }
319
320 /***********************************************************************
321  *           DEBUG_AddBreakpoint
322  *
323  * Add a breakpoint.
324  */
325 void DEBUG_AddBreakpoint( const DBG_VALUE *_value, BOOL (*func)(void) )
326 {
327     DBG_VALUE value = *_value;
328     int num;
329     BYTE ch;
330
331     if( value.type != NULL && value.type == DEBUG_TypeIntConst )
332     {
333         /*
334          * We know that we have the actual offset stored somewhere
335          * else in 32-bit space.  Grab it, and we
336          * should be all set.
337          */
338         unsigned int seg2 = value.addr.seg;
339         value.addr.seg = 0;
340         value.addr.off = DEBUG_GetExprValue(&value, NULL);
341         value.addr.seg = seg2;
342     }
343
344     if ((num = DEBUG_FindBreakpoint(&value.addr, DBG_BREAK)) >= 1) 
345     {
346        breakpoints[num].refcount++;
347        return;
348     }
349
350     if (!DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear( &value.addr ), &ch, sizeof(ch)))
351     {
352        DEBUG_Printf( DBG_CHN_MESG, "Invalid address, can't set breakpoint\n");
353        return;
354     }
355
356     if ((num = DEBUG_InitXPoint(DBG_BREAK, &value.addr)) == -1)
357        return;
358
359     breakpoints[num].u.b.opcode = ch;
360     breakpoints[num].u.b.func = func;
361
362     DEBUG_Printf( DBG_CHN_MESG, "Breakpoint %d at ", num );
363     DEBUG_PrintAddress( &breakpoints[num].addr, breakpoints[num].is32 ? MODE_32 : MODE_16,
364                         TRUE );
365     DEBUG_Printf( DBG_CHN_MESG, "\n" );
366 }
367
368 /***********************************************************************
369  *           DEBUG_AddBreakpointFromId
370  *
371  * Add a breakpoint from a function name (and eventually a line #)
372  */
373 void    DEBUG_AddBreakpointFromId(const char *name, int lineno)
374 {
375    DBG_VALUE    value;
376    int          i;
377
378    if (DEBUG_GetSymbolValue(name, lineno, &value, TRUE)) {
379       DEBUG_AddBreakpoint(&value, NULL);
380       return;
381    }
382
383    DEBUG_Printf(DBG_CHN_MESG, "Unable to add breakpoint, will check again when a new DLL is loaded\n");
384    for (i = 0; i < DEBUG_CurrProcess->num_delayed_bp; i++) {
385       if (!strcmp(name, DEBUG_CurrProcess->delayed_bp[i].name) &&
386           lineno == DEBUG_CurrProcess->delayed_bp[i].lineno) {
387          return;
388       }
389    }
390    DEBUG_CurrProcess->delayed_bp = DBG_realloc(DEBUG_CurrProcess->delayed_bp, 
391                                                sizeof(DBG_DELAYED_BP) * ++DEBUG_CurrProcess->num_delayed_bp);
392
393    DEBUG_CurrProcess->delayed_bp[DEBUG_CurrProcess->num_delayed_bp - 1].name = strcpy(DBG_alloc(strlen(name) + 1), name);
394    DEBUG_CurrProcess->delayed_bp[DEBUG_CurrProcess->num_delayed_bp - 1].lineno = lineno;
395 }
396
397 /***********************************************************************
398  *           DEBUG_AddBreakpointFromLineno
399  *
400  * Add a breakpoint from a line number in current file
401  */
402 void    DEBUG_AddBreakpointFromLineno(int lineno)
403 {
404    DBG_VALUE                    value;
405    
406    DEBUG_GetCurrentAddress(&value.addr);
407    
408    if (lineno != -1) {
409       struct name_hash* nh;
410       
411       DEBUG_FindNearestSymbol(&value.addr, TRUE, &nh, 0, NULL);
412       if (nh == NULL) {
413          DEBUG_Printf(DBG_CHN_MESG, "Unable to add breakpoint\n");
414          return;
415       }
416       DEBUG_GetLineNumberAddr(nh, lineno, &value.addr, TRUE);
417    }
418    
419    value.type = NULL;
420    value.cookie = DV_TARGET;
421    DEBUG_AddBreakpoint( &value, NULL );
422 }
423
424 /***********************************************************************
425  *           DEBUG_CheckDelayedBP
426  *
427  * Check is a registered delayed BP is now available.
428  */
429 void            DEBUG_CheckDelayedBP(void)
430 {
431    DBG_VALUE            value;
432    int                  i = 0;
433    DBG_DELAYED_BP*      dbp = DEBUG_CurrProcess->delayed_bp;
434
435    while (i < DEBUG_CurrProcess->num_delayed_bp) {
436       if (DEBUG_GetSymbolValue(dbp[i].name, dbp[i].lineno, &value, TRUE)) {
437          DEBUG_AddBreakpoint(&value, NULL);
438          memmove(&dbp[i], &dbp[i+1], (--DEBUG_CurrProcess->num_delayed_bp - i) * sizeof(*dbp));
439       } else {
440          i++;
441       }
442    }
443 }
444
445 /***********************************************************************
446  *           DEBUG_AddWatchpoint
447  *
448  * Add a watchpoint.
449  */
450 void DEBUG_AddWatchpoint( const DBG_VALUE *_value, BOOL is_write )
451 {
452    DBG_VALUE    value = *_value;
453    int          num, reg = -1;
454    unsigned     seg2;
455    DWORD        mask = 0;
456    
457    assert(_value->cookie == DV_TARGET || _value->cookie == DV_HOST);
458
459 #ifdef __i386__
460    DEBUG_FixAddress( &value.addr, DEBUG_context.SegCs );
461 #endif
462    
463    if ( value.type != NULL && value.type == DEBUG_TypeIntConst )
464    {
465       /*
466        * We know that we have the actual offset stored somewhere
467        * else in 32-bit space.  Grab it, and we
468        * should be all set.
469        */
470       seg2 = value.addr.seg;
471       value.addr.seg = 0;
472       value.addr.off = DEBUG_GetExprValue(&value, NULL);
473       value.addr.seg = seg2;
474    }
475    
476    for (num = 1; num < next_bp; num++) 
477    {
478       if (breakpoints[num].refcount && breakpoints[num].enabled && 
479           breakpoints[num].type == DBG_WATCH) {
480          mask |= (1 << breakpoints[num].u.w.reg);
481       }
482    }
483 #ifdef __i386__
484    for (reg = 0; reg < 4 && (mask & (1 << reg)); reg++);
485    if (reg == 4)
486    {
487       DEBUG_Printf(DBG_CHN_MESG, "All i386 hardware watchpoints have been set. Delete some\n");
488       return;
489    }
490 #endif
491
492    if ((num = DEBUG_InitXPoint(DBG_WATCH, &value.addr)) == -1)
493       return;
494    
495    breakpoints[num].u.w.len = 4 - 1;
496    if (_value->type && DEBUG_GetObjectSize(_value->type) < 4)
497       breakpoints[num].u.w.len = 2 - 1;
498    
499    if (!DEBUG_GetWatchedValue( num, &breakpoints[num].u.w.oldval)) 
500    {
501       DEBUG_Printf(DBG_CHN_MESG, "Bad address. Watchpoint not set\n");
502       breakpoints[num].refcount = 0;
503    }
504    else
505    {
506       breakpoints[num].u.w.rw = (is_write) ? TRUE : FALSE;
507       breakpoints[reg].u.w.reg = reg;
508    
509       DEBUG_Printf( DBG_CHN_MESG, "Watchpoint %d at ", num );
510       DEBUG_PrintAddress( &breakpoints[num].addr, breakpoints[num].is32 ? MODE_32 : MODE_16, TRUE );
511       DEBUG_Printf( DBG_CHN_MESG, "\n" );
512    }
513 }
514
515 /***********************************************************************
516  *           DEBUG_AddWathpointFromId
517  *
518  * Add a watchpoint from a symbol name (and eventually a line #)
519  */
520 void    DEBUG_AddWatchpointFromId(const char *name)
521 {
522    DBG_VALUE value;
523    
524    if( DEBUG_GetSymbolValue(name, -1, &value, TRUE) )
525       DEBUG_AddWatchpoint( &value, 1 );
526    else
527       DEBUG_Printf(DBG_CHN_MESG, "Unable to add watchpoint\n");
528 }
529
530 /***********************************************************************
531  *           DEBUG_DelBreakpoint
532  *
533  * Delete a breakpoint.
534  */
535 void DEBUG_DelBreakpoint( int num )
536 {
537     if ((num <= 0) || (num >= next_bp) || breakpoints[num].refcount == 0)
538     {
539         DEBUG_Printf( DBG_CHN_MESG, "Invalid breakpoint number %d\n", num );
540         return;
541     }
542
543     if (--breakpoints[num].refcount > 0)
544        return;
545
546     if( breakpoints[num].condition != NULL )
547     {
548        DEBUG_FreeExpr(breakpoints[num].condition);
549        breakpoints[num].condition = NULL;
550     }
551
552     breakpoints[num].enabled = FALSE;
553     breakpoints[num].refcount = 0;
554     breakpoints[num].skipcount = 0;
555 }
556
557 /***********************************************************************
558  *           DEBUG_EnableBreakpoint
559  *
560  * Enable or disable a break point.
561  */
562 void DEBUG_EnableBreakpoint( int num, BOOL enable )
563 {
564     if ((num <= 0) || (num >= next_bp) || breakpoints[num].refcount == 0)
565     {
566         DEBUG_Printf( DBG_CHN_MESG, "Invalid breakpoint number %d\n", num );
567         return;
568     }
569     breakpoints[num].enabled = (enable) ? TRUE : FALSE;
570     breakpoints[num].skipcount = 0;
571 }
572
573
574 /***********************************************************************
575  *           DEBUG_FindTriggeredWatchpoint
576  *
577  * Lookup the watchpoints to see if one has been triggered
578  * Return >= (watch point index) if one is found and *oldval is set to
579  *      the value watched before the TRAP
580  * Return -1 if none found (*oldval is undetermined)
581  *
582  * Unfortunately, Linux does *NOT* (A REAL PITA) report with ptrace 
583  * the DR6 register value, so we have to look with our own need the
584  * cause of the TRAP.
585  * -EP
586  */
587 static int DEBUG_FindTriggeredWatchpoint(LPDWORD oldval)
588 {
589    int                          found = -1;
590 #ifdef __i386__
591    int                          i;
592    
593    /* Method 1 => get triggered watchpoint from context (doesn't work on Linux
594     * 2.2.x). This should be fixed in >= 2.2.16
595     */
596    for (i = 0; i < next_bp; i++) 
597    {
598       DWORD val = 0;
599
600       if (breakpoints[i].refcount && breakpoints[i].enabled && 
601           breakpoints[i].type == DBG_WATCH &&
602           (DEBUG_context.Dr6 & (1 << breakpoints[i].u.w.reg)))
603       {
604          DEBUG_context.Dr6 &= ~(1 << breakpoints[i].u.w.reg);
605          
606          *oldval = breakpoints[i].u.w.oldval;
607          if (DEBUG_GetWatchedValue(i, &val)) {
608             breakpoints[i].u.w.oldval = val;
609             return i;
610          }
611       }
612    }
613    
614    /* Method 1 failed, trying method 2 */
615    
616    /* Method 2 => check if value has changed among registered watchpoints
617     * this really sucks, but this is how gdb 4.18 works on my linux box
618     * -EP
619     */
620    for (i = 0; i < next_bp; i++) 
621    {
622       DWORD val = 0;
623
624       if (breakpoints[i].refcount && breakpoints[i].enabled && 
625           breakpoints[i].type == DBG_WATCH && 
626           DEBUG_GetWatchedValue(i, &val)) 
627       {
628          *oldval = breakpoints[i].u.w.oldval;
629          if (val != *oldval) 
630          {
631             DEBUG_context.Dr6 &= ~(1 << breakpoints[i].u.w.reg);
632             breakpoints[i].u.w.oldval = val;
633             found = i;
634             /* cannot break, because two watch points may have been triggered on
635              * the same access
636              * only one will be reported to the user (FIXME ?)
637              */
638          }
639       }
640    }
641 #endif
642    return found;
643 }
644
645 /***********************************************************************
646  *           DEBUG_InfoBreakpoints
647  *
648  * Display break points information.
649  */
650 void DEBUG_InfoBreakpoints(void)
651 {
652     int i;
653
654     DEBUG_Printf( DBG_CHN_MESG, "Breakpoints:\n" );
655     for (i = 1; i < next_bp; i++)
656     {
657         if (breakpoints[i].refcount && breakpoints[i].type == DBG_BREAK)
658         {
659             DEBUG_Printf( DBG_CHN_MESG, "%d: %c ", i, breakpoints[i].enabled ? 'y' : 'n');
660             DEBUG_PrintAddress( &breakpoints[i].addr, 
661                                 breakpoints[i].is32 ? MODE_32 : MODE_16, TRUE);
662             DEBUG_Printf( DBG_CHN_MESG, " (%u)\n", breakpoints[i].refcount );
663             if( breakpoints[i].condition != NULL )
664             {
665                 DEBUG_Printf(DBG_CHN_MESG, "\t\tstop when  ");
666                 DEBUG_DisplayExpr(breakpoints[i].condition);
667                 DEBUG_Printf(DBG_CHN_MESG, "\n");
668             }
669         }
670     }
671     DEBUG_Printf( DBG_CHN_MESG, "Watchpoints:\n" );
672     for (i = 1; i < next_bp; i++)
673     {
674         if (breakpoints[i].refcount && breakpoints[i].type == DBG_WATCH)
675         {
676             DEBUG_Printf( DBG_CHN_MESG, "%d: %c ", i, breakpoints[i].enabled ? 'y' : 'n');
677             DEBUG_PrintAddress( &breakpoints[i].addr, 
678                                 breakpoints[i].is32 ? MODE_32 : MODE_16, TRUE);
679             DEBUG_Printf( DBG_CHN_MESG, " on %d byte%s (%c)\n", 
680                      breakpoints[i].u.w.len + 1, 
681                      breakpoints[i].u.w.len > 0 ? "s" : "",
682                      breakpoints[i].u.w.rw ? 'W' : 'R');
683             if( breakpoints[i].condition != NULL )
684             {
685                 DEBUG_Printf(DBG_CHN_MESG, "\t\tstop when  ");
686                 DEBUG_DisplayExpr(breakpoints[i].condition);
687                 DEBUG_Printf(DBG_CHN_MESG, "\n");
688             }
689         }
690     }
691 }
692
693 /***********************************************************************
694  *           DEBUG_ShallBreak
695  *
696  * Check whether or not the condition (bp / skipcount) of a break/watch
697  * point are met.
698  */
699 static  BOOL DEBUG_ShallBreak( int bpnum )
700 {
701     if ( breakpoints[bpnum].condition != NULL )
702     {
703         DBG_VALUE value = DEBUG_EvalExpr(breakpoints[bpnum].condition);
704
705         if ( value.type == NULL )
706         {
707             /*
708              * Something wrong - unable to evaluate this expression.
709              */
710             DEBUG_Printf(DBG_CHN_MESG, "Unable to evaluate expression ");
711             DEBUG_DisplayExpr(breakpoints[bpnum].condition);
712             DEBUG_Printf(DBG_CHN_MESG, "\nTurning off condition\n");
713             DEBUG_AddBPCondition(bpnum, NULL);
714         }
715         else if( !DEBUG_GetExprValue( &value, NULL) )
716         {
717             return FALSE;
718         }
719     }
720    
721     if ( breakpoints[bpnum].skipcount > 0 && --breakpoints[bpnum].skipcount > 0 )
722         return FALSE;
723
724    if ((breakpoints[bpnum].type == DBG_BREAK) && breakpoints[bpnum].u.b.func)
725        return breakpoints[bpnum].u.b.func();
726    return TRUE;
727 }
728
729 /***********************************************************************
730  *           DEBUG_ShouldContinue
731  *
732  * Determine if we should continue execution after a SIGTRAP signal when
733  * executing in the given mode.
734  */
735 BOOL DEBUG_ShouldContinue( DBG_ADDR *addr, DWORD code, enum exec_mode mode, int * count )
736 {
737     int         bpnum;
738     DWORD       oldval;
739     int         wpnum;
740     enum dbg_mode addr_mode;
741     struct symbol_info syminfo;
742
743 #ifdef __i386__
744     /* If not single-stepping, back up over the int3 instruction */
745     if (code == EXCEPTION_BREAKPOINT)
746     {
747        DEBUG_context.Eip--;
748        addr->off--;
749     }
750 #endif
751
752     bpnum = DEBUG_FindBreakpoint( addr, DBG_BREAK );
753     breakpoints[0].enabled = FALSE;  /* disable the step-over breakpoint */
754
755     if ((bpnum != 0) && (bpnum != -1))
756     {
757         if (!DEBUG_ShallBreak(bpnum)) return TRUE;
758
759         DEBUG_Printf( DBG_CHN_MESG, "Stopped on breakpoint %d at ", bpnum );
760         syminfo = DEBUG_PrintAddress( &breakpoints[bpnum].addr,
761                                       breakpoints[bpnum].is32 ? MODE_32 : MODE_16, TRUE );
762         DEBUG_Printf( DBG_CHN_MESG, "\n" );
763         
764         if( syminfo.list.sourcefile != NULL )
765             DEBUG_List(&syminfo.list, NULL, 0);
766         return FALSE;
767     }
768
769     wpnum = DEBUG_FindTriggeredWatchpoint(&oldval);
770     if ((wpnum != 0) && (wpnum != -1))
771     {
772        /* If not single-stepping, do not back up over the int3 instruction */
773        if (code == EXCEPTION_BREAKPOINT) 
774        {
775 #ifdef __i386__
776            DEBUG_context.Eip++;
777            addr->off++;
778 #endif
779        }
780        if (!DEBUG_ShallBreak(wpnum)) return TRUE;
781        
782        addr_mode = DEBUG_GetSelectorType( addr->seg );
783        DEBUG_Printf(DBG_CHN_MESG, "Stopped on watchpoint %d at ", wpnum);
784        syminfo = DEBUG_PrintAddress( addr, addr_mode, TRUE );
785        
786        DEBUG_Printf(DBG_CHN_MESG, " values: old=%lu new=%lu\n", 
787                oldval, breakpoints[wpnum].u.w.oldval);
788        if (syminfo.list.sourcefile != NULL)
789           DEBUG_List(&syminfo.list, NULL, 0);
790        return FALSE;
791     }
792
793     /*
794      * If our mode indicates that we are stepping line numbers,
795      * get the current function, and figure out if we are exactly
796      * on a line number or not.
797      */
798     if( mode == EXEC_STEP_OVER || mode == EXEC_STEP_INSTR )
799     {
800         if( DEBUG_CheckLinenoStatus(addr) == AT_LINENUMBER )
801         {
802             (*count)--;
803         }
804     }
805     else if( mode == EXEC_STEPI_OVER || mode == EXEC_STEPI_INSTR )
806     {
807         (*count)--;
808     }
809
810     if( *count > 0 || mode == EXEC_FINISH )
811     {
812         /*
813          * We still need to execute more instructions.
814          */
815         return TRUE;
816     }
817     
818     /*
819      * If we are about to stop, then print out the source line if we
820      * have it.
821      */
822     if (mode != EXEC_CONT && mode != EXEC_PASS && mode != EXEC_FINISH)
823     {
824         DEBUG_FindNearestSymbol( addr, TRUE, NULL, 0, &syminfo.list);
825         if( syminfo.list.sourcefile != NULL )
826         {
827             DEBUG_List(&syminfo.list, NULL, 0);
828         }
829     }
830
831 #ifdef __i386__
832     /* If there's no breakpoint and we are not single-stepping, then we     */
833     /* must have encountered an int3 in the Windows program; let's skip it. */
834     if ((bpnum == -1) && code == EXCEPTION_BREAKPOINT)
835     {
836         DEBUG_context.Eip++;
837         addr->off++;
838     }
839 #endif
840
841     /* no breakpoint, continue if in continuous mode */
842     return (mode == EXEC_CONT || mode == EXEC_PASS || mode == EXEC_FINISH);
843 }
844
845 /***********************************************************************
846  *           DEBUG_SuspendExecution
847  *
848  * Remove all breakpoints before entering the debug loop
849  */
850 void    DEBUG_SuspendExecution( void )
851 {
852    DEBUG_SetBreakpoints( FALSE );
853    breakpoints[0] = DEBUG_CurrThread->stepOverBP;
854 }
855
856 /***********************************************************************
857  *           DEBUG_RestartExecution
858  *
859  * Set the breakpoints to the correct state to restart execution
860  * in the given mode.
861  */
862 enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count )
863 {
864     DBG_ADDR addr;
865     DBG_ADDR addr2;
866     int bp;
867     int delta;
868     int status;
869     enum exec_mode ret_mode;
870     DWORD instr;
871     unsigned char ch;
872
873     DEBUG_GetCurrentAddress( &addr );
874
875     /*
876      * This is the mode we will be running in after we finish.  We would like
877      * to be able to modify this in certain cases.
878      */
879     ret_mode = mode;
880
881     bp = DEBUG_FindBreakpoint( &addr, DBG_BREAK ); 
882     if ( bp != -1 && bp != 0)
883       {
884         /*
885          * If we have set a new value, then save it in the BP number.
886          */
887         if( count != 0 && mode == EXEC_CONT )
888           {
889             breakpoints[bp].skipcount = count;
890           }
891         mode = EXEC_STEPI_INSTR;  /* If there's a breakpoint, skip it */
892       }
893     else
894       {
895         if( mode == EXEC_CONT && count > 1 )
896           {
897             DEBUG_Printf(DBG_CHN_MESG, "Not stopped at any breakpoint; argument ignored.\n");
898           }
899       }
900     
901     if( mode == EXEC_FINISH && DEBUG_IsFctReturn() )
902       {
903         mode = ret_mode = EXEC_STEPI_INSTR;
904       }
905
906     instr = DEBUG_ToLinear( &addr );
907     DEBUG_READ_MEM((void*)instr, &ch, sizeof(ch));
908     /*
909      * See if the function we are stepping into has debug info
910      * and line numbers.  If not, then we step over it instead.
911      * FIXME - we need to check for things like thunks or trampolines,
912      * as the actual function may in fact have debug info.
913      */
914     if ( ch == 0xe8 )
915       {
916         DEBUG_READ_MEM((void*)(instr + 1), &delta, sizeof(delta));
917         addr2 = addr;
918         DEBUG_Disasm(&addr2, FALSE);
919         addr2.off += delta;
920         
921         status = DEBUG_CheckLinenoStatus(&addr2);
922         /*
923          * Anytime we have a trampoline, step over it.
924          */
925         if( ((mode == EXEC_STEP_OVER) || (mode == EXEC_STEPI_OVER))
926             && status == FUNC_IS_TRAMPOLINE )
927           {
928 #if 0
929             DEBUG_Printf(DBG_CHN_MESG, "Not stepping into trampoline at %x (no lines)\n",
930                     addr2.off);
931 #endif
932             mode = EXEC_STEP_OVER_TRAMPOLINE;
933           }
934         
935         if( mode == EXEC_STEP_INSTR && status == FUNC_HAS_NO_LINES )
936           {
937 #if 0
938             DEBUG_Printf(DBG_CHN_MESG, "Not stepping into function at %x (no lines)\n",
939                     addr2.off);
940 #endif
941             mode = EXEC_STEP_OVER;
942           }
943       }
944
945
946     if( mode == EXEC_STEP_INSTR )
947       {
948         if( DEBUG_CheckLinenoStatus(&addr) == FUNC_HAS_NO_LINES )
949           {
950             DEBUG_Printf(DBG_CHN_MESG, "Single stepping until exit from function, \n");
951             DEBUG_Printf(DBG_CHN_MESG, "which has no line number information.\n");
952             
953             ret_mode = mode = EXEC_FINISH;
954           }
955       }
956
957     switch(mode)
958     {
959     case EXEC_CONT: /* Continuous execution */
960     case EXEC_PASS: /* Continue, passing exception */
961 #ifdef __i386__
962         DEBUG_context.EFlags &= ~STEP_FLAG;
963 #endif
964         DEBUG_SetBreakpoints( TRUE );
965         break;
966
967     case EXEC_STEP_OVER_TRAMPOLINE:
968       /*
969        * This is the means by which we step over our conversion stubs
970        * in callfrom*.s and callto*.s.  We dig the appropriate address
971        * off the stack, and we set the breakpoint there instead of the
972        * address just after the call.
973        */
974 #ifdef __i386__
975       DEBUG_READ_MEM((void*)(DEBUG_context.Esp + 
976                              2 * sizeof(unsigned int)), 
977                      &addr.off, sizeof(addr.off));
978       DEBUG_context.EFlags &= ~STEP_FLAG;
979 #endif
980       breakpoints[0].addr    = addr;
981       breakpoints[0].enabled = TRUE;
982       breakpoints[0].refcount = 1;
983       breakpoints[0].skipcount = 0;
984       DEBUG_READ_MEM((void*)DEBUG_ToLinear( &addr ), &breakpoints[0].u.b.opcode, 
985                      sizeof(char));
986       DEBUG_SetBreakpoints( TRUE );
987       break;
988
989     case EXEC_FINISH:
990     case EXEC_STEPI_OVER:  /* Stepping over a call */
991     case EXEC_STEP_OVER:  /* Stepping over a call */
992         if (DEBUG_IsStepOverInstr())
993         {
994 #ifdef __i386__
995             DEBUG_context.EFlags &= ~STEP_FLAG;
996 #endif
997             DEBUG_Disasm(&addr, FALSE);
998             breakpoints[0].addr    = addr;
999             breakpoints[0].enabled = TRUE;
1000             breakpoints[0].refcount = 1;
1001             breakpoints[0].skipcount = 0;
1002             DEBUG_READ_MEM((void*)DEBUG_ToLinear( &addr ), &breakpoints[0].u.b.opcode,
1003                            sizeof(char));
1004             DEBUG_SetBreakpoints( TRUE );
1005             break;
1006         }
1007         /* else fall through to single-stepping */
1008
1009     case EXEC_STEP_INSTR: /* Single-stepping an instruction */
1010     case EXEC_STEPI_INSTR: /* Single-stepping an instruction */
1011 #ifdef __i386__
1012         DEBUG_context.EFlags |= STEP_FLAG;
1013 #endif
1014         break;
1015     default:
1016         RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
1017     }
1018     DEBUG_CurrThread->stepOverBP = breakpoints[0];
1019     return ret_mode;
1020 }
1021
1022 int
1023 DEBUG_AddBPCondition(int num, struct expr * exp)
1024 {
1025     if ((num <= 0) || (num >= next_bp) || !breakpoints[num].refcount)
1026     {
1027         DEBUG_Printf( DBG_CHN_MESG, "Invalid breakpoint number %d\n", num );
1028         return FALSE;
1029     }
1030
1031     if( breakpoints[num].condition != NULL )
1032       {
1033         DEBUG_FreeExpr(breakpoints[num].condition);
1034         breakpoints[num].condition = NULL;
1035       }
1036
1037     if( exp != NULL )
1038       {
1039         breakpoints[num].condition = DEBUG_CloneExpr(exp);
1040       }
1041
1042    return TRUE;
1043 }