none
Data breakpoint not working

    Question

  • I have two debuggers running so that I can do a side by side comparison of code flow, where one is showing a correct path and the other is not.  Both are using data breakpoints to help in my analysis.  ATM, both debuggers are in a Debugging state so that I can step through the code.  I noticed that when I stepped over a one of the instructions, the data breakpoints went off.  I tried to step over the same instruction in the other debugger and it didn't do anything.  I checked and the memory reference is correct and it should cause a message to popup.

    My question is, is VS using a hardware debugging interrupt to detect if an address has changed?  And if so, is it not clearing them when in a Debugging state and not resetting them when the application is told to continue?  As the debugging interrupt is a resource, it should be managed better to prevent multiple debuggers from interfering with each other and should report if there is an issue.  Also, what is the maximum number of data breakpoints available?  If this is not the case, then what is causing the failure to break on data change?  


    I don't mind someone marking a post as "Proposed as answer", but DO NOT mark it as "Answered". If I am the OP, I will decide if a post actually answers my post or not. Thank you.

    Thursday, May 17, 2018 3:42 PM

All replies

  • >>My question is, is VS using a hardware debugging interrupt to detect if an address has changed?<<
    VS is using the debug-registers (guess, did not look it up in DR7  'Write' only) :
    https://groups.google.com/forum/#!topic/microsoft.public.vc.debugger/XZ8-ozqmors
    Looks like VS is setting them on a per-process basis:
    https://blogs.msdn.microsoft.com/oldnewthing/20080509-00/?p=22383
    If I launch 2 instances of Visual Studio and set in each debuggee a Data-Break-Point, attaching windbg 'noninvasively' shows
    following output for debug-registers in each thread-context of the 2 debuggees - only the first debug-register (of DR0-DR3) is occupied:

    Are you by any chance using one instance of VS for the two processes? 

    With kind regards





    Friday, May 18, 2018 11:42 AM
  • Hi MCW,

    I'm not exactly sure what I am supposed to be looking at in regards to the image you posted.  However, I am using 2 instances of VS debugging, each debugging 1 instance of the application (different instances).

    This problem looks to be a bug in VS, as the issue appears to have disappeared, but I cannot confirm.

    I've always have found that VS breakpoint interface has always been a bit buggy (refresh issues, multiple breakpoints for the same line when there shouldn't be, etc...), but this is the first time I've found that a breakpoint actually didn't get hit when it should have been.

    Cheers,

    A


    I don't mind someone marking a post as "Proposed as answer", but DO NOT mark it as "Answered". If I am the OP, I will decide if a post actually answers my post or not. Thank you.

    Friday, May 18, 2018 3:17 PM
  • ...

    I'm not exactly sure what I am supposed to be looking at in regards to the image you posted. 

    ...

    The DR0-DR7 registers are the one, used for Data-Breakpoints
    0:000> rM 0x20
    dr0=0113fdb4 dr1=00000000 dr2=00000000
    dr3=00000000 dr6=ffff0ff1 dr7=000d0001
    DataBreakPoint!main+0x51:
    00ab1711 8bf4            mov     esi,esp
    0:000> .formats 000d0001
    Evaluate expression:
      Hex:     000d0001
      Decimal: 851969
      Octal:   00003200001
      Binary:  00000000 00001101 00000000 00000001
      Chars:   ....
      Time:    Sat Jan 10 12:39:29 1970
      Float:   low 1.19386e-039 high 0
      Double:  4.20929e-318

    DR0-DR3 are the registers, where addresses for breakpoints can be stored.
    With DR7 DebugControl register, you can manipulate break-conditions.
    Only one slot is occupied in this thread context.
    Bits 16-17 shows that only 'Writes' triggers the BP : 01b
    Bits 18-19 specify a four byte range will be covered: 11b

    In the picture in the previous post (left), all thread-contexts of one process have the same entry, one slot, DR0 is occupied.
    If hardware-breakpoints would be system-wide, adding a hardware-breakpoints in a different process may show up (theoretically - for a debugger always gets filtered info) as additional entry in DR1, which is not the case (right side).
    So it looks like Visual Studio sets hardware-breakpoints per process  and not system-wide or per thread.
    Therefore you should have in total 4 Breakpoints per process at your disposal.

    Windbg has some more options. (Setting hwbps  per thread may increase number per process.)
    https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/ba--break-on-access-

    By the way VS does not seem to check plausibility of hwbp-addresses in any way.

    FAIK only one user-mode-debugger can 'register' for receiving DEBUG_EVENTs per process  - (hitting a hwbp is just an EXCEPTION_SINGLE_STEP).
    So it's hard for me to imagine that the two debuggers don't act independently. 
    But certainly this is Microsoft …

    With kind regards


    Saturday, May 19, 2018 1:49 PM
  • Just looking at new 'Time Travel Debugging' feature in WinDbg Preview
    https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/time-travel-debugging-walkthrough
    Obviously there are also 'memory access breakpoints' possible. Maybe an alternative for your debugging scenario.

    With kind regards

    Tuesday, May 22, 2018 5:56 AM
  • Thanks for the interesting info MCW.  Looks like the problem is just a bug in their debugger.  Oh joy.  Without shutting down the debugger (though I'm not sure if I restarted the application), I was able to get the memory breakpoint to work.  I've found that the VS debugger is kinda flaky when it come to their breakpoint interface.

    Thanks again.

    A


    I don't mind someone marking a post as "Proposed as answer", but DO NOT mark it as "Answered". If I am the OP, I will decide if a post actually answers my post or not. Thank you.

    Tuesday, May 22, 2018 8:37 PM
  • Ability to set per thread hw breakpoints means that the OS swaps the DRs automatically with every thread switch.

    Unless Windbg itself interferes in thread switching for processes being debugged.

    MaybeCompletelyW, do you happen to know more details on this?

    --pa

    Tuesday, May 22, 2018 10:31 PM
  • Ability to set per thread hw breakpoints means that the OS swaps the DRs automatically with every thread switch.

    Would think so. For UM debuggers usually implement and handle HWbps with SetThreadContext() assume, DRs are set distinctly with every context-switch - (the actual load/store of DR-registers has to be done by the kernel, for these are privileged instructions).
    In Windbg looks like you are allowed to set them individually for each thread (according to register-output): 
    ~Thread ba Access Size ...

    Now, if wanting to create a process-wide HWbp - which sometimes has its merits - I would set the cpu-context for every thread in the debuggee to the same address - and moreover, for a consistent 'debugging experience,' when receiving a CREATE_THREAD_DEBUG_EVENT, I'd set the DRs accordingly in the cpu-context of the newly arrived thread.
    With windbg you get process-wide hwbp, when using (omitting thread) syntax:

    ba Access Size …

    With kind regards

    Output: first three individual 'r' breakpoints (per thread), then one process-wide (00064864). Last two entries: DRs of threads created after 'process-wide' hwbp was set.
     
    0:000> ~*e rM 0x20
    dr0=00064864 dr1=00000000 dr2=00000000
    dr3=00000000 dr6=ffff0ff0 dr7=000f0101
    win32u!NtUserWaitMessage+0xc:
    76a12b9c c3              ret
    dr0=00012864 dr1=00064864 dr2=00000000
    dr3=00000000 dr6=00000000 dr7=00ff0105
    ntdll!NtWaitForWorkViaWorkerFactory+0xc:
    77c5b1bc c21400          ret     14h
    dr0=00024864 dr1=00064864 dr2=00000000
    dr3=00000000 dr6=00000000 dr7=00ff0105
    ntdll!NtWaitForWorkViaWorkerFactory+0xc:
    77c5b1bc c21400          ret     14h
    dr0=00048864 dr1=00064864 dr2=00000000
    dr3=00000000 dr6=00000000 dr7=00ff0105
    ntdll!NtWaitForWorkViaWorkerFactory+0xc:
    77c5b1bc c21400          ret     14h
    dr0=00064864 dr1=00000000 dr2=00000000
    dr3=00000000 dr6=00000000 dr7=000f0101
    win32u!NtUserMsgWaitForMultipleObjectsEx+0xc:
    76a16e0c c21400          ret     14h
    dr0=00064864 dr1=00000000 dr2=00000000
    dr3=00000000 dr6=ffff0ff0 dr7=000f0101
    win32u!NtUserMsgWaitForMultipleObjectsEx+0xc:
    76a16e0c c21400          ret     14h
    dr0=00064864 dr1=00000000 dr2=00000000
    dr3=00000000 dr6=00000000 dr7=000f0101
    ntdll!NtWaitForMultipleObjects+0xc:

    Wednesday, May 23, 2018 6:54 AM