break.c 31.3 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 ADDRESS* 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 ADDRESS* 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 ADDRESS* 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
    ADDRESS     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 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
struct cb_break_lineno
{
    int         lineno;
    ADDRESS     addr;
};

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

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

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

329
/***********************************************************************
330
 *           break_check_delayed_bp
331 332 333
 *
 * Check is a registered delayed BP is now available.
 */
334
void break_check_delayed_bp(void)
335
{
336 337 338
    struct dbg_lvalue	        lvalue;
    int			        i;
    struct dbg_delayed_bp*	dbp = dbg_curr_process->delayed_bp;
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
            WINE_TRACE("\t%04x:%08lx\n", 
                       dbp[i].u.addr.Segment, dbp[i].u.addr.Offset);
355
        else
356
            WINE_TRACE("\t'%s' @ %d\n", 
357
                       dbp[i].u.symbol.name, dbp[i].u.symbol.lineno);
358

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

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

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

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

395 396 397 398 399 400 401 402 403
    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");
404 405
}

406 407 408 409 410 411 412 413 414
/******************************************************************
 *		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;

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

    break_add_watch(&lval, TRUE);
}

421
/***********************************************************************
422
 *           break_add_watch_from_id
423
 *
424
 * Add a watchpoint from a symbol name
425
 */
426
void	break_add_watch_from_id(const char *name)
427
{
428 429 430 431 432 433 434 435 436 437 438 439 440
    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;
    }
441 442
}

Alexandre Julliard's avatar
Alexandre Julliard committed
443
/***********************************************************************
444
 *           break_delete_xpoint
Alexandre Julliard's avatar
Alexandre Julliard committed
445 446 447
 *
 * Delete a breakpoint.
 */
448
void break_delete_xpoint(int num)
Alexandre Julliard's avatar
Alexandre Julliard committed
449
{
450 451 452 453
    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
454
    {
455
        dbg_printf("Invalid breakpoint number %d\n", num);
Alexandre Julliard's avatar
Alexandre Julliard committed
456 457
        return;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
458

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

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

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
    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
513
}
Alexandre Julliard's avatar
Alexandre Julliard committed
514

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


533
/***********************************************************************
534
 *           find_triggered_watch
535 536 537 538 539 540
 *
 * 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)
 *
541
 * Unfortunately, Linux does *NOT* (A REAL PITA) report with ptrace
542 543 544 545
 * the DR6 register value, so we have to look with our own need the
 * cause of the TRAP.
 * -EP
 */
546
static int find_triggered_watch(LPDWORD oldval)
547
{
548 549 550 551 552 553 554 555 556 557 558
    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;

559
        if (bp[i].refcount && bp[i].enabled && !is_xpoint_break(i) &&
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
            (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;

583
        if (bp[i].refcount && bp[i].enabled && !is_xpoint_break(i) &&
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
            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;
600 601
}

Alexandre Julliard's avatar
Alexandre Julliard committed
602
/***********************************************************************
603
 *           break_info
Alexandre Julliard's avatar
Alexandre Julliard committed
604
 *
605
 * Display break & watch points information.
Alexandre Julliard's avatar
Alexandre Julliard committed
606
 */
607
void break_info(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
608
{
609 610 611 612 613 614 615 616 617
    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)
        {
618
            if (is_xpoint_break(i)) nbp++; else nwp++;
619 620
        }
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
621

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

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

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

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

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

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

729
    *is_break = FALSE;
730
    /* If not single-stepping, back up to the break instruction */
731
    if (code == EXCEPTION_BREAKPOINT)
732
        addr->Offset += be_cpu->adjust_pc_for_break(&dbg_context, TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
733

734
    dbg_curr_thread->stopped_xpoint = find_xpoint(addr, be_xpoint_break);
735
    dbg_curr_process->bp[0].enabled = FALSE;  /* disable the step-over breakpoint */
Alexandre Julliard's avatar
Alexandre Julliard committed
736

737 738 739 740 741 742 743 744 745 746
    if (dbg_curr_thread->stopped_xpoint > 0)
    {
        if (!should_stop(dbg_curr_thread->stopped_xpoint)) return TRUE;

        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");
        return FALSE;
    }

747 748
    if(dbg_curr_thread->stopped_xpoint < 0)
        dbg_curr_thread->stopped_xpoint = find_xpoint(addr, be_xpoint_watch_exec);
749
    if (dbg_curr_thread->stopped_xpoint > 0)
Alexandre Julliard's avatar
Alexandre Julliard committed
750
    {
751 752 753 754 755
        /* 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);

        if (!should_stop(dbg_curr_thread->stopped_xpoint)) return TRUE;
756

757 758
        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);
759
        dbg_printf("\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
760 761
        return FALSE;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
762

763 764
    if(dbg_curr_thread->stopped_xpoint < 0)
        dbg_curr_thread->stopped_xpoint = find_triggered_watch(&oldval);
765
    if (dbg_curr_thread->stopped_xpoint > 0)
766
    {
767 768 769 770
        /* 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);

771
        if (!should_stop(dbg_curr_thread->stopped_xpoint)) return TRUE;
772

773
        dbg_printf("Stopped on watchpoint %d at ", dbg_curr_thread->stopped_xpoint);
774 775
        print_address(addr, TRUE);
        dbg_printf(" values: old=%lu new=%lu\n",
776
                   oldval, dbg_curr_process->bp[dbg_curr_thread->stopped_xpoint].w.oldval);
777
        return FALSE;
778 779
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
780 781 782 783 784
    /*
     * 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.
     */
785
    if (mode == dbg_exec_step_over_line || mode == dbg_exec_step_into_line)
786
    {
787
	if (symbol_get_function_line_status(addr) == dbg_on_a_line_number)
788
	{
Alexandre Julliard's avatar
Alexandre Julliard committed
789
	    (*count)--;
790 791
	}
    }
792
    else if (mode == dbg_exec_step_over_insn || mode == dbg_exec_step_into_insn)
793
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
794
	(*count)--;
795
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
796

797
    if (*count > 0 || mode == dbg_exec_finish)
798
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
799 800 801 802
	/*
	 * We still need to execute more instructions.
	 */
	return TRUE;
803
    }
804

805
    /* If there's no breakpoint and we are not single-stepping, then
806
     * either we must have encountered a break insn in the Windows program
807 808
     * or someone is trying to stop us
     */
809
    if (dbg_curr_thread->stopped_xpoint == -1 && code == EXCEPTION_BREAKPOINT)
810
    {
811
        *is_break = TRUE;
812 813
        addr->Offset += be_cpu->adjust_pc_for_break(&dbg_context, FALSE);
        return FALSE;
814
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
815

816
    /* no breakpoint, continue if in continuous mode */
817
    return mode == dbg_exec_cont || mode == dbg_exec_finish;
Alexandre Julliard's avatar
Alexandre Julliard committed
818 819
}

820
/***********************************************************************
821
 *           break_suspend_execution
822
 *
823
 * Remove all bp before entering the debug loop
824
 */
825
void	break_suspend_execution(void)
826
{
827 828
    break_set_xpoints(FALSE);
    dbg_curr_process->bp[0] = dbg_curr_thread->step_over_bp;
829
}
Alexandre Julliard's avatar
Alexandre Julliard committed
830 831

/***********************************************************************
832
 *           break_restart_execution
Alexandre Julliard's avatar
Alexandre Julliard committed
833
 *
834
 * Set the bp to the correct state to restart execution
Alexandre Julliard's avatar
Alexandre Julliard committed
835 836
 * in the given mode.
 */
837
void break_restart_execution(int count)
Alexandre Julliard's avatar
Alexandre Julliard committed
838
{
839 840 841 842
    ADDRESS                     addr;
    enum dbg_line_status        status;
    enum dbg_exec_mode          mode, ret_mode;
    ADDRESS                     callee;
843
    void*                       linear;
Alexandre Julliard's avatar
Alexandre Julliard committed
844

845
    memory_get_current_pc(&addr);
846
    linear = memory_to_linear_addr(&addr);
Alexandre Julliard's avatar
Alexandre Julliard committed
847

Alexandre Julliard's avatar
Alexandre Julliard committed
848 849 850 851
    /*
     * This is the mode we will be running in after we finish.  We would like
     * to be able to modify this in certain cases.
     */
852
    ret_mode = mode = dbg_curr_thread->exec_mode;
Alexandre Julliard's avatar
Alexandre Julliard committed
853

854 855
    /* we've stopped on a xpoint (other than step over) */
    if (dbg_curr_thread->stopped_xpoint > 0)
856
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
857 858 859
	/*
	 * If we have set a new value, then save it in the BP number.
	 */
860 861
	if (count != 0 && mode == dbg_exec_cont)
        {
862
	    dbg_curr_process->bp[dbg_curr_thread->stopped_xpoint].skipcount = count;
863
        }
864 865 866
        /* 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;
867 868 869 870 871 872
    }
    else if (mode == dbg_exec_cont && count > 1)
    {
        dbg_printf("Not stopped at any breakpoint; argument ignored.\n");
    }

873
    if (mode == dbg_exec_finish && be_cpu->is_function_return(linear))
874 875 876 877
    {
	mode = ret_mode = dbg_exec_step_into_insn;
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
878 879 880 881 882 883
    /*
     * 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.
     */
884
    if (be_cpu->is_function_call(linear, &callee))
885 886 887 888
    {
	status = symbol_get_function_line_status(&callee);
#if 0
        /* FIXME: we need to get the thunk type */
Alexandre Julliard's avatar
Alexandre Julliard committed
889 890 891
	/*
	 * Anytime we have a trampoline, step over it.
	 */
892 893 894 895 896
	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
897
	    mode = EXEC_STEP_OVER_TRAMPOLINE;
898 899 900 901 902 903 904 905 906
        }
#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;
        }
    }
907

908 909 910 911 912 913 914
    if (mode == dbg_exec_step_into_line && 
        symbol_get_function_line_status(&addr) == dbg_no_line_info)
    {
        dbg_printf("Single stepping until exit from function, \n"
                   "which has no line number information.\n");
        ret_mode = mode = dbg_exec_finish;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
915

916
    switch (mode)
Alexandre Julliard's avatar
Alexandre Julliard committed
917
    {
918 919 920
    case dbg_exec_cont: /* Continuous execution */
        be_cpu->single_step(&dbg_context, FALSE);
        break_set_xpoints(TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
921 922
        break;

923
#if 0
Alexandre Julliard's avatar
Alexandre Julliard committed
924
    case EXEC_STEP_OVER_TRAMPOLINE:
925 926 927 928 929 930 931 932
        /*
         * 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);
933
        /* FIXME: we assume stack grows as on an i386 */
934 935 936 937 938 939 940
        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;
941 942
        dbg_curr_process->bp[0].xpoint_type = be_xpoint_break;
        dbg_curr_process->bp[0].condition = NULL;
943 944 945
        be_cpu->single_step(&dbg_context, FALSE);
        break_set_xpoints(TRUE);
        break;
946
#endif
947 948 949 950

    case dbg_exec_finish:
    case dbg_exec_step_over_insn:  /* Stepping over a call */
    case dbg_exec_step_over_line:  /* Stepping over a call */
951
        if (be_cpu->is_step_over_insn(linear))
Alexandre Julliard's avatar
Alexandre Julliard committed
952
        {
953 954 955 956 957
            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;
958 959
            dbg_curr_process->bp[0].xpoint_type = be_xpoint_break;
            dbg_curr_process->bp[0].condition = NULL;
960 961
            be_cpu->single_step(&dbg_context, FALSE);
            break_set_xpoints(TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
962 963 964
            break;
        }
        /* else fall through to single-stepping */
Alexandre Julliard's avatar
Alexandre Julliard committed
965

966 967 968
    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
969
        break;
970
    default: RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
Alexandre Julliard's avatar
Alexandre Julliard committed
971
    }
972 973
    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
974 975
}

976
int break_add_condition(int num, struct expr* exp)
Alexandre Julliard's avatar
Alexandre Julliard committed
977
{
978 979
    if (num <= 0 || num >= dbg_curr_process->next_bp || 
        !dbg_curr_process->bp[num].refcount)
Alexandre Julliard's avatar
Alexandre Julliard committed
980
    {
981
        dbg_printf("Invalid breakpoint number %d\n", num);
Alexandre Julliard's avatar
Alexandre Julliard committed
982 983 984
        return FALSE;
    }

985 986 987 988 989
    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
990

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

993
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
994
}