2

When setting a hardware breakpoint (DR0...), this stores an address (as far as I can see, it looks like a virtual address). Because addresses are shared between processes (at least in 32 bits this can be the case), how does the processor know which process is affected in order to raise the exception? Does this have any implications in a multiprocessor environment?

I know DR7 flags if the bp has global (all tasks) or local (current task only) relevance, but I cannot see how the processor knows when to raise the exception since I can set a hw bp at 410123 for my current pid (task), and other pids might use the same address too.

3
  • Register contexts are associated with a process. Setting a register in process A has no impact to process B.
    – josh poley
    Feb 13 '17 at 19:02
  • 2
    What processor and what operating system are you talking about? Feb 13 '17 at 19:17
  • Platforms x86 and x64 (not sure DRx exists in other processors) and OS that can run on them (Windows, Linux...) @josh poley so the processor always fires and it is the responsibility of, e.g. Windows to clear the registers in any processor context switch? If so, then what about multiprocessor environments? Feb 14 '17 at 8:49
2

The various bits in the DR7 (debug control) register determines the applicability of the hardware breakpoint in question. Such breakpoints can be local or global.

Global breakpoint, as its name suggests affects all tasks. Local breakpoint are specific to the currently executing task. For the Intel Architecture, local breakpoint enable flag bits in the DR7 are cleared on every task switch. Global breakpoint are preserved on task switches.

In Windows, you can only set local hardware breakpoints from user mode.

Now, as per intel documentation local hardware breakpoints are cleared on task switch. So how does local hardware breakpoints work ?

Hardware breakpoints work and fire on the correct process because Windows does not use the hardware task state switching machinery available in the processor. Windows has its own mechanism for context switch. During a context switch, the kernel creates a special structure called the TRAP_FRAME to store information about the debug registers along with other things. The TRAP_FRAME is a part of the thread's complete context.

When the thread is re-scheduled for execution, Windows restores the saved context and with this hardware breakpoints are restored too.

Hence, the processor can never distinguish between a local hardware breakpoint in Process A and Process B. All it sees is a single task executing on each processor. The responsibility of restoring local hardware breakpoints across various processes lies with Windows.


Replies to the comments

(1) On Windows, hardware breakpoints are thread specific. This means if you set a hwbp on an address from a particular thread, the breakpoint will only be triggered when the thread executes/reads/writes that particular address. HWBP are never process wide. Hence, thread2 will never break for a hwbp set from thread1.

(2) The situation is same for Linux. However, it is most likely different for iOS as it runs on a different architecture i.e ARM and not x86.

4
  • Well explained. I'm missing a couple of things, though (i) It is still a bit confusing to picture how DRx are resolved by Windows, ie, if the process1 has 2 threads, each one running in a different processor, and a BP is set from thread1, how does Windows know that thread2 also has to break at that BP? (ii) Do you know if this works in the same way for Linux/iOs? Feb 14 '17 at 13:05
  • @user1156544 See update
    – 0xec
    Feb 14 '17 at 15:45
  • Thanks. I accepted the answer. I suppose that considering (1) a debugger will keep a track on hwbps for the whole process... Otherwise I cannot explain how a user could press a button that creates a new thread to do a task, uses a debugger to set a hwbp in the middle of the task, the thread finishes and then when the user presses the same button (creating a new thread to go through the same instructions as before) the hwbp fires. Feb 14 '17 at 16:37
  • 1
    @user1156544 A debugger typically listens for CREATE_THREAD_DEBUG_EVENT and uses SetThreadContext to set hwbp on a newly created thread. This behaviour is consistent with Olly v2. However Olly1 does not seem to track hwbp across multiple threads.
    – 0xec
    Feb 14 '17 at 18:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.