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