break.c 31.6 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4 5
/*
 * Debugger break-points handling
 *
 * Copyright 1994 Martin von Loewis
 * Copyright 1995 Alexandre Julliard
6
 * Copyright 1999,2000 Eric Pouech
7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliard's avatar
Alexandre Julliard committed
21
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
22

23
#include "config.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
24
#include "debugger.h"
25 26 27
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
Alexandre Julliard's avatar
Alexandre Julliard committed
28

29 30 31 32 33 34 35 36 37 38
static int is_xpoint_break(int bpnum)
{
    int type = dbg_curr_process->bp[bpnum].xpoint_type;

    if (type == be_xpoint_break || type == be_xpoint_watch_exec) return TRUE;
    if (type == be_xpoint_watch_read || type == be_xpoint_watch_write) return FALSE;
    RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
    return 0; /* never reached */
}

Alexandre Julliard's avatar
Alexandre Julliard committed
39
/***********************************************************************
40
 *           break_set_xpoints
Alexandre Julliard's avatar
Alexandre Julliard committed
41
 *
42
 * Set or remove all the breakpoints & watchpoints
Alexandre Julliard's avatar
Alexandre Julliard committed
43
 */
44
void  break_set_xpoints(BOOL set)
Alexandre Julliard's avatar
Alexandre Julliard committed
45
{
46
    static BOOL                 last; /* = 0 = FALSE */
47

48
    unsigned int                i, ret, size;
49 50
    void*                       addr;
    struct dbg_breakpoint*      bp = dbg_curr_process->bp;
51

52 53
    if (set == last) return;
    last = set;
54

55 56
    for (i = 0; i < dbg_curr_process->next_bp; i++)
    {
57
        if (!bp[i].refcount || !bp[i].enabled) continue;
58

59
        if (is_xpoint_break(i))
60 61 62 63
            size = 0;
        else
            size = bp[i].w.len + 1;
        addr = (void*)memory_to_linear_addr(&bp[i].addr);
64

65
        if (set)
66 67 68
            ret = be_cpu->insert_Xpoint(dbg_curr_process->handle,
                                        dbg_curr_process->process_io,
                                        &dbg_context, bp[i].xpoint_type, addr,
69 70
                                        &bp[i].info, size);
        else
71 72 73
            ret = be_cpu->remove_Xpoint(dbg_curr_process->handle, 
                                        dbg_curr_process->process_io,
                                        &dbg_context, bp[i].xpoint_type, addr,
74 75 76
                                        bp[i].info, size);
        if (!ret)
        {
77 78 79
            dbg_printf("Invalid address (");
            print_address(&bp[i].addr, FALSE);
            dbg_printf(") for breakpoint %d, disabling it\n", i);
80 81 82
            bp[i].enabled = FALSE;
        }
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
83 84
}

Alexandre Julliard's avatar
Alexandre Julliard committed
85
/***********************************************************************
86
 *           find_xpoint
Alexandre Julliard's avatar
Alexandre Julliard committed
87 88 89 90
 *
 * Find the breakpoint for a given address. Return the breakpoint
 * number or -1 if none.
 */
91
static int find_xpoint(const ADDRESS64* addr, enum be_xpoint_type type)
Alexandre Julliard's avatar
Alexandre Julliard committed
92
{
93 94 95 96 97 98 99 100 101 102 103
    int                         i;
    void*                       lin = memory_to_linear_addr(addr);
    struct dbg_breakpoint*      bp = dbg_curr_process->bp;

    for (i = 0; i < dbg_curr_process->next_bp; i++)
    {
        if (bp[i].refcount && bp[i].enabled && bp[i].xpoint_type == type &&
            memory_to_linear_addr(&bp[i].addr) == lin)
            return i;
    }
    return -1;
104
}
Alexandre Julliard's avatar
Alexandre Julliard committed
105

106
/***********************************************************************
107
 *           init_xpoint
108 109 110
 *
 * Find an empty slot in BP table to add a new break/watch point
 */
111
static	int init_xpoint(int type, const ADDRESS64* addr)
112
{
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
    int	                        num;
    struct dbg_breakpoint*      bp = dbg_curr_process->bp;

    for (num = (dbg_curr_process->next_bp < MAX_BREAKPOINTS) ? 
             dbg_curr_process->next_bp++ : 1;
         num < MAX_BREAKPOINTS; num++)
    {
        if (bp[num].refcount == 0)
        {
            bp[num].refcount    = 1;
            bp[num].enabled     = TRUE;
            bp[num].xpoint_type = type;
            bp[num].skipcount   = 0;
            bp[num].addr        = *addr;
            return num;
        }
    }

    dbg_printf("Too many bp. Please delete some.\n");
    return -1;
Alexandre Julliard's avatar
Alexandre Julliard committed
133 134
}

135
/***********************************************************************
136
 *           get_watched_value
137 138 139
 *
 * Returns the value watched by watch point 'num'.
 */
140
static	BOOL	get_watched_value(int num, LPDWORD val)
141
{
142 143 144 145 146 147 148 149 150 151 152 153 154 155
    BYTE        buf[4];

    if (!dbg_read_memory(memory_to_linear_addr(&dbg_curr_process->bp[num].addr),
                         buf, dbg_curr_process->bp[num].w.len + 1))
        return FALSE;

    switch (dbg_curr_process->bp[num].w.len + 1)
    {
    case 4:	*val = *(DWORD*)buf;	break;
    case 2:	*val = *(WORD*)buf;	break;
    case 1:	*val = *(BYTE*)buf;	break;
    default: RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
    }
    return TRUE;
156
}
Alexandre Julliard's avatar
Alexandre Julliard committed
157 158

/***********************************************************************
159
 *           break_add_break
Alexandre Julliard's avatar
Alexandre Julliard committed
160 161 162
 *
 * Add a breakpoint.
 */
163
BOOL break_add_break(const ADDRESS64* addr, BOOL verbose, BOOL swbp)
Alexandre Julliard's avatar
Alexandre Julliard committed
164
{
165 166 167
    int                         num;
    BYTE                        ch;
    struct dbg_breakpoint*      bp = dbg_curr_process->bp;
168
    int                         type = swbp ? be_xpoint_break : be_xpoint_watch_exec;
Alexandre Julliard's avatar
Alexandre Julliard committed
169

170
    if ((num = find_xpoint(addr, type)) >= 1)
171
    {
172 173 174 175
        bp[num].refcount++;
        dbg_printf("Breakpoint %d at ", num);
        print_address(&bp[num].addr, TRUE);
        dbg_printf(" (refcount=%d)\n", bp[num].refcount);
176 177 178
        return TRUE;
    }

179
    if (!dbg_read_memory(memory_to_linear_addr(addr), &ch, sizeof(ch)))
180 181
    {
        if (verbose)
182 183 184 185 186
        {
            dbg_printf("Invalid address ");
            print_bare_address(addr);
            dbg_printf(", can't set breakpoint\n");
        }
187 188 189
        return FALSE;
    }

190
    if ((num = init_xpoint(type, addr)) == -1)
191 192
        return FALSE;

193 194 195
    dbg_printf("Breakpoint %d at ", num);
    print_address(&bp[num].addr, TRUE);
    dbg_printf("\n");
196

197
    return TRUE;
198 199 200
}

/***********************************************************************
201
 *           break_add_break_from_lvalue
202 203 204
 *
 * Add a breakpoint.
 */
205
BOOL break_add_break_from_lvalue(const struct dbg_lvalue* lvalue, BOOL swbp)
206
{
207
    ADDRESS64   addr;
208

209
    types_extract_as_address(lvalue, &addr);
210

211
    if (!break_add_break(&addr, TRUE, swbp))
212
    {
213 214
        if (!DBG_IVAR(CanDeferOnBPByAddr))
        {
215 216
            dbg_printf("Invalid address, can't set breakpoint\n"
                       "You can turn on deferring bp by address by setting $CanDeferOnBPByAddr to 1\n");
217 218
            return FALSE;
        }
219 220 221 222
        dbg_printf("Unable to add breakpoint, will check again any time a new DLL is loaded\n");
        dbg_curr_process->delayed_bp = 
            dbg_heap_realloc(dbg_curr_process->delayed_bp,
                             sizeof(struct dbg_delayed_bp) * ++dbg_curr_process->num_delayed_bp);
223

224 225 226
        dbg_curr_process->delayed_bp[dbg_curr_process->num_delayed_bp - 1].is_symbol   = FALSE;
        dbg_curr_process->delayed_bp[dbg_curr_process->num_delayed_bp - 1].software_bp = swbp;
        dbg_curr_process->delayed_bp[dbg_curr_process->num_delayed_bp - 1].u.addr      = addr;
227
        return TRUE;
228
    }
229
    return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
230 231
}

232
/***********************************************************************
233
 *           break_add_break_from_id
234 235 236
 *
 * Add a breakpoint from a function name (and eventually a line #)
 */
237
void	break_add_break_from_id(const char *name, int lineno, BOOL swbp)
238
{
239 240
    struct dbg_lvalue 	lvalue;
    int		        i;
241

242
    switch (symbol_get_lvalue(name, lineno, &lvalue, TRUE))
243
    {
244
    case sglv_found:
245
        break_add_break(&lvalue.addr, TRUE, swbp);
246
        return;
247
    case sglv_unknown:
248
        break;
249
    case sglv_aborted: /* user aborted symbol lookup */
250
        return;
251
    }
252

253 254
    dbg_printf("Unable to add breakpoint, will check again when a new DLL is loaded\n");
    for (i = 0; i < dbg_curr_process->num_delayed_bp; i++)
255
    {
256 257 258
        if (dbg_curr_process->delayed_bp[i].is_symbol &&
            !strcmp(name, dbg_curr_process->delayed_bp[i].u.symbol.name) &&
            lineno == dbg_curr_process->delayed_bp[i].u.symbol.lineno)
259 260
            return;
    }
261 262
    dbg_curr_process->delayed_bp = dbg_heap_realloc(dbg_curr_process->delayed_bp,
                                                    sizeof(struct dbg_delayed_bp) * ++dbg_curr_process->num_delayed_bp);
263

264 265 266
    dbg_curr_process->delayed_bp[dbg_curr_process->num_delayed_bp - 1].is_symbol       = TRUE;
    dbg_curr_process->delayed_bp[dbg_curr_process->num_delayed_bp - 1].software_bp     = swbp;
    dbg_curr_process->delayed_bp[dbg_curr_process->num_delayed_bp - 1].u.symbol.name   = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(name) + 1), name);
267
    dbg_curr_process->delayed_bp[dbg_curr_process->num_delayed_bp - 1].u.symbol.lineno = lineno;
268 269
}

270 271 272
struct cb_break_lineno
{
    int         lineno;
273
    ADDRESS64   addr;
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
};

static BOOL CALLBACK line_cb(SRCCODEINFO* sci, void* user)
{
    struct cb_break_lineno*      bkln = user;

    if (bkln->lineno == sci->LineNumber)
    {
        bkln->addr.Mode = AddrModeFlat;
        bkln->addr.Offset = sci->Address;
        return FALSE;
    }
    return TRUE;
}

289
/***********************************************************************
290
 *           break_add_break_from_lineno
291 292 293
 *
 * Add a breakpoint from a line number in current file
 */
294
void	break_add_break_from_lineno(int lineno, BOOL swbp)
295
{
296
    struct cb_break_lineno      bkln;
297

298
    memory_get_current_pc(&bkln.addr);
299

300 301
    if (lineno != -1)
    {
302
        IMAGEHLP_LINE   il;
303 304


305
        DWORD           disp;
306
        DWORD           linear = (DWORD)memory_to_linear_addr(&bkln.addr);
307

308
        il.SizeOfStruct = sizeof(il);
309
        if (!SymGetLineFromAddr(dbg_curr_process->handle, linear, &disp, &il))
310
        {
311
            dbg_printf("Unable to add breakpoint (unknown address %x)\n", linear);
312
            return;
313
        }
314 315 316 317
        bkln.addr.Offset = 0;
        bkln.lineno = lineno;
        SymEnumLines(dbg_curr_process->handle, linear, NULL, il.FileName, line_cb, &bkln);
        if (!bkln.addr.Offset)
318
        {
319 320
            dbg_printf("Unknown line number\n"
                       "(either out of file, or no code at given line number)\n");
321 322
            return;
        }
323
    }
324

325
    break_add_break(&bkln.addr, TRUE, swbp);
326
}
Alexandre Julliard's avatar
Alexandre Julliard committed
327

328
/***********************************************************************
329
 *           break_check_delayed_bp
330 331 332
 *
 * Check is a registered delayed BP is now available.
 */
333
void break_check_delayed_bp(void)
334
{
335 336 337
    struct dbg_lvalue	        lvalue;
    int			        i;
    struct dbg_delayed_bp*	dbp = dbg_curr_process->delayed_bp;
338
    char                        hexbuf[MAX_OFFSET_TO_STR_LEN];
339

340
    for (i = 0; i < dbg_curr_process->num_delayed_bp; i++)
341 342 343
    {
        if (dbp[i].is_symbol)
        {
344 345
            if (symbol_get_lvalue(dbp[i].u.symbol.name, dbp[i].u.symbol.lineno,
                                  &lvalue, TRUE) != sglv_found)
346
                continue;
347
            if (lvalue.cookie != DLV_TARGET) continue;
348 349
        }
        else
350
            lvalue.addr = dbp[i].u.addr;
351
        WINE_TRACE("trying to add delayed %s-bp\n", dbp[i].is_symbol ? "S" : "A");
352
        if (!dbp[i].is_symbol)
353 354 355
            WINE_TRACE("\t%04x:%s\n", 
                       dbp[i].u.addr.Segment,
                       memory_offset_to_string(hexbuf, dbp[i].u.addr.Offset, 0));
356
        else
357
            WINE_TRACE("\t'%s' @ %d\n", 
358
                       dbp[i].u.symbol.name, dbp[i].u.symbol.lineno);
359

360
        if (break_add_break(&lvalue.addr, FALSE, dbp[i].software_bp))
361
            memmove(&dbp[i], &dbp[i+1], (--dbg_curr_process->num_delayed_bp - i) * sizeof(*dbp));
362
    }
363 364
}

365
/***********************************************************************
366
 *           break_add_watch
367 368 369
 *
 * Add a watchpoint.
 */
370
static void break_add_watch(const struct dbg_lvalue* lvalue, BOOL is_write)
371
{
372
    int         num;
373
    DWORD64     l = 4;
374

375 376 377
    num = init_xpoint((is_write) ? be_xpoint_watch_write : be_xpoint_watch_read,
                      &lvalue->addr);
    if (num == -1) return;
378

379
    if (lvalue->type.id != dbg_itype_none)
380
    {
381
        if (types_get_info(&lvalue->type, TI_GET_LENGTH, &l))
382 383 384 385 386
        {
            switch (l)
            {
            case 4: case 2: case 1: break;
            default:
387 388
                dbg_printf("Unsupported length (%s) for watch-points, defaulting to 4\n",
                           wine_dbgstr_longlong(l));
389 390 391 392 393
                break;
            }
        }
        else dbg_printf("Cannot get watch size, defaulting to 4\n");
    }
394
    dbg_curr_process->bp[num].w.len = (DWORD)l - 1;
395

396 397 398 399 400 401 402 403 404
    if (!get_watched_value(num, &dbg_curr_process->bp[num].w.oldval))
    {
        dbg_printf("Bad address. Watchpoint not set\n");
        dbg_curr_process->bp[num].refcount = 0;
        return;
    }
    dbg_printf("Watchpoint %d at ", num);
    print_address(&dbg_curr_process->bp[num].addr, TRUE);
    dbg_printf("\n");
405 406
}

407 408 409 410 411 412 413 414 415
/******************************************************************
 *		break_add_watch_from_lvalue
 *
 * Adds a watch point from an address (stored in a lvalue)
 */
void break_add_watch_from_lvalue(const struct dbg_lvalue* lvalue)
{
    struct dbg_lvalue   lval;

416
    types_extract_as_address(lvalue, &lval.addr);
417 418 419 420 421
    lval.type.id = dbg_itype_none;

    break_add_watch(&lval, TRUE);
}

422
/***********************************************************************
423
 *           break_add_watch_from_id
424
 *
425
 * Add a watchpoint from a symbol name
426
 */
427
void	break_add_watch_from_id(const char *name)
428
{
429 430 431 432 433 434 435 436 437 438 439 440 441
    struct dbg_lvalue    lvalue;

    switch (symbol_get_lvalue(name, -1, &lvalue, TRUE))
    {
    case sglv_found:
        break_add_watch(&lvalue, 1);
        break;
    case sglv_unknown:
        dbg_printf("Unable to add watchpoint\n");
        break;
    case sglv_aborted: /* user aborted symbol lookup */
        break;
    }
442 443
}

Alexandre Julliard's avatar
Alexandre Julliard committed
444
/***********************************************************************
445
 *           break_delete_xpoint
Alexandre Julliard's avatar
Alexandre Julliard committed
446 447 448
 *
 * Delete a breakpoint.
 */
449
void break_delete_xpoint(int num)
Alexandre Julliard's avatar
Alexandre Julliard committed
450
{
451 452 453 454
    struct dbg_breakpoint*      bp = dbg_curr_process->bp;

    if ((num <= 0) || (num >= dbg_curr_process->next_bp) ||
        bp[num].refcount == 0)
Alexandre Julliard's avatar
Alexandre Julliard committed
455
    {
456
        dbg_printf("Invalid breakpoint number %d\n", num);
Alexandre Julliard's avatar
Alexandre Julliard committed
457 458
        return;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
459

460 461
    if (--bp[num].refcount > 0)
        return;
462

463
    if (bp[num].condition != NULL)
464
    {
465 466
        expr_free(bp[num].condition);
        bp[num].condition = NULL;
467
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
468

469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
    bp[num].enabled = FALSE;
    bp[num].refcount = 0;
    bp[num].skipcount = 0;
}

static inline BOOL module_is_container(const IMAGEHLP_MODULE* wmod_cntnr,
                                     const IMAGEHLP_MODULE* wmod_child)
{
    return wmod_cntnr->BaseOfImage <= wmod_child->BaseOfImage &&
        (DWORD)wmod_cntnr->BaseOfImage + wmod_cntnr->ImageSize >=
        (DWORD)wmod_child->BaseOfImage + wmod_child->ImageSize;
}

/******************************************************************
 *		break_delete_xpoints_from_module
 *
 * Remove all Xpoints from module which base is 'base'
 */
void break_delete_xpoints_from_module(unsigned long base)
{
    IMAGEHLP_MODULE             im, im_elf;
    int                         i;
    DWORD                       linear;
    struct dbg_breakpoint*      bp = dbg_curr_process->bp;

    /* FIXME: should do it also on the ELF sibbling if any */
    im.SizeOfStruct = sizeof(im);
    im_elf.SizeOfStruct = sizeof(im_elf);
    if (!SymGetModuleInfo(dbg_curr_process->handle, base, &im)) return;

    /* try to get in fact the underlying ELF module (if any) */
    if (SymGetModuleInfo(dbg_curr_process->handle, im.BaseOfImage - 1, &im_elf) &&
        im_elf.BaseOfImage <= im.BaseOfImage &&
        (DWORD)im_elf.BaseOfImage + im_elf.ImageSize >= (DWORD)im.BaseOfImage + im.ImageSize)
        im = im_elf;

    for (i = 0; i < dbg_curr_process->next_bp; i++)
    {
        linear = (DWORD)memory_to_linear_addr(&bp[i].addr);
        if (bp[i].refcount && bp[i].enabled &&
            im.BaseOfImage <= linear && linear < im.BaseOfImage + im.ImageSize)
        {
            break_delete_xpoint(i);
        }
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
514
}
Alexandre Julliard's avatar
Alexandre Julliard committed
515

Alexandre Julliard's avatar
Alexandre Julliard committed
516
/***********************************************************************
517
 *           break_enable_xpoint
Alexandre Julliard's avatar
Alexandre Julliard committed
518 519 520
 *
 * Enable or disable a break point.
 */
521
void break_enable_xpoint(int num, BOOL enable)
Alexandre Julliard's avatar
Alexandre Julliard committed
522
{
523 524
    if ((num <= 0) || (num >= dbg_curr_process->next_bp) || 
        dbg_curr_process->bp[num].refcount == 0)
Alexandre Julliard's avatar
Alexandre Julliard committed
525
    {
526
        dbg_printf("Invalid breakpoint number %d\n", num);
Alexandre Julliard's avatar
Alexandre Julliard committed
527 528
        return;
    }
529 530
    dbg_curr_process->bp[num].enabled = (enable) ? TRUE : FALSE;
    dbg_curr_process->bp[num].skipcount = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
531
}
Alexandre Julliard's avatar
Alexandre Julliard committed
532 533


534
/***********************************************************************
535
 *           find_triggered_watch
536 537 538 539 540 541
 *
 * Lookup the watchpoints to see if one has been triggered
 * Return >= (watch point index) if one is found and *oldval is set to
 * 	the value watched before the TRAP
 * Return -1 if none found (*oldval is undetermined)
 *
542
 * Unfortunately, Linux does *NOT* (A REAL PITA) report with ptrace
543 544 545 546
 * the DR6 register value, so we have to look with our own need the
 * cause of the TRAP.
 * -EP
 */
547
static int find_triggered_watch(LPDWORD oldval)
548
{
549 550 551 552 553 554 555 556 557 558 559
    int                         found = -1;
    int                         i;
    struct dbg_breakpoint*      bp = dbg_curr_process->bp;

    /* Method 1 => get triggered watchpoint from context (doesn't work on Linux
     * 2.2.x). This should be fixed in >= 2.2.16
     */
    for (i = 0; i < dbg_curr_process->next_bp; i++)
    {
        DWORD val = 0;

560
        if (bp[i].refcount && bp[i].enabled && !is_xpoint_break(i) &&
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
            (be_cpu->is_watchpoint_set(&dbg_context, bp[i].info)))
        {
            be_cpu->clear_watchpoint(&dbg_context, bp[i].info);

            *oldval = bp[i].w.oldval;
            if (get_watched_value(i, &val))
            {
                bp[i].w.oldval = val;
                return i;
            }
        }
    }

    /* Method 1 failed, trying method 2 */

    /* Method 2 => check if value has changed among registered watchpoints
     * this really sucks, but this is how gdb 4.18 works on my linux box
     * -EP
     */
    for (i = 0; i < dbg_curr_process->next_bp; i++)
    {
        DWORD val = 0;

584
        if (bp[i].refcount && bp[i].enabled && !is_xpoint_break(i) &&
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
            get_watched_value(i, &val))
        {
            *oldval = bp[i].w.oldval;
            if (val != *oldval)
            {
                be_cpu->clear_watchpoint(&dbg_context, bp[i].info);
                bp[i].w.oldval = val;
                found = i;
                /* cannot break, because two watch points may have been triggered on
                 * the same access
                 * only one will be reported to the user (FIXME ?)
                 */
            }
        }
    }
    return found;
601 602
}

Alexandre Julliard's avatar
Alexandre Julliard committed
603
/***********************************************************************
604
 *           break_info
Alexandre Julliard's avatar
Alexandre Julliard committed
605
 *
606
 * Display break & watch points information.
Alexandre Julliard's avatar
Alexandre Julliard committed
607
 */
608
void break_info(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
609
{
610 611 612 613 614 615 616 617 618
    int                         i;
    int                         nbp = 0, nwp = 0;
    struct dbg_delayed_bp*	dbp = dbg_curr_process->delayed_bp;
    struct dbg_breakpoint*      bp = dbg_curr_process->bp;

    for (i = 1; i < dbg_curr_process->next_bp; i++)
    {
        if (bp[i].refcount)
        {
619
            if (is_xpoint_break(i)) nbp++; else nwp++;
620 621
        }
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
622

623
    if (nbp)
Alexandre Julliard's avatar
Alexandre Julliard committed
624
    {
625 626
        dbg_printf("Breakpoints:\n");
        for (i = 1; i < dbg_curr_process->next_bp; i++)
Alexandre Julliard's avatar
Alexandre Julliard committed
627
        {
628
            if (!bp[i].refcount || !is_xpoint_break(i))
629 630 631
                continue;
            dbg_printf("%d: %c ", i, bp[i].enabled ? 'y' : 'n');
            print_address(&bp[i].addr, TRUE);
632 633
            dbg_printf(" (%u)%s\n", bp[i].refcount, 
                       bp[i].xpoint_type == be_xpoint_watch_exec ? " (hardware assisted)" : "");
634
	    if (bp[i].condition != NULL)
635
	    {
636 637 638
	        dbg_printf("\t\tstop when  ");
 		expr_print(bp[i].condition);
		dbg_printf("\n");
639
	    }
Alexandre Julliard's avatar
Alexandre Julliard committed
640 641
        }
    }
642 643
    else dbg_printf("No breakpoints\n");
    if (nwp)
644
    {
645 646
        dbg_printf("Watchpoints:\n");
        for (i = 1; i < dbg_curr_process->next_bp; i++)
647
        {
648
            if (!bp[i].refcount || is_xpoint_break(i))
649 650 651 652 653 654 655
                continue;
            dbg_printf("%d: %c ", i, bp[i].enabled ? 'y' : 'n');
            print_address(&bp[i].addr, TRUE);
            dbg_printf(" on %d byte%s (%c)\n",
                       bp[i].w.len + 1, bp[i].w.len > 0 ? "s" : "",
                       bp[i].xpoint_type == be_xpoint_watch_write ? 'W' : 'R');
	    if (bp[i].condition != NULL)
656
	    {
657 658 659
	        dbg_printf("\t\tstop when ");
 		expr_print(bp[i].condition);
		dbg_printf("\n");
660 661 662
	    }
        }
    }
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682
    else dbg_printf("No watchpoints\n");
    if (dbg_curr_process->num_delayed_bp)
    {
        dbg_printf("Delayed breakpoints:\n");
        for (i = 0; i < dbg_curr_process->num_delayed_bp; i++)
        {
            if (dbp[i].is_symbol)
            {
                dbg_printf("%d: %s", i, dbp[i].u.symbol.name);
                if (dbp[i].u.symbol.lineno != -1)
                    dbg_printf(" at line %u", dbp[i].u.symbol.lineno);
            }
            else
            {
                dbg_printf("%d: ", i);
                print_address(&dbp[i].u.addr, FALSE);
            }
            dbg_printf("\n");
        }
    }
683 684 685
}

/***********************************************************************
686
 *           should_stop
687 688 689 690
 *
 * Check whether or not the condition (bp / skipcount) of a break/watch
 * point are met.
 */
691
static	BOOL should_stop(int bpnum)
692
{
693 694 695
    struct dbg_breakpoint*      bp = &dbg_curr_process->bp[bpnum];

    if (bp->condition != NULL)
696
    {
697
        struct dbg_lvalue lvalue = expr_eval(bp->condition);
698

699
        if (lvalue.type.id == dbg_itype_none)
700 701 702 703
        {
	    /*
	     * Something wrong - unable to evaluate this expression.
	     */
704 705 706 707
	    dbg_printf("Unable to evaluate expression ");
	    expr_print(bp->condition);
	    dbg_printf("\nTurning off condition\n");
	    break_add_condition(bpnum, NULL);
708
        }
709
        else if (!types_extract_as_integer(&lvalue))
710 711 712 713
        {
	    return FALSE;
        }
    }
714

715 716
    if (bp->skipcount > 0) bp->skipcount--;
    return bp->skipcount == 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
717
}
Alexandre Julliard's avatar
Alexandre Julliard committed
718

Alexandre Julliard's avatar
Alexandre Julliard committed
719
/***********************************************************************
720
 *           break_should_continue
Alexandre Julliard's avatar
Alexandre Julliard committed
721 722 723 724
 *
 * Determine if we should continue execution after a SIGTRAP signal when
 * executing in the given mode.
 */
725
BOOL break_should_continue(ADDRESS64* addr, DWORD code)
Alexandre Julliard's avatar
Alexandre Julliard committed
726
{
727
    enum dbg_exec_mode  mode = dbg_curr_thread->exec_mode;
Alexandre Julliard's avatar
Alexandre Julliard committed
728

Alexandre Julliard's avatar
Alexandre Julliard committed
729

730
    if (dbg_curr_thread->stopped_xpoint > 0)
731
    {
732
        if (!should_stop(dbg_curr_thread->stopped_xpoint)) return TRUE;
733

734 735 736 737 738 739 740 741 742 743 744 745
        switch (dbg_curr_process->bp[dbg_curr_thread->stopped_xpoint].xpoint_type)
        {
        case be_xpoint_break:
        case be_xpoint_watch_exec:
            dbg_printf("Stopped on breakpoint %d at ", dbg_curr_thread->stopped_xpoint);
            print_address(&dbg_curr_process->bp[dbg_curr_thread->stopped_xpoint].addr, TRUE);
            dbg_printf("\n");
            break;
        case be_xpoint_watch_read:
        case be_xpoint_watch_write:
            dbg_printf("Stopped on watchpoint %d at ", dbg_curr_thread->stopped_xpoint);
            print_address(addr, TRUE);
746 747
            dbg_printf(" new value %u\n",
                       dbg_curr_process->bp[dbg_curr_thread->stopped_xpoint].w.oldval);
748
        }
749
        return FALSE;
750 751
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
752 753 754 755 756
    /*
     * If our mode indicates that we are stepping line numbers,
     * get the current function, and figure out if we are exactly
     * on a line number or not.
     */
757
    if (mode == dbg_exec_step_over_line || mode == dbg_exec_step_into_line)
758
    {
759
	if (symbol_get_function_line_status(addr) == dbg_on_a_line_number)
760
            dbg_curr_thread->exec_count--;
761
    }
762
    else if (mode == dbg_exec_step_over_insn || mode == dbg_exec_step_into_insn)
763
        dbg_curr_thread->exec_count--;
Alexandre Julliard's avatar
Alexandre Julliard committed
764

765
    if (dbg_curr_thread->exec_count > 0 || mode == dbg_exec_finish)
766
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
767 768 769 770
	/*
	 * We still need to execute more instructions.
	 */
	return TRUE;
771
    }
772

773 774 775 776 777
    /* no breakpoint, continue if in continuous mode */
    return mode == dbg_exec_cont || mode == dbg_exec_finish;
}

/***********************************************************************
778
 *           break_adjust_pc
779
 *
780
 * Adjust PC to the address where the trap (if any) actually occurred
781 782
 * Also sets dbg_curr_thread->stopped_xpoint
 */
783
void break_adjust_pc(ADDRESS64* addr, DWORD code, BOOL first_chance, BOOL* is_break)
784 785 786
{
    DWORD	        oldval = 0;

787 788 789 790 791 792 793
    /* break / watch points are handled on first chance */
    if ( !first_chance )
    {
        *is_break = TRUE;
        dbg_curr_thread->stopped_xpoint = -1;
        return;
    }
794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
    *is_break = FALSE;

    /* If not single-stepping, back up to the break instruction */
    if (code == EXCEPTION_BREAKPOINT)
        addr->Offset += be_cpu->adjust_pc_for_break(&dbg_context, TRUE);

    dbg_curr_thread->stopped_xpoint = find_xpoint(addr, be_xpoint_break);
    dbg_curr_process->bp[0].enabled = FALSE;  /* disable the step-over breakpoint */

    if (dbg_curr_thread->stopped_xpoint > 0) return;

    if (dbg_curr_thread->stopped_xpoint < 0)
    {
        dbg_curr_thread->stopped_xpoint = find_xpoint(addr, be_xpoint_watch_exec);
        if (dbg_curr_thread->stopped_xpoint < 0)
            dbg_curr_thread->stopped_xpoint = find_triggered_watch(&oldval);
        if (dbg_curr_thread->stopped_xpoint > 0)
        {
            /* If not single-stepping, do not back up over the break instruction */
            if (code == EXCEPTION_BREAKPOINT)
                addr->Offset += be_cpu->adjust_pc_for_break(&dbg_context, FALSE);
            return;
        }
    }

819
    /* If there's no breakpoint and we are not single-stepping, then
820
     * either we must have encountered a break insn in the Windows program
821 822
     * or someone is trying to stop us
     */
823
    if (dbg_curr_thread->stopped_xpoint == -1 && code == EXCEPTION_BREAKPOINT)
824
    {
825
        *is_break = TRUE;
826
        addr->Offset += be_cpu->adjust_pc_for_break(&dbg_context, FALSE);
827
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
828 829
}

830
/***********************************************************************
831
 *           break_suspend_execution
832
 *
833
 * Remove all bp before entering the debug loop
834
 */
835
void	break_suspend_execution(void)
836
{
837 838
    break_set_xpoints(FALSE);
    dbg_curr_process->bp[0] = dbg_curr_thread->step_over_bp;
839
}
Alexandre Julliard's avatar
Alexandre Julliard committed
840 841

/***********************************************************************
842
 *           break_restart_execution
Alexandre Julliard's avatar
Alexandre Julliard committed
843
 *
844
 * Set the bp to the correct state to restart execution
Alexandre Julliard's avatar
Alexandre Julliard committed
845 846
 * in the given mode.
 */
847
void break_restart_execution(int count)
Alexandre Julliard's avatar
Alexandre Julliard committed
848
{
849
    ADDRESS64                   addr;
850 851
    enum dbg_line_status        status;
    enum dbg_exec_mode          mode, ret_mode;
852
    ADDRESS64                   callee;
853
    void*                       linear;
Alexandre Julliard's avatar
Alexandre Julliard committed
854

855
    memory_get_current_pc(&addr);
856
    linear = memory_to_linear_addr(&addr);
Alexandre Julliard's avatar
Alexandre Julliard committed
857

Alexandre Julliard's avatar
Alexandre Julliard committed
858 859 860 861
    /*
     * This is the mode we will be running in after we finish.  We would like
     * to be able to modify this in certain cases.
     */
862
    ret_mode = mode = dbg_curr_thread->exec_mode;
Alexandre Julliard's avatar
Alexandre Julliard committed
863

864 865
    /* we've stopped on a xpoint (other than step over) */
    if (dbg_curr_thread->stopped_xpoint > 0)
866
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
867 868 869
	/*
	 * If we have set a new value, then save it in the BP number.
	 */
870 871
	if (count != 0 && mode == dbg_exec_cont)
        {
872
	    dbg_curr_process->bp[dbg_curr_thread->stopped_xpoint].skipcount = count;
873
        }
874 875 876
        /* If we've stopped on a breakpoint, single step over it (, then run) */
        if (is_xpoint_break(dbg_curr_thread->stopped_xpoint))
            mode = dbg_exec_step_into_insn;
877 878 879 880 881 882
    }
    else if (mode == dbg_exec_cont && count > 1)
    {
        dbg_printf("Not stopped at any breakpoint; argument ignored.\n");
    }

883
    if (mode == dbg_exec_finish && be_cpu->is_function_return(linear))
884 885 886 887
    {
	mode = ret_mode = dbg_exec_step_into_insn;
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
888 889 890 891 892 893
    /*
     * See if the function we are stepping into has debug info
     * and line numbers.  If not, then we step over it instead.
     * FIXME - we need to check for things like thunks or trampolines,
     * as the actual function may in fact have debug info.
     */
894
    if (be_cpu->is_function_call(linear, &callee))
895 896 897 898
    {
	status = symbol_get_function_line_status(&callee);
#if 0
        /* FIXME: we need to get the thunk type */
Alexandre Julliard's avatar
Alexandre Julliard committed
899 900 901
	/*
	 * Anytime we have a trampoline, step over it.
	 */
902 903 904 905 906
	if ((mode == EXEC_STEP_OVER || mode == EXEC_STEPI_OVER)
	    && status == dbg_in_a_thunk)
        {
            WINE_WARN("Not stepping into trampoline at %p (no lines)\n", 
                      memory_to_linear_addr(&callee));
Alexandre Julliard's avatar
Alexandre Julliard committed
907
	    mode = EXEC_STEP_OVER_TRAMPOLINE;
908 909 910 911 912 913 914 915 916
        }
#endif
	if (mode == dbg_exec_step_into_line && status == dbg_no_line_info)
        {
            WINE_WARN("Not stepping into function at %p (no lines)\n",
                      memory_to_linear_addr(&callee));
	    mode = dbg_exec_step_over_line;
        }
    }
917

918 919 920
    if (mode == dbg_exec_step_into_line && 
        symbol_get_function_line_status(&addr) == dbg_no_line_info)
    {
921
        dbg_printf("Single stepping until exit from function,\n"
922 923 924
                   "which has no line number information.\n");
        ret_mode = mode = dbg_exec_finish;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
925

926
    switch (mode)
Alexandre Julliard's avatar
Alexandre Julliard committed
927
    {
928 929 930
    case dbg_exec_cont: /* Continuous execution */
        be_cpu->single_step(&dbg_context, FALSE);
        break_set_xpoints(TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
931 932
        break;

933
#if 0
Alexandre Julliard's avatar
Alexandre Julliard committed
934
    case EXEC_STEP_OVER_TRAMPOLINE:
935 936 937 938 939 940 941 942
        /*
         * This is the means by which we step over our conversion stubs
         * in callfrom*.s and callto*.s.  We dig the appropriate address
         * off the stack, and we set the breakpoint there instead of the
         * address just after the call.
         */
        be_cpu->get_addr(dbg_curr_thread->handle, &dbg_context,
                         be_cpu_addr_stack, &addr);
943
        /* FIXME: we assume stack grows as on an i386 */
944 945 946 947 948 949 950
        addr.Offset += 2 * sizeof(unsigned int);
        dbg_read_memory(memory_to_linear_addr(&addr),
                        &addr.Offset, sizeof(addr.Offset));
        dbg_curr_process->bp[0].addr = addr;
        dbg_curr_process->bp[0].enabled = TRUE;
        dbg_curr_process->bp[0].refcount = 1;
        dbg_curr_process->bp[0].skipcount = 0;
951 952
        dbg_curr_process->bp[0].xpoint_type = be_xpoint_break;
        dbg_curr_process->bp[0].condition = NULL;
953 954 955
        be_cpu->single_step(&dbg_context, FALSE);
        break_set_xpoints(TRUE);
        break;
956
#endif
957 958 959 960

    case dbg_exec_finish:
    case dbg_exec_step_over_insn:  /* Stepping over a call */
    case dbg_exec_step_over_line:  /* Stepping over a call */
961
        if (be_cpu->is_step_over_insn(linear))
Alexandre Julliard's avatar
Alexandre Julliard committed
962
        {
963 964 965 966 967
            be_cpu->disasm_one_insn(&addr, FALSE);
            dbg_curr_process->bp[0].addr = addr;
            dbg_curr_process->bp[0].enabled = TRUE;
            dbg_curr_process->bp[0].refcount = 1;
	    dbg_curr_process->bp[0].skipcount = 0;
968 969
            dbg_curr_process->bp[0].xpoint_type = be_xpoint_break;
            dbg_curr_process->bp[0].condition = NULL;
970 971
            be_cpu->single_step(&dbg_context, FALSE);
            break_set_xpoints(TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
972 973 974
            break;
        }
        /* else fall through to single-stepping */
Alexandre Julliard's avatar
Alexandre Julliard committed
975

976 977 978
    case dbg_exec_step_into_line: /* Single-stepping a line */
    case dbg_exec_step_into_insn: /* Single-stepping an instruction */
        be_cpu->single_step(&dbg_context, TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
979
        break;
980
    default: RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
Alexandre Julliard's avatar
Alexandre Julliard committed
981
    }
982 983
    dbg_curr_thread->step_over_bp = dbg_curr_process->bp[0];
    dbg_curr_thread->exec_mode = ret_mode;
Alexandre Julliard's avatar
Alexandre Julliard committed
984 985
}

986
int break_add_condition(int num, struct expr* exp)
Alexandre Julliard's avatar
Alexandre Julliard committed
987
{
988 989
    if (num <= 0 || num >= dbg_curr_process->next_bp || 
        !dbg_curr_process->bp[num].refcount)
Alexandre Julliard's avatar
Alexandre Julliard committed
990
    {
991
        dbg_printf("Invalid breakpoint number %d\n", num);
Alexandre Julliard's avatar
Alexandre Julliard committed
992 993 994
        return FALSE;
    }

995 996 997 998 999
    if (dbg_curr_process->bp[num].condition != NULL)
    {
	expr_free(dbg_curr_process->bp[num].condition);
	dbg_curr_process->bp[num].condition = NULL;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1000

1001
    if (exp != NULL) dbg_curr_process->bp[num].condition = expr_clone(exp, NULL);
Alexandre Julliard's avatar
Alexandre Julliard committed
1002

1003
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1004
}